1158 lines
36 KiB
C
1158 lines
36 KiB
C
/*++
|
||
|
||
Copyright (c) 1990 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
srvinit.c
|
||
|
||
Abstract:
|
||
|
||
This is the main initialization file for the Windows 32-bit Base API
|
||
Server DLL.
|
||
|
||
Author:
|
||
|
||
Steve Wood (stevewo) 10-Oct-1990
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "basesrv.h"
|
||
|
||
UNICODE_STRING BaseSrvCSDString;
|
||
|
||
RTL_QUERY_REGISTRY_TABLE BaseServerRegistryConfigurationTable[] = {
|
||
{NULL, RTL_QUERY_REGISTRY_DIRECT,
|
||
L"CSDVersion", &BaseSrvCSDString,
|
||
REG_NONE, NULL, 0},
|
||
|
||
{NULL, 0,
|
||
NULL, NULL,
|
||
REG_NONE, NULL, 0}
|
||
};
|
||
|
||
PCSR_API_ROUTINE BaseServerApiDispatchTable[ BasepMaxApiNumber+1 ] = {
|
||
BaseSrvCreateProcess,
|
||
BaseSrvCreateThread,
|
||
BaseSrvGetTempFile,
|
||
BaseSrvExitProcess,
|
||
BaseSrvDebugProcess,
|
||
BaseSrvCheckVDM,
|
||
BaseSrvUpdateVDMEntry,
|
||
BaseSrvGetNextVDMCommand,
|
||
BaseSrvExitVDM,
|
||
BaseSrvIsFirstVDM,
|
||
BaseSrvGetVDMExitCode,
|
||
BaseSrvSetReenterCount,
|
||
BaseSrvSetProcessShutdownParam,
|
||
BaseSrvGetProcessShutdownParam,
|
||
BaseSrvNlsSetUserInfo,
|
||
BaseSrvNlsSetMultipleUserInfo,
|
||
BaseSrvNlsCreateSortSection,
|
||
BaseSrvNlsPreserveSection,
|
||
BaseSrvSetVDMCurDirs,
|
||
BaseSrvGetVDMCurDirs,
|
||
BaseSrvBatNotification,
|
||
BaseSrvRegisterWowExec,
|
||
BaseSrvSoundSentryNotification,
|
||
BaseSrvRefreshIniFileMapping,
|
||
BaseSrvDefineDosDevice,
|
||
NULL
|
||
};
|
||
|
||
BOOLEAN BaseServerApiServerValidTable[ BasepMaxApiNumber+1 ] = {
|
||
TRUE, // SrvCreateProcess,
|
||
TRUE, // SrvCreateThread,
|
||
TRUE, // SrvGetTempFile,
|
||
FALSE, // SrvExitProcess,
|
||
FALSE, // SrvDebugProcess,
|
||
TRUE, // SrvCheckVDM,
|
||
TRUE, // SrvUpdateVDMEntry
|
||
TRUE, // SrvGetNextVDMCommand
|
||
TRUE, // SrvExitVDM
|
||
TRUE, // SrvIsFirstVDM
|
||
TRUE, // SrvGetVDMExitCode
|
||
TRUE, // SrvSetReenterCount
|
||
TRUE, // SrvSetProcessShutdownParam
|
||
TRUE, // SrvGetProcessShutdownParam
|
||
TRUE, // SrvNlsSetUserInfo
|
||
TRUE, // SrvNlsSetMultipleUserInfo
|
||
TRUE, // SrvNlsCreateSortSection
|
||
TRUE, // SrvNlsPreserveSection
|
||
TRUE, // SrvSetVDMCurDirs
|
||
TRUE, // SrvGetVDMCurDirs
|
||
TRUE, // SrvBatNotification
|
||
TRUE, // SrvRegisterWowExec
|
||
TRUE, // SrvSoundSentryNotification
|
||
TRUE, // SrvRefreshIniFileMapping
|
||
TRUE, // SrvDefineDosDevice
|
||
FALSE
|
||
};
|
||
|
||
#if DBG
|
||
PSZ BaseServerApiNameTable[ BasepMaxApiNumber+1 ] = {
|
||
"BaseCreateProcess",
|
||
"BaseCreateThread",
|
||
"BaseGetTempFile",
|
||
"BaseExitProcess",
|
||
"BaseDebugProcess",
|
||
"BaseCheckVDM",
|
||
"BaseUpdateVDMEntry",
|
||
"BaseGetNextVDMCommand",
|
||
"BaseExitVDM",
|
||
"BaseIsFirstVDM",
|
||
"BaseGetVDMExitCode",
|
||
"BaseSetReenterCount",
|
||
"BaseSetProcessShutdownParam",
|
||
"BaseGetProcessShutdownParam",
|
||
"BaseNlsSetUserInfo",
|
||
"BaseNlsSetMultipleUserInfo",
|
||
"BaseNlsCreateSortSection",
|
||
"BaseNlsPreserveSection",
|
||
"BaseSetVDMCurDirs",
|
||
"BaseGetVDMCurDirs",
|
||
"BaseBatNotification",
|
||
"BaseRegisterWowExec",
|
||
"BaseSoundSentryNotification",
|
||
"BaseSrvRefreshIniFileMapping"
|
||
"BaseDefineDosDevice",
|
||
NULL
|
||
};
|
||
#endif // DBG
|
||
|
||
HANDLE BaseSrvNamedObjectDirectory;
|
||
RTL_CRITICAL_SECTION BaseSrvDosDeviceCritSec;
|
||
|
||
BOOLEAN BaseSrvFirstClient = TRUE;
|
||
|
||
WORD
|
||
ConvertUnicodeToWord( PWSTR s );
|
||
|
||
NTSTATUS
|
||
CreateBaseAcl( PACL *Dacl );
|
||
|
||
WORD
|
||
ConvertUnicodeToWord( PWSTR s )
|
||
{
|
||
NTSTATUS Status;
|
||
ULONG Result;
|
||
UNICODE_STRING UnicodeString;
|
||
|
||
while (*s && *s <= L' ') {
|
||
s += 1;
|
||
}
|
||
|
||
RtlInitUnicodeString( &UnicodeString, s );
|
||
Status = RtlUnicodeStringToInteger( &UnicodeString,
|
||
10,
|
||
&Result
|
||
);
|
||
if (!NT_SUCCESS( Status )) {
|
||
Result = 0;
|
||
}
|
||
|
||
|
||
return (WORD)Result;
|
||
}
|
||
|
||
|
||
#ifdef WX86
|
||
|
||
PKEY_VALUE_PARTIAL_INFORMATION
|
||
Wx86QueryValueKey(
|
||
HANDLE KeyHandle,
|
||
PWCHAR ValueName
|
||
)
|
||
{
|
||
NTSTATUS Status;
|
||
ULONG ResultLength;
|
||
UNICODE_STRING UnicodeString;
|
||
PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation, RetKeyValueInfo;
|
||
BYTE ValueBuffer[MAX_PATH*sizeof(WCHAR) + sizeof(KEY_VALUE_PARTIAL_INFORMATION)];
|
||
|
||
KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
|
||
|
||
RtlInitUnicodeString( &UnicodeString, ValueName);
|
||
Status = NtQueryValueKey(KeyHandle,
|
||
&UnicodeString,
|
||
KeyValuePartialInformation,
|
||
KeyValueInformation,
|
||
sizeof( ValueBuffer ),
|
||
&ResultLength
|
||
);
|
||
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
RetKeyValueInfo = RtlAllocateHeap(RtlProcessHeap(), 0, ResultLength);
|
||
if (RetKeyValueInfo) {
|
||
RtlMoveMemory(RetKeyValueInfo,
|
||
KeyValueInformation,
|
||
ResultLength
|
||
);
|
||
}
|
||
}
|
||
else if (Status == STATUS_BUFFER_OVERFLOW) {
|
||
RetKeyValueInfo = RtlAllocateHeap(RtlProcessHeap(), 0, ResultLength);
|
||
if (RetKeyValueInfo) {
|
||
Status = NtQueryValueKey(KeyHandle,
|
||
&UnicodeString,
|
||
KeyValuePartialInformation,
|
||
RetKeyValueInfo,
|
||
ResultLength,
|
||
&ResultLength
|
||
);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
RtlFreeHeap(RtlProcessHeap(), 0, RetKeyValueInfo);
|
||
RetKeyValueInfo = NULL;
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
RetKeyValueInfo = NULL;
|
||
}
|
||
|
||
|
||
return RetKeyValueInfo;
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
* Initializes the volatile registry entries for Wx86.
|
||
* \Registry\Machine\HARDWARE\DESCRIPTION\System\Wx86FloatingPointProcessor
|
||
*/
|
||
|
||
void
|
||
SetupWx86KeyMapping(void)
|
||
{
|
||
NTSTATUS Status;
|
||
ULONG Processors, ProcessorCount;
|
||
HANDLE KeyHandle, ParentKeyHandle;
|
||
PKEY_VALUE_PARTIAL_INFORMATION Identifier;
|
||
PKEY_VALUE_PARTIAL_INFORMATION ConfigurationData;
|
||
PKEY_VALUE_PARTIAL_INFORMATION ComponentInformation;
|
||
UNICODE_STRING UnicodeString;
|
||
UNICODE_STRING ClassUnicode;
|
||
OBJECT_ATTRIBUTES Obja;
|
||
WCHAR wcProcessor[64];
|
||
|
||
|
||
//
|
||
// If the Wx86\\KeyRemapping\\FloatingPointProcessor does not exist
|
||
// don't create the Wx86FloatingPointProcessor. So that x86 apps
|
||
// will think there isn't any fpu.
|
||
//
|
||
|
||
RtlInitUnicodeString(&UnicodeString,
|
||
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Wx86\\KeyRemapping\\FloatingPointProcessor"
|
||
);
|
||
|
||
InitializeObjectAttributes(&Obja,
|
||
&UnicodeString,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
Status = NtOpenKey(&KeyHandle, KEY_READ | KEY_WRITE, &Obja);
|
||
if (!NT_SUCCESS(Status)) {
|
||
return;
|
||
}
|
||
NtClose(KeyHandle);
|
||
|
||
|
||
//
|
||
// Create Wx86FloatingPointProcessor key
|
||
//
|
||
|
||
|
||
RtlInitUnicodeString(&ClassUnicode, L"Processor");
|
||
|
||
RtlInitUnicodeString(
|
||
&UnicodeString,
|
||
L"\\Registry\\Machine\\Hardware\\Description\\System\\Wx86FloatingPointProcessor"
|
||
);
|
||
|
||
InitializeObjectAttributes(&Obja,
|
||
&UnicodeString,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
Status = NtCreateKey(&ParentKeyHandle,
|
||
KEY_READ | KEY_WRITE | KEY_CREATE_SUB_KEY,
|
||
&Obja,
|
||
0, // TitleIndex ?
|
||
&ClassUnicode,
|
||
REG_OPTION_VOLATILE,
|
||
NULL
|
||
);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
RtlInitUnicodeString(&UnicodeString,
|
||
L"\\Registry\\Machine\\Hardware\\Description\\System\\CentralProcessor\\0"
|
||
);
|
||
|
||
InitializeObjectAttributes(&Obja,
|
||
&UnicodeString,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
Status = NtOpenKey(&KeyHandle, KEY_READ, &Obja);
|
||
if (!NT_SUCCESS(Status)) {
|
||
NtClose(ParentKeyHandle);
|
||
return;
|
||
}
|
||
|
||
|
||
Identifier = Wx86QueryValueKey(KeyHandle, L"Identifier");
|
||
ConfigurationData = Wx86QueryValueKey(KeyHandle, L"Configuration Data");
|
||
ComponentInformation = Wx86QueryValueKey(KeyHandle, L"Component Information");
|
||
|
||
NtClose(KeyHandle);
|
||
KeyHandle = NULL;
|
||
|
||
|
||
|
||
Processors = BaseSrvpStaticServerData->SysInfo.NumberOfProcessors;
|
||
ProcessorCount = 0;
|
||
|
||
while (Processors--) {
|
||
swprintf(wcProcessor, L"%d", ProcessorCount++);
|
||
|
||
RtlInitUnicodeString(&UnicodeString, wcProcessor);
|
||
InitializeObjectAttributes(&Obja,
|
||
&UnicodeString,
|
||
OBJ_CASE_INSENSITIVE,
|
||
ParentKeyHandle,
|
||
NULL
|
||
);
|
||
|
||
Status = NtCreateKey(&KeyHandle,
|
||
KEY_READ | KEY_WRITE,
|
||
&Obja,
|
||
0,
|
||
NULL,
|
||
REG_OPTION_VOLATILE,
|
||
NULL
|
||
);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
KeyHandle = NULL;
|
||
goto SWMCleanup;
|
||
}
|
||
|
||
if (ComponentInformation) {
|
||
RtlInitUnicodeString(&UnicodeString, L"Component Information");
|
||
Status = NtSetValueKey(KeyHandle,
|
||
&UnicodeString,
|
||
0,
|
||
ComponentInformation->Type,
|
||
ComponentInformation->Data,
|
||
ComponentInformation->DataLength
|
||
);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
goto SWMCleanup;
|
||
}
|
||
}
|
||
|
||
if (ConfigurationData) {
|
||
RtlInitUnicodeString(&UnicodeString, L"Configuration Data");
|
||
Status = NtSetValueKey(KeyHandle,
|
||
&UnicodeString,
|
||
0,
|
||
ConfigurationData->Type,
|
||
ConfigurationData->Data,
|
||
ConfigurationData->DataLength
|
||
);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
goto SWMCleanup;
|
||
}
|
||
}
|
||
|
||
if (Identifier) {
|
||
RtlInitUnicodeString(&UnicodeString, L"Identifier");
|
||
Status = NtSetValueKey(KeyHandle,
|
||
&UnicodeString,
|
||
0,
|
||
Identifier->Type,
|
||
Identifier->Data,
|
||
Identifier->DataLength
|
||
);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
goto SWMCleanup;
|
||
}
|
||
}
|
||
|
||
NtClose(KeyHandle);
|
||
KeyHandle = NULL;
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
SWMCleanup:
|
||
|
||
if (ConfigurationData) {
|
||
RtlFreeHeap( RtlProcessHeap(), 0, ConfigurationData);
|
||
}
|
||
if (ComponentInformation) {
|
||
RtlFreeHeap( RtlProcessHeap(), 0, ComponentInformation);
|
||
}
|
||
if (Identifier) {
|
||
RtlFreeHeap( RtlProcessHeap(), 0, Identifier);
|
||
}
|
||
if (ParentKeyHandle) {
|
||
NtClose(ParentKeyHandle);
|
||
}
|
||
if (KeyHandle) {
|
||
NtClose(KeyHandle);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
#endif
|
||
|
||
|
||
|
||
|
||
|
||
NTSTATUS
|
||
ServerDllInitialization(
|
||
PCSR_SERVER_DLL LoadedServerDll
|
||
)
|
||
{
|
||
NTSTATUS Status;
|
||
UNICODE_STRING UnicodeString;
|
||
OBJECT_ATTRIBUTES Obja;
|
||
PSECURITY_DESCRIPTOR PrimarySecurityDescriptor;
|
||
PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
|
||
ULONG ResultLength;
|
||
PVOID p;
|
||
WCHAR NameBuffer[ MAX_PATH ];
|
||
WCHAR ValueBuffer[ 400 ];
|
||
UNICODE_STRING NameString, ValueString;
|
||
HANDLE KeyHandle;
|
||
PWSTR s, s1;
|
||
PACL Dacl;
|
||
|
||
BaseSrvHeap = RtlProcessHeap();
|
||
BaseSrvTag = RtlCreateTagHeap( BaseSrvHeap,
|
||
0,
|
||
L"BASESRV!",
|
||
L"TMP\0"
|
||
L"VDM\0"
|
||
);
|
||
|
||
BaseSrvSharedHeap = LoadedServerDll->SharedStaticServerData;
|
||
BaseSrvSharedTag = RtlCreateTagHeap( BaseSrvSharedHeap,
|
||
0,
|
||
L"BASESHR!",
|
||
L"INIT\0"
|
||
L"INI\0"
|
||
);
|
||
|
||
LoadedServerDll->ApiNumberBase = BASESRV_FIRST_API_NUMBER;
|
||
LoadedServerDll->MaxApiNumber = BasepMaxApiNumber;
|
||
LoadedServerDll->ApiDispatchTable = BaseServerApiDispatchTable;
|
||
LoadedServerDll->ApiServerValidTable = BaseServerApiServerValidTable;
|
||
#if DBG
|
||
LoadedServerDll->ApiNameTable = BaseServerApiNameTable;
|
||
#else
|
||
LoadedServerDll->ApiNameTable = NULL;
|
||
#endif
|
||
LoadedServerDll->PerProcessDataLength = 0;
|
||
LoadedServerDll->PerThreadDataLength = 0;
|
||
LoadedServerDll->ConnectRoutine = BaseClientConnectRoutine;
|
||
LoadedServerDll->DisconnectRoutine = BaseClientDisconnectRoutine;
|
||
LoadedServerDll->AddThreadRoutine = NULL;
|
||
LoadedServerDll->DeleteThreadRoutine = NULL;
|
||
|
||
RtlInitializeCriticalSection( &BaseSrvDosDeviceCritSec );
|
||
|
||
wcscpy( NameBuffer, L"%SystemRoot%" );
|
||
RtlInitUnicodeString( &NameString, NameBuffer );
|
||
ValueString.Buffer = ValueBuffer;
|
||
ValueString.MaximumLength = sizeof( ValueBuffer );
|
||
Status = RtlExpandEnvironmentStrings_U( NULL,
|
||
&NameString,
|
||
&ValueString,
|
||
NULL
|
||
);
|
||
ASSERT( NT_SUCCESS( Status ) );
|
||
ValueBuffer[ ValueString.Length / sizeof( WCHAR ) ] = UNICODE_NULL;
|
||
RtlCreateUnicodeString( &BaseSrvWindowsDirectory, ValueBuffer );
|
||
|
||
wcscat( NameBuffer, L"\\System32" );
|
||
RtlInitUnicodeString( &NameString, NameBuffer );
|
||
Status = RtlExpandEnvironmentStrings_U( NULL,
|
||
&NameString,
|
||
&ValueString,
|
||
NULL
|
||
);
|
||
ASSERT( NT_SUCCESS( Status ) );
|
||
ValueBuffer[ ValueString.Length / sizeof( WCHAR ) ] = UNICODE_NULL;
|
||
RtlCreateUnicodeString( &BaseSrvWindowsSystemDirectory, ValueBuffer );
|
||
|
||
//
|
||
// need to synch this w/ user's desktop concept
|
||
//
|
||
|
||
RtlInitUnicodeString( &UnicodeString, L"\\BaseNamedObjects" );
|
||
|
||
//
|
||
// initialize base static server data
|
||
//
|
||
|
||
BaseSrvpStaticServerData = RtlAllocateHeap( BaseSrvSharedHeap,
|
||
MAKE_SHARED_TAG( INIT_TAG ),
|
||
sizeof( BASE_STATIC_SERVER_DATA )
|
||
);
|
||
if ( !BaseSrvpStaticServerData ) {
|
||
return STATUS_NO_MEMORY;
|
||
}
|
||
LoadedServerDll->SharedStaticServerData = (PVOID)BaseSrvpStaticServerData;
|
||
|
||
Status = NtQuerySystemInformation(
|
||
SystemTimeOfDayInformation,
|
||
(PVOID)&BaseSrvpStaticServerData->TimeOfDay,
|
||
sizeof(BaseSrvpStaticServerData->TimeOfDay),
|
||
NULL
|
||
);
|
||
if ( !NT_SUCCESS( Status ) ) {
|
||
return Status;
|
||
}
|
||
|
||
//
|
||
// windows directory
|
||
//
|
||
|
||
BaseSrvpStaticServerData->WindowsDirectory = BaseSrvWindowsDirectory;
|
||
p = RtlAllocateHeap( BaseSrvSharedHeap,
|
||
MAKE_SHARED_TAG( INIT_TAG ),
|
||
BaseSrvWindowsDirectory.MaximumLength
|
||
);
|
||
if ( !p ) {
|
||
return STATUS_NO_MEMORY;
|
||
}
|
||
RtlMoveMemory(p,BaseSrvpStaticServerData->WindowsDirectory.Buffer,BaseSrvWindowsDirectory.MaximumLength);
|
||
BaseSrvpStaticServerData->WindowsDirectory.Buffer = p;
|
||
|
||
//
|
||
// windows system directory
|
||
//
|
||
|
||
BaseSrvpStaticServerData->WindowsSystemDirectory = BaseSrvWindowsSystemDirectory;
|
||
p = RtlAllocateHeap( BaseSrvSharedHeap,
|
||
MAKE_SHARED_TAG( INIT_TAG ),
|
||
BaseSrvWindowsSystemDirectory.MaximumLength
|
||
);
|
||
if ( !p ) {
|
||
return STATUS_NO_MEMORY;
|
||
}
|
||
RtlMoveMemory(p,BaseSrvpStaticServerData->WindowsSystemDirectory.Buffer,BaseSrvWindowsSystemDirectory.MaximumLength);
|
||
BaseSrvpStaticServerData->WindowsSystemDirectory.Buffer = p;
|
||
|
||
//
|
||
// named object directory
|
||
//
|
||
|
||
BaseSrvpStaticServerData->NamedObjectDirectory = UnicodeString;
|
||
BaseSrvpStaticServerData->NamedObjectDirectory.MaximumLength = UnicodeString.Length+(USHORT)sizeof(UNICODE_NULL);
|
||
p = RtlAllocateHeap( BaseSrvSharedHeap,
|
||
MAKE_SHARED_TAG( INIT_TAG ),
|
||
UnicodeString.Length + sizeof( UNICODE_NULL )
|
||
);
|
||
if ( !p ) {
|
||
return STATUS_NO_MEMORY;
|
||
}
|
||
RtlMoveMemory(p,BaseSrvpStaticServerData->NamedObjectDirectory.Buffer,BaseSrvpStaticServerData->NamedObjectDirectory.MaximumLength);
|
||
BaseSrvpStaticServerData->NamedObjectDirectory.Buffer = p;
|
||
|
||
BaseSrvCSDString.Buffer = &ValueBuffer[ 300 ];
|
||
BaseSrvCSDString.Length = 0;
|
||
BaseSrvCSDString.MaximumLength = 100 * sizeof( WCHAR );
|
||
|
||
Status = RtlQueryRegistryValues( RTL_REGISTRY_WINDOWS_NT,
|
||
L"",
|
||
BaseServerRegistryConfigurationTable,
|
||
NULL,
|
||
NULL
|
||
);
|
||
if (NT_SUCCESS( Status )) {
|
||
wcsncpy( BaseSrvpStaticServerData->CSDVersion,
|
||
BaseSrvCSDString.Buffer,
|
||
BaseSrvCSDString.Length
|
||
);
|
||
BaseSrvpStaticServerData->CSDVersion[ BaseSrvCSDString.Length ] = UNICODE_NULL;
|
||
}
|
||
else {
|
||
BaseSrvpStaticServerData->CSDVersion[ 0 ] = UNICODE_NULL;
|
||
}
|
||
|
||
Status = NtQuerySystemInformation( SystemBasicInformation,
|
||
(PVOID)&BaseSrvpStaticServerData->SysInfo,
|
||
sizeof( BaseSrvpStaticServerData->SysInfo ),
|
||
NULL
|
||
);
|
||
if (!NT_SUCCESS( Status )) {
|
||
return( Status );
|
||
}
|
||
|
||
Status = BaseSrvInitializeIniFileMappings( BaseSrvpStaticServerData );
|
||
if ( !NT_SUCCESS(Status) ){
|
||
return Status;
|
||
}
|
||
|
||
BaseSrvpStaticServerData->DefaultSeparateVDM = FALSE;
|
||
|
||
RtlInitUnicodeString( &NameString, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\WOW" );
|
||
InitializeObjectAttributes( &Obja,
|
||
&NameString,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL );
|
||
|
||
Status = NtOpenKey( &KeyHandle,
|
||
KEY_READ,
|
||
&Obja
|
||
);
|
||
if (NT_SUCCESS(Status)) {
|
||
RtlInitUnicodeString( &NameString, L"DefaultSeparateVDM" );
|
||
KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
|
||
Status = NtQueryValueKey( KeyHandle,
|
||
&NameString,
|
||
KeyValuePartialInformation,
|
||
KeyValueInformation,
|
||
sizeof( ValueBuffer ),
|
||
&ResultLength
|
||
);
|
||
if (NT_SUCCESS(Status)) {
|
||
if (KeyValueInformation->Type == REG_DWORD) {
|
||
BaseSrvpStaticServerData->DefaultSeparateVDM = *(PULONG)KeyValueInformation->Data != 0;
|
||
}
|
||
else
|
||
if (KeyValueInformation->Type == REG_SZ) {
|
||
if (!_wcsicmp( (PWSTR)KeyValueInformation->Data, L"yes" ) ||
|
||
!_wcsicmp( (PWSTR)KeyValueInformation->Data, L"1" )) {
|
||
BaseSrvpStaticServerData->DefaultSeparateVDM = TRUE;
|
||
}
|
||
}
|
||
}
|
||
|
||
NtClose( KeyHandle );
|
||
}
|
||
|
||
#ifdef WX86
|
||
BaseSrvpStaticServerData->Wx86Enabled = FALSE;
|
||
|
||
RtlInitUnicodeString( &NameString, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\wx86" );
|
||
InitializeObjectAttributes( &Obja,
|
||
&NameString,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
Status = NtOpenKey( &KeyHandle,
|
||
KEY_READ,
|
||
&Obja
|
||
);
|
||
if (NT_SUCCESS(Status)) {
|
||
RtlInitUnicodeString( &NameString, L"cmdline" );
|
||
KeyValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer;
|
||
Status = NtQueryValueKey( KeyHandle,
|
||
&NameString,
|
||
KeyValuePartialInformation,
|
||
KeyValueInformation,
|
||
sizeof( ValueBuffer ),
|
||
&ResultLength
|
||
);
|
||
if (NT_SUCCESS(Status)) {
|
||
if (KeyValueInformation->Type == REG_SZ &&
|
||
*(PWSTR)KeyValueInformation->Data)
|
||
{
|
||
BaseSrvpStaticServerData->Wx86Enabled = TRUE;
|
||
|
||
SetupWx86KeyMapping();
|
||
|
||
}
|
||
}
|
||
|
||
NtClose( KeyHandle );
|
||
}
|
||
#endif
|
||
|
||
|
||
//
|
||
// Following code is direct from Jimk. Why is there a 1k constant
|
||
//
|
||
|
||
PrimarySecurityDescriptor = RtlAllocateHeap( BaseSrvHeap, MAKE_TAG( TMP_TAG ), 1024 );
|
||
if ( !PrimarySecurityDescriptor ) {
|
||
return STATUS_NO_MEMORY;
|
||
}
|
||
|
||
Status = RtlCreateSecurityDescriptor (
|
||
PrimarySecurityDescriptor,
|
||
SECURITY_DESCRIPTOR_REVISION1
|
||
);
|
||
if ( !NT_SUCCESS(Status) ){
|
||
return Status;
|
||
}
|
||
|
||
//
|
||
// Create an ACL that allows full access to System and partial access to world
|
||
//
|
||
|
||
Status = CreateBaseAcl( &Dacl );
|
||
|
||
if ( !NT_SUCCESS(Status) ){
|
||
return Status;
|
||
}
|
||
|
||
Status = RtlSetDaclSecurityDescriptor (
|
||
PrimarySecurityDescriptor,
|
||
TRUE, //DaclPresent,
|
||
Dacl, //Dacl
|
||
FALSE //DaclDefaulted OPTIONAL
|
||
);
|
||
if ( !NT_SUCCESS(Status) ){
|
||
return Status;
|
||
}
|
||
|
||
InitializeObjectAttributes( &Obja,
|
||
&UnicodeString,
|
||
OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_PERMANENT,
|
||
NULL,
|
||
PrimarySecurityDescriptor
|
||
);
|
||
Status = NtCreateDirectoryObject( &BaseSrvNamedObjectDirectory,
|
||
DIRECTORY_ALL_ACCESS,
|
||
&Obja
|
||
);
|
||
|
||
|
||
if ( !NT_SUCCESS(Status) ){
|
||
return Status;
|
||
}
|
||
|
||
RtlFreeHeap( BaseSrvHeap, 0, Dacl );
|
||
RtlFreeHeap( BaseSrvHeap, 0,PrimarySecurityDescriptor );
|
||
|
||
BaseSrvVDMInit();
|
||
|
||
//
|
||
// Initialize the shared heap for the NLS information.
|
||
//
|
||
BaseSrvNLSInit(BaseSrvpStaticServerData);
|
||
|
||
return( STATUS_SUCCESS );
|
||
}
|
||
|
||
NTSTATUS
|
||
BaseClientConnectRoutine(
|
||
IN PCSR_PROCESS Process,
|
||
IN OUT PVOID ConnectionInfo,
|
||
IN OUT PULONG ConnectionInfoLength
|
||
)
|
||
{
|
||
return ( BaseSrvNlsConnect( Process,
|
||
ConnectionInfo,
|
||
ConnectionInfoLength ) );
|
||
}
|
||
|
||
VOID
|
||
BaseClientDisconnectRoutine(
|
||
IN PCSR_PROCESS Process
|
||
)
|
||
{
|
||
BaseSrvCleanupVDMResources (Process);
|
||
}
|
||
|
||
ULONG
|
||
BaseSrvDefineDosDevice(
|
||
IN OUT PCSR_API_MSG m,
|
||
IN OUT PCSR_REPLY_STATUS ReplyStatus
|
||
)
|
||
{
|
||
NTSTATUS Status;
|
||
PBASE_DEFINEDOSDEVICE_MSG a = (PBASE_DEFINEDOSDEVICE_MSG)&m->u.ApiMessageData;
|
||
UNICODE_STRING LinkName;
|
||
UNICODE_STRING LinkValue;
|
||
HANDLE LinkHandle;
|
||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
PWSTR Buffer, s, Src, Dst, pchValue;
|
||
ULONG cchBuffer, cch;
|
||
ULONG cchName, cchValue, cchSrc, cchSrcStr, cchDst;
|
||
BOOLEAN QueryNeeded, MatchFound, RevertToSelfNeeded, DeleteRequest;
|
||
ULONG ReturnedLength;
|
||
SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
|
||
SECURITY_DESCRIPTOR SecurityDescriptor;
|
||
CHAR Acl[256]; // 256 is more than big enough
|
||
ULONG AclLength=256;
|
||
PSID WorldSid;
|
||
|
||
cchBuffer = 4096;
|
||
Buffer = RtlAllocateHeap( BaseSrvHeap,
|
||
MAKE_TAG( TMP_TAG ),
|
||
cchBuffer * sizeof( WCHAR )
|
||
);
|
||
if (Buffer == NULL) {
|
||
return (ULONG)STATUS_NO_MEMORY;
|
||
}
|
||
|
||
Status = RtlEnterCriticalSection( &BaseSrvDosDeviceCritSec );
|
||
if (!NT_SUCCESS( Status )) {
|
||
RtlFreeHeap( BaseSrvHeap, 0, Buffer );
|
||
return (ULONG)Status;
|
||
}
|
||
|
||
if (a->Flags & DDD_REMOVE_DEFINITION) {
|
||
DeleteRequest = TRUE;
|
||
}
|
||
else {
|
||
DeleteRequest = FALSE;
|
||
}
|
||
|
||
LinkHandle = NULL;
|
||
try {
|
||
s = Buffer;
|
||
cch = cchBuffer;
|
||
cchName = _snwprintf( s,
|
||
cch,
|
||
L"\\??\\%wZ",
|
||
&a->DeviceName
|
||
);
|
||
s += cchName + 1;
|
||
cch -= (cchName + 1);
|
||
|
||
RtlInitUnicodeString( &LinkName, Buffer );
|
||
InitializeObjectAttributes( &ObjectAttributes,
|
||
&LinkName,
|
||
OBJ_CASE_INSENSITIVE,
|
||
(HANDLE) NULL,
|
||
(PSECURITY_DESCRIPTOR)NULL
|
||
);
|
||
QueryNeeded = TRUE;
|
||
RevertToSelfNeeded = CsrImpersonateClient( NULL ); // This stacks client contexts
|
||
Status = NtOpenSymbolicLinkObject( &LinkHandle,
|
||
SYMBOLIC_LINK_QUERY | DELETE,
|
||
&ObjectAttributes
|
||
);
|
||
if (RevertToSelfNeeded) {
|
||
CsrRevertToSelf(); // This unstacks client contexts
|
||
}
|
||
if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
|
||
LinkHandle = NULL;
|
||
if (DeleteRequest) {
|
||
if (a->TargetPath.Length == 0) {
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
|
||
leave;
|
||
}
|
||
|
||
QueryNeeded = FALSE;
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
else
|
||
if (!NT_SUCCESS( Status )) {
|
||
LinkHandle = NULL;
|
||
leave;
|
||
}
|
||
|
||
if (a->TargetPath.Length != 0) {
|
||
cchValue = wcslen( Src = a->TargetPath.Buffer );
|
||
if ((cchValue + 1) >= cch) {
|
||
Status = STATUS_TOO_MANY_NAMES;
|
||
leave;
|
||
}
|
||
|
||
RtlMoveMemory( s, Src, (cchValue + 1) * sizeof( WCHAR ) );
|
||
pchValue = s;
|
||
s += cchValue + 1;
|
||
cch -= (cchValue + 1);
|
||
}
|
||
else {
|
||
pchValue = NULL;
|
||
cchValue = 0;
|
||
}
|
||
|
||
if (QueryNeeded) {
|
||
LinkValue.Length = 0;
|
||
LinkValue.MaximumLength = (USHORT)(cch * sizeof( WCHAR ));
|
||
LinkValue.Buffer = s;
|
||
ReturnedLength = 0;
|
||
Status = NtQuerySymbolicLinkObject( LinkHandle,
|
||
&LinkValue,
|
||
&ReturnedLength
|
||
);
|
||
if (ReturnedLength == (ULONG)LinkValue.MaximumLength) {
|
||
Status = STATUS_BUFFER_OVERFLOW;
|
||
}
|
||
|
||
if (!NT_SUCCESS( Status )) {
|
||
leave;
|
||
}
|
||
|
||
s[ ReturnedLength / sizeof( WCHAR ) ] = UNICODE_NULL;
|
||
LinkValue.MaximumLength = (USHORT)(ReturnedLength + sizeof( UNICODE_NULL ));
|
||
}
|
||
else {
|
||
if (DeleteRequest) {
|
||
RtlInitUnicodeString( &LinkValue, NULL );
|
||
}
|
||
else {
|
||
RtlInitUnicodeString( &LinkValue, s - (cchValue + 1) );
|
||
}
|
||
}
|
||
|
||
if (LinkHandle != NULL) {
|
||
Status = NtMakeTemporaryObject( LinkHandle );
|
||
NtClose( LinkHandle );
|
||
LinkHandle = NULL;
|
||
}
|
||
|
||
if (!NT_SUCCESS( Status )) {
|
||
leave;
|
||
}
|
||
|
||
if (DeleteRequest) {
|
||
Src = Dst = LinkValue.Buffer;
|
||
cchSrc = LinkValue.MaximumLength / sizeof( WCHAR );
|
||
cchDst = 0;
|
||
MatchFound = FALSE;
|
||
while (*Src) {
|
||
cchSrcStr = 0;
|
||
s = Src;
|
||
while (*Src++) {
|
||
cchSrcStr++;
|
||
}
|
||
|
||
if (!MatchFound) {
|
||
if ((a->Flags & DDD_EXACT_MATCH_ON_REMOVE &&
|
||
cchValue == cchSrcStr &&
|
||
!_wcsicmp( s, pchValue )
|
||
) ||
|
||
(!(a->Flags & DDD_EXACT_MATCH_ON_REMOVE) &&
|
||
(cchValue == 0 || !_wcsnicmp( s, pchValue, cchValue ))
|
||
)
|
||
) {
|
||
MatchFound = TRUE;
|
||
}
|
||
else {
|
||
goto CopySrc;
|
||
}
|
||
}
|
||
else {
|
||
CopySrc:
|
||
if (s != Dst) {
|
||
RtlMoveMemory( Dst, s, (cchSrcStr + 1) * sizeof( WCHAR ) );
|
||
}
|
||
Dst += cchSrcStr + 1;
|
||
}
|
||
}
|
||
*Dst++ = UNICODE_NULL;
|
||
LinkValue.Length = wcslen( LinkValue.Buffer ) * sizeof( UNICODE_NULL );
|
||
if (LinkValue.Length != 0) {
|
||
LinkValue.MaximumLength = (USHORT)((PCHAR)Dst - (PCHAR)LinkValue.Buffer);
|
||
}
|
||
}
|
||
else
|
||
if (QueryNeeded) {
|
||
LinkValue.Buffer -= (cchValue + 1);
|
||
LinkValue.Length = (USHORT)(cchValue * sizeof( WCHAR ));
|
||
LinkValue.MaximumLength += LinkValue.Length + sizeof( UNICODE_NULL );
|
||
}
|
||
|
||
//
|
||
// Create a new value for the link.
|
||
//
|
||
|
||
if (LinkValue.Length != 0) {
|
||
//
|
||
// Create the new symbolic link object with a security descriptor
|
||
// that grants world SYMBOLIC_LINK_QUERY access.
|
||
//
|
||
|
||
Status = RtlAllocateAndInitializeSid( &WorldSidAuthority,
|
||
1,
|
||
SECURITY_WORLD_RID,
|
||
0, 0, 0, 0, 0, 0, 0,
|
||
&WorldSid
|
||
);
|
||
|
||
if (!NT_SUCCESS( Status )) {
|
||
leave;
|
||
}
|
||
|
||
Status = RtlCreateSecurityDescriptor( &SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION );
|
||
|
||
ASSERT(NT_SUCCESS(Status));
|
||
|
||
Status = RtlCreateAcl( (PACL)Acl,
|
||
AclLength,
|
||
ACL_REVISION2
|
||
);
|
||
ASSERT(NT_SUCCESS(Status));
|
||
|
||
Status = RtlAddAccessAllowedAce( (PACL)Acl,
|
||
ACL_REVISION2,
|
||
SYMBOLIC_LINK_QUERY | DELETE,
|
||
WorldSid
|
||
);
|
||
|
||
ASSERT(NT_SUCCESS(Status));
|
||
|
||
//
|
||
// Sid has been copied into the ACL
|
||
//
|
||
|
||
RtlFreeSid( WorldSid );
|
||
|
||
Status = RtlSetDaclSecurityDescriptor ( &SecurityDescriptor,
|
||
TRUE,
|
||
(PACL)Acl,
|
||
TRUE // Don't over-ride inherited protection
|
||
);
|
||
ASSERT(NT_SUCCESS(Status));
|
||
|
||
ObjectAttributes.SecurityDescriptor = &SecurityDescriptor;
|
||
ObjectAttributes.Attributes |= OBJ_PERMANENT;
|
||
Status = NtCreateSymbolicLinkObject( &LinkHandle,
|
||
SYMBOLIC_LINK_ALL_ACCESS,
|
||
&ObjectAttributes,
|
||
&LinkValue
|
||
);
|
||
if (NT_SUCCESS( Status )) {
|
||
NtClose( LinkHandle );
|
||
if (DeleteRequest && !MatchFound) {
|
||
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||
}
|
||
}
|
||
|
||
LinkHandle = NULL;
|
||
}
|
||
}
|
||
finally {
|
||
if (LinkHandle != NULL) {
|
||
NtClose( LinkHandle );
|
||
}
|
||
RtlFreeHeap( BaseSrvHeap, 0, Buffer );
|
||
RtlLeaveCriticalSection( &BaseSrvDosDeviceCritSec );
|
||
}
|
||
|
||
return (ULONG)Status;
|
||
ReplyStatus; // get rid of unreferenced parameter warning message
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
CreateBaseAcl(
|
||
PACL *Dacl
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Creates the ACL for the BaseNamedObjects directory.
|
||
|
||
Arguments:
|
||
|
||
Dacl - Supplies a pointer to a PDACL that will be filled in with
|
||
the resultant ACL (allocated out of the process heap). The caller
|
||
is responsible for freeing this memory.
|
||
|
||
Return Value:
|
||
|
||
STATUS_NO_MEMORY or Success
|
||
|
||
--*/
|
||
{
|
||
PSID LocalSystemSid;
|
||
PSID WorldSid;
|
||
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
|
||
SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
|
||
NTSTATUS Status;
|
||
ACCESS_MASK WorldAccess;
|
||
ACCESS_MASK SystemAccess;
|
||
ULONG AclLength;
|
||
|
||
Status = RtlAllocateAndInitializeSid(
|
||
&NtAuthority,
|
||
1,
|
||
SECURITY_LOCAL_SYSTEM_RID,
|
||
0, 0, 0, 0, 0, 0, 0,
|
||
&LocalSystemSid
|
||
);
|
||
|
||
if (!NT_SUCCESS( Status )) {
|
||
return( Status );
|
||
}
|
||
|
||
Status = RtlAllocateAndInitializeSid(
|
||
&WorldAuthority,
|
||
1,
|
||
SECURITY_WORLD_RID,
|
||
0, 0, 0, 0, 0, 0, 0,
|
||
&WorldSid
|
||
);
|
||
|
||
if (!NT_SUCCESS( Status )) {
|
||
return( Status );
|
||
}
|
||
|
||
WorldAccess = DIRECTORY_ALL_ACCESS & ~(WRITE_OWNER | WRITE_DAC | DELETE );
|
||
SystemAccess = DIRECTORY_ALL_ACCESS;
|
||
|
||
AclLength = sizeof( ACL ) +
|
||
2 * sizeof( ACCESS_ALLOWED_ACE ) +
|
||
RtlLengthSid( LocalSystemSid ) +
|
||
RtlLengthSid( WorldSid );
|
||
|
||
*Dacl = RtlAllocateHeap( BaseSrvHeap, MAKE_TAG( TMP_TAG ), AclLength );
|
||
|
||
if (*Dacl == NULL) {
|
||
return( STATUS_NO_MEMORY );
|
||
}
|
||
|
||
Status = RtlCreateAcl (*Dacl, AclLength, ACL_REVISION2 );
|
||
|
||
if (!NT_SUCCESS( Status )) {
|
||
return( Status );
|
||
}
|
||
|
||
Status = RtlAddAccessAllowedAce ( *Dacl, ACL_REVISION2, WorldAccess, WorldSid );
|
||
|
||
if (NT_SUCCESS( Status )) {
|
||
Status = RtlAddAccessAllowedAce ( *Dacl, ACL_REVISION2, SystemAccess, LocalSystemSid );
|
||
}
|
||
|
||
//
|
||
// These have been copied in, free them.
|
||
//
|
||
|
||
RtlFreeHeap( BaseSrvHeap, 0, LocalSystemSid );
|
||
RtlFreeHeap( BaseSrvHeap, 0, WorldSid );
|
||
|
||
return( Status );
|
||
}
|