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
;
22 HANDLE BaseSrvHeap
= NULL
; // Our own heap.
23 HANDLE BaseSrvSharedHeap
= NULL
; // Shared heap with CSR. (CsrSrvSharedSectionHeap)
24 PBASE_STATIC_SERVER_DATA BaseStaticServerData
= NULL
; // Data that we can share amongst processes. Initialized inside BaseSrvSharedHeap.
26 // Windows Server 2003 table from http://j00ru.vexillium.org/csrss_list/api_list.html#Windows_2k3
27 PCSR_API_ROUTINE BaseServerApiDispatchTable
[BasepMaxApiNumber
- BASESRV_FIRST_API_NUMBER
] =
35 BaseSrvUpdateVDMEntry
,
36 BaseSrvGetNextVDMCommand
,
39 BaseSrvGetVDMExitCode
,
40 BaseSrvSetReenterCount
,
41 BaseSrvSetProcessShutdownParam
,
42 BaseSrvGetProcessShutdownParam
,
43 BaseSrvNlsSetUserInfo
,
44 BaseSrvNlsSetMultipleUserInfo
,
45 BaseSrvNlsCreateSection
,
48 BaseSrvBatNotification
,
49 BaseSrvRegisterWowExec
,
50 BaseSrvSoundSentryNotification
,
51 BaseSrvRefreshIniFileMapping
,
52 BaseSrvDefineDosDevice
,
53 BaseSrvSetTermsrvAppInstallMode
,
54 BaseSrvNlsUpdateCacheCount
,
55 BaseSrvSetTermsrvClientTimeZone
,
56 BaseSrvSxsCreateActivationContext
,
57 BaseSrvRegisterThread
,
58 BaseSrvNlsGetUserInfo
,
61 BOOLEAN BaseServerApiServerValidTable
[BasepMaxApiNumber
- BASESRV_FIRST_API_NUMBER
] =
63 TRUE
, // BaseSrvCreateProcess
64 TRUE
, // BaseSrvCreateThread
65 TRUE
, // BaseSrvGetTempFile
66 FALSE
, // BaseSrvExitProcess
67 FALSE
, // BaseSrvDebugProcess
68 TRUE
, // BaseSrvCheckVDM
69 TRUE
, // BaseSrvUpdateVDMEntry
70 TRUE
, // BaseSrvGetNextVDMCommand
71 TRUE
, // BaseSrvExitVDM
72 TRUE
, // BaseSrvIsFirstVDM
73 TRUE
, // BaseSrvGetVDMExitCode
74 TRUE
, // BaseSrvSetReenterCount
75 TRUE
, // BaseSrvSetProcessShutdownParam
76 TRUE
, // BaseSrvGetProcessShutdownParam
77 TRUE
, // BaseSrvNlsSetUserInfo
78 TRUE
, // BaseSrvNlsSetMultipleUserInfo
79 TRUE
, // BaseSrvNlsCreateSection
80 TRUE
, // BaseSrvSetVDMCurDirs
81 TRUE
, // BaseSrvGetVDMCurDirs
82 TRUE
, // BaseSrvBatNotification
83 TRUE
, // BaseSrvRegisterWowExec
84 TRUE
, // BaseSrvSoundSentryNotification
85 TRUE
, // BaseSrvRefreshIniFileMapping
86 TRUE
, // BaseSrvDefineDosDevice
87 FALSE
, // BaseSrvSetTermsrvAppInstallMode
88 FALSE
, // BaseSrvNlsUpdateCacheCount
89 FALSE
, // BaseSrvSetTermsrvClientTimeZone
90 FALSE
, // BaseSrvSxsCreateActivationContext
91 FALSE
, // BaseSrvRegisterThread
92 FALSE
, // BaseSrvNlsGetUserInfo
95 PCHAR BaseServerApiNameTable
[BasepMaxApiNumber
- BASESRV_FIRST_API_NUMBER
] =
103 "BaseUpdateVDMEntry",
104 "BaseGetNextVDMCommand",
107 "BaseGetVDMExitCode",
108 "BaseSetReenterCount",
109 "BaseSetProcessShutdownParam",
110 "BaseGetProcessShutdownParam",
111 "BaseNlsSetUserInfo",
112 "BaseNlsSetMultipleUserInfo",
113 "BaseNlsCreateSection",
116 "BaseBatNotification",
117 "BaseRegisterWowExec",
118 "BaseSoundSentryNotification",
119 "BaseRefreshIniFileMapping",
120 "BaseDefineDosDevice",
121 "BaseSetTermsrvAppInstallMode",
122 "BaseNlsUpdateCacheCount",
123 "BaseSetTermsrvClientTimeZone",
124 "BaseSxsCreateActivationContext",
125 "BaseRegisterThread",
126 "BaseNlsGetUserInfo",
130 /* FUNCTIONS ******************************************************************/
134 CreateBaseAcls(OUT PACL
* Dacl
,
135 OUT PACL
* RestrictedDacl
)
137 PSID SystemSid
, WorldSid
, RestrictedSid
;
138 SID_IDENTIFIER_AUTHORITY NtAuthority
= {SECURITY_NT_AUTHORITY
};
139 SID_IDENTIFIER_AUTHORITY WorldAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
142 UCHAR KeyValueBuffer
[0x40];
143 PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo
;
144 UNICODE_STRING KeyName
;
145 ULONG ProtectionMode
= 0;
151 OBJECT_ATTRIBUTES ObjectAttributes
;
153 /* Open the Session Manager Key */
154 RtlInitUnicodeString(&KeyName
, SM_REG_KEY
);
155 InitializeObjectAttributes(&ObjectAttributes
,
157 OBJ_CASE_INSENSITIVE
,
160 Status
= NtOpenKey(&hKey
, KEY_READ
, &ObjectAttributes
);
161 if (NT_SUCCESS(Status
))
163 /* Read the key value */
164 RtlInitUnicodeString(&KeyName
, L
"ProtectionMode");
165 Status
= NtQueryValueKey(hKey
,
167 KeyValuePartialInformation
,
169 sizeof(KeyValueBuffer
),
172 /* Make sure it's what we expect it to be */
173 KeyValuePartialInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)KeyValueBuffer
;
174 if ((NT_SUCCESS(Status
)) && (KeyValuePartialInfo
->Type
== REG_DWORD
) &&
175 (*(PULONG
)KeyValuePartialInfo
->Data
))
177 /* Save the Protection Mode */
178 ProtectionMode
= *(PULONG
)KeyValuePartialInfo
->Data
;
181 /* Close the handle */
186 /* Allocate the System SID */
187 Status
= RtlAllocateAndInitializeSid(&NtAuthority
,
188 1, SECURITY_LOCAL_SYSTEM_RID
,
191 ASSERT(NT_SUCCESS(Status
));
193 /* Allocate the World SID */
194 Status
= RtlAllocateAndInitializeSid(&WorldAuthority
,
195 1, SECURITY_WORLD_RID
,
198 ASSERT(NT_SUCCESS(Status
));
200 /* Allocate the restricted SID */
201 Status
= RtlAllocateAndInitializeSid(&NtAuthority
,
202 1, SECURITY_RESTRICTED_CODE_RID
,
205 ASSERT(NT_SUCCESS(Status
));
207 /* Allocate one ACL with 3 ACEs each for one SID */
208 AclLength
= sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) +
209 RtlLengthSid(SystemSid
) +
210 RtlLengthSid(WorldSid
) +
211 RtlLengthSid(RestrictedSid
);
212 *Dacl
= RtlAllocateHeap(BaseSrvHeap
, 0, AclLength
);
213 ASSERT(*Dacl
!= NULL
);
215 /* Set the correct header fields */
216 Status
= RtlCreateAcl(*Dacl
, AclLength
, ACL_REVISION2
);
217 ASSERT(NT_SUCCESS(Status
));
219 /* Give the appropriate rights to each SID */
220 /* FIXME: Should check SessionId/ProtectionMode */
221 Status
= RtlAddAccessAllowedAce(*Dacl
, ACL_REVISION2
, DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
| DIRECTORY_CREATE_OBJECT
| DIRECTORY_CREATE_SUBDIRECTORY
| READ_CONTROL
, WorldSid
);
222 ASSERT(NT_SUCCESS(Status
));
223 Status
= RtlAddAccessAllowedAce(*Dacl
, ACL_REVISION2
, DIRECTORY_ALL_ACCESS
, SystemSid
);
224 ASSERT(NT_SUCCESS(Status
));
225 Status
= RtlAddAccessAllowedAce(*Dacl
, ACL_REVISION2
, DIRECTORY_TRAVERSE
, RestrictedSid
);
226 ASSERT(NT_SUCCESS(Status
));
228 /* Now allocate the restricted DACL */
229 *RestrictedDacl
= RtlAllocateHeap(BaseSrvHeap
, 0, AclLength
);
230 ASSERT(*RestrictedDacl
!= NULL
);
233 Status
= RtlCreateAcl(*RestrictedDacl
, AclLength
, ACL_REVISION2
);
234 ASSERT(NT_SUCCESS(Status
));
236 /* And add the same ACEs as before */
237 /* FIXME: Not really fully correct */
238 Status
= RtlAddAccessAllowedAce(*RestrictedDacl
, ACL_REVISION2
, DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
| DIRECTORY_CREATE_OBJECT
| DIRECTORY_CREATE_SUBDIRECTORY
| READ_CONTROL
, WorldSid
);
239 ASSERT(NT_SUCCESS(Status
));
240 Status
= RtlAddAccessAllowedAce(*RestrictedDacl
, ACL_REVISION2
, DIRECTORY_ALL_ACCESS
, SystemSid
);
241 ASSERT(NT_SUCCESS(Status
));
242 Status
= RtlAddAccessAllowedAce(*RestrictedDacl
, ACL_REVISION2
, DIRECTORY_TRAVERSE
, RestrictedSid
);
243 ASSERT(NT_SUCCESS(Status
));
245 /* The SIDs are captured, can free them now */
246 RtlFreeSid(RestrictedSid
);
247 RtlFreeSid(WorldSid
);
248 RtlFreeSid(SystemSid
);
254 BaseInitializeStaticServerData(IN PCSR_SERVER_DLL LoadedServerDll
)
257 WCHAR Buffer
[MAX_PATH
];
259 UNICODE_STRING SystemRootString
;
260 UNICODE_STRING UnexpandedSystemRootString
= RTL_CONSTANT_STRING(L
"%SystemRoot%");
261 UNICODE_STRING BaseSrvCSDString
;
262 UNICODE_STRING BaseSrvWindowsDirectory
;
263 UNICODE_STRING BaseSrvWindowsSystemDirectory
;
264 UNICODE_STRING BnoString
;
265 OBJECT_ATTRIBUTES ObjectAttributes
;
267 HANDLE BaseSrvNamedObjectDirectory
;
268 HANDLE BaseSrvRestrictedObjectDirectory
;
269 PACL BnoDacl
, BnoRestrictedDacl
;
270 PSECURITY_DESCRIPTOR BnoSd
;
272 UNICODE_STRING DirectoryName
, SymlinkName
;
274 RTL_QUERY_REGISTRY_TABLE BaseServerRegistryConfigurationTable
[2] =
278 RTL_QUERY_REGISTRY_DIRECT
,
287 /* Initialize the memory */
288 BaseSrvHeap
= RtlGetProcessHeap(); // Initialize our own heap.
289 BaseSrvSharedHeap
= LoadedServerDll
->SharedSection
; // Get the CSR shared heap.
291 /* Get the session ID */
292 SessionId
= NtCurrentPeb()->SessionId
;
294 /* Get the Windows directory */
295 RtlInitEmptyUnicodeString(&SystemRootString
, Buffer
, sizeof(Buffer
));
296 Status
= RtlExpandEnvironmentStrings_U(NULL
,
297 &UnexpandedSystemRootString
,
300 ASSERT(NT_SUCCESS(Status
));
302 /* Create the base directory */
303 Buffer
[SystemRootString
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
304 Status
= RtlCreateUnicodeString(&BaseSrvWindowsDirectory
,
305 SystemRootString
.Buffer
);
306 ASSERT(NT_SUCCESS(Status
));
308 /* Create the system directory */
309 wcscat(SystemRootString
.Buffer
, L
"\\System32");
310 Status
= RtlCreateUnicodeString(&BaseSrvWindowsSystemDirectory
,
311 SystemRootString
.Buffer
);
312 ASSERT(NT_SUCCESS(Status
));
314 /* FIXME: Check Session ID */
315 wcscpy(Buffer
, L
"\\BaseNamedObjects");
316 RtlInitUnicodeString(&BnoString
, Buffer
);
318 /* Allocate the server data */
319 BaseStaticServerData
= RtlAllocateHeap(BaseSrvSharedHeap
,
321 sizeof(BASE_STATIC_SERVER_DATA
));
322 ASSERT(BaseStaticServerData
!= NULL
);
324 /* Process timezone information */
325 BaseStaticServerData
->TermsrvClientTimeZoneId
= TIME_ZONE_ID_INVALID
;
326 BaseStaticServerData
->TermsrvClientTimeZoneChangeNum
= 0;
327 Status
= NtQuerySystemInformation(SystemTimeOfDayInformation
,
328 &BaseStaticServerData
->TimeOfDay
,
329 sizeof(BaseStaticServerData
->TimeOfDay
),
331 ASSERT(NT_SUCCESS(Status
));
333 /* Make a shared heap copy of the Windows directory */
334 BaseStaticServerData
->WindowsDirectory
= BaseSrvWindowsDirectory
;
335 HeapBuffer
= RtlAllocateHeap(BaseSrvSharedHeap
,
337 BaseSrvWindowsDirectory
.MaximumLength
);
339 RtlCopyMemory(HeapBuffer
,
340 BaseStaticServerData
->WindowsDirectory
.Buffer
,
341 BaseSrvWindowsDirectory
.MaximumLength
);
342 BaseStaticServerData
->WindowsDirectory
.Buffer
= HeapBuffer
;
344 /* Make a shared heap copy of the System directory */
345 BaseStaticServerData
->WindowsSystemDirectory
= BaseSrvWindowsSystemDirectory
;
346 HeapBuffer
= RtlAllocateHeap(BaseSrvSharedHeap
,
348 BaseSrvWindowsSystemDirectory
.MaximumLength
);
350 RtlCopyMemory(HeapBuffer
,
351 BaseStaticServerData
->WindowsSystemDirectory
.Buffer
,
352 BaseSrvWindowsSystemDirectory
.MaximumLength
);
353 BaseStaticServerData
->WindowsSystemDirectory
.Buffer
= HeapBuffer
;
355 /* This string is not used */
356 RtlInitEmptyUnicodeString(&BaseStaticServerData
->WindowsSys32x86Directory
,
360 /* Make a shared heap copy of the BNO directory */
361 BaseStaticServerData
->NamedObjectDirectory
= BnoString
;
362 BaseStaticServerData
->NamedObjectDirectory
.MaximumLength
= BnoString
.Length
+
363 sizeof(UNICODE_NULL
);
364 HeapBuffer
= RtlAllocateHeap(BaseSrvSharedHeap
,
366 BaseStaticServerData
->NamedObjectDirectory
.MaximumLength
);
368 RtlCopyMemory(HeapBuffer
,
369 BaseStaticServerData
->NamedObjectDirectory
.Buffer
,
370 BaseStaticServerData
->NamedObjectDirectory
.MaximumLength
);
371 BaseStaticServerData
->NamedObjectDirectory
.Buffer
= HeapBuffer
;
374 * Confirmed that in Windows, CSDNumber and RCNumber are actually Length
375 * and MaximumLength of the CSD String, since the same UNICODE_STRING is
376 * being queried twice, the first time as a ULONG!
378 * Somehow, in Windows this doesn't cause a buffer overflow, but it might
379 * in ReactOS, so this code is disabled until someone figures out WTF.
381 BaseStaticServerData
->CSDNumber
= 0;
382 BaseStaticServerData
->RCNumber
= 0;
384 /* Initialize the CSD string and query its value from the registry */
385 RtlInitEmptyUnicodeString(&BaseSrvCSDString
, Buffer
, sizeof(Buffer
));
386 Status
= RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT
,
388 BaseServerRegistryConfigurationTable
,
391 if (NT_SUCCESS(Status
))
393 /* Copy into the shared buffer */
394 wcsncpy(BaseStaticServerData
->CSDVersion
,
395 BaseSrvCSDString
.Buffer
,
396 BaseSrvCSDString
.Length
/ sizeof(WCHAR
));
400 /* NULL-terminate to indicate nothing is there */
401 BaseStaticServerData
->CSDVersion
[0] = UNICODE_NULL
;
404 /* Cache the system information */
405 Status
= NtQuerySystemInformation(SystemBasicInformation
,
406 &BaseStaticServerData
->SysInfo
,
407 sizeof(BaseStaticServerData
->SysInfo
),
409 ASSERT(NT_SUCCESS(Status
));
411 /* FIXME: Should query the registry for these */
412 BaseStaticServerData
->DefaultSeparateVDM
= FALSE
;
413 BaseStaticServerData
->IsWowTaskReady
= FALSE
;
415 /* Allocate a security descriptor and create it */
416 BnoSd
= RtlAllocateHeap(BaseSrvHeap
, 0, 1024);
418 Status
= RtlCreateSecurityDescriptor(BnoSd
, SECURITY_DESCRIPTOR_REVISION
);
419 ASSERT(NT_SUCCESS(Status
));
421 /* Create the BNO and \Restricted DACLs */
422 Status
= CreateBaseAcls(&BnoDacl
, &BnoRestrictedDacl
);
423 ASSERT(NT_SUCCESS(Status
));
425 /* Set the BNO DACL as active for now */
426 Status
= RtlSetDaclSecurityDescriptor(BnoSd
, TRUE
, BnoDacl
, FALSE
);
427 ASSERT(NT_SUCCESS(Status
));
429 /* Create the BNO directory */
430 RtlInitUnicodeString(&BnoString
, L
"\\BaseNamedObjects");
431 InitializeObjectAttributes(&ObjectAttributes
,
433 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
436 Status
= NtCreateDirectoryObject(&BaseSrvNamedObjectDirectory
,
437 DIRECTORY_ALL_ACCESS
,
439 ASSERT(NT_SUCCESS(Status
));
441 /* Check if we are session 0 */
444 /* Mark this as a session 0 directory */
445 Status
= NtSetInformationObject(BaseSrvNamedObjectDirectory
,
446 ObjectSessionInformation
,
449 ASSERT(NT_SUCCESS(Status
));
452 /* Check if LUID device maps are enabled */
453 Status
= NtQueryInformationProcess(NtCurrentProcess(),
454 ProcessLUIDDeviceMapsEnabled
,
458 ASSERT(NT_SUCCESS(Status
));
459 BaseStaticServerData
->LUIDDeviceMapsEnabled
= (BOOLEAN
)LuidEnabled
;
460 if (!BaseStaticServerData
->LUIDDeviceMapsEnabled
)
462 /* Make Global point back to BNO */
463 RtlInitUnicodeString(&DirectoryName
, L
"Global");
464 RtlInitUnicodeString(&SymlinkName
, L
"\\BaseNamedObjects");
465 InitializeObjectAttributes(&ObjectAttributes
,
467 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
468 BaseSrvNamedObjectDirectory
,
470 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
471 SYMBOLIC_LINK_ALL_ACCESS
,
474 if ((NT_SUCCESS(Status
)) && SessionId
== 0) NtClose(SymHandle
);
476 /* Make local point back to \Sessions\x\BNO */
477 RtlInitUnicodeString(&DirectoryName
, L
"Local");
478 ASSERT(SessionId
== 0);
479 InitializeObjectAttributes(&ObjectAttributes
,
481 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
482 BaseSrvNamedObjectDirectory
,
484 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
485 SYMBOLIC_LINK_ALL_ACCESS
,
488 if ((NT_SUCCESS(Status
)) && SessionId
== 0) NtClose(SymHandle
);
490 /* Make Session point back to BNOLINKS */
491 RtlInitUnicodeString(&DirectoryName
, L
"Session");
492 RtlInitUnicodeString(&SymlinkName
, L
"\\Sessions\\BNOLINKS");
493 InitializeObjectAttributes(&ObjectAttributes
,
495 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
496 BaseSrvNamedObjectDirectory
,
498 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
499 SYMBOLIC_LINK_ALL_ACCESS
,
502 if ((NT_SUCCESS(Status
)) && SessionId
== 0) NtClose(SymHandle
);
504 /* Create the BNO\Restricted directory and set the restricted DACL */
505 RtlInitUnicodeString(&DirectoryName
, L
"Restricted");
506 Status
= RtlSetDaclSecurityDescriptor(BnoSd
, TRUE
, BnoRestrictedDacl
, FALSE
);
507 ASSERT(NT_SUCCESS(Status
));
508 InitializeObjectAttributes(&ObjectAttributes
,
510 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
511 BaseSrvNamedObjectDirectory
,
513 Status
= NtCreateDirectoryObject(&BaseSrvRestrictedObjectDirectory
,
514 DIRECTORY_ALL_ACCESS
,
516 ASSERT(NT_SUCCESS(Status
));
519 /* Finally, set the pointer */
520 LoadedServerDll
->SharedSection
= BaseStaticServerData
;
523 CSR_SERVER_DLL_INIT(ServerDllInitialization
)
525 /* Setup the DLL Object */
526 LoadedServerDll
->ApiBase
= BASESRV_FIRST_API_NUMBER
;
527 LoadedServerDll
->HighestApiSupported
= BasepMaxApiNumber
;
528 LoadedServerDll
->DispatchTable
= BaseServerApiDispatchTable
;
529 LoadedServerDll
->ValidTable
= BaseServerApiServerValidTable
;
530 LoadedServerDll
->NameTable
= BaseServerApiNameTable
;
531 LoadedServerDll
->SizeOfProcessData
= 0;
532 LoadedServerDll
->ConnectCallback
= NULL
;
533 LoadedServerDll
->DisconnectCallback
= NULL
;
534 LoadedServerDll
->ShutdownProcessCallback
= NULL
;
536 BaseSrvDllInstance
= LoadedServerDll
->ServerHandle
;
538 BaseInitializeStaticServerData(LoadedServerDll
);
540 /* Initialize DOS devices management */
541 BaseInitDefineDosDevice();
544 return STATUS_SUCCESS
;
549 DllMain(IN HINSTANCE hInstanceDll
,
551 IN LPVOID lpReserved
)
553 UNREFERENCED_PARAMETER(hInstanceDll
);
554 UNREFERENCED_PARAMETER(dwReason
);
555 UNREFERENCED_PARAMETER(lpReserved
);
557 if (DLL_PROCESS_DETACH
== dwReason
)
559 BaseCleanupDefineDosDevice();