reactos/subsystems/win/basesrv/init.c

562 lines
22 KiB
C
Raw Normal View History

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS/Win32 Base enviroment Subsystem Server
* FILE: subsystems/win/basesrv/init.c
* PURPOSE: Initialization
* PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
*/
/* INCLUDES *******************************************************************/
#include "basesrv.h"
#define NDEBUG
#include <debug.h>
/* GLOBALS ********************************************************************/
HANDLE BaseSrvDllInstance = NULL;
/* Memory */
HANDLE BaseSrvHeap = NULL; // Our own heap.
HANDLE BaseSrvSharedHeap = NULL; // Shared heap with CSR. (CsrSrvSharedSectionHeap)
PBASE_STATIC_SERVER_DATA BaseStaticServerData = NULL; // Data that we can share amongst processes. Initialized inside BaseSrvSharedHeap.
// Windows Server 2003 table from http://j00ru.vexillium.org/csrss_list/api_list.html#Windows_2k3
PCSR_API_ROUTINE BaseServerApiDispatchTable[BasepMaxApiNumber - BASESRV_FIRST_API_NUMBER] =
{
BaseSrvCreateProcess,
BaseSrvCreateThread,
BaseSrvGetTempFile,
BaseSrvExitProcess,
// BaseSrvDebugProcess,
// BaseSrvCheckVDM,
// BaseSrvUpdateVDMEntry,
// BaseSrvGetNextVDMCommand,
// BaseSrvExitVDM,
// BaseSrvIsFirstVDM,
// BaseSrvGetVDMExitCode,
// BaseSrvSetReenterCount,
BaseSrvSetProcessShutdownParam,
BaseSrvGetProcessShutdownParam,
// BaseSrvNlsSetUserInfo,
// BaseSrvNlsSetMultipleUserInfo,
// BaseSrvNlsCreateSection,
// BaseSrvSetVDMCurDirs,
// BaseSrvGetVDMCurDirs,
// BaseSrvBatNotification,
// BaseSrvRegisterWowExec,
BaseSrvSoundSentryNotification,
// BaseSrvRefreshIniFileMapping,
BaseSrvDefineDosDevice,
// BaseSrvSetTermsrvAppInstallMode,
// BaseSrvNlsUpdateCacheCount,
// BaseSrvSetTermsrvClientTimeZone,
// BaseSrvSxsCreateActivationContext,
// BaseSrvRegisterThread,
// BaseSrvNlsGetUserInfo,
};
BOOLEAN BaseServerApiServerValidTable[BasepMaxApiNumber - BASESRV_FIRST_API_NUMBER] =
{
TRUE, // BaseSrvCreateProcess
TRUE, // BaseSrvCreateThread
TRUE, // BaseSrvGetTempFile
FALSE, // BaseSrvExitProcess
// FALSE, // BaseSrvDebugProcess
// TRUE, // BaseSrvCheckVDM
// TRUE, // BaseSrvUpdateVDMEntry
// TRUE, // BaseSrvGetNextVDMCommand
// TRUE, // BaseSrvExitVDM
// TRUE, // BaseSrvIsFirstVDM
// TRUE, // BaseSrvGetVDMExitCode
// TRUE, // BaseSrvSetReenterCount
TRUE, // BaseSrvSetProcessShutdownParam
TRUE, // BaseSrvGetProcessShutdownParam
// TRUE, // BaseSrvNlsSetUserInfo
// TRUE, // BaseSrvNlsSetMultipleUserInfo
// TRUE, // BaseSrvNlsCreateSection
// TRUE, // BaseSrvSetVDMCurDirs
// TRUE, // BaseSrvGetVDMCurDirs
// TRUE, // BaseSrvBatNotification
// TRUE, // BaseSrvRegisterWowExec
TRUE, // BaseSrvSoundSentryNotification
// TRUE, // BaseSrvRefreshIniFileMapping
TRUE, // BaseSrvDefineDosDevice
// FALSE, // BaseSrvSetTermsrvAppInstallMode
// FALSE, // BaseSrvNlsUpdateCacheCount
// FALSE, // BaseSrvSetTermsrvClientTimeZone
// FALSE, // BaseSrvSxsCreateActivationContext
// FALSE, // BaseSrvRegisterThread
// FALSE, // BaseSrvNlsGetUserInfo
};
PCHAR BaseServerApiNameTable[BasepMaxApiNumber - BASESRV_FIRST_API_NUMBER] =
{
"BaseCreateProcess",
"BaseCreateThread",
"BaseGetTempFile",
"BaseExitProcess",
// "BaseDebugProcess",
// "BaseCheckVDM",
// "BaseUpdateVDMEntry",
// "BaseGetNextVDMCommand",
// "BaseExitVDM",
// "BaseIsFirstVDM",
// "BaseGetVDMExitCode",
// "BaseSetReenterCount",
"BaseSetProcessShutdownParam",
"BaseGetProcessShutdownParam",
// "BaseNlsSetUserInfo",
// "BaseNlsSetMultipleUserInfo",
// "BaseNlsCreateSection",
// "BaseSetVDMCurDirs",
// "BaseGetVDMCurDirs",
// "BaseBatNotification",
// "BaseRegisterWowExec",
"BaseSoundSentryNotification",
// "BaseRefreshIniFileMapping",
"BaseDefineDosDevice",
// "BaseSetTermsrvAppInstallMode",
// "BaseNlsUpdateCacheCount",
// "BaseSetTermsrvClientTimeZone",
// "BaseSxsCreateActivationContext",
// "BaseRegisterThread",
// "BaseNlsGetUserInfo",
};
/* FUNCTIONS ******************************************************************/
NTSTATUS
NTAPI
CreateBaseAcls(OUT PACL* Dacl,
OUT PACL* RestrictedDacl)
{
PSID SystemSid, WorldSid, RestrictedSid;
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
NTSTATUS Status;
// UCHAR KeyValueBuffer[0x40];
// PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo;
// UNICODE_STRING KeyName;
// ULONG ProtectionMode = 0;
ULONG AclLength; // , ResultLength;
// HANDLE hKey;
// OBJECT_ATTRIBUTES ObjectAttributes;
/* Open the Session Manager Key */
/*
RtlInitUnicodeString(&KeyName, SM_REG_KEY);
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes);
if (NT_SUCCESS(Status))
{
/\* Read the key value *\/
RtlInitUnicodeString(&KeyName, L"ProtectionMode");
Status = NtQueryValueKey(hKey,
&KeyName,
KeyValuePartialInformation,
KeyValueBuffer,
sizeof(KeyValueBuffer),
&ResultLength);
/\* Make sure it's what we expect it to be *\/
KeyValuePartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
if ((NT_SUCCESS(Status)) && (KeyValuePartialInfo->Type == REG_DWORD) &&
(*(PULONG)KeyValuePartialInfo->Data))
{
/\* Save the Protection Mode *\/
// ProtectionMode = *(PULONG)KeyValuePartialInfo->Data;
}
/\* Close the handle *\/
NtClose(hKey);
}
*/
/* Allocate the System SID */
Status = RtlAllocateAndInitializeSid(&NtAuthority,
1, SECURITY_LOCAL_SYSTEM_RID,
0, 0, 0, 0, 0, 0, 0,
&SystemSid);
ASSERT(NT_SUCCESS(Status));
/* Allocate the World SID */
Status = RtlAllocateAndInitializeSid(&WorldAuthority,
1, SECURITY_WORLD_RID,
0, 0, 0, 0, 0, 0, 0,
&WorldSid);
ASSERT(NT_SUCCESS(Status));
/* Allocate the restricted SID */
Status = RtlAllocateAndInitializeSid(&NtAuthority,
1, SECURITY_RESTRICTED_CODE_RID,
0, 0, 0, 0, 0, 0, 0,
&RestrictedSid);
ASSERT(NT_SUCCESS(Status));
/* Allocate one ACL with 3 ACEs each for one SID */
AclLength = sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) +
RtlLengthSid(SystemSid) +
RtlLengthSid(RestrictedSid) +
RtlLengthSid(WorldSid);
*Dacl = RtlAllocateHeap(BaseSrvHeap, 0, AclLength);
ASSERT(*Dacl != NULL);
/* Set the correct header fields */
Status = RtlCreateAcl(*Dacl, AclLength, ACL_REVISION2);
ASSERT(NT_SUCCESS(Status));
/* Give the appropriate rights to each SID */
/* FIXME: Should check SessionId/ProtectionMode */
Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_QUERY | DIRECTORY_TRAVERSE | DIRECTORY_CREATE_OBJECT | DIRECTORY_CREATE_SUBDIRECTORY | READ_CONTROL, WorldSid);
ASSERT(NT_SUCCESS(Status));
Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_ALL_ACCESS, SystemSid);
ASSERT(NT_SUCCESS(Status));
Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_TRAVERSE, RestrictedSid);
ASSERT(NT_SUCCESS(Status));
/* Now allocate the restricted DACL */
*RestrictedDacl = RtlAllocateHeap(BaseSrvHeap, 0, AclLength);
ASSERT(*RestrictedDacl != NULL);
/* Initialize it */
Status = RtlCreateAcl(*RestrictedDacl, AclLength, ACL_REVISION2);
ASSERT(NT_SUCCESS(Status));
/* And add the same ACEs as before */
/* FIXME: Not really fully correct */
Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_QUERY | DIRECTORY_TRAVERSE | DIRECTORY_CREATE_OBJECT | DIRECTORY_CREATE_SUBDIRECTORY | READ_CONTROL, WorldSid);
ASSERT(NT_SUCCESS(Status));
Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_ALL_ACCESS, SystemSid);
ASSERT(NT_SUCCESS(Status));
Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_TRAVERSE, RestrictedSid);
ASSERT(NT_SUCCESS(Status));
/* The SIDs are captured, can free them now */
RtlFreeHeap(BaseSrvHeap, 0, SystemSid);
RtlFreeHeap(BaseSrvHeap, 0, WorldSid);
RtlFreeHeap(BaseSrvHeap, 0, RestrictedSid);
return Status;
}
VOID
NTAPI
BaseInitializeStaticServerData(IN PCSR_SERVER_DLL LoadedServerDll)
{
NTSTATUS Status;
WCHAR Buffer[MAX_PATH];
PWCHAR HeapBuffer;
UNICODE_STRING SystemRootString;
UNICODE_STRING UnexpandedSystemRootString = RTL_CONSTANT_STRING(L"%SystemRoot%");
UNICODE_STRING BaseSrvCSDString;
UNICODE_STRING BaseSrvWindowsDirectory;
UNICODE_STRING BaseSrvWindowsSystemDirectory;
UNICODE_STRING BnoString;
OBJECT_ATTRIBUTES ObjectAttributes;
ULONG SessionId;
HANDLE BaseSrvNamedObjectDirectory;
HANDLE BaseSrvRestrictedObjectDirectory;
PACL BnoDacl, BnoRestrictedDacl;
PSECURITY_DESCRIPTOR BnoSd;
HANDLE SymHandle;
UNICODE_STRING DirectoryName, SymlinkName;
ULONG LuidEnabled;
RTL_QUERY_REGISTRY_TABLE BaseServerRegistryConfigurationTable[2] =
{
{
NULL,
RTL_QUERY_REGISTRY_DIRECT,
L"CSDVersion",
&BaseSrvCSDString,
REG_NONE, NULL, 0
},
{0}
};
/* Initialize the memory */
BaseSrvHeap = RtlGetProcessHeap(); // Initialize our own heap.
BaseSrvSharedHeap = LoadedServerDll->SharedSection; // Get the CSR shared heap.
/* Get the session ID */
SessionId = NtCurrentPeb()->SessionId;
/* Get the Windows directory */
RtlInitEmptyUnicodeString(&SystemRootString, Buffer, sizeof(Buffer));
Status = RtlExpandEnvironmentStrings_U(NULL,
&UnexpandedSystemRootString,
&SystemRootString,
NULL);
ASSERT(NT_SUCCESS(Status));
/* Create the base directory */
Buffer[SystemRootString.Length / sizeof(WCHAR)] = UNICODE_NULL;
Status = RtlCreateUnicodeString(&BaseSrvWindowsDirectory,
SystemRootString.Buffer);
ASSERT(NT_SUCCESS(Status));
/* Create the system directory */
wcscat(SystemRootString.Buffer, L"\\System32");
Status = RtlCreateUnicodeString(&BaseSrvWindowsSystemDirectory,
SystemRootString.Buffer);
ASSERT(NT_SUCCESS(Status));
/* FIXME: Check Session ID */
wcscpy(Buffer, L"\\BaseNamedObjects");
RtlInitUnicodeString(&BnoString, Buffer);
/* Allocate the server data */
BaseStaticServerData = RtlAllocateHeap(BaseSrvSharedHeap,
HEAP_ZERO_MEMORY,
sizeof(BASE_STATIC_SERVER_DATA));
ASSERT(BaseStaticServerData != NULL);
/* Process timezone information */
BaseStaticServerData->TermsrvClientTimeZoneId = TIME_ZONE_ID_INVALID;
BaseStaticServerData->TermsrvClientTimeZoneChangeNum = 0;
Status = NtQuerySystemInformation(SystemTimeOfDayInformation,
&BaseStaticServerData->TimeOfDay,
sizeof(BaseStaticServerData->TimeOfDay),
NULL);
ASSERT(NT_SUCCESS(Status));
/* Make a shared heap copy of the Windows directory */
BaseStaticServerData->WindowsDirectory = BaseSrvWindowsDirectory;
HeapBuffer = RtlAllocateHeap(BaseSrvSharedHeap,
0,
BaseSrvWindowsDirectory.MaximumLength);
ASSERT(HeapBuffer);
RtlCopyMemory(HeapBuffer,
BaseStaticServerData->WindowsDirectory.Buffer,
BaseSrvWindowsDirectory.MaximumLength);
BaseStaticServerData->WindowsDirectory.Buffer = HeapBuffer;
/* Make a shared heap copy of the System directory */
BaseStaticServerData->WindowsSystemDirectory = BaseSrvWindowsSystemDirectory;
HeapBuffer = RtlAllocateHeap(BaseSrvSharedHeap,
0,
BaseSrvWindowsSystemDirectory.MaximumLength);
ASSERT(HeapBuffer);
RtlCopyMemory(HeapBuffer,
BaseStaticServerData->WindowsSystemDirectory.Buffer,
BaseSrvWindowsSystemDirectory.MaximumLength);
BaseStaticServerData->WindowsSystemDirectory.Buffer = HeapBuffer;
/* This string is not used */
RtlInitEmptyUnicodeString(&BaseStaticServerData->WindowsSys32x86Directory,
NULL,
0);
/* Make a shared heap copy of the BNO directory */
BaseStaticServerData->NamedObjectDirectory = BnoString;
BaseStaticServerData->NamedObjectDirectory.MaximumLength = BnoString.Length +
sizeof(UNICODE_NULL);
HeapBuffer = RtlAllocateHeap(BaseSrvSharedHeap,
0,
BaseStaticServerData->NamedObjectDirectory.MaximumLength);
ASSERT(HeapBuffer);
RtlCopyMemory(HeapBuffer,
BaseStaticServerData->NamedObjectDirectory.Buffer,
BaseStaticServerData->NamedObjectDirectory.MaximumLength);
BaseStaticServerData->NamedObjectDirectory.Buffer = HeapBuffer;
/*
* Confirmed that in Windows, CSDNumber and RCNumber are actually Length
* and MaximumLength of the CSD String, since the same UNICODE_STRING is
* being queried twice, the first time as a ULONG!
*
* Somehow, in Windows this doesn't cause a buffer overflow, but it might
* in ReactOS, so this code is disabled until someone figures out WTF.
*/
BaseStaticServerData->CSDNumber = 0;
BaseStaticServerData->RCNumber = 0;
/* Initialize the CSD string and query its value from the registry */
RtlInitEmptyUnicodeString(&BaseSrvCSDString, Buffer, sizeof(Buffer));
Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
L"",
BaseServerRegistryConfigurationTable,
NULL,
NULL);
if (NT_SUCCESS(Status))
{
/* Copy into the shared buffer */
wcsncpy(BaseStaticServerData->CSDVersion,
BaseSrvCSDString.Buffer,
BaseSrvCSDString.Length / sizeof(WCHAR));
}
else
{
/* NULL-terminate to indicate nothing is there */
BaseStaticServerData->CSDVersion[0] = UNICODE_NULL;
}
/* Cache the system information */
Status = NtQuerySystemInformation(SystemBasicInformation,
&BaseStaticServerData->SysInfo,
sizeof(BaseStaticServerData->SysInfo),
NULL);
ASSERT(NT_SUCCESS(Status));
/* FIXME: Should query the registry for these */
BaseStaticServerData->DefaultSeparateVDM = FALSE;
BaseStaticServerData->IsWowTaskReady = FALSE;
/* Allocate a security descriptor and create it */
BnoSd = RtlAllocateHeap(BaseSrvHeap, 0, 1024);
ASSERT(BnoSd);
Status = RtlCreateSecurityDescriptor(BnoSd, SECURITY_DESCRIPTOR_REVISION);
ASSERT(NT_SUCCESS(Status));
/* Create the BNO and \Restricted DACLs */
Status = CreateBaseAcls(&BnoDacl, &BnoRestrictedDacl);
ASSERT(NT_SUCCESS(Status));
/* Set the BNO DACL as active for now */
Status = RtlSetDaclSecurityDescriptor(BnoSd, TRUE, BnoDacl, FALSE);
ASSERT(NT_SUCCESS(Status));
/* Create the BNO directory */
RtlInitUnicodeString(&BnoString, L"\\BaseNamedObjects");
InitializeObjectAttributes(&ObjectAttributes,
&BnoString,
OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
NULL,
BnoSd);
Status = NtCreateDirectoryObject(&BaseSrvNamedObjectDirectory,
DIRECTORY_ALL_ACCESS,
&ObjectAttributes);
ASSERT(NT_SUCCESS(Status));
/* Check if we are session 0 */
if (SessionId == 0)
{
/* Mark this as a session 0 directory */
Status = NtSetInformationObject(BaseSrvNamedObjectDirectory,
ObjectSessionInformation,
NULL,
0);
ASSERT(NT_SUCCESS(Status));
}
/* Check if LUID device maps are enabled */
Status = NtQueryInformationProcess(NtCurrentProcess(),
ProcessLUIDDeviceMapsEnabled,
&LuidEnabled,
sizeof(LuidEnabled),
NULL);
ASSERT(NT_SUCCESS(Status));
BaseStaticServerData->LUIDDeviceMapsEnabled = LuidEnabled;
if (!BaseStaticServerData->LUIDDeviceMapsEnabled)
{
/* Make Global point back to BNO */
RtlInitUnicodeString(&DirectoryName, L"Global");
RtlInitUnicodeString(&SymlinkName, L"\\BaseNamedObjects");
InitializeObjectAttributes(&ObjectAttributes,
&DirectoryName,
OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
BaseSrvNamedObjectDirectory,
BnoSd);
Status = NtCreateSymbolicLinkObject(&SymHandle,
SYMBOLIC_LINK_ALL_ACCESS,
&ObjectAttributes,
&SymlinkName);
if ((NT_SUCCESS(Status)) && SessionId == 0) NtClose(SymHandle);
/* Make local point back to \Sessions\x\BNO */
RtlInitUnicodeString(&DirectoryName, L"Local");
ASSERT(SessionId == 0);
InitializeObjectAttributes(&ObjectAttributes,
&DirectoryName,
OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
BaseSrvNamedObjectDirectory,
BnoSd);
Status = NtCreateSymbolicLinkObject(&SymHandle,
SYMBOLIC_LINK_ALL_ACCESS,
&ObjectAttributes,
&SymlinkName);
if ((NT_SUCCESS(Status)) && SessionId == 0) NtClose(SymHandle);
/* Make Session point back to BNOLINKS */
RtlInitUnicodeString(&DirectoryName, L"Session");
RtlInitUnicodeString(&SymlinkName, L"\\Sessions\\BNOLINKS");
InitializeObjectAttributes(&ObjectAttributes,
&DirectoryName,
OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
BaseSrvNamedObjectDirectory,
BnoSd);
Status = NtCreateSymbolicLinkObject(&SymHandle,
SYMBOLIC_LINK_ALL_ACCESS,
&ObjectAttributes,
&SymlinkName);
if ((NT_SUCCESS(Status)) && SessionId == 0) NtClose(SymHandle);
/* Create the BNO\Restricted directory and set the restricted DACL */
RtlInitUnicodeString(&DirectoryName, L"Restricted");
Status = RtlSetDaclSecurityDescriptor(BnoSd, TRUE, BnoRestrictedDacl, FALSE);
ASSERT(NT_SUCCESS(Status));
InitializeObjectAttributes(&ObjectAttributes,
&DirectoryName,
OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
BaseSrvNamedObjectDirectory,
BnoSd);
Status = NtCreateDirectoryObject(&BaseSrvRestrictedObjectDirectory,
DIRECTORY_ALL_ACCESS,
&ObjectAttributes);
ASSERT(NT_SUCCESS(Status));
}
/* Finally, set the pointer */
LoadedServerDll->SharedSection = BaseStaticServerData;
}
CSR_SERVER_DLL_INIT(ServerDllInitialization)
{
/* Setup the DLL Object */
LoadedServerDll->ApiBase = BASESRV_FIRST_API_NUMBER; // ApiNumberBase
LoadedServerDll->HighestApiSupported = BasepMaxApiNumber; // MaxApiNumber
LoadedServerDll->DispatchTable = BaseServerApiDispatchTable;
LoadedServerDll->ValidTable = BaseServerApiServerValidTable;
LoadedServerDll->NameTable = BaseServerApiNameTable;
LoadedServerDll->SizeOfProcessData = 0;
LoadedServerDll->ConnectCallback = NULL;
LoadedServerDll->DisconnectCallback = NULL;
LoadedServerDll->ShutdownProcessCallback = NULL;
BaseSrvDllInstance = LoadedServerDll->ServerHandle;
BaseInitializeStaticServerData(LoadedServerDll);
/* Initialize DOS devices management */
BaseInitDefineDosDevice();
/* All done */
return STATUS_SUCCESS;
}
BOOL
NTAPI
DllMain(IN HINSTANCE hInstanceDll,
IN DWORD dwReason,
IN LPVOID lpReserved)
{
UNREFERENCED_PARAMETER(hInstanceDll);
UNREFERENCED_PARAMETER(dwReason);
UNREFERENCED_PARAMETER(lpReserved);
if (DLL_PROCESS_DETACH == dwReason)
{
BaseCleanupDefineDosDevice();
}
return TRUE;
}
/* EOF */