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