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
};
141 // UCHAR KeyValueBuffer[0x40];
142 // PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo;
143 // UNICODE_STRING KeyName;
144 // ULONG ProtectionMode = 0;
145 ULONG AclLength
; // , ResultLength;
147 // OBJECT_ATTRIBUTES ObjectAttributes;
149 /* Open the Session Manager Key */
151 RtlInitUnicodeString(&KeyName, SM_REG_KEY);
152 InitializeObjectAttributes(&ObjectAttributes,
154 OBJ_CASE_INSENSITIVE,
157 Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes);
158 if (NT_SUCCESS(Status))
160 /\* Read the key value *\/
161 RtlInitUnicodeString(&KeyName, L"ProtectionMode");
162 Status = NtQueryValueKey(hKey,
164 KeyValuePartialInformation,
166 sizeof(KeyValueBuffer),
169 /\* Make sure it's what we expect it to be *\/
170 KeyValuePartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
171 if ((NT_SUCCESS(Status)) && (KeyValuePartialInfo->Type == REG_DWORD) &&
172 (*(PULONG)KeyValuePartialInfo->Data))
174 /\* Save the Protection Mode *\/
175 // ProtectionMode = *(PULONG)KeyValuePartialInfo->Data;
178 /\* Close the handle *\/
183 /* Allocate the System SID */
184 Status
= RtlAllocateAndInitializeSid(&NtAuthority
,
185 1, SECURITY_LOCAL_SYSTEM_RID
,
188 ASSERT(NT_SUCCESS(Status
));
190 /* Allocate the World SID */
191 Status
= RtlAllocateAndInitializeSid(&WorldAuthority
,
192 1, SECURITY_WORLD_RID
,
195 ASSERT(NT_SUCCESS(Status
));
197 /* Allocate the restricted SID */
198 Status
= RtlAllocateAndInitializeSid(&NtAuthority
,
199 1, SECURITY_RESTRICTED_CODE_RID
,
202 ASSERT(NT_SUCCESS(Status
));
204 /* Allocate one ACL with 3 ACEs each for one SID */
205 AclLength
= sizeof(ACL
) + 3 * sizeof(ACCESS_ALLOWED_ACE
) +
206 RtlLengthSid(SystemSid
) +
207 RtlLengthSid(WorldSid
) +
208 RtlLengthSid(RestrictedSid
);
209 *Dacl
= RtlAllocateHeap(BaseSrvHeap
, 0, AclLength
);
210 ASSERT(*Dacl
!= NULL
);
212 /* Set the correct header fields */
213 Status
= RtlCreateAcl(*Dacl
, AclLength
, ACL_REVISION2
);
214 ASSERT(NT_SUCCESS(Status
));
216 /* Give the appropriate rights to each SID */
217 /* FIXME: Should check SessionId/ProtectionMode */
218 Status
= RtlAddAccessAllowedAce(*Dacl
, ACL_REVISION2
, DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
| DIRECTORY_CREATE_OBJECT
| DIRECTORY_CREATE_SUBDIRECTORY
| READ_CONTROL
, WorldSid
);
219 ASSERT(NT_SUCCESS(Status
));
220 Status
= RtlAddAccessAllowedAce(*Dacl
, ACL_REVISION2
, DIRECTORY_ALL_ACCESS
, SystemSid
);
221 ASSERT(NT_SUCCESS(Status
));
222 Status
= RtlAddAccessAllowedAce(*Dacl
, ACL_REVISION2
, DIRECTORY_TRAVERSE
, RestrictedSid
);
223 ASSERT(NT_SUCCESS(Status
));
225 /* Now allocate the restricted DACL */
226 *RestrictedDacl
= RtlAllocateHeap(BaseSrvHeap
, 0, AclLength
);
227 ASSERT(*RestrictedDacl
!= NULL
);
230 Status
= RtlCreateAcl(*RestrictedDacl
, AclLength
, ACL_REVISION2
);
231 ASSERT(NT_SUCCESS(Status
));
233 /* And add the same ACEs as before */
234 /* FIXME: Not really fully correct */
235 Status
= RtlAddAccessAllowedAce(*RestrictedDacl
, ACL_REVISION2
, DIRECTORY_QUERY
| DIRECTORY_TRAVERSE
| DIRECTORY_CREATE_OBJECT
| DIRECTORY_CREATE_SUBDIRECTORY
| READ_CONTROL
, WorldSid
);
236 ASSERT(NT_SUCCESS(Status
));
237 Status
= RtlAddAccessAllowedAce(*RestrictedDacl
, ACL_REVISION2
, DIRECTORY_ALL_ACCESS
, SystemSid
);
238 ASSERT(NT_SUCCESS(Status
));
239 Status
= RtlAddAccessAllowedAce(*RestrictedDacl
, ACL_REVISION2
, DIRECTORY_TRAVERSE
, RestrictedSid
);
240 ASSERT(NT_SUCCESS(Status
));
242 /* The SIDs are captured, can free them now */
243 RtlFreeSid(RestrictedSid
);
244 RtlFreeSid(WorldSid
);
245 RtlFreeSid(SystemSid
);
251 BaseInitializeStaticServerData(IN PCSR_SERVER_DLL LoadedServerDll
)
254 WCHAR Buffer
[MAX_PATH
];
256 UNICODE_STRING SystemRootString
;
257 UNICODE_STRING UnexpandedSystemRootString
= RTL_CONSTANT_STRING(L
"%SystemRoot%");
258 UNICODE_STRING BaseSrvCSDString
;
259 UNICODE_STRING BaseSrvWindowsDirectory
;
260 UNICODE_STRING BaseSrvWindowsSystemDirectory
;
261 UNICODE_STRING BnoString
;
262 OBJECT_ATTRIBUTES ObjectAttributes
;
264 HANDLE BaseSrvNamedObjectDirectory
;
265 HANDLE BaseSrvRestrictedObjectDirectory
;
266 PACL BnoDacl
, BnoRestrictedDacl
;
267 PSECURITY_DESCRIPTOR BnoSd
;
269 UNICODE_STRING DirectoryName
, SymlinkName
;
271 RTL_QUERY_REGISTRY_TABLE BaseServerRegistryConfigurationTable
[2] =
275 RTL_QUERY_REGISTRY_DIRECT
,
284 /* Initialize the memory */
285 BaseSrvHeap
= RtlGetProcessHeap(); // Initialize our own heap.
286 BaseSrvSharedHeap
= LoadedServerDll
->SharedSection
; // Get the CSR shared heap.
288 /* Get the session ID */
289 SessionId
= NtCurrentPeb()->SessionId
;
291 /* Get the Windows directory */
292 RtlInitEmptyUnicodeString(&SystemRootString
, Buffer
, sizeof(Buffer
));
293 Status
= RtlExpandEnvironmentStrings_U(NULL
,
294 &UnexpandedSystemRootString
,
297 ASSERT(NT_SUCCESS(Status
));
299 /* Create the base directory */
300 Buffer
[SystemRootString
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
301 Status
= RtlCreateUnicodeString(&BaseSrvWindowsDirectory
,
302 SystemRootString
.Buffer
);
303 ASSERT(NT_SUCCESS(Status
));
305 /* Create the system directory */
306 wcscat(SystemRootString
.Buffer
, L
"\\System32");
307 Status
= RtlCreateUnicodeString(&BaseSrvWindowsSystemDirectory
,
308 SystemRootString
.Buffer
);
309 ASSERT(NT_SUCCESS(Status
));
311 /* FIXME: Check Session ID */
312 wcscpy(Buffer
, L
"\\BaseNamedObjects");
313 RtlInitUnicodeString(&BnoString
, Buffer
);
315 /* Allocate the server data */
316 BaseStaticServerData
= RtlAllocateHeap(BaseSrvSharedHeap
,
318 sizeof(BASE_STATIC_SERVER_DATA
));
319 ASSERT(BaseStaticServerData
!= NULL
);
321 /* Process timezone information */
322 BaseStaticServerData
->TermsrvClientTimeZoneId
= TIME_ZONE_ID_INVALID
;
323 BaseStaticServerData
->TermsrvClientTimeZoneChangeNum
= 0;
324 Status
= NtQuerySystemInformation(SystemTimeOfDayInformation
,
325 &BaseStaticServerData
->TimeOfDay
,
326 sizeof(BaseStaticServerData
->TimeOfDay
),
328 ASSERT(NT_SUCCESS(Status
));
330 /* Make a shared heap copy of the Windows directory */
331 BaseStaticServerData
->WindowsDirectory
= BaseSrvWindowsDirectory
;
332 HeapBuffer
= RtlAllocateHeap(BaseSrvSharedHeap
,
334 BaseSrvWindowsDirectory
.MaximumLength
);
336 RtlCopyMemory(HeapBuffer
,
337 BaseStaticServerData
->WindowsDirectory
.Buffer
,
338 BaseSrvWindowsDirectory
.MaximumLength
);
339 BaseStaticServerData
->WindowsDirectory
.Buffer
= HeapBuffer
;
341 /* Make a shared heap copy of the System directory */
342 BaseStaticServerData
->WindowsSystemDirectory
= BaseSrvWindowsSystemDirectory
;
343 HeapBuffer
= RtlAllocateHeap(BaseSrvSharedHeap
,
345 BaseSrvWindowsSystemDirectory
.MaximumLength
);
347 RtlCopyMemory(HeapBuffer
,
348 BaseStaticServerData
->WindowsSystemDirectory
.Buffer
,
349 BaseSrvWindowsSystemDirectory
.MaximumLength
);
350 BaseStaticServerData
->WindowsSystemDirectory
.Buffer
= HeapBuffer
;
352 /* This string is not used */
353 RtlInitEmptyUnicodeString(&BaseStaticServerData
->WindowsSys32x86Directory
,
357 /* Make a shared heap copy of the BNO directory */
358 BaseStaticServerData
->NamedObjectDirectory
= BnoString
;
359 BaseStaticServerData
->NamedObjectDirectory
.MaximumLength
= BnoString
.Length
+
360 sizeof(UNICODE_NULL
);
361 HeapBuffer
= RtlAllocateHeap(BaseSrvSharedHeap
,
363 BaseStaticServerData
->NamedObjectDirectory
.MaximumLength
);
365 RtlCopyMemory(HeapBuffer
,
366 BaseStaticServerData
->NamedObjectDirectory
.Buffer
,
367 BaseStaticServerData
->NamedObjectDirectory
.MaximumLength
);
368 BaseStaticServerData
->NamedObjectDirectory
.Buffer
= HeapBuffer
;
371 * Confirmed that in Windows, CSDNumber and RCNumber are actually Length
372 * and MaximumLength of the CSD String, since the same UNICODE_STRING is
373 * being queried twice, the first time as a ULONG!
375 * Somehow, in Windows this doesn't cause a buffer overflow, but it might
376 * in ReactOS, so this code is disabled until someone figures out WTF.
378 BaseStaticServerData
->CSDNumber
= 0;
379 BaseStaticServerData
->RCNumber
= 0;
381 /* Initialize the CSD string and query its value from the registry */
382 RtlInitEmptyUnicodeString(&BaseSrvCSDString
, Buffer
, sizeof(Buffer
));
383 Status
= RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT
,
385 BaseServerRegistryConfigurationTable
,
388 if (NT_SUCCESS(Status
))
390 /* Copy into the shared buffer */
391 wcsncpy(BaseStaticServerData
->CSDVersion
,
392 BaseSrvCSDString
.Buffer
,
393 BaseSrvCSDString
.Length
/ sizeof(WCHAR
));
397 /* NULL-terminate to indicate nothing is there */
398 BaseStaticServerData
->CSDVersion
[0] = UNICODE_NULL
;
401 /* Cache the system information */
402 Status
= NtQuerySystemInformation(SystemBasicInformation
,
403 &BaseStaticServerData
->SysInfo
,
404 sizeof(BaseStaticServerData
->SysInfo
),
406 ASSERT(NT_SUCCESS(Status
));
408 /* FIXME: Should query the registry for these */
409 BaseStaticServerData
->DefaultSeparateVDM
= FALSE
;
410 BaseStaticServerData
->IsWowTaskReady
= FALSE
;
412 /* Allocate a security descriptor and create it */
413 BnoSd
= RtlAllocateHeap(BaseSrvHeap
, 0, 1024);
415 Status
= RtlCreateSecurityDescriptor(BnoSd
, SECURITY_DESCRIPTOR_REVISION
);
416 ASSERT(NT_SUCCESS(Status
));
418 /* Create the BNO and \Restricted DACLs */
419 Status
= CreateBaseAcls(&BnoDacl
, &BnoRestrictedDacl
);
420 ASSERT(NT_SUCCESS(Status
));
422 /* Set the BNO DACL as active for now */
423 Status
= RtlSetDaclSecurityDescriptor(BnoSd
, TRUE
, BnoDacl
, FALSE
);
424 ASSERT(NT_SUCCESS(Status
));
426 /* Create the BNO directory */
427 RtlInitUnicodeString(&BnoString
, L
"\\BaseNamedObjects");
428 InitializeObjectAttributes(&ObjectAttributes
,
430 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
433 Status
= NtCreateDirectoryObject(&BaseSrvNamedObjectDirectory
,
434 DIRECTORY_ALL_ACCESS
,
436 ASSERT(NT_SUCCESS(Status
));
438 /* Check if we are session 0 */
441 /* Mark this as a session 0 directory */
442 Status
= NtSetInformationObject(BaseSrvNamedObjectDirectory
,
443 ObjectSessionInformation
,
446 ASSERT(NT_SUCCESS(Status
));
449 /* Check if LUID device maps are enabled */
450 Status
= NtQueryInformationProcess(NtCurrentProcess(),
451 ProcessLUIDDeviceMapsEnabled
,
455 ASSERT(NT_SUCCESS(Status
));
456 BaseStaticServerData
->LUIDDeviceMapsEnabled
= LuidEnabled
;
457 if (!BaseStaticServerData
->LUIDDeviceMapsEnabled
)
459 /* Make Global point back to BNO */
460 RtlInitUnicodeString(&DirectoryName
, L
"Global");
461 RtlInitUnicodeString(&SymlinkName
, L
"\\BaseNamedObjects");
462 InitializeObjectAttributes(&ObjectAttributes
,
464 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
465 BaseSrvNamedObjectDirectory
,
467 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
468 SYMBOLIC_LINK_ALL_ACCESS
,
471 if ((NT_SUCCESS(Status
)) && SessionId
== 0) NtClose(SymHandle
);
473 /* Make local point back to \Sessions\x\BNO */
474 RtlInitUnicodeString(&DirectoryName
, L
"Local");
475 ASSERT(SessionId
== 0);
476 InitializeObjectAttributes(&ObjectAttributes
,
478 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
479 BaseSrvNamedObjectDirectory
,
481 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
482 SYMBOLIC_LINK_ALL_ACCESS
,
485 if ((NT_SUCCESS(Status
)) && SessionId
== 0) NtClose(SymHandle
);
487 /* Make Session point back to BNOLINKS */
488 RtlInitUnicodeString(&DirectoryName
, L
"Session");
489 RtlInitUnicodeString(&SymlinkName
, L
"\\Sessions\\BNOLINKS");
490 InitializeObjectAttributes(&ObjectAttributes
,
492 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
493 BaseSrvNamedObjectDirectory
,
495 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
496 SYMBOLIC_LINK_ALL_ACCESS
,
499 if ((NT_SUCCESS(Status
)) && SessionId
== 0) NtClose(SymHandle
);
501 /* Create the BNO\Restricted directory and set the restricted DACL */
502 RtlInitUnicodeString(&DirectoryName
, L
"Restricted");
503 Status
= RtlSetDaclSecurityDescriptor(BnoSd
, TRUE
, BnoRestrictedDacl
, FALSE
);
504 ASSERT(NT_SUCCESS(Status
));
505 InitializeObjectAttributes(&ObjectAttributes
,
507 OBJ_OPENIF
| OBJ_PERMANENT
| OBJ_CASE_INSENSITIVE
,
508 BaseSrvNamedObjectDirectory
,
510 Status
= NtCreateDirectoryObject(&BaseSrvRestrictedObjectDirectory
,
511 DIRECTORY_ALL_ACCESS
,
513 ASSERT(NT_SUCCESS(Status
));
516 /* Finally, set the pointer */
517 LoadedServerDll
->SharedSection
= BaseStaticServerData
;
520 CSR_SERVER_DLL_INIT(ServerDllInitialization
)
522 /* Setup the DLL Object */
523 LoadedServerDll
->ApiBase
= BASESRV_FIRST_API_NUMBER
; // ApiNumberBase
524 LoadedServerDll
->HighestApiSupported
= BasepMaxApiNumber
; // MaxApiNumber
525 LoadedServerDll
->DispatchTable
= BaseServerApiDispatchTable
;
526 LoadedServerDll
->ValidTable
= BaseServerApiServerValidTable
;
527 LoadedServerDll
->NameTable
= BaseServerApiNameTable
;
528 LoadedServerDll
->SizeOfProcessData
= 0;
529 LoadedServerDll
->ConnectCallback
= NULL
;
530 LoadedServerDll
->DisconnectCallback
= NULL
;
531 LoadedServerDll
->ShutdownProcessCallback
= NULL
;
533 BaseSrvDllInstance
= LoadedServerDll
->ServerHandle
;
535 BaseInitializeStaticServerData(LoadedServerDll
);
537 /* Initialize DOS devices management */
538 BaseInitDefineDosDevice();
541 return STATUS_SUCCESS
;
546 DllMain(IN HINSTANCE hInstanceDll
,
548 IN LPVOID lpReserved
)
550 UNREFERENCED_PARAMETER(hInstanceDll
);
551 UNREFERENCED_PARAMETER(dwReason
);
552 UNREFERENCED_PARAMETER(lpReserved
);
554 if (DLL_PROCESS_DETACH
== dwReason
)
556 BaseCleanupDefineDosDevice();