ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dllmain.c
Go to the documentation of this file.
00001 /* $Id: dllmain.c 56414 2012-04-25 10:17:29Z tfaber $
00002  *
00003  * COPYRIGHT:       See COPYING in the top level directory
00004  * PROJECT:         ReactOS system libraries
00005  * FILE:            lib/kernel32/misc/dllmain.c
00006  * PURPOSE:         Initialization
00007  * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
00008  *                  Aleksey Bragin (aleksey@reactos.org)
00009  * UPDATE HISTORY:
00010  *                  Created 01/11/98
00011  */
00012 
00013 /* INCLUDES ******************************************************************/
00014 
00015 #include <k32.h>
00016 
00017 #define NDEBUG
00018 #include <debug.h>
00019 
00020 /* GLOBALS *******************************************************************/
00021 
00022 PBASE_STATIC_SERVER_DATA BaseStaticServerData;
00023 
00024 BOOLEAN BaseRunningInServerProcess;
00025 
00026 WCHAR BaseDefaultPathBuffer[6140];
00027 
00028 HANDLE BaseNamedObjectDirectory;
00029 HMODULE hCurrentModule = NULL;
00030 HMODULE kernel32_handle = NULL;
00031 PPEB Peb;
00032 ULONG SessionId;
00033 BOOL ConsoleInitialized = FALSE;
00034 static BOOL DllInitialized = FALSE;
00035 
00036 BOOL WINAPI
00037 DllMain(HANDLE hInst,
00038     DWORD dwReason,
00039     LPVOID lpReserved);
00040 
00041 /* Critical section for various kernel32 data structures */
00042 RTL_CRITICAL_SECTION BaseDllDirectoryLock;
00043 RTL_CRITICAL_SECTION ConsoleLock;
00044 
00045 extern BOOL WINAPI DefaultConsoleCtrlHandler(DWORD Event);
00046 extern __declspec(noreturn) VOID CALLBACK ConsoleControlDispatcher(DWORD CodeAndFlag);
00047 extern PHANDLER_ROUTINE InitialHandler[1];
00048 extern PHANDLER_ROUTINE* CtrlHandlers;
00049 extern ULONG NrCtrlHandlers;
00050 extern ULONG NrAllocatedHandlers;
00051 extern BOOL FASTCALL NlsInit(VOID);
00052 extern VOID FASTCALL NlsUninit(VOID);
00053 BOOLEAN InWindows = FALSE;
00054 
00055 #define WIN_OBJ_DIR L"\\Windows"
00056 #define SESSION_DIR L"\\Sessions"
00057 
00058 /* FUNCTIONS *****************************************************************/
00059 
00060 BOOL
00061 WINAPI
00062 BasepInitConsole(VOID)
00063 {
00064     CSR_API_MESSAGE Request;
00065     ULONG CsrRequest;
00066     NTSTATUS Status;
00067     BOOLEAN NotConsole = FALSE;
00068     PRTL_USER_PROCESS_PARAMETERS Parameters = NtCurrentPeb()->ProcessParameters;
00069     LPCWSTR ExeName;
00070     STARTUPINFO si;
00071     WCHAR SessionDir[256];
00072     ULONG SessionId = NtCurrentPeb()->SessionId;
00073     BOOLEAN InServer;
00074     
00075     WCHAR lpTest[MAX_PATH];
00076     GetModuleFileNameW(NULL, lpTest, MAX_PATH);
00077     DPRINT("BasepInitConsole for : %S\n", lpTest);
00078     DPRINT("Our current console handles are: %lx, %lx, %lx %lx\n",
00079            Parameters->ConsoleHandle, Parameters->StandardInput,
00080            Parameters->StandardOutput, Parameters->StandardError);
00081 
00082     /* We have nothing to do if this isn't a console app... */
00083     if (RtlImageNtHeader(GetModuleHandle(NULL))->OptionalHeader.Subsystem !=
00084         IMAGE_SUBSYSTEM_WINDOWS_CUI)
00085     {
00086         DPRINT("Image is not a console application\n");
00087         Parameters->ConsoleHandle = NULL;
00088         Request.Data.AllocConsoleRequest.ConsoleNeeded = FALSE;
00089     }
00090     else
00091     {
00092         /* Assume one is needed */
00093         GetStartupInfo(&si);
00094         Request.Data.AllocConsoleRequest.ConsoleNeeded = TRUE;
00095         Request.Data.AllocConsoleRequest.ShowCmd = si.wShowWindow;
00096 
00097         /* Handle the special flags given to us by BasepInitializeEnvironment */
00098         if (Parameters->ConsoleHandle == HANDLE_DETACHED_PROCESS)
00099         {
00100             /* No console to create */
00101             DPRINT("No console to create\n");
00102             Parameters->ConsoleHandle = NULL;
00103             Request.Data.AllocConsoleRequest.ConsoleNeeded = FALSE;
00104         }
00105         else if (Parameters->ConsoleHandle == HANDLE_CREATE_NEW_CONSOLE)
00106         {
00107             /* We'll get the real one soon */
00108             DPRINT("Creating new console\n");
00109             Parameters->ConsoleHandle = NULL;
00110         }
00111         else if (Parameters->ConsoleHandle == HANDLE_CREATE_NO_WINDOW)
00112         {
00113             /* We'll get the real one soon */
00114             DPRINT("Creating new invisible console\n");
00115             Parameters->ConsoleHandle = NULL;
00116             Request.Data.AllocConsoleRequest.ShowCmd = SW_HIDE;
00117         }
00118         else
00119         {
00120             if (Parameters->ConsoleHandle == INVALID_HANDLE_VALUE)
00121             {
00122                 Parameters->ConsoleHandle = 0;
00123             }
00124             DPRINT("Using existing console: %x\n", Parameters->ConsoleHandle);
00125         }
00126     }
00127 
00128     /* Initialize Console Ctrl Handler and input EXE name */
00129     ConsoleInitialized = TRUE;
00130     RtlInitializeCriticalSection(&ConsoleLock);
00131     NrAllocatedHandlers = 1;
00132     NrCtrlHandlers = 1;
00133     CtrlHandlers = InitialHandler;
00134     CtrlHandlers[0] = DefaultConsoleCtrlHandler;
00135 
00136     ExeName = wcsrchr(Parameters->ImagePathName.Buffer, L'\\');
00137     if (ExeName)
00138         SetConsoleInputExeNameW(ExeName + 1);
00139 
00140     /* Now use the proper console handle */
00141     Request.Data.AllocConsoleRequest.Console = Parameters->ConsoleHandle;
00142     
00143     /* Setup the right Object Directory path */
00144     if (!SessionId)
00145     {
00146         /* Use the raw path */
00147         wcscpy(SessionDir, WIN_OBJ_DIR);
00148     }
00149     else
00150     {
00151         /* Use the session path */
00152         swprintf(SessionDir,
00153                  L"%ws\\%ld%ws",
00154                  SESSION_DIR,
00155                  SessionId,
00156                  WIN_OBJ_DIR);
00157     }
00158 
00159     /* Connect to the base server */
00160     DPRINT("Connecting to CSR...\n");
00161     Status = CsrClientConnectToServer(SessionDir,
00162                                       2,
00163                                       NULL,
00164                                       NULL,
00165                                       &InServer);
00166     if (!NT_SUCCESS(Status))
00167     {
00168         DPRINT1("Failed to connect to CSR (Status %lx)\n", Status);
00169         return FALSE;
00170     }
00171 
00172     /* Nothing to do for server-to-server */
00173     if (InServer) return TRUE;
00174 
00175     /*
00176      * Normally, we should be connecting to the Console CSR Server...
00177      * but we don't have one yet, so we will instead simply send a create
00178      * console message to the Base Server. When we finally have a Console
00179      * Server, this code should be changed to send connection data instead.
00180      */
00181     CsrRequest = MAKE_CSR_API(ALLOC_CONSOLE, CSR_CONSOLE);
00182     Request.Data.AllocConsoleRequest.CtrlDispatcher = ConsoleControlDispatcher;
00183     Status = CsrClientCallServer(&Request,
00184                                  NULL,
00185                                  CsrRequest,
00186                                  sizeof(CSR_API_MESSAGE));
00187     if(!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Request.Status))
00188     {
00189         DPRINT1("CSR Failed to give us a console\n");
00190         /* We're lying here, so at least the process can load... */
00191         return TRUE;
00192     }
00193 
00194     /* Nothing to do if not a console app */
00195     if (NotConsole) return TRUE;
00196 
00197     /* We got the handles, let's set them */
00198     if ((Parameters->ConsoleHandle = Request.Data.AllocConsoleRequest.Console))
00199     {
00200         /* If we already had some, don't use the new ones */
00201         if (!Parameters->StandardInput)
00202         {
00203             Parameters->StandardInput = Request.Data.AllocConsoleRequest.InputHandle;
00204         }
00205         if (!Parameters->StandardOutput)
00206         {
00207             Parameters->StandardOutput = Request.Data.AllocConsoleRequest.OutputHandle;
00208         }
00209         if (!Parameters->StandardError)
00210         {
00211             Parameters->StandardError = Request.Data.AllocConsoleRequest.OutputHandle;
00212         }
00213     }
00214 
00215     DPRINT("Console setup: %lx, %lx, %lx, %lx\n",
00216             Parameters->ConsoleHandle,
00217             Parameters->StandardInput,
00218             Parameters->StandardOutput,
00219             Parameters->StandardError);
00220     return TRUE;
00221 }
00222 
00223 NTSTATUS
00224 NTAPI
00225 BaseCreateThreadPoolThread(IN PTHREAD_START_ROUTINE Function,
00226                            IN PVOID Parameter,
00227                            OUT PHANDLE ThreadHandle)
00228 {
00229     NTSTATUS Status;
00230 
00231     /* Create a Win32 thread */
00232     *ThreadHandle = CreateRemoteThread(NtCurrentProcess(),
00233                                        NULL,
00234                                        0,
00235                                        Function,
00236                                        Parameter,
00237                                        CREATE_SUSPENDED,
00238                                        NULL);
00239     if (!(*ThreadHandle))
00240     {
00241         /* Get the status value if we couldn't get a handle */
00242         Status = NtCurrentTeb()->LastStatusValue;
00243         if (NT_SUCCESS(Status)) Status = STATUS_UNSUCCESSFUL;
00244     }
00245     else
00246     {
00247         /* Set success code */
00248         Status = STATUS_SUCCESS;
00249     }
00250 
00251     /* All done */
00252     return Status;
00253 }
00254 
00255 NTSTATUS
00256 NTAPI
00257 BaseExitThreadPoolThread(IN NTSTATUS ExitStatus)
00258 {
00259     /* Exit the thread */
00260     ExitThread(ExitStatus);
00261 }
00262 
00263 BOOL
00264 WINAPI
00265 DllMain(HANDLE hDll,
00266         DWORD dwReason,
00267         LPVOID lpReserved)
00268 {
00269     NTSTATUS Status;
00270     ULONG Dummy;
00271     ULONG DummySize = sizeof(Dummy);
00272     WCHAR SessionDir[256];
00273 
00274     DPRINT("DllMain(hInst %lx, dwReason %lu)\n",
00275            hDll, dwReason);
00276 
00277     Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;
00278 
00279     /* Cache the PEB and Session ID */
00280     Peb = NtCurrentPeb();
00281     SessionId = Peb->SessionId;
00282 
00283     switch (dwReason)
00284     {
00285         case DLL_PROCESS_ATTACH:
00286         
00287         /* Set no filter intially */
00288         GlobalTopLevelExceptionFilter = RtlEncodePointer(NULL);
00289         
00290         /* Enable the Rtl thread pool and timer queue to use proper Win32 thread */
00291         RtlSetThreadPoolStartFunc(BaseCreateThreadPoolThread, BaseExitThreadPoolThread);
00292 
00293         /* Don't bother us for each thread */
00294         LdrDisableThreadCalloutsForDll((PVOID)hDll);
00295 
00296         /* Initialize default path to NULL */
00297         RtlInitUnicodeString(&BaseDefaultPath, NULL);
00298 
00299         /* Setup the right Object Directory path */
00300         if (!SessionId)
00301         {
00302             /* Use the raw path */
00303             wcscpy(SessionDir, WIN_OBJ_DIR);
00304         }
00305         else
00306         {
00307             /* Use the session path */
00308             swprintf(SessionDir,
00309                      L"%ws\\%ld%ws",
00310                      SESSION_DIR,
00311                      SessionId,
00312                      WIN_OBJ_DIR);
00313         }
00314 
00315         /* Connect to the base server */
00316         DPRINT("Connecting to CSR...\n");
00317         Status = CsrClientConnectToServer(SessionDir,
00318                                           InWindows ? 1 : 0,
00319                                           &Dummy,
00320                                           &DummySize,
00321                                           &BaseRunningInServerProcess);
00322         if (!NT_SUCCESS(Status))
00323         {
00324             DPRINT1("Failed to connect to CSR (Status %lx)\n", Status);
00325             NtTerminateProcess(NtCurrentProcess(), Status);
00326             return FALSE;
00327         }
00328 
00329         /* Get the server data */
00330         ASSERT(Peb->ReadOnlyStaticServerData);
00331         BaseStaticServerData = Peb->ReadOnlyStaticServerData[CSR_CONSOLE];
00332         ASSERT(BaseStaticServerData);
00333 
00334         /* Check if we are running a CSR Server */
00335         if (!BaseRunningInServerProcess)
00336         {
00337             /* Set the termination port for the thread */
00338             DPRINT("Creating new thread for CSR\n");
00339             CsrNewThread();
00340         }
00341 
00342         /* Initialize heap handle table */
00343         BaseDllInitializeMemoryManager();
00344 
00345         /* Set HMODULE for our DLL */
00346         kernel32_handle = hCurrentModule = hDll;
00347 
00348         /* Set the directories */
00349         BaseWindowsDirectory = BaseStaticServerData->WindowsDirectory;
00350         BaseWindowsSystemDirectory = BaseStaticServerData->WindowsSystemDirectory;
00351 
00352         /* Construct the default path (using the static buffer) */
00353         _snwprintf(BaseDefaultPathBuffer, sizeof(BaseDefaultPathBuffer) / sizeof(WCHAR),
00354             L".;%wZ;%wZ\\system;%wZ;", &BaseWindowsSystemDirectory, &BaseWindowsDirectory, &BaseWindowsDirectory);
00355 
00356         BaseDefaultPath.Buffer = BaseDefaultPathBuffer;
00357         BaseDefaultPath.Length = wcslen(BaseDefaultPathBuffer) * sizeof(WCHAR);
00358         BaseDefaultPath.MaximumLength = sizeof(BaseDefaultPathBuffer);
00359 
00360         /* Use remaining part of the default path buffer for the append path */
00361         BaseDefaultPathAppend.Buffer = (PWSTR)((ULONG_PTR)BaseDefaultPathBuffer + BaseDefaultPath.Length);
00362         BaseDefaultPathAppend.Length = 0;
00363         BaseDefaultPathAppend.MaximumLength = BaseDefaultPath.MaximumLength - BaseDefaultPath.Length;
00364 
00365         /* Initialize command line */
00366         InitCommandLines();
00367 
00368         /* Initialize the DLL critical section */
00369         RtlInitializeCriticalSection(&BaseDllDirectoryLock);
00370 
00371         /* Initialize the National Language Support routines */
00372         if (!NlsInit())
00373         {
00374             DPRINT1("NLS Init failed\n");
00375             return FALSE;
00376         }
00377 
00378         /* Initialize Console Support */
00379         if (!BasepInitConsole())
00380         {
00381             DPRINT1("Failure to set up console\n");
00382             return FALSE;
00383         }
00384 
00385         /* Initialize application certification globals */
00386         InitializeListHead(&BasepAppCertDllsList);
00387         RtlInitializeCriticalSection(&gcsAppCert);
00388 
00389         /* Insert more dll attach stuff here! */
00390         DllInitialized = TRUE;
00391         DPRINT("Initialization complete\n");
00392         break;
00393 
00394         case DLL_PROCESS_DETACH:
00395 
00396             DPRINT("DLL_PROCESS_DETACH\n");
00397             if (DllInitialized == TRUE)
00398             {
00399                 /* Insert more dll detach stuff here! */
00400                 NlsUninit();
00401 
00402                 /* Delete DLL critical section */
00403                 if (ConsoleInitialized == TRUE)
00404                 {
00405                     ConsoleInitialized = FALSE;
00406                     RtlDeleteCriticalSection (&ConsoleLock);
00407                 }
00408                 RtlDeleteCriticalSection (&BaseDllDirectoryLock);
00409             }
00410             break;
00411 
00412         default:
00413             break;
00414     }
00415 
00416     return TRUE;
00417 }
00418 
00419 /* EOF */

Generated on Fri May 25 2012 04:20:40 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.