mirror of https://github.com/lianthony/NT4.0
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.
1157 lines
36 KiB
1157 lines
36 KiB
/*++
|
|
|
|
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 );
|
|
}
|