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
, // BasepDebugProcess
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",
128 "BaseRegisterThread",
129 "BaseNlsGetUserInfo",
133 /* FUNCTIONS ******************************************************************/
137 CreateBaseAcls(OUT PACL
* Dacl
,
138 OUT PACL
* RestrictedDacl
)
140 PSID SystemSid
, WorldSid
, RestrictedSid
;
141 SID_IDENTIFIER_AUTHORITY NtAuthority
= {SECURITY_NT_AUTHORITY
};
142 SID_IDENTIFIER_AUTHORITY WorldAuthority
= {SECURITY_WORLD_SID_AUTHORITY
};
145 UCHAR KeyValueBuffer
[0x40];
146 PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo
;
147 UNICODE_STRING KeyName
;
148 ULONG ProtectionMode
= 0;
154 OBJECT_ATTRIBUTES ObjectAttributes
;
156 /* Open the Session Manager Key */
157 RtlInitUnicodeString(&KeyName
, SM_REG_KEY
);
158 InitializeObjectAttributes(&ObjectAttributes
,
160 OBJ_CASE_INSENSITIVE
,
163 Status
= NtOpenKey(&hKey
, KEY_READ
, &ObjectAttributes
);
164 if (NT_SUCCESS(Status
))
166 /* Read the key value */
167 RtlInitUnicodeString(&KeyName
, L
"ProtectionMode");
168 Status
= NtQueryValueKey(hKey
,
170 KeyValuePartialInformation
,
172 sizeof(KeyValueBuffer
),
175 /* Make sure it's what we expect it to be */
176 KeyValuePartialInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)KeyValueBuffer
;
177 if ((NT_SUCCESS(Status
)) && (KeyValuePartialInfo
->Type
== REG_DWORD
) &&
178 (*(PULONG
)KeyValuePartialInfo
->Data
))
180 /* Save the Protection Mode */
181 ProtectionMode
= *(PULONG
)KeyValuePartialInfo
->Data
;
184 /* Close the handle */
189 /* Allocate the System SID */
190 Status
= RtlAllocateAndInitializeSid(&NtAuthority
,
191 1, SECURITY_LOCAL_SYSTEM_RID
,
194 ASSERT(NT_SUCCESS(Status
));
196 /* Allocate the World SID */
197 Status
= RtlAllocateAndInitializeSid(&WorldAuthority
,
198 1, SECURITY_WORLD_RID
,
201 ASSERT(NT_SUCCESS(Status
));
203 /* Allocate the restricted SID */
204 Status
= RtlAllocateAndInitializeSid(&NtAuthority
,
205 1, SECURITY_RESTRICTED_CODE_RID
,
208 ASSERT(NT_SUCCESS(Status
));
210 /* Allocate one ACL with 3 ACEs each for one SID */
211 AclLength
= sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) +
212 RtlLengthSid(SystemSid
) +
213 RtlLengthSid(WorldSid
) +
214 RtlLengthSid(RestrictedSid
);
215 *Dacl
= RtlAllocateHeap(BaseSrvHeap
, 0, AclLength
);
216 ASSERT(*Dacl
!= NULL
);
218 /* Set the correct header fields */
219 Status
= RtlCreateAcl(*Dacl
, AclLength
, ACL_REVISION2
);
220 ASSERT(NT_SUCCESS(Status
));
222 /* Give the appropriate rights to each SID */
223 /* FIXME: Should check SessionId/ProtectionMode */
224 Status
= RtlAddAccessAllowedAce(*Dacl
, ACL_REVISION2
, DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
| DIRECTORY_CREATE_OBJECT
| DIRECTORY_CREATE_SUBDIRECTORY
| READ_CONTROL
, WorldSid
);
225 ASSERT(NT_SUCCESS(Status
));
226 Status
= RtlAddAccessAllowedAce(*Dacl
, ACL_REVISION2
, DIRECTORY_ALL_ACCESS
, SystemSid
);
227 ASSERT(NT_SUCCESS(Status
));
228 Status
= RtlAddAccessAllowedAce(*Dacl
, ACL_REVISION2
, DIRECTORY_TRAVERSE
, RestrictedSid
);
229 ASSERT(NT_SUCCESS(Status
));
231 /* Now allocate the restricted DACL */
232 *RestrictedDacl
= RtlAllocateHeap(BaseSrvHeap
, 0, AclLength
);
233 ASSERT(*RestrictedDacl
!= NULL
);
236 Status
= RtlCreateAcl(*RestrictedDacl
, AclLength
, ACL_REVISION2
);
237 ASSERT(NT_SUCCESS(Status
));
239 /* And add the same ACEs as before */
240 /* FIXME: Not really fully correct */
241 Status
= RtlAddAccessAllowedAce(*RestrictedDacl
, ACL_REVISION2
, DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
| DIRECTORY_CREATE_OBJECT
| DIRECTORY_CREATE_SUBDIRECTORY
| READ_CONTROL
, WorldSid
);
242 ASSERT(NT_SUCCESS(Status
));
243 Status
= RtlAddAccessAllowedAce(*RestrictedDacl
, ACL_REVISION2
, DIRECTORY_ALL_ACCESS
, SystemSid
);
244 ASSERT(NT_SUCCESS(Status
));
245 Status
= RtlAddAccessAllowedAce(*RestrictedDacl
, ACL_REVISION2
, DIRECTORY_TRAVERSE
, RestrictedSid
);
246 ASSERT(NT_SUCCESS(Status
));
248 /* The SIDs are captured, can free them now */
249 RtlFreeSid(RestrictedSid
);
250 RtlFreeSid(WorldSid
);
251 RtlFreeSid(SystemSid
);
257 BaseInitializeStaticServerData(IN PCSR_SERVER_DLL LoadedServerDll
)
260 WCHAR Buffer
[MAX_PATH
];
262 UNICODE_STRING SystemRootString
;
263 UNICODE_STRING UnexpandedSystemRootString
= RTL_CONSTANT_STRING(L
"%SystemRoot%");
264 UNICODE_STRING BaseSrvCSDString
;
265 UNICODE_STRING BaseSrvWindowsDirectory
;
266 UNICODE_STRING BaseSrvWindowsSystemDirectory
;
267 UNICODE_STRING BnoString
;
268 OBJECT_ATTRIBUTES ObjectAttributes
;
270 HANDLE BaseSrvNamedObjectDirectory
;
271 HANDLE BaseSrvRestrictedObjectDirectory
;
272 PACL BnoDacl
, BnoRestrictedDacl
;
273 PSECURITY_DESCRIPTOR BnoSd
;
275 UNICODE_STRING DirectoryName
, SymlinkName
;
277 RTL_QUERY_REGISTRY_TABLE BaseServerRegistryConfigurationTable
[2] =
281 RTL_QUERY_REGISTRY_DIRECT
,
290 /* Initialize the memory */
291 BaseSrvHeap
= RtlGetProcessHeap(); // Initialize our own heap.
292 BaseSrvSharedHeap
= LoadedServerDll
->SharedSection
; // Get the CSR shared heap.
294 /* Get the session ID */
295 SessionId
= NtCurrentPeb()->SessionId
;
297 /* Get the Windows directory */
298 RtlInitEmptyUnicodeString(&SystemRootString
, Buffer
, sizeof(Buffer
));
299 Status
= RtlExpandEnvironmentStrings_U(NULL
,
300 &UnexpandedSystemRootString
,
303 ASSERT(NT_SUCCESS(Status
));
305 /* Create the base directory */
306 Buffer
[SystemRootString
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
307 Status
= RtlCreateUnicodeString(&BaseSrvWindowsDirectory
,
308 SystemRootString
.Buffer
);
309 ASSERT(NT_SUCCESS(Status
));
311 /* Create the system directory */
312 wcscat(SystemRootString
.Buffer
, L
"\\System32");
313 Status
= RtlCreateUnicodeString(&BaseSrvWindowsSystemDirectory
,
314 SystemRootString
.Buffer
);
315 ASSERT(NT_SUCCESS(Status
));
317 /* Create the kernel32 path */
318 wcscat(SystemRootString
.Buffer
, L
"\\kernel32.dll");
319 Status
= RtlCreateUnicodeString(&BaseSrvKernel32DllPath
,
320 SystemRootString
.Buffer
);
321 ASSERT(NT_SUCCESS(Status
));
323 /* FIXME: Check Session ID */
324 wcscpy(Buffer
, L
"\\BaseNamedObjects");
325 RtlInitUnicodeString(&BnoString
, Buffer
);
327 /* Allocate the server data */
328 BaseStaticServerData
= RtlAllocateHeap(BaseSrvSharedHeap
,
330 sizeof(BASE_STATIC_SERVER_DATA
));
331 ASSERT(BaseStaticServerData
!= NULL
);
333 /* Process timezone information */
334 BaseStaticServerData
->TermsrvClientTimeZoneId
= TIME_ZONE_ID_INVALID
;
335 BaseStaticServerData
->TermsrvClientTimeZoneChangeNum
= 0;
336 Status
= NtQuerySystemInformation(SystemTimeOfDayInformation
,
337 &BaseStaticServerData
->TimeOfDay
,
338 sizeof(BaseStaticServerData
->TimeOfDay
),
340 ASSERT(NT_SUCCESS(Status
));
342 /* Make a shared heap copy of the Windows directory */
343 BaseStaticServerData
->WindowsDirectory
= BaseSrvWindowsDirectory
;
344 HeapBuffer
= RtlAllocateHeap(BaseSrvSharedHeap
,
346 BaseSrvWindowsDirectory
.MaximumLength
);
348 RtlCopyMemory(HeapBuffer
,
349 BaseStaticServerData
->WindowsDirectory
.Buffer
,
350 BaseSrvWindowsDirectory
.MaximumLength
);
351 BaseStaticServerData
->WindowsDirectory
.Buffer
= HeapBuffer
;
353 /* Make a shared heap copy of the System directory */
354 BaseStaticServerData
->WindowsSystemDirectory
= BaseSrvWindowsSystemDirectory
;
355 HeapBuffer
= RtlAllocateHeap(BaseSrvSharedHeap
,
357 BaseSrvWindowsSystemDirectory
.MaximumLength
);
359 RtlCopyMemory(HeapBuffer
,
360 BaseStaticServerData
->WindowsSystemDirectory
.Buffer
,
361 BaseSrvWindowsSystemDirectory
.MaximumLength
);
362 BaseStaticServerData
->WindowsSystemDirectory
.Buffer
= HeapBuffer
;
364 /* This string is not used */
365 RtlInitEmptyUnicodeString(&BaseStaticServerData
->WindowsSys32x86Directory
,
369 /* Make a shared heap copy of the BNO directory */
370 BaseStaticServerData
->NamedObjectDirectory
= BnoString
;
371 BaseStaticServerData
->NamedObjectDirectory
.MaximumLength
= BnoString
.Length
+
372 sizeof(UNICODE_NULL
);
373 HeapBuffer
= RtlAllocateHeap(BaseSrvSharedHeap
,
375 BaseStaticServerData
->NamedObjectDirectory
.MaximumLength
);
377 RtlCopyMemory(HeapBuffer
,
378 BaseStaticServerData
->NamedObjectDirectory
.Buffer
,
379 BaseStaticServerData
->NamedObjectDirectory
.MaximumLength
);
380 BaseStaticServerData
->NamedObjectDirectory
.Buffer
= HeapBuffer
;
383 * Confirmed that in Windows, CSDNumber and RCNumber are actually Length
384 * and MaximumLength of the CSD String, since the same UNICODE_STRING is
385 * being queried twice, the first time as a ULONG!
387 * Somehow, in Windows this doesn't cause a buffer overflow, but it might
388 * in ReactOS, so this code is disabled until someone figures out WTF.
390 BaseStaticServerData
->CSDNumber
= 0;
391 BaseStaticServerData
->RCNumber
= 0;
393 /* Initialize the CSD string and query its value from the registry */
394 RtlInitEmptyUnicodeString(&BaseSrvCSDString
, Buffer
, sizeof(Buffer
));
395 Status
= RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT
,
397 BaseServerRegistryConfigurationTable
,
400 if (NT_SUCCESS(Status
))
402 /* Copy into the shared buffer */
403 wcsncpy(BaseStaticServerData
->CSDVersion
,
404 BaseSrvCSDString
.Buffer
,
405 BaseSrvCSDString
.Length
/ sizeof(WCHAR
));
409 /* NULL-terminate to indicate nothing is there */
410 BaseStaticServerData
->CSDVersion
[0] = UNICODE_NULL
;
413 /* Cache the system information */
414 Status
= NtQuerySystemInformation(SystemBasicInformation
,
415 &BaseStaticServerData
->SysInfo
,
416 sizeof(BaseStaticServerData
->SysInfo
),
418 ASSERT(NT_SUCCESS(Status
));
420 /* FIXME: Should query the registry for these */
421 BaseStaticServerData
->DefaultSeparateVDM
= FALSE
;
422 BaseStaticServerData
->IsWowTaskReady
= FALSE
;
424 /* Allocate a security descriptor and create it */
425 BnoSd
= RtlAllocateHeap(BaseSrvHeap
, 0, 1024);
427 Status
= RtlCreateSecurityDescriptor(BnoSd
, SECURITY_DESCRIPTOR_REVISION
);
428 ASSERT(NT_SUCCESS(Status
));
430 /* Create the BNO and \Restricted DACLs */
431 Status
= CreateBaseAcls(&BnoDacl
, &BnoRestrictedDacl
);
432 ASSERT(NT_SUCCESS(Status
));
434 /* Set the BNO DACL as active for now */
435 Status
= RtlSetDaclSecurityDescriptor(BnoSd
, TRUE
, BnoDacl
, FALSE
);
436 ASSERT(NT_SUCCESS(Status
));
438 /* Create the BNO directory */
439 RtlInitUnicodeString(&BnoString
, L
"\\BaseNamedObjects");
440 InitializeObjectAttributes(&ObjectAttributes
,
442 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
445 Status
= NtCreateDirectoryObject(&BaseSrvNamedObjectDirectory
,
446 DIRECTORY_ALL_ACCESS
,
448 ASSERT(NT_SUCCESS(Status
));
450 /* Check if we are session 0 */
453 /* Mark this as a session 0 directory */
454 Status
= NtSetInformationObject(BaseSrvNamedObjectDirectory
,
455 ObjectSessionInformation
,
458 ASSERT(NT_SUCCESS(Status
));
461 /* Check if LUID device maps are enabled */
462 Status
= NtQueryInformationProcess(NtCurrentProcess(),
463 ProcessLUIDDeviceMapsEnabled
,
467 ASSERT(NT_SUCCESS(Status
));
468 BaseStaticServerData
->LUIDDeviceMapsEnabled
= (BOOLEAN
)LuidEnabled
;
469 if (!BaseStaticServerData
->LUIDDeviceMapsEnabled
)
471 /* Make Global point back to BNO */
472 RtlInitUnicodeString(&DirectoryName
, L
"Global");
473 RtlInitUnicodeString(&SymlinkName
, L
"\\BaseNamedObjects");
474 InitializeObjectAttributes(&ObjectAttributes
,
476 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
477 BaseSrvNamedObjectDirectory
,
479 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
480 SYMBOLIC_LINK_ALL_ACCESS
,
483 if ((NT_SUCCESS(Status
)) && SessionId
== 0) NtClose(SymHandle
);
485 /* Make local point back to \Sessions\x\BNO */
486 RtlInitUnicodeString(&DirectoryName
, L
"Local");
487 ASSERT(SessionId
== 0);
488 InitializeObjectAttributes(&ObjectAttributes
,
490 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
491 BaseSrvNamedObjectDirectory
,
493 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
494 SYMBOLIC_LINK_ALL_ACCESS
,
497 if ((NT_SUCCESS(Status
)) && SessionId
== 0) NtClose(SymHandle
);
499 /* Make Session point back to BNOLINKS */
500 RtlInitUnicodeString(&DirectoryName
, L
"Session");
501 RtlInitUnicodeString(&SymlinkName
, L
"\\Sessions\\BNOLINKS");
502 InitializeObjectAttributes(&ObjectAttributes
,
504 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
505 BaseSrvNamedObjectDirectory
,
507 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
508 SYMBOLIC_LINK_ALL_ACCESS
,
511 if ((NT_SUCCESS(Status
)) && SessionId
== 0) NtClose(SymHandle
);
513 /* Create the BNO\Restricted directory and set the restricted DACL */
514 RtlInitUnicodeString(&DirectoryName
, L
"Restricted");
515 Status
= RtlSetDaclSecurityDescriptor(BnoSd
, TRUE
, BnoRestrictedDacl
, FALSE
);
516 ASSERT(NT_SUCCESS(Status
));
517 InitializeObjectAttributes(&ObjectAttributes
,
519 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
520 BaseSrvNamedObjectDirectory
,
522 Status
= NtCreateDirectoryObject(&BaseSrvRestrictedObjectDirectory
,
523 DIRECTORY_ALL_ACCESS
,
525 ASSERT(NT_SUCCESS(Status
));
528 /* Finally, set the pointer */
529 LoadedServerDll
->SharedSection
= BaseStaticServerData
;
532 CSR_SERVER_DLL_INIT(ServerDllInitialization
)
534 /* Setup the DLL Object */
535 LoadedServerDll
->ApiBase
= BASESRV_FIRST_API_NUMBER
;
536 LoadedServerDll
->HighestApiSupported
= BasepMaxApiNumber
;
537 LoadedServerDll
->DispatchTable
= BaseServerApiDispatchTable
;
538 LoadedServerDll
->ValidTable
= BaseServerApiServerValidTable
;
539 LoadedServerDll
->NameTable
= BaseServerApiNameTable
;
540 LoadedServerDll
->SizeOfProcessData
= 0;
541 LoadedServerDll
->ConnectCallback
= NULL
;
542 LoadedServerDll
->DisconnectCallback
= NULL
;
543 LoadedServerDll
->ShutdownProcessCallback
= NULL
;
545 BaseSrvDllInstance
= LoadedServerDll
->ServerHandle
;
547 BaseInitializeStaticServerData(LoadedServerDll
);
549 /* Initialize DOS devices management */
550 BaseInitDefineDosDevice();
553 return STATUS_SUCCESS
;
558 DllMain(IN HINSTANCE hInstanceDll
,
560 IN LPVOID lpReserved
)
562 UNREFERENCED_PARAMETER(hInstanceDll
);
563 UNREFERENCED_PARAMETER(dwReason
);
564 UNREFERENCED_PARAMETER(lpReserved
);
566 if (DLL_PROCESS_DETACH
== dwReason
)
568 BaseCleanupDefineDosDevice();