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
] =
33 // BaseSrvDebugProcess,
35 // BaseSrvUpdateVDMEntry,
36 // BaseSrvGetNextVDMCommand,
39 // BaseSrvGetVDMExitCode,
40 // BaseSrvSetReenterCount,
41 BaseSrvSetProcessShutdownParam
,
42 BaseSrvGetProcessShutdownParam
,
43 // BaseSrvNlsSetUserInfo,
44 // BaseSrvNlsSetMultipleUserInfo,
45 // BaseSrvNlsCreateSection,
46 // BaseSrvSetVDMCurDirs,
47 // BaseSrvGetVDMCurDirs,
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
] =
101 // "BaseDebugProcess",
103 // "BaseUpdateVDMEntry",
104 // "BaseGetNextVDMCommand",
107 // "BaseGetVDMExitCode",
108 // "BaseSetReenterCount",
109 "BaseSetProcessShutdownParam",
110 "BaseGetProcessShutdownParam",
111 // "BaseNlsSetUserInfo",
112 // "BaseNlsSetMultipleUserInfo",
113 // "BaseNlsCreateSection",
114 // "BaseSetVDMCurDirs",
115 // "BaseGetVDMCurDirs",
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();