[BASESRV]
[reactos.git] / subsystems / win / basesrv / init.c
1 /*
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)
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "basesrv.h"
12 #include "vdm.h"
13
14 #include <winreg.h>
15
16 #define NDEBUG
17 #include <debug.h>
18
19 #include "api.h"
20
21 /* GLOBALS ********************************************************************/
22
23 HANDLE BaseSrvDllInstance = NULL;
24 extern UNICODE_STRING BaseSrvKernel32DllPath;
25
26 /* Memory */
27 HANDLE BaseSrvHeap = NULL; // Our own heap.
28 HANDLE BaseSrvSharedHeap = NULL; // Shared heap with CSR. (CsrSrvSharedSectionHeap)
29 PBASE_STATIC_SERVER_DATA BaseStaticServerData = NULL; // Data that we can share amongst processes. Initialized inside BaseSrvSharedHeap.
30
31 PINIFILE_MAPPING BaseSrvIniFileMapping;
32
33 // Windows Server 2003 table from http://j00ru.vexillium.org/csrss_list/api_list.html#Windows_2k3
34 PCSR_API_ROUTINE BaseServerApiDispatchTable[BasepMaxApiNumber - BASESRV_FIRST_API_NUMBER] =
35 {
36 BaseSrvCreateProcess,
37 BaseSrvCreateThread,
38 BaseSrvGetTempFile,
39 BaseSrvExitProcess,
40 BaseSrvDebugProcess,
41 BaseSrvCheckVDM,
42 BaseSrvUpdateVDMEntry,
43 BaseSrvGetNextVDMCommand,
44 BaseSrvExitVDM,
45 BaseSrvIsFirstVDM,
46 BaseSrvGetVDMExitCode,
47 BaseSrvSetReenterCount,
48 BaseSrvSetProcessShutdownParam,
49 BaseSrvGetProcessShutdownParam,
50 BaseSrvNlsSetUserInfo,
51 BaseSrvNlsSetMultipleUserInfo,
52 BaseSrvNlsCreateSection,
53 BaseSrvSetVDMCurDirs,
54 BaseSrvGetVDMCurDirs,
55 BaseSrvBatNotification,
56 BaseSrvRegisterWowExec,
57 BaseSrvSoundSentryNotification,
58 BaseSrvRefreshIniFileMapping,
59 BaseSrvDefineDosDevice,
60 BaseSrvSetTermsrvAppInstallMode,
61 BaseSrvNlsUpdateCacheCount,
62 BaseSrvSetTermsrvClientTimeZone,
63 BaseSrvSxsCreateActivationContext,
64 BaseSrvUnknown,
65 BaseSrvRegisterThread,
66 BaseSrvNlsGetUserInfo,
67 };
68
69 BOOLEAN BaseServerApiServerValidTable[BasepMaxApiNumber - BASESRV_FIRST_API_NUMBER] =
70 {
71 TRUE, // BaseSrvCreateProcess
72 TRUE, // BaseSrvCreateThread
73 TRUE, // BaseSrvGetTempFile
74 FALSE, // BaseSrvExitProcess
75 FALSE, // BaseSrvDebugProcess
76 TRUE, // BaseSrvCheckVDM
77 TRUE, // BaseSrvUpdateVDMEntry
78 TRUE, // BaseSrvGetNextVDMCommand
79 TRUE, // BaseSrvExitVDM
80 TRUE, // BaseSrvIsFirstVDM
81 TRUE, // BaseSrvGetVDMExitCode
82 TRUE, // BaseSrvSetReenterCount
83 TRUE, // BaseSrvSetProcessShutdownParam
84 TRUE, // BaseSrvGetProcessShutdownParam
85 TRUE, // BaseSrvNlsSetUserInfo
86 TRUE, // BaseSrvNlsSetMultipleUserInfo
87 TRUE, // BaseSrvNlsCreateSection
88 TRUE, // BaseSrvSetVDMCurDirs
89 TRUE, // BaseSrvGetVDMCurDirs
90 TRUE, // BaseSrvBatNotification
91 TRUE, // BaseSrvRegisterWowExec
92 TRUE, // BaseSrvSoundSentryNotification
93 TRUE, // BaseSrvRefreshIniFileMapping
94 TRUE, // BaseSrvDefineDosDevice
95 TRUE, // BaseSrvSetTermsrvAppInstallMode
96 TRUE, // BaseSrvNlsUpdateCacheCount
97 TRUE, // BaseSrvSetTermsrvClientTimeZone
98 TRUE, // BaseSrvSxsCreateActivationContext
99 TRUE, // BaseSrvUnknown
100 TRUE, // BaseSrvRegisterThread
101 TRUE, // BaseSrvNlsGetUserInfo
102 };
103
104 /*
105 * On Windows Server 2003, CSR Servers contain
106 * the API Names Table only in Debug Builds.
107 */
108 #ifdef CSR_DBG
109 PCHAR BaseServerApiNameTable[BasepMaxApiNumber - BASESRV_FIRST_API_NUMBER] =
110 {
111 "BaseCreateProcess",
112 "BaseCreateThread",
113 "BaseGetTempFile",
114 "BaseExitProcess",
115 "BaseDebugProcess",
116 "BaseCheckVDM",
117 "BaseUpdateVDMEntry",
118 "BaseGetNextVDMCommand",
119 "BaseExitVDM",
120 "BaseIsFirstVDM",
121 "BaseGetVDMExitCode",
122 "BaseSetReenterCount",
123 "BaseSetProcessShutdownParam",
124 "BaseGetProcessShutdownParam",
125 "BaseNlsSetUserInfo",
126 "BaseNlsSetMultipleUserInfo",
127 "BaseNlsCreateSection",
128 "BaseSetVDMCurDirs",
129 "BaseGetVDMCurDirs",
130 "BaseBatNotification",
131 "BaseRegisterWowExec",
132 "BaseSoundSentryNotification",
133 "BaseRefreshIniFileMapping",
134 "BaseDefineDosDevice",
135 "BaseSetTermsrvAppInstallMode",
136 "BaseNlsUpdateCacheCount",
137 "BaseSetTermsrvClientTimeZone",
138 "BaseSxsCreateActivationContext",
139 "BaseUnknown",
140 "BaseRegisterThread",
141 "BaseNlsGetUserInfo",
142 };
143 #endif
144
145 /* FUNCTIONS ******************************************************************/
146
147 NTSTATUS
148 NTAPI
149 BaseSrvInitializeIniFileMappings(IN PBASE_STATIC_SERVER_DATA StaticServerData)
150 {
151 /* Allocate the mapping blob */
152 BaseSrvIniFileMapping = RtlAllocateHeap(BaseSrvSharedHeap,
153 HEAP_ZERO_MEMORY,
154 sizeof(*BaseSrvIniFileMapping));
155 if (BaseSrvIniFileMapping == NULL)
156 {
157 DPRINT1("BASESRV: Unable to allocate memory in shared heap for IniFileMapping\n");
158 return STATUS_NO_MEMORY;
159 }
160
161 /* Set it*/
162 StaticServerData->IniFileMapping = BaseSrvIniFileMapping;
163
164 /* FIXME: Do the work to initialize the mappings */
165 return STATUS_SUCCESS;
166 }
167
168 NTSTATUS
169 NTAPI
170 CreateBaseAcls(OUT PACL* Dacl,
171 OUT PACL* RestrictedDacl)
172 {
173 PSID SystemSid, WorldSid, RestrictedSid;
174 SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
175 SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
176 NTSTATUS Status;
177 #if 0 // Unused code
178 UCHAR KeyValueBuffer[0x40];
179 PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo;
180 UNICODE_STRING KeyName;
181 ULONG ProtectionMode = 0;
182 #endif
183 ULONG AclLength;
184 #if 0 // Unused code
185 ULONG ResultLength;
186 HANDLE hKey;
187 OBJECT_ATTRIBUTES ObjectAttributes;
188
189 /* Open the Session Manager Key */
190 RtlInitUnicodeString(&KeyName, SM_REG_KEY);
191 InitializeObjectAttributes(&ObjectAttributes,
192 &KeyName,
193 OBJ_CASE_INSENSITIVE,
194 NULL,
195 NULL);
196 Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes);
197 if (NT_SUCCESS(Status))
198 {
199 /* Read the key value */
200 RtlInitUnicodeString(&KeyName, L"ProtectionMode");
201 Status = NtQueryValueKey(hKey,
202 &KeyName,
203 KeyValuePartialInformation,
204 KeyValueBuffer,
205 sizeof(KeyValueBuffer),
206 &ResultLength);
207
208 /* Make sure it's what we expect it to be */
209 KeyValuePartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
210 if ((NT_SUCCESS(Status)) && (KeyValuePartialInfo->Type == REG_DWORD) &&
211 (*(PULONG)KeyValuePartialInfo->Data))
212 {
213 /* Save the Protection Mode */
214 ProtectionMode = *(PULONG)KeyValuePartialInfo->Data;
215 }
216
217 /* Close the handle */
218 NtClose(hKey);
219 }
220 #endif
221
222 /* Allocate the System SID */
223 Status = RtlAllocateAndInitializeSid(&NtAuthority,
224 1, SECURITY_LOCAL_SYSTEM_RID,
225 0, 0, 0, 0, 0, 0, 0,
226 &SystemSid);
227 ASSERT(NT_SUCCESS(Status));
228
229 /* Allocate the World SID */
230 Status = RtlAllocateAndInitializeSid(&WorldAuthority,
231 1, SECURITY_WORLD_RID,
232 0, 0, 0, 0, 0, 0, 0,
233 &WorldSid);
234 ASSERT(NT_SUCCESS(Status));
235
236 /* Allocate the restricted SID */
237 Status = RtlAllocateAndInitializeSid(&NtAuthority,
238 1, SECURITY_RESTRICTED_CODE_RID,
239 0, 0, 0, 0, 0, 0, 0,
240 &RestrictedSid);
241 ASSERT(NT_SUCCESS(Status));
242
243 /* Allocate one ACL with 3 ACEs each for one SID */
244 AclLength = sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) +
245 RtlLengthSid(SystemSid) +
246 RtlLengthSid(WorldSid) +
247 RtlLengthSid(RestrictedSid);
248 *Dacl = RtlAllocateHeap(BaseSrvHeap, 0, AclLength);
249 ASSERT(*Dacl != NULL);
250
251 /* Set the correct header fields */
252 Status = RtlCreateAcl(*Dacl, AclLength, ACL_REVISION2);
253 ASSERT(NT_SUCCESS(Status));
254
255 /* Give the appropriate rights to each SID */
256 /* FIXME: Should check SessionId/ProtectionMode */
257 Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_QUERY | DIRECTORY_TRAVERSE | DIRECTORY_CREATE_OBJECT | DIRECTORY_CREATE_SUBDIRECTORY | READ_CONTROL, WorldSid);
258 ASSERT(NT_SUCCESS(Status));
259 Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_ALL_ACCESS, SystemSid);
260 ASSERT(NT_SUCCESS(Status));
261 Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_TRAVERSE, RestrictedSid);
262 ASSERT(NT_SUCCESS(Status));
263
264 /* Now allocate the restricted DACL */
265 *RestrictedDacl = RtlAllocateHeap(BaseSrvHeap, 0, AclLength);
266 ASSERT(*RestrictedDacl != NULL);
267
268 /* Initialize it */
269 Status = RtlCreateAcl(*RestrictedDacl, AclLength, ACL_REVISION2);
270 ASSERT(NT_SUCCESS(Status));
271
272 /* And add the same ACEs as before */
273 /* FIXME: Not really fully correct */
274 Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_QUERY | DIRECTORY_TRAVERSE | DIRECTORY_CREATE_OBJECT | DIRECTORY_CREATE_SUBDIRECTORY | READ_CONTROL, WorldSid);
275 ASSERT(NT_SUCCESS(Status));
276 Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_ALL_ACCESS, SystemSid);
277 ASSERT(NT_SUCCESS(Status));
278 Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_TRAVERSE, RestrictedSid);
279 ASSERT(NT_SUCCESS(Status));
280
281 /* The SIDs are captured, can free them now */
282 RtlFreeSid(RestrictedSid);
283 RtlFreeSid(WorldSid);
284 RtlFreeSid(SystemSid);
285 return Status;
286 }
287
288 VOID
289 NTAPI
290 BaseInitializeStaticServerData(IN PCSR_SERVER_DLL LoadedServerDll)
291 {
292 NTSTATUS Status;
293 BOOLEAN Success;
294 WCHAR Buffer[MAX_PATH];
295 PWCHAR HeapBuffer;
296 UNICODE_STRING SystemRootString;
297 UNICODE_STRING UnexpandedSystemRootString = RTL_CONSTANT_STRING(L"%SystemRoot%");
298 UNICODE_STRING BaseSrvCSDString;
299 UNICODE_STRING BaseSrvWindowsDirectory;
300 UNICODE_STRING BaseSrvWindowsSystemDirectory;
301 UNICODE_STRING BnoString;
302 OBJECT_ATTRIBUTES ObjectAttributes;
303 ULONG SessionId;
304 HANDLE BaseSrvNamedObjectDirectory;
305 HANDLE BaseSrvRestrictedObjectDirectory;
306 PACL BnoDacl, BnoRestrictedDacl;
307 PSECURITY_DESCRIPTOR BnoSd;
308 HANDLE SymHandle;
309 UNICODE_STRING DirectoryName, SymlinkName;
310 ULONG LuidEnabled;
311 RTL_QUERY_REGISTRY_TABLE BaseServerRegistryConfigurationTable[2] =
312 {
313 {
314 NULL,
315 RTL_QUERY_REGISTRY_DIRECT,
316 L"CSDVersion",
317 &BaseSrvCSDString,
318 REG_NONE, NULL, 0
319 },
320
321 {0}
322 };
323
324 /* Initialize the memory */
325 BaseSrvHeap = RtlGetProcessHeap(); // Initialize our own heap.
326 BaseSrvSharedHeap = LoadedServerDll->SharedSection; // Get the CSR shared heap.
327
328 /* Get the session ID */
329 SessionId = NtCurrentPeb()->SessionId;
330
331 /* Get the Windows directory */
332 RtlInitEmptyUnicodeString(&SystemRootString, Buffer, sizeof(Buffer));
333 Status = RtlExpandEnvironmentStrings_U(NULL,
334 &UnexpandedSystemRootString,
335 &SystemRootString,
336 NULL);
337 ASSERT(NT_SUCCESS(Status));
338
339 /* Create the base directory */
340 Buffer[SystemRootString.Length / sizeof(WCHAR)] = UNICODE_NULL;
341 Success = RtlCreateUnicodeString(&BaseSrvWindowsDirectory,
342 SystemRootString.Buffer);
343 ASSERT(Success);
344
345 /* Create the system directory */
346 wcscat(SystemRootString.Buffer, L"\\System32");
347 Success = RtlCreateUnicodeString(&BaseSrvWindowsSystemDirectory,
348 SystemRootString.Buffer);
349 ASSERT(Success);
350
351 /* Create the kernel32 path */
352 wcscat(SystemRootString.Buffer, L"\\kernel32.dll");
353 Success = RtlCreateUnicodeString(&BaseSrvKernel32DllPath,
354 SystemRootString.Buffer);
355 ASSERT(Success);
356
357 /* FIXME: Check Session ID */
358 wcscpy(Buffer, L"\\BaseNamedObjects");
359 RtlInitUnicodeString(&BnoString, Buffer);
360
361 /* Allocate the server data */
362 BaseStaticServerData = RtlAllocateHeap(BaseSrvSharedHeap,
363 HEAP_ZERO_MEMORY,
364 sizeof(BASE_STATIC_SERVER_DATA));
365 ASSERT(BaseStaticServerData != NULL);
366
367 /* Process timezone information */
368 BaseStaticServerData->TermsrvClientTimeZoneId = TIME_ZONE_ID_INVALID;
369 BaseStaticServerData->TermsrvClientTimeZoneChangeNum = 0;
370 Status = NtQuerySystemInformation(SystemTimeOfDayInformation,
371 &BaseStaticServerData->TimeOfDay,
372 sizeof(BaseStaticServerData->TimeOfDay),
373 NULL);
374 ASSERT(NT_SUCCESS(Status));
375
376 /* Make a shared heap copy of the Windows directory */
377 BaseStaticServerData->WindowsDirectory = BaseSrvWindowsDirectory;
378 HeapBuffer = RtlAllocateHeap(BaseSrvSharedHeap,
379 0,
380 BaseSrvWindowsDirectory.MaximumLength);
381 ASSERT(HeapBuffer);
382 RtlCopyMemory(HeapBuffer,
383 BaseStaticServerData->WindowsDirectory.Buffer,
384 BaseSrvWindowsDirectory.MaximumLength);
385 BaseStaticServerData->WindowsDirectory.Buffer = HeapBuffer;
386
387 /* Make a shared heap copy of the System directory */
388 BaseStaticServerData->WindowsSystemDirectory = BaseSrvWindowsSystemDirectory;
389 HeapBuffer = RtlAllocateHeap(BaseSrvSharedHeap,
390 0,
391 BaseSrvWindowsSystemDirectory.MaximumLength);
392 ASSERT(HeapBuffer);
393 RtlCopyMemory(HeapBuffer,
394 BaseStaticServerData->WindowsSystemDirectory.Buffer,
395 BaseSrvWindowsSystemDirectory.MaximumLength);
396 BaseStaticServerData->WindowsSystemDirectory.Buffer = HeapBuffer;
397
398 /* This string is not used */
399 RtlInitEmptyUnicodeString(&BaseStaticServerData->WindowsSys32x86Directory,
400 NULL,
401 0);
402
403 /* Make a shared heap copy of the BNO directory */
404 BaseStaticServerData->NamedObjectDirectory = BnoString;
405 BaseStaticServerData->NamedObjectDirectory.MaximumLength = BnoString.Length +
406 sizeof(UNICODE_NULL);
407 HeapBuffer = RtlAllocateHeap(BaseSrvSharedHeap,
408 0,
409 BaseStaticServerData->NamedObjectDirectory.MaximumLength);
410 ASSERT(HeapBuffer);
411 RtlCopyMemory(HeapBuffer,
412 BaseStaticServerData->NamedObjectDirectory.Buffer,
413 BaseStaticServerData->NamedObjectDirectory.MaximumLength);
414 BaseStaticServerData->NamedObjectDirectory.Buffer = HeapBuffer;
415
416 /*
417 * Confirmed that in Windows, CSDNumber and RCNumber are actually Length
418 * and MaximumLength of the CSD String, since the same UNICODE_STRING is
419 * being queried twice, the first time as a ULONG!
420 *
421 * Somehow, in Windows this doesn't cause a buffer overflow, but it might
422 * in ReactOS, so this code is disabled until someone figures out WTF.
423 */
424 BaseStaticServerData->CSDNumber = 0;
425 BaseStaticServerData->RCNumber = 0;
426
427 /* Initialize the CSD string and query its value from the registry */
428 RtlInitEmptyUnicodeString(&BaseSrvCSDString, Buffer, sizeof(Buffer));
429 Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
430 L"",
431 BaseServerRegistryConfigurationTable,
432 NULL,
433 NULL);
434 if (NT_SUCCESS(Status))
435 {
436 /* Copy into the shared buffer */
437 wcsncpy(BaseStaticServerData->CSDVersion,
438 BaseSrvCSDString.Buffer,
439 BaseSrvCSDString.Length / sizeof(WCHAR));
440 }
441 else
442 {
443 /* NULL-terminate to indicate nothing is there */
444 BaseStaticServerData->CSDVersion[0] = UNICODE_NULL;
445 }
446
447 /* Cache the system information */
448 Status = NtQuerySystemInformation(SystemBasicInformation,
449 &BaseStaticServerData->SysInfo,
450 sizeof(BaseStaticServerData->SysInfo),
451 NULL);
452 ASSERT(NT_SUCCESS(Status));
453
454 /* Setup the ini file mappings */
455 Status = BaseSrvInitializeIniFileMappings(BaseStaticServerData);
456 ASSERT(NT_SUCCESS(Status));
457
458 /* FIXME: Should query the registry for these */
459 BaseStaticServerData->DefaultSeparateVDM = FALSE;
460 BaseStaticServerData->IsWowTaskReady = FALSE;
461
462 /* Allocate a security descriptor and create it */
463 BnoSd = RtlAllocateHeap(BaseSrvHeap, 0, 1024);
464 ASSERT(BnoSd);
465 Status = RtlCreateSecurityDescriptor(BnoSd, SECURITY_DESCRIPTOR_REVISION);
466 ASSERT(NT_SUCCESS(Status));
467
468 /* Create the BNO and \Restricted DACLs */
469 Status = CreateBaseAcls(&BnoDacl, &BnoRestrictedDacl);
470 ASSERT(NT_SUCCESS(Status));
471
472 /* Set the BNO DACL as active for now */
473 Status = RtlSetDaclSecurityDescriptor(BnoSd, TRUE, BnoDacl, FALSE);
474 ASSERT(NT_SUCCESS(Status));
475
476 /* Create the BNO directory */
477 RtlInitUnicodeString(&BnoString, L"\\BaseNamedObjects");
478 InitializeObjectAttributes(&ObjectAttributes,
479 &BnoString,
480 OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
481 NULL,
482 BnoSd);
483 Status = NtCreateDirectoryObject(&BaseSrvNamedObjectDirectory,
484 DIRECTORY_ALL_ACCESS,
485 &ObjectAttributes);
486 ASSERT(NT_SUCCESS(Status));
487
488 /* Check if we are session 0 */
489 if (SessionId == 0)
490 {
491 /* Mark this as a session 0 directory */
492 Status = NtSetInformationObject(BaseSrvNamedObjectDirectory,
493 ObjectSessionInformation,
494 NULL,
495 0);
496 ASSERT(NT_SUCCESS(Status));
497 }
498
499 /* Check if LUID device maps are enabled */
500 Status = NtQueryInformationProcess(NtCurrentProcess(),
501 ProcessLUIDDeviceMapsEnabled,
502 &LuidEnabled,
503 sizeof(LuidEnabled),
504 NULL);
505 ASSERT(NT_SUCCESS(Status));
506 BaseStaticServerData->LUIDDeviceMapsEnabled = (BOOLEAN)LuidEnabled;
507 if (!BaseStaticServerData->LUIDDeviceMapsEnabled)
508 {
509 /* Make Global point back to BNO */
510 RtlInitUnicodeString(&DirectoryName, L"Global");
511 RtlInitUnicodeString(&SymlinkName, L"\\BaseNamedObjects");
512 InitializeObjectAttributes(&ObjectAttributes,
513 &DirectoryName,
514 OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
515 BaseSrvNamedObjectDirectory,
516 BnoSd);
517 Status = NtCreateSymbolicLinkObject(&SymHandle,
518 SYMBOLIC_LINK_ALL_ACCESS,
519 &ObjectAttributes,
520 &SymlinkName);
521 if ((NT_SUCCESS(Status)) && SessionId == 0) NtClose(SymHandle);
522
523 /* Make local point back to \Sessions\x\BNO */
524 RtlInitUnicodeString(&DirectoryName, L"Local");
525 ASSERT(SessionId == 0);
526 InitializeObjectAttributes(&ObjectAttributes,
527 &DirectoryName,
528 OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
529 BaseSrvNamedObjectDirectory,
530 BnoSd);
531 Status = NtCreateSymbolicLinkObject(&SymHandle,
532 SYMBOLIC_LINK_ALL_ACCESS,
533 &ObjectAttributes,
534 &SymlinkName);
535 if ((NT_SUCCESS(Status)) && SessionId == 0) NtClose(SymHandle);
536
537 /* Make Session point back to BNOLINKS */
538 RtlInitUnicodeString(&DirectoryName, L"Session");
539 RtlInitUnicodeString(&SymlinkName, L"\\Sessions\\BNOLINKS");
540 InitializeObjectAttributes(&ObjectAttributes,
541 &DirectoryName,
542 OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
543 BaseSrvNamedObjectDirectory,
544 BnoSd);
545 Status = NtCreateSymbolicLinkObject(&SymHandle,
546 SYMBOLIC_LINK_ALL_ACCESS,
547 &ObjectAttributes,
548 &SymlinkName);
549 if ((NT_SUCCESS(Status)) && SessionId == 0) NtClose(SymHandle);
550
551 /* Create the BNO\Restricted directory and set the restricted DACL */
552 RtlInitUnicodeString(&DirectoryName, L"Restricted");
553 Status = RtlSetDaclSecurityDescriptor(BnoSd, TRUE, BnoRestrictedDacl, FALSE);
554 ASSERT(NT_SUCCESS(Status));
555 InitializeObjectAttributes(&ObjectAttributes,
556 &DirectoryName,
557 OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
558 BaseSrvNamedObjectDirectory,
559 BnoSd);
560 Status = NtCreateDirectoryObject(&BaseSrvRestrictedObjectDirectory,
561 DIRECTORY_ALL_ACCESS,
562 &ObjectAttributes);
563 ASSERT(NT_SUCCESS(Status));
564 }
565
566 /* Initialize NLS */
567 BaseSrvNLSInit(BaseStaticServerData);
568
569 /* Finally, set the pointer */
570 LoadedServerDll->SharedSection = BaseStaticServerData;
571 }
572
573 CSR_SERVER_DLL_INIT(ServerDllInitialization)
574 {
575 /* Setup the DLL Object */
576 LoadedServerDll->ApiBase = BASESRV_FIRST_API_NUMBER;
577 LoadedServerDll->HighestApiSupported = BasepMaxApiNumber;
578 LoadedServerDll->DispatchTable = BaseServerApiDispatchTable;
579 LoadedServerDll->ValidTable = BaseServerApiServerValidTable;
580 #ifdef CSR_DBG
581 LoadedServerDll->NameTable = BaseServerApiNameTable;
582 #endif
583 LoadedServerDll->SizeOfProcessData = 0;
584 LoadedServerDll->ConnectCallback = NULL;
585 LoadedServerDll->DisconnectCallback = NULL;
586 LoadedServerDll->ShutdownProcessCallback = NULL;
587
588 BaseSrvDllInstance = LoadedServerDll->ServerHandle;
589
590 BaseInitializeStaticServerData(LoadedServerDll);
591
592 /* Initialize DOS devices management */
593 BaseInitDefineDosDevice();
594
595 /* Initialize VDM support */
596 BaseInitializeVDM();
597
598 /* All done */
599 return STATUS_SUCCESS;
600 }
601
602 BOOL
603 NTAPI
604 DllMain(IN HINSTANCE hInstanceDll,
605 IN DWORD dwReason,
606 IN LPVOID lpReserved)
607 {
608 UNREFERENCED_PARAMETER(hInstanceDll);
609 UNREFERENCED_PARAMETER(dwReason);
610 UNREFERENCED_PARAMETER(lpReserved);
611
612 if (DLL_PROCESS_DETACH == dwReason)
613 {
614 BaseCleanupDefineDosDevice();
615 }
616
617 return TRUE;
618 }
619
620 /* EOF */