2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS/Win32 Base enviroment Subsystem Server
4 * FILE: subsystems/win/basesrv/init.c
5 * PURPOSE: Initialization
6 * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
9 /* INCLUDES *******************************************************************/
16 /* GLOBALS ********************************************************************/
18 HANDLE BaseSrvDllInstance
= NULL
;
21 HANDLE BaseSrvHeap
= NULL
; // Our own heap.
22 HANDLE BaseSrvSharedHeap
= NULL
; // Shared heap with CSR. (CsrSrvSharedSectionHeap)
23 PBASE_STATIC_SERVER_DATA BaseStaticServerData
= NULL
; // Data that we can share amongst processes. Initialized inside BaseSrvSharedHeap.
25 // Windows Server 2003 table from http://j00ru.vexillium.org/csrss_list/api_list.html#Windows_2k3
26 PCSR_API_ROUTINE BaseServerApiDispatchTable
[BasepMaxApiNumber
- BASESRV_FIRST_API_NUMBER
] =
32 // BaseSrvDebugProcess,
34 // BaseSrvUpdateVDMEntry,
35 // BaseSrvGetNextVDMCommand,
38 // BaseSrvGetVDMExitCode,
39 // BaseSrvSetReenterCount,
40 BaseSrvSetProcessShutdownParam
,
41 BaseSrvGetProcessShutdownParam
,
42 // BaseSrvNlsSetUserInfo,
43 // BaseSrvNlsSetMultipleUserInfo,
44 // BaseSrvNlsCreateSection,
45 // BaseSrvSetVDMCurDirs,
46 // BaseSrvGetVDMCurDirs,
47 // BaseSrvBatNotification,
48 // BaseSrvRegisterWowExec,
49 BaseSrvSoundSentryNotification
,
50 // BaseSrvRefreshIniFileMapping,
51 BaseSrvDefineDosDevice
,
52 // BaseSrvSetTermsrvAppInstallMode,
53 // BaseSrvNlsUpdateCacheCount,
54 // BaseSrvSetTermsrvClientTimeZone,
55 // BaseSrvSxsCreateActivationContext,
56 // BaseSrvRegisterThread,
57 // BaseSrvNlsGetUserInfo,
60 BOOLEAN BaseServerApiServerValidTable
[BasepMaxApiNumber
- BASESRV_FIRST_API_NUMBER
] =
62 TRUE
, // BaseSrvCreateProcess
63 TRUE
, // BaseSrvCreateThread
64 TRUE
, // BaseSrvGetTempFile
65 FALSE
, // BaseSrvExitProcess
66 // FALSE, // BaseSrvDebugProcess
67 // TRUE, // BaseSrvCheckVDM
68 // TRUE, // BaseSrvUpdateVDMEntry
69 // TRUE, // BaseSrvGetNextVDMCommand
70 // TRUE, // BaseSrvExitVDM
71 // TRUE, // BaseSrvIsFirstVDM
72 // TRUE, // BaseSrvGetVDMExitCode
73 // TRUE, // BaseSrvSetReenterCount
74 TRUE
, // BaseSrvSetProcessShutdownParam
75 TRUE
, // BaseSrvGetProcessShutdownParam
76 // TRUE, // BaseSrvNlsSetUserInfo
77 // TRUE, // BaseSrvNlsSetMultipleUserInfo
78 // TRUE, // BaseSrvNlsCreateSection
79 // TRUE, // BaseSrvSetVDMCurDirs
80 // TRUE, // BaseSrvGetVDMCurDirs
81 // TRUE, // BaseSrvBatNotification
82 // TRUE, // BaseSrvRegisterWowExec
83 TRUE
, // BaseSrvSoundSentryNotification
84 // TRUE, // BaseSrvRefreshIniFileMapping
85 TRUE
, // BaseSrvDefineDosDevice
86 // FALSE, // BaseSrvSetTermsrvAppInstallMode
87 // FALSE, // BaseSrvNlsUpdateCacheCount
88 // FALSE, // BaseSrvSetTermsrvClientTimeZone
89 // FALSE, // BaseSrvSxsCreateActivationContext
90 // FALSE, // BaseSrvRegisterThread
91 // FALSE, // BaseSrvNlsGetUserInfo
94 PCHAR BaseServerApiNameTable
[BasepMaxApiNumber
- BASESRV_FIRST_API_NUMBER
] =
100 // "BaseDebugProcess",
102 // "BaseUpdateVDMEntry",
103 // "BaseGetNextVDMCommand",
106 // "BaseGetVDMExitCode",
107 // "BaseSetReenterCount",
108 "BaseSetProcessShutdownParam",
109 "BaseGetProcessShutdownParam",
110 // "BaseNlsSetUserInfo",
111 // "BaseNlsSetMultipleUserInfo",
112 // "BaseNlsCreateSection",
113 // "BaseSetVDMCurDirs",
114 // "BaseGetVDMCurDirs",
115 // "BaseBatNotification",
116 // "BaseRegisterWowExec",
117 "BaseSoundSentryNotification",
118 // "BaseRefreshIniFileMapping",
119 "BaseDefineDosDevice",
120 // "BaseSetTermsrvAppInstallMode",
121 // "BaseNlsUpdateCacheCount",
122 // "BaseSetTermsrvClientTimeZone",
123 // "BaseSxsCreateActivationContext",
124 // "BaseRegisterThread",
125 // "BaseNlsGetUserInfo",
129 /* FUNCTIONS ******************************************************************/
133 CreateBaseAcls(OUT PACL
* Dacl
,
134 OUT PACL
* RestrictedDacl
)
136 PSID SystemSid
, WorldSid
, RestrictedSid
;
137 SID_IDENTIFIER_AUTHORITY NtAuthority
= {SECURITY_NT_AUTHORITY
};
138 SID_IDENTIFIER_AUTHORITY WorldAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
140 // UCHAR KeyValueBuffer[0x40];
141 // PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo;
142 // UNICODE_STRING KeyName;
143 // ULONG ProtectionMode = 0;
144 ULONG AclLength
; // , ResultLength;
146 // OBJECT_ATTRIBUTES ObjectAttributes;
148 /* Open the Session Manager Key */
150 RtlInitUnicodeString(&KeyName, SM_REG_KEY);
151 InitializeObjectAttributes(&ObjectAttributes,
153 OBJ_CASE_INSENSITIVE,
156 Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes);
157 if (NT_SUCCESS(Status))
159 /\* Read the key value *\/
160 RtlInitUnicodeString(&KeyName, L"ProtectionMode");
161 Status = NtQueryValueKey(hKey,
163 KeyValuePartialInformation,
165 sizeof(KeyValueBuffer),
168 /\* Make sure it's what we expect it to be *\/
169 KeyValuePartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
170 if ((NT_SUCCESS(Status)) && (KeyValuePartialInfo->Type == REG_DWORD) &&
171 (*(PULONG)KeyValuePartialInfo->Data))
173 /\* Save the Protection Mode *\/
174 // ProtectionMode = *(PULONG)KeyValuePartialInfo->Data;
177 /\* Close the handle *\/
182 /* Allocate the System SID */
183 Status
= RtlAllocateAndInitializeSid(&NtAuthority
,
184 1, SECURITY_LOCAL_SYSTEM_RID
,
187 ASSERT(NT_SUCCESS(Status
));
189 /* Allocate the World SID */
190 Status
= RtlAllocateAndInitializeSid(&WorldAuthority
,
191 1, SECURITY_WORLD_RID
,
194 ASSERT(NT_SUCCESS(Status
));
196 /* Allocate the restricted SID */
197 Status
= RtlAllocateAndInitializeSid(&NtAuthority
,
198 1, SECURITY_RESTRICTED_CODE_RID
,
201 ASSERT(NT_SUCCESS(Status
));
203 /* Allocate one ACL with 3 ACEs each for one SID */
204 AclLength
= sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) +
205 RtlLengthSid(SystemSid
) +
206 RtlLengthSid(WorldSid
) +
207 RtlLengthSid(RestrictedSid
);
208 *Dacl
= RtlAllocateHeap(BaseSrvHeap
, 0, AclLength
);
209 ASSERT(*Dacl
!= NULL
);
211 /* Set the correct header fields */
212 Status
= RtlCreateAcl(*Dacl
, AclLength
, ACL_REVISION2
);
213 ASSERT(NT_SUCCESS(Status
));
215 /* Give the appropriate rights to each SID */
216 /* FIXME: Should check SessionId/ProtectionMode */
217 Status
= RtlAddAccessAllowedAce(*Dacl
, ACL_REVISION2
, DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
| DIRECTORY_CREATE_OBJECT
| DIRECTORY_CREATE_SUBDIRECTORY
| READ_CONTROL
, WorldSid
);
218 ASSERT(NT_SUCCESS(Status
));
219 Status
= RtlAddAccessAllowedAce(*Dacl
, ACL_REVISION2
, DIRECTORY_ALL_ACCESS
, SystemSid
);
220 ASSERT(NT_SUCCESS(Status
));
221 Status
= RtlAddAccessAllowedAce(*Dacl
, ACL_REVISION2
, DIRECTORY_TRAVERSE
, RestrictedSid
);
222 ASSERT(NT_SUCCESS(Status
));
224 /* Now allocate the restricted DACL */
225 *RestrictedDacl
= RtlAllocateHeap(BaseSrvHeap
, 0, AclLength
);
226 ASSERT(*RestrictedDacl
!= NULL
);
229 Status
= RtlCreateAcl(*RestrictedDacl
, AclLength
, ACL_REVISION2
);
230 ASSERT(NT_SUCCESS(Status
));
232 /* And add the same ACEs as before */
233 /* FIXME: Not really fully correct */
234 Status
= RtlAddAccessAllowedAce(*RestrictedDacl
, ACL_REVISION2
, DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
| DIRECTORY_CREATE_OBJECT
| DIRECTORY_CREATE_SUBDIRECTORY
| READ_CONTROL
, WorldSid
);
235 ASSERT(NT_SUCCESS(Status
));
236 Status
= RtlAddAccessAllowedAce(*RestrictedDacl
, ACL_REVISION2
, DIRECTORY_ALL_ACCESS
, SystemSid
);
237 ASSERT(NT_SUCCESS(Status
));
238 Status
= RtlAddAccessAllowedAce(*RestrictedDacl
, ACL_REVISION2
, DIRECTORY_TRAVERSE
, RestrictedSid
);
239 ASSERT(NT_SUCCESS(Status
));
241 /* The SIDs are captured, can free them now */
242 RtlFreeSid(RestrictedSid
);
243 RtlFreeSid(WorldSid
);
244 RtlFreeSid(SystemSid
);
250 BaseInitializeStaticServerData(IN PCSR_SERVER_DLL LoadedServerDll
)
253 WCHAR Buffer
[MAX_PATH
];
255 UNICODE_STRING SystemRootString
;
256 UNICODE_STRING UnexpandedSystemRootString
= RTL_CONSTANT_STRING(L
"%SystemRoot%");
257 UNICODE_STRING BaseSrvCSDString
;
258 UNICODE_STRING BaseSrvWindowsDirectory
;
259 UNICODE_STRING BaseSrvWindowsSystemDirectory
;
260 UNICODE_STRING BnoString
;
261 OBJECT_ATTRIBUTES ObjectAttributes
;
263 HANDLE BaseSrvNamedObjectDirectory
;
264 HANDLE BaseSrvRestrictedObjectDirectory
;
265 PACL BnoDacl
, BnoRestrictedDacl
;
266 PSECURITY_DESCRIPTOR BnoSd
;
268 UNICODE_STRING DirectoryName
, SymlinkName
;
270 RTL_QUERY_REGISTRY_TABLE BaseServerRegistryConfigurationTable
[2] =
274 RTL_QUERY_REGISTRY_DIRECT
,
283 /* Initialize the memory */
284 BaseSrvHeap
= RtlGetProcessHeap(); // Initialize our own heap.
285 BaseSrvSharedHeap
= LoadedServerDll
->SharedSection
; // Get the CSR shared heap.
287 /* Get the session ID */
288 SessionId
= NtCurrentPeb()->SessionId
;
290 /* Get the Windows directory */
291 RtlInitEmptyUnicodeString(&SystemRootString
, Buffer
, sizeof(Buffer
));
292 Status
= RtlExpandEnvironmentStrings_U(NULL
,
293 &UnexpandedSystemRootString
,
296 ASSERT(NT_SUCCESS(Status
));
298 /* Create the base directory */
299 Buffer
[SystemRootString
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
300 Status
= RtlCreateUnicodeString(&BaseSrvWindowsDirectory
,
301 SystemRootString
.Buffer
);
302 ASSERT(NT_SUCCESS(Status
));
304 /* Create the system directory */
305 wcscat(SystemRootString
.Buffer
, L
"\\System32");
306 Status
= RtlCreateUnicodeString(&BaseSrvWindowsSystemDirectory
,
307 SystemRootString
.Buffer
);
308 ASSERT(NT_SUCCESS(Status
));
310 /* FIXME: Check Session ID */
311 wcscpy(Buffer
, L
"\\BaseNamedObjects");
312 RtlInitUnicodeString(&BnoString
, Buffer
);
314 /* Allocate the server data */
315 BaseStaticServerData
= RtlAllocateHeap(BaseSrvSharedHeap
,
317 sizeof(BASE_STATIC_SERVER_DATA
));
318 ASSERT(BaseStaticServerData
!= NULL
);
320 /* Process timezone information */
321 BaseStaticServerData
->TermsrvClientTimeZoneId
= TIME_ZONE_ID_INVALID
;
322 BaseStaticServerData
->TermsrvClientTimeZoneChangeNum
= 0;
323 Status
= NtQuerySystemInformation(SystemTimeOfDayInformation
,
324 &BaseStaticServerData
->TimeOfDay
,
325 sizeof(BaseStaticServerData
->TimeOfDay
),
327 ASSERT(NT_SUCCESS(Status
));
329 /* Make a shared heap copy of the Windows directory */
330 BaseStaticServerData
->WindowsDirectory
= BaseSrvWindowsDirectory
;
331 HeapBuffer
= RtlAllocateHeap(BaseSrvSharedHeap
,
333 BaseSrvWindowsDirectory
.MaximumLength
);
335 RtlCopyMemory(HeapBuffer
,
336 BaseStaticServerData
->WindowsDirectory
.Buffer
,
337 BaseSrvWindowsDirectory
.MaximumLength
);
338 BaseStaticServerData
->WindowsDirectory
.Buffer
= HeapBuffer
;
340 /* Make a shared heap copy of the System directory */
341 BaseStaticServerData
->WindowsSystemDirectory
= BaseSrvWindowsSystemDirectory
;
342 HeapBuffer
= RtlAllocateHeap(BaseSrvSharedHeap
,
344 BaseSrvWindowsSystemDirectory
.MaximumLength
);
346 RtlCopyMemory(HeapBuffer
,
347 BaseStaticServerData
->WindowsSystemDirectory
.Buffer
,
348 BaseSrvWindowsSystemDirectory
.MaximumLength
);
349 BaseStaticServerData
->WindowsSystemDirectory
.Buffer
= HeapBuffer
;
351 /* This string is not used */
352 RtlInitEmptyUnicodeString(&BaseStaticServerData
->WindowsSys32x86Directory
,
356 /* Make a shared heap copy of the BNO directory */
357 BaseStaticServerData
->NamedObjectDirectory
= BnoString
;
358 BaseStaticServerData
->NamedObjectDirectory
.MaximumLength
= BnoString
.Length
+
359 sizeof(UNICODE_NULL
);
360 HeapBuffer
= RtlAllocateHeap(BaseSrvSharedHeap
,
362 BaseStaticServerData
->NamedObjectDirectory
.MaximumLength
);
364 RtlCopyMemory(HeapBuffer
,
365 BaseStaticServerData
->NamedObjectDirectory
.Buffer
,
366 BaseStaticServerData
->NamedObjectDirectory
.MaximumLength
);
367 BaseStaticServerData
->NamedObjectDirectory
.Buffer
= HeapBuffer
;
370 * Confirmed that in Windows, CSDNumber and RCNumber are actually Length
371 * and MaximumLength of the CSD String, since the same UNICODE_STRING is
372 * being queried twice, the first time as a ULONG!
374 * Somehow, in Windows this doesn't cause a buffer overflow, but it might
375 * in ReactOS, so this code is disabled until someone figures out WTF.
377 BaseStaticServerData
->CSDNumber
= 0;
378 BaseStaticServerData
->RCNumber
= 0;
380 /* Initialize the CSD string and query its value from the registry */
381 RtlInitEmptyUnicodeString(&BaseSrvCSDString
, Buffer
, sizeof(Buffer
));
382 Status
= RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT
,
384 BaseServerRegistryConfigurationTable
,
387 if (NT_SUCCESS(Status
))
389 /* Copy into the shared buffer */
390 wcsncpy(BaseStaticServerData
->CSDVersion
,
391 BaseSrvCSDString
.Buffer
,
392 BaseSrvCSDString
.Length
/ sizeof(WCHAR
));
396 /* NULL-terminate to indicate nothing is there */
397 BaseStaticServerData
->CSDVersion
[0] = UNICODE_NULL
;
400 /* Cache the system information */
401 Status
= NtQuerySystemInformation(SystemBasicInformation
,
402 &BaseStaticServerData
->SysInfo
,
403 sizeof(BaseStaticServerData
->SysInfo
),
405 ASSERT(NT_SUCCESS(Status
));
407 /* FIXME: Should query the registry for these */
408 BaseStaticServerData
->DefaultSeparateVDM
= FALSE
;
409 BaseStaticServerData
->IsWowTaskReady
= FALSE
;
411 /* Allocate a security descriptor and create it */
412 BnoSd
= RtlAllocateHeap(BaseSrvHeap
, 0, 1024);
414 Status
= RtlCreateSecurityDescriptor(BnoSd
, SECURITY_DESCRIPTOR_REVISION
);
415 ASSERT(NT_SUCCESS(Status
));
417 /* Create the BNO and \Restricted DACLs */
418 Status
= CreateBaseAcls(&BnoDacl
, &BnoRestrictedDacl
);
419 ASSERT(NT_SUCCESS(Status
));
421 /* Set the BNO DACL as active for now */
422 Status
= RtlSetDaclSecurityDescriptor(BnoSd
, TRUE
, BnoDacl
, FALSE
);
423 ASSERT(NT_SUCCESS(Status
));
425 /* Create the BNO directory */
426 RtlInitUnicodeString(&BnoString
, L
"\\BaseNamedObjects");
427 InitializeObjectAttributes(&ObjectAttributes
,
429 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
432 Status
= NtCreateDirectoryObject(&BaseSrvNamedObjectDirectory
,
433 DIRECTORY_ALL_ACCESS
,
435 ASSERT(NT_SUCCESS(Status
));
437 /* Check if we are session 0 */
440 /* Mark this as a session 0 directory */
441 Status
= NtSetInformationObject(BaseSrvNamedObjectDirectory
,
442 ObjectSessionInformation
,
445 ASSERT(NT_SUCCESS(Status
));
448 /* Check if LUID device maps are enabled */
449 Status
= NtQueryInformationProcess(NtCurrentProcess(),
450 ProcessLUIDDeviceMapsEnabled
,
454 ASSERT(NT_SUCCESS(Status
));
455 BaseStaticServerData
->LUIDDeviceMapsEnabled
= LuidEnabled
;
456 if (!BaseStaticServerData
->LUIDDeviceMapsEnabled
)
458 /* Make Global point back to BNO */
459 RtlInitUnicodeString(&DirectoryName
, L
"Global");
460 RtlInitUnicodeString(&SymlinkName
, L
"\\BaseNamedObjects");
461 InitializeObjectAttributes(&ObjectAttributes
,
463 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
464 BaseSrvNamedObjectDirectory
,
466 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
467 SYMBOLIC_LINK_ALL_ACCESS
,
470 if ((NT_SUCCESS(Status
)) && SessionId
== 0) NtClose(SymHandle
);
472 /* Make local point back to \Sessions\x\BNO */
473 RtlInitUnicodeString(&DirectoryName
, L
"Local");
474 ASSERT(SessionId
== 0);
475 InitializeObjectAttributes(&ObjectAttributes
,
477 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
478 BaseSrvNamedObjectDirectory
,
480 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
481 SYMBOLIC_LINK_ALL_ACCESS
,
484 if ((NT_SUCCESS(Status
)) && SessionId
== 0) NtClose(SymHandle
);
486 /* Make Session point back to BNOLINKS */
487 RtlInitUnicodeString(&DirectoryName
, L
"Session");
488 RtlInitUnicodeString(&SymlinkName
, L
"\\Sessions\\BNOLINKS");
489 InitializeObjectAttributes(&ObjectAttributes
,
491 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
492 BaseSrvNamedObjectDirectory
,
494 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
495 SYMBOLIC_LINK_ALL_ACCESS
,
498 if ((NT_SUCCESS(Status
)) && SessionId
== 0) NtClose(SymHandle
);
500 /* Create the BNO\Restricted directory and set the restricted DACL */
501 RtlInitUnicodeString(&DirectoryName
, L
"Restricted");
502 Status
= RtlSetDaclSecurityDescriptor(BnoSd
, TRUE
, BnoRestrictedDacl
, FALSE
);
503 ASSERT(NT_SUCCESS(Status
));
504 InitializeObjectAttributes(&ObjectAttributes
,
506 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
507 BaseSrvNamedObjectDirectory
,
509 Status
= NtCreateDirectoryObject(&BaseSrvRestrictedObjectDirectory
,
510 DIRECTORY_ALL_ACCESS
,
512 ASSERT(NT_SUCCESS(Status
));
515 /* Finally, set the pointer */
516 LoadedServerDll
->SharedSection
= BaseStaticServerData
;
519 CSR_SERVER_DLL_INIT(ServerDllInitialization
)
521 /* Setup the DLL Object */
522 LoadedServerDll
->ApiBase
= BASESRV_FIRST_API_NUMBER
; // ApiNumberBase
523 LoadedServerDll
->HighestApiSupported
= BasepMaxApiNumber
; // MaxApiNumber
524 LoadedServerDll
->DispatchTable
= BaseServerApiDispatchTable
;
525 LoadedServerDll
->ValidTable
= BaseServerApiServerValidTable
;
526 LoadedServerDll
->NameTable
= BaseServerApiNameTable
;
527 LoadedServerDll
->SizeOfProcessData
= 0;
528 LoadedServerDll
->ConnectCallback
= NULL
;
529 LoadedServerDll
->DisconnectCallback
= NULL
;
530 LoadedServerDll
->ShutdownProcessCallback
= NULL
;
532 BaseSrvDllInstance
= LoadedServerDll
->ServerHandle
;
534 BaseInitializeStaticServerData(LoadedServerDll
);
536 /* Initialize DOS devices management */
537 BaseInitDefineDosDevice();
540 return STATUS_SUCCESS
;
545 DllMain(IN HINSTANCE hInstanceDll
,
547 IN LPVOID lpReserved
)
549 UNREFERENCED_PARAMETER(hInstanceDll
);
550 UNREFERENCED_PARAMETER(dwReason
);
551 UNREFERENCED_PARAMETER(lpReserved
);
553 if (DLL_PROCESS_DETACH
== dwReason
)
555 BaseCleanupDefineDosDevice();