Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendllmain.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
1.7.6.1
|