2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Base API Server DLL
4 * FILE: subsystems/win/basesrv/init.c
5 * PURPOSE: Initialization
6 * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
9 /* INCLUDES *******************************************************************/
17 /* GLOBALS ********************************************************************/
19 HANDLE BaseSrvDllInstance
= NULL
;
20 extern UNICODE_STRING BaseSrvKernel32DllPath
;
23 HANDLE BaseSrvHeap
= NULL
; // Our own heap.
24 HANDLE BaseSrvSharedHeap
= NULL
; // Shared heap with CSR. (CsrSrvSharedSectionHeap)
25 PBASE_STATIC_SERVER_DATA BaseStaticServerData
= NULL
; // Data that we can share amongst processes. Initialized inside BaseSrvSharedHeap.
27 // Windows Server 2003 table from http://j00ru.vexillium.org/csrss_list/api_list.html#Windows_2k3
28 PCSR_API_ROUTINE BaseServerApiDispatchTable
[BasepMaxApiNumber
- BASESRV_FIRST_API_NUMBER
] =
36 BaseSrvUpdateVDMEntry
,
37 BaseSrvGetNextVDMCommand
,
40 BaseSrvGetVDMExitCode
,
41 BaseSrvSetReenterCount
,
42 BaseSrvSetProcessShutdownParam
,
43 BaseSrvGetProcessShutdownParam
,
44 BaseSrvNlsSetUserInfo
,
45 BaseSrvNlsSetMultipleUserInfo
,
46 BaseSrvNlsCreateSection
,
49 BaseSrvBatNotification
,
50 BaseSrvRegisterWowExec
,
51 BaseSrvSoundSentryNotification
,
52 BaseSrvRefreshIniFileMapping
,
53 BaseSrvDefineDosDevice
,
54 BaseSrvSetTermsrvAppInstallMode
,
55 BaseSrvNlsUpdateCacheCount
,
56 BaseSrvSetTermsrvClientTimeZone
,
57 BaseSrvSxsCreateActivationContext
,
59 BaseSrvRegisterThread
,
60 BaseSrvNlsGetUserInfo
,
63 BOOLEAN BaseServerApiServerValidTable
[BasepMaxApiNumber
- BASESRV_FIRST_API_NUMBER
] =
65 TRUE
, // BaseSrvCreateProcess
66 TRUE
, // BaseSrvCreateThread
67 TRUE
, // BaseSrvGetTempFile
68 FALSE
, // BaseSrvExitProcess
69 FALSE
, // BaseSrvDebugProcess
70 TRUE
, // BaseSrvCheckVDM
71 TRUE
, // BaseSrvUpdateVDMEntry
72 TRUE
, // BaseSrvGetNextVDMCommand
73 TRUE
, // BaseSrvExitVDM
74 TRUE
, // BaseSrvIsFirstVDM
75 TRUE
, // BaseSrvGetVDMExitCode
76 TRUE
, // BaseSrvSetReenterCount
77 TRUE
, // BaseSrvSetProcessShutdownParam
78 TRUE
, // BaseSrvGetProcessShutdownParam
79 TRUE
, // BaseSrvNlsSetUserInfo
80 TRUE
, // BaseSrvNlsSetMultipleUserInfo
81 TRUE
, // BaseSrvNlsCreateSection
82 TRUE
, // BaseSrvSetVDMCurDirs
83 TRUE
, // BaseSrvGetVDMCurDirs
84 TRUE
, // BaseSrvBatNotification
85 TRUE
, // BaseSrvRegisterWowExec
86 TRUE
, // BaseSrvSoundSentryNotification
87 TRUE
, // BaseSrvRefreshIniFileMapping
88 TRUE
, // BaseSrvDefineDosDevice
89 TRUE
, // BaseSrvSetTermsrvAppInstallMode
90 TRUE
, // BaseSrvNlsUpdateCacheCount
91 TRUE
, // BaseSrvSetTermsrvClientTimeZone
92 TRUE
, // BaseSrvSxsCreateActivationContext
93 TRUE
, // BaseSrvUnknown
94 TRUE
, // BaseSrvRegisterThread
95 TRUE
, // BaseSrvNlsGetUserInfo
98 PCHAR BaseServerApiNameTable
[BasepMaxApiNumber
- BASESRV_FIRST_API_NUMBER
] =
106 "BaseUpdateVDMEntry",
107 "BaseGetNextVDMCommand",
110 "BaseGetVDMExitCode",
111 "BaseSetReenterCount",
112 "BaseSetProcessShutdownParam",
113 "BaseGetProcessShutdownParam",
114 "BaseNlsSetUserInfo",
115 "BaseNlsSetMultipleUserInfo",
116 "BaseNlsCreateSection",
119 "BaseBatNotification",
120 "BaseRegisterWowExec",
121 "BaseSoundSentryNotification",
122 "BaseRefreshIniFileMapping",
123 "BaseDefineDosDevice",
124 "BaseSetTermsrvAppInstallMode",
125 "BaseNlsUpdateCacheCount",
126 "BaseSetTermsrvClientTimeZone",
127 "BaseSxsCreateActivationContext",
129 "BaseRegisterThread",
130 "BaseNlsGetUserInfo",
134 /* FUNCTIONS ******************************************************************/
138 CreateBaseAcls(OUT PACL
* Dacl
,
139 OUT PACL
* RestrictedDacl
)
141 PSID SystemSid
, WorldSid
, RestrictedSid
;
142 SID_IDENTIFIER_AUTHORITY NtAuthority
= {SECURITY_NT_AUTHORITY
};
143 SID_IDENTIFIER_AUTHORITY WorldAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
146 UCHAR KeyValueBuffer
[0x40];
147 PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo
;
148 UNICODE_STRING KeyName
;
149 ULONG ProtectionMode
= 0;
155 OBJECT_ATTRIBUTES ObjectAttributes
;
157 /* Open the Session Manager Key */
158 RtlInitUnicodeString(&KeyName
, SM_REG_KEY
);
159 InitializeObjectAttributes(&ObjectAttributes
,
161 OBJ_CASE_INSENSITIVE
,
164 Status
= NtOpenKey(&hKey
, KEY_READ
, &ObjectAttributes
);
165 if (NT_SUCCESS(Status
))
167 /* Read the key value */
168 RtlInitUnicodeString(&KeyName
, L
"ProtectionMode");
169 Status
= NtQueryValueKey(hKey
,
171 KeyValuePartialInformation
,
173 sizeof(KeyValueBuffer
),
176 /* Make sure it's what we expect it to be */
177 KeyValuePartialInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)KeyValueBuffer
;
178 if ((NT_SUCCESS(Status
)) && (KeyValuePartialInfo
->Type
== REG_DWORD
) &&
179 (*(PULONG
)KeyValuePartialInfo
->Data
))
181 /* Save the Protection Mode */
182 ProtectionMode
= *(PULONG
)KeyValuePartialInfo
->Data
;
185 /* Close the handle */
190 /* Allocate the System SID */
191 Status
= RtlAllocateAndInitializeSid(&NtAuthority
,
192 1, SECURITY_LOCAL_SYSTEM_RID
,
195 ASSERT(NT_SUCCESS(Status
));
197 /* Allocate the World SID */
198 Status
= RtlAllocateAndInitializeSid(&WorldAuthority
,
199 1, SECURITY_WORLD_RID
,
202 ASSERT(NT_SUCCESS(Status
));
204 /* Allocate the restricted SID */
205 Status
= RtlAllocateAndInitializeSid(&NtAuthority
,
206 1, SECURITY_RESTRICTED_CODE_RID
,
209 ASSERT(NT_SUCCESS(Status
));
211 /* Allocate one ACL with 3 ACEs each for one SID */
212 AclLength
= sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) +
213 RtlLengthSid(SystemSid
) +
214 RtlLengthSid(WorldSid
) +
215 RtlLengthSid(RestrictedSid
);
216 *Dacl
= RtlAllocateHeap(BaseSrvHeap
, 0, AclLength
);
217 ASSERT(*Dacl
!= NULL
);
219 /* Set the correct header fields */
220 Status
= RtlCreateAcl(*Dacl
, AclLength
, ACL_REVISION2
);
221 ASSERT(NT_SUCCESS(Status
));
223 /* Give the appropriate rights to each SID */
224 /* FIXME: Should check SessionId/ProtectionMode */
225 Status
= RtlAddAccessAllowedAce(*Dacl
, ACL_REVISION2
, DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
| DIRECTORY_CREATE_OBJECT
| DIRECTORY_CREATE_SUBDIRECTORY
| READ_CONTROL
, WorldSid
);
226 ASSERT(NT_SUCCESS(Status
));
227 Status
= RtlAddAccessAllowedAce(*Dacl
, ACL_REVISION2
, DIRECTORY_ALL_ACCESS
, SystemSid
);
228 ASSERT(NT_SUCCESS(Status
));
229 Status
= RtlAddAccessAllowedAce(*Dacl
, ACL_REVISION2
, DIRECTORY_TRAVERSE
, RestrictedSid
);
230 ASSERT(NT_SUCCESS(Status
));
232 /* Now allocate the restricted DACL */
233 *RestrictedDacl
= RtlAllocateHeap(BaseSrvHeap
, 0, AclLength
);
234 ASSERT(*RestrictedDacl
!= NULL
);
237 Status
= RtlCreateAcl(*RestrictedDacl
, AclLength
, ACL_REVISION2
);
238 ASSERT(NT_SUCCESS(Status
));
240 /* And add the same ACEs as before */
241 /* FIXME: Not really fully correct */
242 Status
= RtlAddAccessAllowedAce(*RestrictedDacl
, ACL_REVISION2
, DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
| DIRECTORY_CREATE_OBJECT
| DIRECTORY_CREATE_SUBDIRECTORY
| READ_CONTROL
, WorldSid
);
243 ASSERT(NT_SUCCESS(Status
));
244 Status
= RtlAddAccessAllowedAce(*RestrictedDacl
, ACL_REVISION2
, DIRECTORY_ALL_ACCESS
, SystemSid
);
245 ASSERT(NT_SUCCESS(Status
));
246 Status
= RtlAddAccessAllowedAce(*RestrictedDacl
, ACL_REVISION2
, DIRECTORY_TRAVERSE
, RestrictedSid
);
247 ASSERT(NT_SUCCESS(Status
));
249 /* The SIDs are captured, can free them now */
250 RtlFreeSid(RestrictedSid
);
251 RtlFreeSid(WorldSid
);
252 RtlFreeSid(SystemSid
);
258 BaseInitializeStaticServerData(IN PCSR_SERVER_DLL LoadedServerDll
)
261 WCHAR Buffer
[MAX_PATH
];
263 UNICODE_STRING SystemRootString
;
264 UNICODE_STRING UnexpandedSystemRootString
= RTL_CONSTANT_STRING(L
"%SystemRoot%");
265 UNICODE_STRING BaseSrvCSDString
;
266 UNICODE_STRING BaseSrvWindowsDirectory
;
267 UNICODE_STRING BaseSrvWindowsSystemDirectory
;
268 UNICODE_STRING BnoString
;
269 OBJECT_ATTRIBUTES ObjectAttributes
;
271 HANDLE BaseSrvNamedObjectDirectory
;
272 HANDLE BaseSrvRestrictedObjectDirectory
;
273 PACL BnoDacl
, BnoRestrictedDacl
;
274 PSECURITY_DESCRIPTOR BnoSd
;
276 UNICODE_STRING DirectoryName
, SymlinkName
;
278 RTL_QUERY_REGISTRY_TABLE BaseServerRegistryConfigurationTable
[2] =
282 RTL_QUERY_REGISTRY_DIRECT
,
291 /* Initialize the memory */
292 BaseSrvHeap
= RtlGetProcessHeap(); // Initialize our own heap.
293 BaseSrvSharedHeap
= LoadedServerDll
->SharedSection
; // Get the CSR shared heap.
295 /* Get the session ID */
296 SessionId
= NtCurrentPeb()->SessionId
;
298 /* Get the Windows directory */
299 RtlInitEmptyUnicodeString(&SystemRootString
, Buffer
, sizeof(Buffer
));
300 Status
= RtlExpandEnvironmentStrings_U(NULL
,
301 &UnexpandedSystemRootString
,
304 ASSERT(NT_SUCCESS(Status
));
306 /* Create the base directory */
307 Buffer
[SystemRootString
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
308 Status
= RtlCreateUnicodeString(&BaseSrvWindowsDirectory
,
309 SystemRootString
.Buffer
);
310 ASSERT(NT_SUCCESS(Status
));
312 /* Create the system directory */
313 wcscat(SystemRootString
.Buffer
, L
"\\System32");
314 Status
= RtlCreateUnicodeString(&BaseSrvWindowsSystemDirectory
,
315 SystemRootString
.Buffer
);
316 ASSERT(NT_SUCCESS(Status
));
318 /* Create the kernel32 path */
319 wcscat(SystemRootString
.Buffer
, L
"\\kernel32.dll");
320 Status
= RtlCreateUnicodeString(&BaseSrvKernel32DllPath
,
321 SystemRootString
.Buffer
);
322 ASSERT(NT_SUCCESS(Status
));
324 /* FIXME: Check Session ID */
325 wcscpy(Buffer
, L
"\\BaseNamedObjects");
326 RtlInitUnicodeString(&BnoString
, Buffer
);
328 /* Allocate the server data */
329 BaseStaticServerData
= RtlAllocateHeap(BaseSrvSharedHeap
,
331 sizeof(BASE_STATIC_SERVER_DATA
));
332 ASSERT(BaseStaticServerData
!= NULL
);
334 /* Process timezone information */
335 BaseStaticServerData
->TermsrvClientTimeZoneId
= TIME_ZONE_ID_INVALID
;
336 BaseStaticServerData
->TermsrvClientTimeZoneChangeNum
= 0;
337 Status
= NtQuerySystemInformation(SystemTimeOfDayInformation
,
338 &BaseStaticServerData
->TimeOfDay
,
339 sizeof(BaseStaticServerData
->TimeOfDay
),
341 ASSERT(NT_SUCCESS(Status
));
343 /* Make a shared heap copy of the Windows directory */
344 BaseStaticServerData
->WindowsDirectory
= BaseSrvWindowsDirectory
;
345 HeapBuffer
= RtlAllocateHeap(BaseSrvSharedHeap
,
347 BaseSrvWindowsDirectory
.MaximumLength
);
349 RtlCopyMemory(HeapBuffer
,
350 BaseStaticServerData
->WindowsDirectory
.Buffer
,
351 BaseSrvWindowsDirectory
.MaximumLength
);
352 BaseStaticServerData
->WindowsDirectory
.Buffer
= HeapBuffer
;
354 /* Make a shared heap copy of the System directory */
355 BaseStaticServerData
->WindowsSystemDirectory
= BaseSrvWindowsSystemDirectory
;
356 HeapBuffer
= RtlAllocateHeap(BaseSrvSharedHeap
,
358 BaseSrvWindowsSystemDirectory
.MaximumLength
);
360 RtlCopyMemory(HeapBuffer
,
361 BaseStaticServerData
->WindowsSystemDirectory
.Buffer
,
362 BaseSrvWindowsSystemDirectory
.MaximumLength
);
363 BaseStaticServerData
->WindowsSystemDirectory
.Buffer
= HeapBuffer
;
365 /* This string is not used */
366 RtlInitEmptyUnicodeString(&BaseStaticServerData
->WindowsSys32x86Directory
,
370 /* Make a shared heap copy of the BNO directory */
371 BaseStaticServerData
->NamedObjectDirectory
= BnoString
;
372 BaseStaticServerData
->NamedObjectDirectory
.MaximumLength
= BnoString
.Length
+
373 sizeof(UNICODE_NULL
);
374 HeapBuffer
= RtlAllocateHeap(BaseSrvSharedHeap
,
376 BaseStaticServerData
->NamedObjectDirectory
.MaximumLength
);
378 RtlCopyMemory(HeapBuffer
,
379 BaseStaticServerData
->NamedObjectDirectory
.Buffer
,
380 BaseStaticServerData
->NamedObjectDirectory
.MaximumLength
);
381 BaseStaticServerData
->NamedObjectDirectory
.Buffer
= HeapBuffer
;
384 * Confirmed that in Windows, CSDNumber and RCNumber are actually Length
385 * and MaximumLength of the CSD String, since the same UNICODE_STRING is
386 * being queried twice, the first time as a ULONG!
388 * Somehow, in Windows this doesn't cause a buffer overflow, but it might
389 * in ReactOS, so this code is disabled until someone figures out WTF.
391 BaseStaticServerData
->CSDNumber
= 0;
392 BaseStaticServerData
->RCNumber
= 0;
394 /* Initialize the CSD string and query its value from the registry */
395 RtlInitEmptyUnicodeString(&BaseSrvCSDString
, Buffer
, sizeof(Buffer
));
396 Status
= RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT
,
398 BaseServerRegistryConfigurationTable
,
401 if (NT_SUCCESS(Status
))
403 /* Copy into the shared buffer */
404 wcsncpy(BaseStaticServerData
->CSDVersion
,
405 BaseSrvCSDString
.Buffer
,
406 BaseSrvCSDString
.Length
/ sizeof(WCHAR
));
410 /* NULL-terminate to indicate nothing is there */
411 BaseStaticServerData
->CSDVersion
[0] = UNICODE_NULL
;
414 /* Cache the system information */
415 Status
= NtQuerySystemInformation(SystemBasicInformation
,
416 &BaseStaticServerData
->SysInfo
,
417 sizeof(BaseStaticServerData
->SysInfo
),
419 ASSERT(NT_SUCCESS(Status
));
421 /* FIXME: Should query the registry for these */
422 BaseStaticServerData
->DefaultSeparateVDM
= FALSE
;
423 BaseStaticServerData
->IsWowTaskReady
= FALSE
;
425 /* Allocate a security descriptor and create it */
426 BnoSd
= RtlAllocateHeap(BaseSrvHeap
, 0, 1024);
428 Status
= RtlCreateSecurityDescriptor(BnoSd
, SECURITY_DESCRIPTOR_REVISION
);
429 ASSERT(NT_SUCCESS(Status
));
431 /* Create the BNO and \Restricted DACLs */
432 Status
= CreateBaseAcls(&BnoDacl
, &BnoRestrictedDacl
);
433 ASSERT(NT_SUCCESS(Status
));
435 /* Set the BNO DACL as active for now */
436 Status
= RtlSetDaclSecurityDescriptor(BnoSd
, TRUE
, BnoDacl
, FALSE
);
437 ASSERT(NT_SUCCESS(Status
));
439 /* Create the BNO directory */
440 RtlInitUnicodeString(&BnoString
, L
"\\BaseNamedObjects");
441 InitializeObjectAttributes(&ObjectAttributes
,
443 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
446 Status
= NtCreateDirectoryObject(&BaseSrvNamedObjectDirectory
,
447 DIRECTORY_ALL_ACCESS
,
449 ASSERT(NT_SUCCESS(Status
));
451 /* Check if we are session 0 */
454 /* Mark this as a session 0 directory */
455 Status
= NtSetInformationObject(BaseSrvNamedObjectDirectory
,
456 ObjectSessionInformation
,
459 ASSERT(NT_SUCCESS(Status
));
462 /* Check if LUID device maps are enabled */
463 Status
= NtQueryInformationProcess(NtCurrentProcess(),
464 ProcessLUIDDeviceMapsEnabled
,
468 ASSERT(NT_SUCCESS(Status
));
469 BaseStaticServerData
->LUIDDeviceMapsEnabled
= (BOOLEAN
)LuidEnabled
;
470 if (!BaseStaticServerData
->LUIDDeviceMapsEnabled
)
472 /* Make Global point back to BNO */
473 RtlInitUnicodeString(&DirectoryName
, L
"Global");
474 RtlInitUnicodeString(&SymlinkName
, L
"\\BaseNamedObjects");
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 local point back to \Sessions\x\BNO */
487 RtlInitUnicodeString(&DirectoryName
, L
"Local");
488 ASSERT(SessionId
== 0);
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 /* Make Session point back to BNOLINKS */
501 RtlInitUnicodeString(&DirectoryName
, L
"Session");
502 RtlInitUnicodeString(&SymlinkName
, L
"\\Sessions\\BNOLINKS");
503 InitializeObjectAttributes(&ObjectAttributes
,
505 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
506 BaseSrvNamedObjectDirectory
,
508 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
509 SYMBOLIC_LINK_ALL_ACCESS
,
512 if ((NT_SUCCESS(Status
)) && SessionId
== 0) NtClose(SymHandle
);
514 /* Create the BNO\Restricted directory and set the restricted DACL */
515 RtlInitUnicodeString(&DirectoryName
, L
"Restricted");
516 Status
= RtlSetDaclSecurityDescriptor(BnoSd
, TRUE
, BnoRestrictedDacl
, FALSE
);
517 ASSERT(NT_SUCCESS(Status
));
518 InitializeObjectAttributes(&ObjectAttributes
,
520 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
521 BaseSrvNamedObjectDirectory
,
523 Status
= NtCreateDirectoryObject(&BaseSrvRestrictedObjectDirectory
,
524 DIRECTORY_ALL_ACCESS
,
526 ASSERT(NT_SUCCESS(Status
));
530 BaseSrvNLSInit(BaseStaticServerData
);
532 /* Finally, set the pointer */
533 LoadedServerDll
->SharedSection
= BaseStaticServerData
;
536 CSR_SERVER_DLL_INIT(ServerDllInitialization
)
538 /* Setup the DLL Object */
539 LoadedServerDll
->ApiBase
= BASESRV_FIRST_API_NUMBER
;
540 LoadedServerDll
->HighestApiSupported
= BasepMaxApiNumber
;
541 LoadedServerDll
->DispatchTable
= BaseServerApiDispatchTable
;
542 LoadedServerDll
->ValidTable
= BaseServerApiServerValidTable
;
543 LoadedServerDll
->NameTable
= BaseServerApiNameTable
;
544 LoadedServerDll
->SizeOfProcessData
= 0;
545 LoadedServerDll
->ConnectCallback
= NULL
;
546 LoadedServerDll
->DisconnectCallback
= NULL
;
547 LoadedServerDll
->ShutdownProcessCallback
= NULL
;
549 BaseSrvDllInstance
= LoadedServerDll
->ServerHandle
;
551 BaseInitializeStaticServerData(LoadedServerDll
);
553 /* Initialize DOS devices management */
554 BaseInitDefineDosDevice();
557 return STATUS_SUCCESS
;
562 DllMain(IN HINSTANCE hInstanceDll
,
564 IN LPVOID lpReserved
)
566 UNREFERENCED_PARAMETER(hInstanceDll
);
567 UNREFERENCED_PARAMETER(dwReason
);
568 UNREFERENCED_PARAMETER(lpReserved
);
570 if (DLL_PROCESS_DETACH
== dwReason
)
572 BaseCleanupDefineDosDevice();