/*++ Copyright (c) 1990 Microsoft Corporation Module Name: baseinit.c Abstract: This module implements Win32 base initialization Author: Mark Lucovsky (markl) 26-Sep-1990 Revision History: --*/ #include "basedll.h" // // Divides by 10000 // BOOLEAN BaseRunningInServerProcess; UINT_PTR SystemRangeStart; #if defined(_WIN64) || defined(BUILD_WOW6432) SYSTEM_BASIC_INFORMATION SysInfo; #endif WCHAR BaseDefaultPathBuffer[ 3072 ]; WCHAR PsapiDllString[] = L"psapi.dll"; ULONG GetPerUserWindowsDirectory(PWCHAR TermSrvWindowsPath, ULONG len); // // Dispatch functions for Oem/Ansi sensitive conversions // NTSTATUS (*Basep8BitStringToUnicodeString)( PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString ) = RtlAnsiStringToUnicodeString; NTSTATUS (*BasepUnicodeStringTo8BitString)( PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString ) = RtlUnicodeStringToAnsiString; ULONG (*BasepUnicodeStringTo8BitSize)( PUNICODE_STRING UnicodeString ) = BasepUnicodeStringToAnsiSize; ULONG (*Basep8BitStringToUnicodeSize)( PANSI_STRING AnsiString ) = BasepAnsiStringToUnicodeSize; VOID WINAPI SetFileApisToOEM( VOID ) { Basep8BitStringToUnicodeString = RtlOemStringToUnicodeString; BasepUnicodeStringTo8BitString = RtlUnicodeStringToOemString; BasepUnicodeStringTo8BitSize = BasepUnicodeStringToOemSize; Basep8BitStringToUnicodeSize = BasepOemStringToUnicodeSize; } VOID WINAPI SetFileApisToANSI( VOID ) { Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString; BasepUnicodeStringTo8BitString = RtlUnicodeStringToAnsiString; BasepUnicodeStringTo8BitSize = BasepUnicodeStringToAnsiSize; Basep8BitStringToUnicodeSize = BasepAnsiStringToUnicodeSize; } BOOL WINAPI AreFileApisANSI( VOID ) { return Basep8BitStringToUnicodeString == RtlAnsiStringToUnicodeString; } BOOLEAN ConDllInitialize( IN ULONG Reason, IN PWSTR pObjectDirectory OPTIONAL ); BOOLEAN NlsDllInitialize( IN PVOID DllHandle, IN ULONG Reason, IN PBASE_STATIC_SERVER_DATA BaseStaticServerData ); BOOLEAN NlsThreadCleanup(void); #if DBG VOID WINAPI AssertDelayLoadFailureMapsAreSorted ( VOID ); #endif UNICODE_STRING BasePathVariableName = RTL_CONSTANT_STRING(L"PATH"); UNICODE_STRING BaseUserProfileVariableName = RTL_CONSTANT_STRING(L"USERPROFILE"); UNICODE_STRING BaseTmpVariableName = RTL_CONSTANT_STRING(L"TMP"); UNICODE_STRING BaseTempVariableName = RTL_CONSTANT_STRING(L"TEMP"); UNICODE_STRING BaseDotVariableName = RTL_CONSTANT_STRING(L"."); UNICODE_STRING BaseDotTmpSuffixName = RTL_CONSTANT_STRING(L".tmp"); UNICODE_STRING BaseDotComSuffixName = RTL_CONSTANT_STRING(L".com"); UNICODE_STRING BaseDotPifSuffixName = RTL_CONSTANT_STRING(L".pif"); UNICODE_STRING BaseDotExeSuffixName = RTL_CONSTANT_STRING(L".exe"); UNICODE_STRING BaseConsoleInput = RTL_CONSTANT_STRING(L"CONIN$"); UNICODE_STRING BaseConsoleOutput = RTL_CONSTANT_STRING(L"CONOUT$"); UNICODE_STRING BaseConsoleGeneric = RTL_CONSTANT_STRING(L"CON"); BOOLEAN BaseDllInitialize( IN PVOID DllHandle, IN ULONG Reason, IN PCONTEXT Context OPTIONAL ) /*++ Routine Description: This function implements Win32 base dll initialization. It's primary purpose is to create the Base heap. Arguments: DllHandle - Saved in BaseDllHandle global variable Context - Not Used Return Value: STATUS_SUCCESS --*/ { BOOLEAN Success; NTSTATUS Status; PPEB Peb; LPWSTR p, p1; BOOLEAN ServerProcess; HANDLE hNlsCacheMutant; USHORT Size; #if !defined(BUILD_WOW6432) ULONG SizeMutant; #endif WCHAR szSessionDir[MAX_SESSION_PATH]; SessionId = NtCurrentPeb()->SessionId; BaseDllHandle = DllHandle; Success = TRUE; Peb = NtCurrentPeb(); switch ( Reason ) { case DLL_PROCESS_ATTACH: Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString; RtlSetThreadPoolStartFunc( BaseCreateThreadPoolThread, BaseExitThreadPoolThread ); LdrSetDllManifestProber(&BasepProbeForDllManifest); BaseDllTag = RtlCreateTagHeap( RtlProcessHeap(), 0, L"BASEDLL!", L"TMP\0" L"BACKUP\0" L"INI\0" L"FIND\0" L"GMEM\0" L"LMEM\0" L"ENV\0" L"RES\0" L"VDM\0" ); BaseIniFileUpdateCount = 0; BaseDllInitializeMemoryManager(); RtlInitUnicodeString( &BaseDefaultPath, NULL ); // // Connect to BASESRV.DLL in the server process // #if !defined(BUILD_WOW6432) SizeMutant = sizeof(hNlsCacheMutant); #endif if ( SessionId == 0 ) { // // Console Session // wcscpy(szSessionDir, WINSS_OBJECT_DIRECTORY_NAME); } else { swprintf(szSessionDir,L"%ws\\%ld%ws",SESSION_ROOT,SessionId,WINSS_OBJECT_DIRECTORY_NAME); } #if defined(BUILD_WOW6432) || defined(_WIN64) Status = NtQuerySystemInformation(SystemBasicInformation, &SysInfo, sizeof(SYSTEM_BASIC_INFORMATION), NULL ); if (!NT_SUCCESS(Status)) { return FALSE; } #endif #if defined(BUILD_WOW6432) Status = CsrBaseClientConnectToServer(szSessionDir, &hNlsCacheMutant, &ServerProcess ); #else Status = CsrClientConnectToServer( szSessionDir, BASESRV_SERVERDLL_INDEX, &hNlsCacheMutant, &SizeMutant, &ServerProcess ); #endif if (!NT_SUCCESS( Status )) { return FALSE; } BaseStaticServerData = BASE_SHARED_SERVER_DATA; if (!ServerProcess) { CsrNewThread(); BaseRunningInServerProcess = FALSE; } else { BaseRunningInServerProcess = TRUE; } BaseCSDVersion = BaseStaticServerData->CSDVersion; BaseCSDNumber = BaseStaticServerData->CSDNumber; BaseRCNumber = BaseStaticServerData->RCNumber; if ((BaseCSDVersion) && (!Peb->CSDVersion.Buffer)) { RtlInitUnicodeString(&Peb->CSDVersion, BaseCSDVersion); } BASE_SERVER_STR_TO_LOCAL_STR(&BaseWindowsDirectory, &BaseStaticServerData->WindowsDirectory); BASE_SERVER_STR_TO_LOCAL_STR(&BaseWindowsSystemDirectory, &BaseStaticServerData->WindowsSystemDirectory); #ifdef WX86 BASE_SERVER_STR_TO_LOCAL_STR(&BaseWindowsSys32x86Directory, &BaseStaticServerData->WindowsSys32x86Directory); #endif BaseUnicodeCommandLine = NtCurrentPeb()->ProcessParameters->CommandLine; Status = RtlUnicodeStringToAnsiString( &BaseAnsiCommandLine, &BaseUnicodeCommandLine, TRUE ); if ( !NT_SUCCESS(Status) ){ BaseAnsiCommandLine.Buffer = NULL; BaseAnsiCommandLine.Length = 0; BaseAnsiCommandLine.MaximumLength = 0; } p = BaseDefaultPathBuffer; p1 = BaseWindowsSystemDirectory.Buffer; while( *p = *p1++) { p++; } *p++ = L';'; #ifdef WX86 // // Wx86 system dir follows 32 bit system dir // p1 = BaseWindowsSys32x86Directory.Buffer; while( *p = *p1++) { p++; } *p++ = L';'; #endif // // 16bit system directory follows 32bit system directory // p1 = BaseWindowsDirectory.Buffer; while( *p = *p1++) { p++; } p1 = L"\\system"; while( *p = *p1++) { p++; } *p++ = L';'; p1 = BaseWindowsDirectory.Buffer; while( *p = *p1++) { p++; } *p++ = L';'; if (IsTerminalServer()) { WCHAR TermSrvWindowsPath[MAX_PATH]; if (GetPerUserWindowsDirectory(TermSrvWindowsPath, MAX_PATH)) { p1 = TermSrvWindowsPath; while( *p = *p1++) { p++; } *p++ = L';'; } } *p = UNICODE_NULL; BaseDefaultPath.Buffer = BaseDefaultPathBuffer; BaseDefaultPath.Length = (USHORT)((ULONG_PTR)p - (ULONG_PTR)BaseDefaultPathBuffer); BaseDefaultPath.MaximumLength = sizeof( BaseDefaultPathBuffer ); BaseDefaultPathAppend.Buffer = p; BaseDefaultPathAppend.Length = 0; BaseDefaultPathAppend.MaximumLength = (USHORT) (BaseDefaultPath.MaximumLength - BaseDefaultPath.Length); if (!NT_SUCCESS(RtlInitializeCriticalSection(&BaseDllDirectoryLock))) { return FALSE; } BaseDllInitializeIniFileMappings( BaseStaticServerData ); if ( Peb->ProcessParameters ) { if ( Peb->ProcessParameters->Flags & RTL_USER_PROC_PROFILE_USER ) { LoadLibraryW(PsapiDllString); } if (Peb->ProcessParameters->DebugFlags) { DbgBreakPoint(); } } // // call the NLS API initialization routine // if ( !NlsDllInitialize( DllHandle, Reason, BaseStaticServerData ) ) { return FALSE; } // // call the console initialization routine // if ( !ConDllInitialize(Reason,szSessionDir) ) { return FALSE; } InitializeListHead( &BasepAppCertDllsList ); if (!NT_SUCCESS(RtlInitializeCriticalSection(&gcsAppCert))) { return FALSE; } if (!NT_SUCCESS(RtlInitializeCriticalSection(&gcsAppCompat))) { return(FALSE); } #if DBG AssertDelayLoadFailureMapsAreSorted (); #endif break; case DLL_PROCESS_DETACH: // // Make sure any open registry keys are closed. // if (BaseIniFileUpdateCount != 0) { WriteProfileStringW( NULL, NULL, NULL ); } break; case DLL_THREAD_ATTACH: // // call the console initialization routine // if ( !ConDllInitialize(Reason,NULL) ) { return FALSE; } break; case DLL_THREAD_DETACH: // // Delete the thread NLS cache, if exists. // NlsThreadCleanup(); break; default: break; } return Success; } NTSTATUS NTAPI BaseProcessInitPostImport() /* Routine Description: Called by the ntdll process initialization code after all of the import tables for the static imports of the EXE have been processed, but before any DLL_PROCESS_ATTACHes are sent with the exception of kernel32.dll's. Needed for the terminal server app compat hooks. */ { NTSTATUS Status = STATUS_INTERNAL_ERROR; // // Intialize TerminalServer(Hydra) hook function pointers for app compatibility // if (IsTerminalServer()) InitializeTermsrvFpns(); Status = STATUS_SUCCESS; // Exit: return Status; } HANDLE BaseGetNamedObjectDirectory( VOID ) { OBJECT_ATTRIBUTES Obja; NTSTATUS Status; UNICODE_STRING RestrictedObjectDirectory; ACCESS_MASK DirAccess = DIRECTORY_ALL_ACCESS & ~(DELETE | WRITE_DAC | WRITE_OWNER); HANDLE hRootNamedObject; HANDLE BaseHandle; if ( BaseNamedObjectDirectory != NULL) { return BaseNamedObjectDirectory; } RtlAcquirePebLock(); if ( !BaseNamedObjectDirectory ) { BASE_READ_REMOTE_STR_TEMP(TempStr); InitializeObjectAttributes( &Obja, BASE_READ_REMOTE_STR(BaseStaticServerData->NamedObjectDirectory, TempStr), OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = NtOpenDirectoryObject( &BaseHandle, DirAccess, &Obja ); // if the intial open failed, try again with just traverse, and // open the restricted subdirectory if ( !NT_SUCCESS(Status) ) { Status = NtOpenDirectoryObject( &hRootNamedObject, DIRECTORY_TRAVERSE, &Obja ); if ( NT_SUCCESS(Status) ) { RtlInitUnicodeString( &RestrictedObjectDirectory, L"Restricted"); InitializeObjectAttributes( &Obja, &RestrictedObjectDirectory, OBJ_CASE_INSENSITIVE, hRootNamedObject, NULL ); Status = NtOpenDirectoryObject( &BaseHandle, DirAccess, &Obja ); NtClose( hRootNamedObject ); } } if ( NT_SUCCESS(Status) ) { BaseNamedObjectDirectory = BaseHandle; } } RtlReleasePebLock(); return BaseNamedObjectDirectory; }