dd7f5d16a2312375646076aa8335c9c18b7d58f0
[reactos.git] / subsystems / win / basesrv / init.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS/Win32 base enviroment subsystem server
4 * FILE: subsystems/win/basesrv/init.c
5 * PURPOSE: Initialization
6 * PROGRAMMERS: Hermes Belusca-Maito (hermes.belusca@sfr.fr)
7 */
8
9 #include "basesrv.h"
10
11 #define NDEBUG
12 #include <debug.h>
13
14 HANDLE DllHandle = NULL;
15 HANDLE BaseApiPort = NULL;
16
17 extern LIST_ENTRY DosDeviceHistory;
18 extern RTL_CRITICAL_SECTION BaseDefineDosDeviceCritSec;
19
20 // Windows NT 4 tables, adapted from http://j00ru.vexillium.org/csrss_list/api_list.html#Windows_NT
21 // It is for testing purposes. After that I will update it to 2k3 version and add stubs.
22 // Some names are also deduced from the subsystems/win32/csrss/csrsrv/server.c ones.
23 PCSR_API_ROUTINE BaseServerApiDispatchTable[BasepMaxApiNumber] =
24 {
25 BaseSrvCreateProcess,
26 BaseSrvCreateThread,
27 BaseSrvGetTempFile,
28 BaseSrvExitProcess,
29 // BaseSrvDebugProcess,
30 BaseSrvCheckVDM,
31 BaseSrvUpdateVDMEntry,
32 // BaseSrvGetNextVDMCommand,
33 // BaseSrvExitVDM,
34 // BaseSrvIsFirstVDM,
35 BaseSrvGetVDMExitCode,
36 // BaseSrvSetReenterCount,
37 BaseSrvSetProcessShutdownParam,
38 BaseSrvGetProcessShutdownParam,
39 // BaseSrvNlsSetUserInfo,
40 // BaseSrvNlsSetMultipleUserInfo,
41 // BaseSrvNlsCreateSortSection,
42 // BaseSrvNlsPreserveSection,
43 // BaseSrvSetVDMCurDirs,
44 // BaseSrvGetVDMCurDirs,
45 // BaseSrvBatNotification,
46 // BaseSrvRegisterWowExec,
47 BaseSrvSoundSentryNotification,
48 // BaseSrvRefreshIniFileMapping,
49 BaseSrvDefineDosDevice
50 };
51
52 BOOLEAN BaseServerApiServerValidTable[BasepMaxApiNumber] =
53 {
54 TRUE, // SrvCreateProcess,
55 TRUE, // SrvCreateThread,
56 TRUE, // SrvGetTempFile,
57 FALSE, // SrvExitProcess,
58 // FALSE, // SrvDebugProcess,
59 TRUE, // SrvCheckVDM,
60 TRUE, // SrvUpdateVDMEntry
61 // TRUE, // SrvGetNextVDMCommand
62 // TRUE, // SrvExitVDM
63 // TRUE, // SrvIsFirstVDM
64 TRUE, // SrvGetVDMExitCode
65 // TRUE, // SrvSetReenterCount
66 TRUE, // SrvSetProcessShutdownParam
67 TRUE, // SrvGetProcessShutdownParam
68 // TRUE, // SrvNlsSetUserInfo
69 // TRUE, // SrvNlsSetMultipleUserInfo
70 // TRUE, // SrvNlsCreateSortSection
71 // TRUE, // SrvNlsPreserveSection
72 // TRUE, // SrvSetVDMCurDirs
73 // TRUE, // SrvGetVDMCurDirs
74 // TRUE, // SrvBatNotification
75 // TRUE, // SrvRegisterWowExec
76 TRUE, // SrvSoundSentryNotification
77 // TRUE, // SrvRefreshIniFileMapping
78 TRUE, // SrvDefineDosDevice
79 // FALSE
80 };
81
82 PCHAR BaseServerApiNameTable[BasepMaxApiNumber] =
83 {
84 "BaseCreateProcess",
85 "BaseCreateThread",
86 "BaseGetTempFile",
87 "BaseExitProcess",
88 // "BaseDebugProcess",
89 "BaseCheckVDM",
90 "BaseUpdateVDMEntry",
91 // "BaseGetNextVDMCommand",
92 // "BaseExitVDM",
93 // "BaseIsFirstVDM",
94 "BaseGetVDMExitCode",
95 // "BaseSetReenterCount",
96 "BaseSetProcessShutdownParam",
97 "BaseGetProcessShutdownParam",
98 // "BaseNlsSetUserInfo",
99 // "BaseNlsSetMultipleUserInfo",
100 // "BaseNlsCreateSortSection",
101 // "BaseNlsPreserveSection",
102 // "BaseSetVDMCurDirs",
103 // "BaseGetVDMCurDirs",
104 // "BaseBatNotification",
105 // "BaseRegisterWowExec",
106 "BaseSoundSentryNotification",
107 // "BaseSrvRefreshIniFileMapping"
108 "BaseDefineDosDevice",
109 // NULL
110 };
111
112
113 /* FUNCTIONS ******************************************************************/
114
115 VOID
116 NTAPI
117 BasepFakeStaticServerData(VOID)
118 {
119 NTSTATUS Status;
120 WCHAR Buffer[MAX_PATH];
121 PWCHAR HeapBuffer;
122 UNICODE_STRING SystemRootString;
123 UNICODE_STRING UnexpandedSystemRootString = RTL_CONSTANT_STRING(L"%SystemRoot%");
124 UNICODE_STRING BaseSrvCSDString;
125 UNICODE_STRING BaseSrvWindowsDirectory;
126 UNICODE_STRING BaseSrvWindowsSystemDirectory;
127 UNICODE_STRING BnoString;
128 OBJECT_ATTRIBUTES ObjectAttributes;
129 ULONG SessionId;
130 HANDLE BaseSrvNamedObjectDirectory;
131 HANDLE BaseSrvRestrictedObjectDirectory;
132 PACL BnoDacl, BnoRestrictedDacl;
133 PSECURITY_DESCRIPTOR BnoSd;
134 HANDLE SymHandle;
135 UNICODE_STRING DirectoryName, SymlinkName;
136 ULONG LuidEnabled;
137 RTL_QUERY_REGISTRY_TABLE BaseServerRegistryConfigurationTable[2] =
138 {
139 {
140 NULL,
141 RTL_QUERY_REGISTRY_DIRECT,
142 L"CSDVersion",
143 &BaseSrvCSDString,
144 REG_NONE, NULL, 0
145 },
146
147 {0}
148 };
149
150 /* Get the session ID */
151 SessionId = NtCurrentPeb()->SessionId;
152
153 /* Get the Windows directory */
154 RtlInitEmptyUnicodeString(&SystemRootString, Buffer, sizeof(Buffer));
155 Status = RtlExpandEnvironmentStrings_U(NULL,
156 &UnexpandedSystemRootString,
157 &SystemRootString,
158 NULL);
159 ASSERT(NT_SUCCESS(Status));
160
161 /* Create the base directory */
162 Buffer[SystemRootString.Length / sizeof(WCHAR)] = UNICODE_NULL;
163 Status = RtlCreateUnicodeString(&BaseSrvWindowsDirectory,
164 SystemRootString.Buffer);
165 ASSERT(NT_SUCCESS(Status));
166
167 /* Create the system directory */
168 wcscat(SystemRootString.Buffer, L"\\System32");
169 Status = RtlCreateUnicodeString(&BaseSrvWindowsSystemDirectory,
170 SystemRootString.Buffer);
171 ASSERT(NT_SUCCESS(Status));
172
173 /* FIXME: Check Session ID */
174 wcscpy(Buffer, L"\\BaseNamedObjects");
175 RtlInitUnicodeString(&BnoString, Buffer);
176
177 /* Allocate the server data */
178 BaseStaticServerData = RtlAllocateHeap(CsrSrvSharedSectionHeap,
179 HEAP_ZERO_MEMORY,
180 sizeof(BASE_STATIC_SERVER_DATA));
181 ASSERT(BaseStaticServerData != NULL);
182
183 /* Process timezone information */
184 BaseStaticServerData->TermsrvClientTimeZoneId = TIME_ZONE_ID_INVALID;
185 BaseStaticServerData->TermsrvClientTimeZoneChangeNum = 0;
186 Status = NtQuerySystemInformation(SystemTimeOfDayInformation,
187 &BaseStaticServerData->TimeOfDay,
188 sizeof(BaseStaticServerData->TimeOfDay),
189 NULL);
190 ASSERT(NT_SUCCESS(Status));
191
192 /* Make a shared heap copy of the Windows directory */
193 BaseStaticServerData->WindowsDirectory = BaseSrvWindowsDirectory;
194 HeapBuffer = RtlAllocateHeap(CsrSrvSharedSectionHeap,
195 0,
196 BaseSrvWindowsDirectory.MaximumLength);
197 ASSERT(HeapBuffer);
198 RtlCopyMemory(HeapBuffer,
199 BaseStaticServerData->WindowsDirectory.Buffer,
200 BaseSrvWindowsDirectory.MaximumLength);
201 BaseStaticServerData->WindowsDirectory.Buffer = HeapBuffer;
202
203 /* Make a shared heap copy of the System directory */
204 BaseStaticServerData->WindowsSystemDirectory = BaseSrvWindowsSystemDirectory;
205 HeapBuffer = RtlAllocateHeap(CsrSrvSharedSectionHeap,
206 0,
207 BaseSrvWindowsSystemDirectory.MaximumLength);
208 ASSERT(HeapBuffer);
209 RtlCopyMemory(HeapBuffer,
210 BaseStaticServerData->WindowsSystemDirectory.Buffer,
211 BaseSrvWindowsSystemDirectory.MaximumLength);
212 BaseStaticServerData->WindowsSystemDirectory.Buffer = HeapBuffer;
213
214 /* This string is not used */
215 RtlInitEmptyUnicodeString(&BaseStaticServerData->WindowsSys32x86Directory,
216 NULL,
217 0);
218
219 /* Make a shared heap copy of the BNO directory */
220 BaseStaticServerData->NamedObjectDirectory = BnoString;
221 BaseStaticServerData->NamedObjectDirectory.MaximumLength = BnoString.Length +
222 sizeof(UNICODE_NULL);
223 HeapBuffer = RtlAllocateHeap(CsrSrvSharedSectionHeap,
224 0,
225 BaseStaticServerData->NamedObjectDirectory.MaximumLength);
226 ASSERT(HeapBuffer);
227 RtlCopyMemory(HeapBuffer,
228 BaseStaticServerData->NamedObjectDirectory.Buffer,
229 BaseStaticServerData->NamedObjectDirectory.MaximumLength);
230 BaseStaticServerData->NamedObjectDirectory.Buffer = HeapBuffer;
231
232 /*
233 * Confirmed that in Windows, CSDNumber and RCNumber are actually Length
234 * and MaximumLength of the CSD String, since the same UNICODE_STRING is
235 * being queried twice, the first time as a ULONG!
236 *
237 * Somehow, in Windows this doesn't cause a buffer overflow, but it might
238 * in ReactOS, so this code is disabled until someone figures out WTF.
239 */
240 BaseStaticServerData->CSDNumber = 0;
241 BaseStaticServerData->RCNumber = 0;
242
243 /* Initialize the CSD string and query its value from the registry */
244 RtlInitEmptyUnicodeString(&BaseSrvCSDString, Buffer, sizeof(Buffer));
245 Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
246 L"",
247 BaseServerRegistryConfigurationTable,
248 NULL,
249 NULL);
250 if (NT_SUCCESS(Status))
251 {
252 /* Copy into the shared buffer */
253 wcsncpy(BaseStaticServerData->CSDVersion,
254 BaseSrvCSDString.Buffer,
255 BaseSrvCSDString.Length / sizeof(WCHAR));
256 }
257 else
258 {
259 /* NULL-terminate to indicate nothing is there */
260 BaseStaticServerData->CSDVersion[0] = UNICODE_NULL;
261 }
262
263 /* Cache the system information */
264 Status = NtQuerySystemInformation(SystemBasicInformation,
265 &BaseStaticServerData->SysInfo,
266 sizeof(BaseStaticServerData->SysInfo),
267 NULL);
268 ASSERT(NT_SUCCESS(Status));
269
270 /* FIXME: Should query the registry for these */
271 BaseStaticServerData->DefaultSeparateVDM = FALSE;
272 BaseStaticServerData->IsWowTaskReady = FALSE;
273
274 /* Allocate a security descriptor and create it */
275 BnoSd = RtlAllocateHeap(CsrHeap, 0, 1024);
276 ASSERT(BnoSd);
277 Status = RtlCreateSecurityDescriptor(BnoSd, SECURITY_DESCRIPTOR_REVISION);
278 ASSERT(NT_SUCCESS(Status));
279
280 /* Create the BNO and \Restricted DACLs */
281 Status = CreateBaseAcls(&BnoDacl, &BnoRestrictedDacl);
282 ASSERT(NT_SUCCESS(Status));
283
284 /* Set the BNO DACL as active for now */
285 Status = RtlSetDaclSecurityDescriptor(BnoSd, TRUE, BnoDacl, FALSE);
286 ASSERT(NT_SUCCESS(Status));
287
288 /* Create the BNO directory */
289 RtlInitUnicodeString(&BnoString, L"\\BaseNamedObjects");
290 InitializeObjectAttributes(&ObjectAttributes,
291 &BnoString,
292 OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
293 NULL,
294 BnoSd);
295 Status = NtCreateDirectoryObject(&BaseSrvNamedObjectDirectory,
296 DIRECTORY_ALL_ACCESS,
297 &ObjectAttributes);
298 ASSERT(NT_SUCCESS(Status));
299
300 /* Check if we are session 0 */
301 if (SessionId == 0)
302 {
303 /* Mark this as a session 0 directory */
304 Status = NtSetInformationObject(BaseSrvNamedObjectDirectory,
305 ObjectSessionInformation,
306 NULL,
307 0);
308 ASSERT(NT_SUCCESS(Status));
309 }
310
311 /* Check if LUID device maps are enabled */
312 Status = NtQueryInformationProcess(NtCurrentProcess(),
313 ProcessLUIDDeviceMapsEnabled,
314 &LuidEnabled,
315 sizeof(LuidEnabled),
316 NULL);
317 ASSERT(NT_SUCCESS(Status));
318 BaseStaticServerData->LUIDDeviceMapsEnabled = LuidEnabled;
319 if (!BaseStaticServerData->LUIDDeviceMapsEnabled)
320 {
321 /* Make Global point back to BNO */
322 RtlInitUnicodeString(&DirectoryName, L"Global");
323 RtlInitUnicodeString(&SymlinkName, L"\\BaseNamedObjects");
324 InitializeObjectAttributes(&ObjectAttributes,
325 &DirectoryName,
326 OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
327 BaseSrvNamedObjectDirectory,
328 BnoSd);
329 Status = NtCreateSymbolicLinkObject(&SymHandle,
330 SYMBOLIC_LINK_ALL_ACCESS,
331 &ObjectAttributes,
332 &SymlinkName);
333 if ((NT_SUCCESS(Status)) && SessionId == 0) NtClose(SymHandle);
334
335 /* Make local point back to \Sessions\x\BNO */
336 RtlInitUnicodeString(&DirectoryName, L"Local");
337 ASSERT(SessionId == 0);
338 InitializeObjectAttributes(&ObjectAttributes,
339 &DirectoryName,
340 OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
341 BaseSrvNamedObjectDirectory,
342 BnoSd);
343 Status = NtCreateSymbolicLinkObject(&SymHandle,
344 SYMBOLIC_LINK_ALL_ACCESS,
345 &ObjectAttributes,
346 &SymlinkName);
347 if ((NT_SUCCESS(Status)) && SessionId == 0) NtClose(SymHandle);
348
349 /* Make Session point back to BNOLINKS */
350 RtlInitUnicodeString(&DirectoryName, L"Session");
351 RtlInitUnicodeString(&SymlinkName, L"\\Sessions\\BNOLINKS");
352 InitializeObjectAttributes(&ObjectAttributes,
353 &DirectoryName,
354 OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
355 BaseSrvNamedObjectDirectory,
356 BnoSd);
357 Status = NtCreateSymbolicLinkObject(&SymHandle,
358 SYMBOLIC_LINK_ALL_ACCESS,
359 &ObjectAttributes,
360 &SymlinkName);
361 if ((NT_SUCCESS(Status)) && SessionId == 0) NtClose(SymHandle);
362
363 /* Create the BNO\Restricted directory and set the restricted DACL */
364 RtlInitUnicodeString(&DirectoryName, L"Restricted");
365 Status = RtlSetDaclSecurityDescriptor(BnoSd, TRUE, BnoRestrictedDacl, FALSE);
366 ASSERT(NT_SUCCESS(Status));
367 InitializeObjectAttributes(&ObjectAttributes,
368 &DirectoryName,
369 OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
370 BaseSrvNamedObjectDirectory,
371 BnoSd);
372 Status = NtCreateDirectoryObject(&BaseSrvRestrictedObjectDirectory,
373 DIRECTORY_ALL_ACCESS,
374 &ObjectAttributes);
375 ASSERT(NT_SUCCESS(Status));
376 }
377
378 /* Finally, set the pointer */
379 CsrSrvSharedStaticServerData[CSR_CONSOLE] = BaseStaticServerData;
380 }
381
382
383 VOID WINAPI BaseStaticServerThread(PVOID x)
384 {
385 NTSTATUS Status = STATUS_SUCCESS;
386 PPORT_MESSAGE Request = (PPORT_MESSAGE)x;
387 PPORT_MESSAGE Reply = NULL;
388 ULONG MessageType = 0;
389
390 DPRINT("BASESRV: %s called\n", __FUNCTION__);
391
392 MessageType = Request->u2.s2.Type;
393 DPRINT("BASESRV: %s received a message (Type=%d)\n",
394 __FUNCTION__, MessageType);
395 switch (MessageType)
396 {
397 default:
398 Reply = Request;
399 Status = NtReplyPort(BaseApiPort, Reply);
400 break;
401 }
402 }
403
404
405 CSR_SERVER_DLL_INIT(ServerDllInitialization)
406 {
407 // NTSTATUS Status = STATUS_SUCCESS;
408
409 /*
410 DPRINT("BASSRV: %s(%ld,...) called\n", __FUNCTION__, ArgumentCount);
411
412 BaseApiPort = CsrQueryApiPort ();
413 Status = CsrAddStaticServerThread(BaseStaticServerThread);
414 if (NT_SUCCESS(Status))
415 {
416 //TODO initialize the BASE server
417 }
418 return STATUS_SUCCESS;
419 */
420
421 /* Setup the DLL Object */
422 LoadedServerDll->ApiBase = BASESRV_FIRST_API_NUMBER; // ApiNumberBase
423 LoadedServerDll->HighestApiSupported = BasepMaxApiNumber; // MaxApiNumber
424 LoadedServerDll->DispatchTable = BaseServerApiDispatchTable;
425 LoadedServerDll->ValidTable = BaseServerApiServerValidTable;
426 LoadedServerDll->NameTable = BaseServerApiNameTable;
427 LoadedServerDll->SizeOfProcessData = 0;
428 LoadedServerDll->ConnectCallback = NULL;
429 LoadedServerDll->DisconnectCallback = NULL;
430
431 BasepFakeStaticServerData();
432
433 RtlInitializeCriticalSection(&BaseDefineDosDeviceCritSec);
434 InitializeListHead(&DosDeviceHistory);
435
436 /* All done */
437 return STATUS_SUCCESS;
438 }
439
440 BOOL
441 NTAPI
442 DllMain(IN HANDLE hDll,
443 IN DWORD dwReason,
444 IN LPVOID lpReserved)
445 {
446 UNREFERENCED_PARAMETER(dwReason);
447 UNREFERENCED_PARAMETER(lpReserved);
448
449 if (DLL_PROCESS_ATTACH == dwReason)
450 {
451 DllHandle = hDll;
452 }
453 else if (DLL_PROCESS_DETACH == dwReason)
454 {
455 BaseCleanupDefineDosDevice();
456 }
457
458 return TRUE;
459 }
460
461 /* EOF */