xref: /reactos/subsystems/win/basesrv/init.c (revision 3a7f8d36)
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 "api.h"
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 /* GLOBALS ********************************************************************/
18 
19 HANDLE BaseSrvDllInstance = NULL;
20 
21 /* Memory */
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.
25 
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] =
28 {
29     BaseSrvCreateProcess,
30     BaseSrvCreateThread,
31     BaseSrvGetTempFile,
32     BaseSrvExitProcess,
33     // BaseSrvDebugProcess,
34     // BaseSrvCheckVDM,
35     // BaseSrvUpdateVDMEntry,
36     // BaseSrvGetNextVDMCommand,
37     // BaseSrvExitVDM,
38     // BaseSrvIsFirstVDM,
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,
59 };
60 
61 BOOLEAN BaseServerApiServerValidTable[BasepMaxApiNumber - BASESRV_FIRST_API_NUMBER] =
62 {
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
93 };
94 
95 PCHAR BaseServerApiNameTable[BasepMaxApiNumber - BASESRV_FIRST_API_NUMBER] =
96 {
97     "BaseCreateProcess",
98     "BaseCreateThread",
99     "BaseGetTempFile",
100     "BaseExitProcess",
101     // "BaseDebugProcess",
102     // "BaseCheckVDM",
103     // "BaseUpdateVDMEntry",
104     // "BaseGetNextVDMCommand",
105     // "BaseExitVDM",
106     // "BaseIsFirstVDM",
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",
127 };
128 
129 
130 /* FUNCTIONS ******************************************************************/
131 
132 NTSTATUS
133 NTAPI
134 CreateBaseAcls(OUT PACL* Dacl,
135                OUT PACL* RestrictedDacl)
136 {
137     PSID SystemSid, WorldSid, RestrictedSid;
138     SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
139     SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
140     NTSTATUS Status;
141     // UCHAR KeyValueBuffer[0x40];
142     // PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo;
143     // UNICODE_STRING KeyName;
144     // ULONG ProtectionMode = 0;
145     ULONG AclLength; // , ResultLength;
146     // HANDLE hKey;
147     // OBJECT_ATTRIBUTES ObjectAttributes;
148 
149     /* Open the Session Manager Key */
150     /*
151     RtlInitUnicodeString(&KeyName, SM_REG_KEY);
152     InitializeObjectAttributes(&ObjectAttributes,
153                                &KeyName,
154                                OBJ_CASE_INSENSITIVE,
155                                NULL,
156                                NULL);
157     Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes);
158     if (NT_SUCCESS(Status))
159     {
160         /\* Read the key value *\/
161         RtlInitUnicodeString(&KeyName, L"ProtectionMode");
162         Status = NtQueryValueKey(hKey,
163                                  &KeyName,
164                                  KeyValuePartialInformation,
165                                  KeyValueBuffer,
166                                  sizeof(KeyValueBuffer),
167                                  &ResultLength);
168 
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))
173         {
174             /\* Save the Protection Mode *\/
175             // ProtectionMode = *(PULONG)KeyValuePartialInfo->Data;
176         }
177 
178         /\* Close the handle *\/
179         NtClose(hKey);
180     }
181     */
182 
183     /* Allocate the System SID */
184     Status = RtlAllocateAndInitializeSid(&NtAuthority,
185                                          1, SECURITY_LOCAL_SYSTEM_RID,
186                                          0, 0, 0, 0, 0, 0, 0,
187                                          &SystemSid);
188     ASSERT(NT_SUCCESS(Status));
189 
190     /* Allocate the World SID */
191     Status = RtlAllocateAndInitializeSid(&WorldAuthority,
192                                          1, SECURITY_WORLD_RID,
193                                          0, 0, 0, 0, 0, 0, 0,
194                                          &WorldSid);
195     ASSERT(NT_SUCCESS(Status));
196 
197     /* Allocate the restricted SID */
198     Status = RtlAllocateAndInitializeSid(&NtAuthority,
199                                          1, SECURITY_RESTRICTED_CODE_RID,
200                                          0, 0, 0, 0, 0, 0, 0,
201                                          &RestrictedSid);
202     ASSERT(NT_SUCCESS(Status));
203 
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);
211 
212     /* Set the correct header fields */
213     Status = RtlCreateAcl(*Dacl, AclLength, ACL_REVISION2);
214     ASSERT(NT_SUCCESS(Status));
215 
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));
224 
225     /* Now allocate the restricted DACL */
226     *RestrictedDacl = RtlAllocateHeap(BaseSrvHeap, 0, AclLength);
227     ASSERT(*RestrictedDacl != NULL);
228 
229     /* Initialize it */
230     Status = RtlCreateAcl(*RestrictedDacl, AclLength, ACL_REVISION2);
231     ASSERT(NT_SUCCESS(Status));
232 
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));
241 
242     /* The SIDs are captured, can free them now */
243     RtlFreeSid(RestrictedSid);
244     RtlFreeSid(WorldSid);
245     RtlFreeSid(SystemSid);
246     return Status;
247 }
248 
249 VOID
250 NTAPI
251 BaseInitializeStaticServerData(IN PCSR_SERVER_DLL LoadedServerDll)
252 {
253     NTSTATUS Status;
254     WCHAR Buffer[MAX_PATH];
255     PWCHAR HeapBuffer;
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;
263     ULONG SessionId;
264     HANDLE BaseSrvNamedObjectDirectory;
265     HANDLE BaseSrvRestrictedObjectDirectory;
266     PACL BnoDacl, BnoRestrictedDacl;
267     PSECURITY_DESCRIPTOR BnoSd;
268     HANDLE SymHandle;
269     UNICODE_STRING DirectoryName, SymlinkName;
270     ULONG LuidEnabled;
271     RTL_QUERY_REGISTRY_TABLE BaseServerRegistryConfigurationTable[2] =
272     {
273         {
274             NULL,
275             RTL_QUERY_REGISTRY_DIRECT,
276             L"CSDVersion",
277             &BaseSrvCSDString,
278             REG_NONE, NULL, 0
279         },
280 
281         {0}
282     };
283 
284     /* Initialize the memory */
285     BaseSrvHeap = RtlGetProcessHeap();                  // Initialize our own heap.
286     BaseSrvSharedHeap = LoadedServerDll->SharedSection; // Get the CSR shared heap.
287 
288     /* Get the session ID */
289     SessionId = NtCurrentPeb()->SessionId;
290 
291     /* Get the Windows directory */
292     RtlInitEmptyUnicodeString(&SystemRootString, Buffer, sizeof(Buffer));
293     Status = RtlExpandEnvironmentStrings_U(NULL,
294                                            &UnexpandedSystemRootString,
295                                            &SystemRootString,
296                                            NULL);
297     ASSERT(NT_SUCCESS(Status));
298 
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));
304 
305     /* Create the system directory */
306     wcscat(SystemRootString.Buffer, L"\\System32");
307     Status = RtlCreateUnicodeString(&BaseSrvWindowsSystemDirectory,
308                                     SystemRootString.Buffer);
309     ASSERT(NT_SUCCESS(Status));
310 
311     /* FIXME: Check Session ID */
312     wcscpy(Buffer, L"\\BaseNamedObjects");
313     RtlInitUnicodeString(&BnoString, Buffer);
314 
315     /* Allocate the server data */
316     BaseStaticServerData = RtlAllocateHeap(BaseSrvSharedHeap,
317                                            HEAP_ZERO_MEMORY,
318                                            sizeof(BASE_STATIC_SERVER_DATA));
319     ASSERT(BaseStaticServerData != NULL);
320 
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),
327                                       NULL);
328     ASSERT(NT_SUCCESS(Status));
329 
330     /* Make a shared heap copy of the Windows directory */
331     BaseStaticServerData->WindowsDirectory = BaseSrvWindowsDirectory;
332     HeapBuffer = RtlAllocateHeap(BaseSrvSharedHeap,
333                                  0,
334                                  BaseSrvWindowsDirectory.MaximumLength);
335     ASSERT(HeapBuffer);
336     RtlCopyMemory(HeapBuffer,
337                   BaseStaticServerData->WindowsDirectory.Buffer,
338                   BaseSrvWindowsDirectory.MaximumLength);
339     BaseStaticServerData->WindowsDirectory.Buffer = HeapBuffer;
340 
341     /* Make a shared heap copy of the System directory */
342     BaseStaticServerData->WindowsSystemDirectory = BaseSrvWindowsSystemDirectory;
343     HeapBuffer = RtlAllocateHeap(BaseSrvSharedHeap,
344                                  0,
345                                  BaseSrvWindowsSystemDirectory.MaximumLength);
346     ASSERT(HeapBuffer);
347     RtlCopyMemory(HeapBuffer,
348                   BaseStaticServerData->WindowsSystemDirectory.Buffer,
349                   BaseSrvWindowsSystemDirectory.MaximumLength);
350     BaseStaticServerData->WindowsSystemDirectory.Buffer = HeapBuffer;
351 
352     /* This string is not used */
353     RtlInitEmptyUnicodeString(&BaseStaticServerData->WindowsSys32x86Directory,
354                               NULL,
355                               0);
356 
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,
362                                  0,
363                                  BaseStaticServerData->NamedObjectDirectory.MaximumLength);
364     ASSERT(HeapBuffer);
365     RtlCopyMemory(HeapBuffer,
366                   BaseStaticServerData->NamedObjectDirectory.Buffer,
367                   BaseStaticServerData->NamedObjectDirectory.MaximumLength);
368     BaseStaticServerData->NamedObjectDirectory.Buffer = HeapBuffer;
369 
370     /*
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!
374      *
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.
377      */
378     BaseStaticServerData->CSDNumber = 0;
379     BaseStaticServerData->RCNumber = 0;
380 
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,
384                                     L"",
385                                     BaseServerRegistryConfigurationTable,
386                                     NULL,
387                                     NULL);
388     if (NT_SUCCESS(Status))
389     {
390         /* Copy into the shared buffer */
391         wcsncpy(BaseStaticServerData->CSDVersion,
392                 BaseSrvCSDString.Buffer,
393                 BaseSrvCSDString.Length / sizeof(WCHAR));
394     }
395     else
396     {
397         /* NULL-terminate to indicate nothing is there */
398         BaseStaticServerData->CSDVersion[0] = UNICODE_NULL;
399     }
400 
401     /* Cache the system information */
402     Status = NtQuerySystemInformation(SystemBasicInformation,
403                                       &BaseStaticServerData->SysInfo,
404                                       sizeof(BaseStaticServerData->SysInfo),
405                                       NULL);
406     ASSERT(NT_SUCCESS(Status));
407 
408     /* FIXME: Should query the registry for these */
409     BaseStaticServerData->DefaultSeparateVDM = FALSE;
410     BaseStaticServerData->IsWowTaskReady = FALSE;
411 
412     /* Allocate a security descriptor and create it */
413     BnoSd = RtlAllocateHeap(BaseSrvHeap, 0, 1024);
414     ASSERT(BnoSd);
415     Status = RtlCreateSecurityDescriptor(BnoSd, SECURITY_DESCRIPTOR_REVISION);
416     ASSERT(NT_SUCCESS(Status));
417 
418     /* Create the BNO and \Restricted DACLs */
419     Status = CreateBaseAcls(&BnoDacl, &BnoRestrictedDacl);
420     ASSERT(NT_SUCCESS(Status));
421 
422     /* Set the BNO DACL as active for now */
423     Status = RtlSetDaclSecurityDescriptor(BnoSd, TRUE, BnoDacl, FALSE);
424     ASSERT(NT_SUCCESS(Status));
425 
426     /* Create the BNO directory */
427     RtlInitUnicodeString(&BnoString, L"\\BaseNamedObjects");
428     InitializeObjectAttributes(&ObjectAttributes,
429                                &BnoString,
430                                OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
431                                NULL,
432                                BnoSd);
433     Status = NtCreateDirectoryObject(&BaseSrvNamedObjectDirectory,
434                                      DIRECTORY_ALL_ACCESS,
435                                      &ObjectAttributes);
436     ASSERT(NT_SUCCESS(Status));
437 
438     /* Check if we are session 0 */
439     if (SessionId == 0)
440     {
441         /* Mark this as a session 0 directory */
442         Status = NtSetInformationObject(BaseSrvNamedObjectDirectory,
443                                         ObjectSessionInformation,
444                                         NULL,
445                                         0);
446         ASSERT(NT_SUCCESS(Status));
447     }
448 
449     /* Check if LUID device maps are enabled */
450     Status = NtQueryInformationProcess(NtCurrentProcess(),
451                                        ProcessLUIDDeviceMapsEnabled,
452                                        &LuidEnabled,
453                                        sizeof(LuidEnabled),
454                                        NULL);
455     ASSERT(NT_SUCCESS(Status));
456     BaseStaticServerData->LUIDDeviceMapsEnabled = LuidEnabled;
457     if (!BaseStaticServerData->LUIDDeviceMapsEnabled)
458     {
459         /* Make Global point back to BNO */
460         RtlInitUnicodeString(&DirectoryName, L"Global");
461         RtlInitUnicodeString(&SymlinkName, L"\\BaseNamedObjects");
462         InitializeObjectAttributes(&ObjectAttributes,
463                                    &DirectoryName,
464                                    OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
465                                    BaseSrvNamedObjectDirectory,
466                                    BnoSd);
467         Status = NtCreateSymbolicLinkObject(&SymHandle,
468                                             SYMBOLIC_LINK_ALL_ACCESS,
469                                             &ObjectAttributes,
470                                             &SymlinkName);
471         if ((NT_SUCCESS(Status)) && SessionId == 0) NtClose(SymHandle);
472 
473         /* Make local point back to \Sessions\x\BNO */
474         RtlInitUnicodeString(&DirectoryName, L"Local");
475         ASSERT(SessionId == 0);
476         InitializeObjectAttributes(&ObjectAttributes,
477                                    &DirectoryName,
478                                    OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
479                                    BaseSrvNamedObjectDirectory,
480                                    BnoSd);
481         Status = NtCreateSymbolicLinkObject(&SymHandle,
482                                             SYMBOLIC_LINK_ALL_ACCESS,
483                                             &ObjectAttributes,
484                                             &SymlinkName);
485         if ((NT_SUCCESS(Status)) && SessionId == 0) NtClose(SymHandle);
486 
487         /* Make Session point back to BNOLINKS */
488         RtlInitUnicodeString(&DirectoryName, L"Session");
489         RtlInitUnicodeString(&SymlinkName, L"\\Sessions\\BNOLINKS");
490         InitializeObjectAttributes(&ObjectAttributes,
491                                    &DirectoryName,
492                                    OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
493                                    BaseSrvNamedObjectDirectory,
494                                    BnoSd);
495         Status = NtCreateSymbolicLinkObject(&SymHandle,
496                                             SYMBOLIC_LINK_ALL_ACCESS,
497                                             &ObjectAttributes,
498                                             &SymlinkName);
499         if ((NT_SUCCESS(Status)) && SessionId == 0) NtClose(SymHandle);
500 
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,
506                                    &DirectoryName,
507                                    OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
508                                    BaseSrvNamedObjectDirectory,
509                                    BnoSd);
510         Status = NtCreateDirectoryObject(&BaseSrvRestrictedObjectDirectory,
511                                          DIRECTORY_ALL_ACCESS,
512                                          &ObjectAttributes);
513         ASSERT(NT_SUCCESS(Status));
514     }
515 
516     /* Finally, set the pointer */
517     LoadedServerDll->SharedSection = BaseStaticServerData;
518 }
519 
520 CSR_SERVER_DLL_INIT(ServerDllInitialization)
521 {
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;
532 
533     BaseSrvDllInstance = LoadedServerDll->ServerHandle;
534 
535     BaseInitializeStaticServerData(LoadedServerDll);
536 
537     /* Initialize DOS devices management */
538     BaseInitDefineDosDevice();
539 
540     /* All done */
541     return STATUS_SUCCESS;
542 }
543 
544 BOOL
545 NTAPI
546 DllMain(IN HINSTANCE hInstanceDll,
547         IN DWORD dwReason,
548         IN LPVOID lpReserved)
549 {
550     UNREFERENCED_PARAMETER(hInstanceDll);
551     UNREFERENCED_PARAMETER(dwReason);
552     UNREFERENCED_PARAMETER(lpReserved);
553 
554     if (DLL_PROCESS_DETACH == dwReason)
555     {
556         BaseCleanupDefineDosDevice();
557     }
558 
559     return TRUE;
560 }
561 
562 /* EOF */
563