Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

656 lines
18 KiB

/*++
Copyright (c) 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"
ULONG BaseDllTag;
BOOLEAN BaseRunningInServerProcess;
UINT_PTR SystemRangeStart;
#if defined(_WIN64) || defined(BUILD_WOW6432)
SYSTEM_BASIC_INFORMATION SysInfo;
SYSTEM_PROCESSOR_INFORMATION NativeProcessorInfo;
#endif
WCHAR BaseDefaultPathBuffer[ 3072 ];
extern const WCHAR PsapiDllString[] = L"psapi.dll";
UNICODE_STRING BaseDefaultPath;
UNICODE_STRING BaseDefaultPathAppend;
PWSTR BaseCSDVersion;
WORD BaseCSDNumber;
WORD BaseRCNumber;
UNICODE_STRING BaseUnicodeCommandLine;
ANSI_STRING BaseAnsiCommandLine;
LPSTARTUPINFOA BaseAnsiStartupInfo;
PBASE_STATIC_SERVER_DATA BaseStaticServerData;
ULONG BaseIniFileUpdateCount;
RTL_CRITICAL_SECTION gcsAppCert;
LIST_ENTRY BasepAppCertDllsList;
RTL_CRITICAL_SECTION gcsAppCompat;
PTERMSRVFORMATOBJECTNAME gpTermsrvFormatObjectName;
PTERMSRVGETCOMPUTERNAME gpTermsrvGetComputerName;
PTERMSRVADJUSTPHYMEMLIMITS gpTermsrvAdjustPhyMemLimits;
PTERMSRVGETWINDOWSDIRECTORYA gpTermsrvGetWindowsDirectoryA;
PTERMSRVGETWINDOWSDIRECTORYW gpTermsrvGetWindowsDirectoryW;
PTERMSRVCONVERTSYSROOTTOUSERDIR gpTermsrvConvertSysRootToUserDir;
PTERMSRVBUILDINIFILENAME gpTermsrvBuildIniFileName;
PTERMSRVCORINIFILE gpTermsrvCORIniFile;
PTERMSRVUPDATEALLUSERMENU gpTermsrvUpdateAllUserMenu;
PGETTERMSRCOMPATFLAGS gpGetTermsrCompatFlags;
PTERMSRVBUILDSYSINIPATH gpTermsrvBuildSysIniPath;
PTERMSRVCOPYINIFILE gpTermsrvCopyIniFile;
PTERMSRVGETSTRING gpTermsrvGetString;
PTERMSRVLOGINSTALLINIFILE gpTermsrvLogInstallIniFile;
HANDLE BaseDllHandle;
HANDLE BaseNamedObjectDirectory;
PVOID BaseHeap;
RTL_HANDLE_TABLE BaseHeapHandleTable;
UNICODE_STRING BaseWindowsDirectory;
UNICODE_STRING BaseWindowsSystemDirectory;
UNICODE_STRING BaseDllDirectory = { 0, 0, NULL };
RTL_CRITICAL_SECTION BaseDllDirectoryLock;
RTL_CRITICAL_SECTION BaseLZSemTable;
#ifdef WX86
UNICODE_STRING BaseWindowsSys32x86Directory;
#endif
//
// 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
);
VOID
NlsThreadCleanup(
VOID);
#if DBG
VOID
WINAPI
AssertDelayLoadFailureMapsAreSorted (
VOID
);
#endif
extern const UNICODE_STRING BasePathVariableName = RTL_CONSTANT_STRING(L"PATH");
extern const UNICODE_STRING BaseUserProfileVariableName = RTL_CONSTANT_STRING(L"USERPROFILE");
extern const UNICODE_STRING BaseTmpVariableName = RTL_CONSTANT_STRING(L"TMP");
extern const UNICODE_STRING BaseTempVariableName = RTL_CONSTANT_STRING(L"TEMP");
extern const UNICODE_STRING BaseDotVariableName = RTL_CONSTANT_STRING(L".");
extern const UNICODE_STRING BaseDotTmpSuffixName = RTL_CONSTANT_STRING(L".tmp");
extern const UNICODE_STRING BaseDotComSuffixName = RTL_CONSTANT_STRING(L".com");
extern const UNICODE_STRING BaseDotPifSuffixName = RTL_CONSTANT_STRING(L".pif");
extern const UNICODE_STRING BaseDotExeSuffixName = RTL_CONSTANT_STRING(L".exe");
extern const UNICODE_STRING BaseConsoleInput = RTL_CONSTANT_STRING(L"CONIN$");
extern const UNICODE_STRING BaseConsoleOutput = RTL_CONSTANT_STRING(L"CONOUT$");
extern const 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];
Peb = NtCurrentPeb();
SessionId = Peb->SessionId;
BaseDllHandle = DllHandle;
Success = TRUE;
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();
BaseDefaultPath.Length = 0;
BaseDefaultPath.MaximumLength = 0;
BaseDefaultPath.Buffer = 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;
}
Status = RtlGetNativeSystemInformation(
SystemProcessorInformation,
&NativeProcessorInfo,
sizeof(SYSTEM_PROCESSOR_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 = Peb->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];
SIZE_T TermSrvWindowsPathLength = 0;
NTSTATUS TermSrvWindowsPathStatus;
TermSrvWindowsPathStatus = GetPerUserWindowsDirectory(
TermSrvWindowsPath,
RTL_NUMBER_OF(TermSrvWindowsPath),
&TermSrvWindowsPathLength
);
if (NT_SUCCESS(TermSrvWindowsPathStatus)
&& TermSrvWindowsPathLength != 0
) {
RtlCopyMemory(p, TermSrvWindowsPath, (TermSrvWindowsPathLength * sizeof(p[0])));
p += TermSrvWindowsPathLength;
*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;
}
if (!NT_SUCCESS(RtlInitializeCriticalSection(&BaseLZSemTable))) {
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()) {
Status = BasepInitializeTermsrvFpns();
if (!NT_SUCCESS(Status)) {
goto Exit;
}
}
Status = STATUS_SUCCESS;
Exit:
return Status;
}
HANDLE
BaseGetNamedObjectDirectory(
VOID
)
{
OBJECT_ATTRIBUTES Obja;
NTSTATUS Status;
const static UNICODE_STRING RestrictedObjectDirectory = RTL_CONSTANT_STRING(L"Restricted");
ACCESS_MASK DirAccess = DIRECTORY_ALL_ACCESS &
~(DELETE | WRITE_DAC | WRITE_OWNER);
HANDLE hRootNamedObject;
HANDLE BaseHandle;
HANDLE Token, NewToken;
if ( BaseNamedObjectDirectory != NULL) {
return BaseNamedObjectDirectory;
}
if (NtCurrentTeb()->IsImpersonating) {
//
// If we're impersonating, save the impersonation token, and
// revert to self for the duration of the directory creation.
//
Status = NtOpenThreadToken(NtCurrentThread(),
TOKEN_IMPERSONATE,
TRUE,
&Token);
if (! NT_SUCCESS(Status)) {
return BaseNamedObjectDirectory;
}
NewToken = NULL;
Status = NtSetInformationThread(NtCurrentThread(),
ThreadImpersonationToken,
(PVOID) &NewToken,
(ULONG) sizeof(NewToken));
if (! NT_SUCCESS(Status)) {
NtClose(Token);
return BaseNamedObjectDirectory;
}
} else {
Token = NULL;
}
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) ) {
InitializeObjectAttributes( &Obja,
(PUNICODE_STRING)&RestrictedObjectDirectory,
OBJ_CASE_INSENSITIVE,
hRootNamedObject,
NULL
);
Status = NtOpenDirectoryObject( &BaseHandle,
DirAccess,
&Obja
);
NtClose( hRootNamedObject );
}
}
if ( NT_SUCCESS(Status) ) {
BaseNamedObjectDirectory = BaseHandle;
}
}
RtlReleasePebLock();
if (Token) {
NtSetInformationThread(NtCurrentThread(),
ThreadImpersonationToken,
(PVOID) &Token,
(ULONG) sizeof(Token));
NtClose(Token);
}
return BaseNamedObjectDirectory;
}