Fixed creation of environment variable SystemDrive.
[reactos.git] / reactos / subsys / smss / init.c
1 /* $Id: init.c,v 1.32 2002/03/18 22:44:42 hbirr Exp $
2 *
3 * init.c - Session Manager initialization
4 *
5 * ReactOS Operating System
6 *
7 * --------------------------------------------------------------------
8 *
9 * This software is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of the
12 * License, or (at your option) any later version.
13 *
14 * This software is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this software; see the file COPYING.LIB. If not, write
21 * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
22 * MA 02139, USA.
23 *
24 * --------------------------------------------------------------------
25 *
26 * 19990530 (Emanuele Aliberti)
27 * Compiled successfully with egcs 1.1.2
28 */
29 #include <ntos.h>
30 #include <ntdll/rtl.h>
31 #include <napi/lpc.h>
32 #include <napi/shared_data.h>
33
34 #include "smss.h"
35
36 #define NDEBUG
37
38 /* TYPES ********************************************************************/
39
40 /*
41 * NOTE: This is only used until the dos device links are
42 * read from the registry!!
43 */
44 typedef struct
45 {
46 PWSTR DeviceName;
47 PWSTR LinkName;
48 } LINKDATA, *PLINKDATA;
49
50 /* GLOBAL VARIABLES *********************************************************/
51
52 HANDLE SmApiPort = INVALID_HANDLE_VALUE;
53 HANDLE DbgSsApiPort = INVALID_HANDLE_VALUE;
54 HANDLE DbgUiApiPort = INVALID_HANDLE_VALUE;
55
56 PWSTR SmSystemEnvironment = NULL;
57
58
59 /* FUNCTIONS ****************************************************************/
60
61 static VOID
62 SmCreatePagingFiles (VOID)
63 {
64 UNICODE_STRING FileName;
65 LARGE_INTEGER InitialSize;
66 LARGE_INTEGER MaximumSize;
67 NTSTATUS Status;
68
69 /* FIXME: Read file names from registry */
70
71 RtlInitUnicodeString (&FileName,
72 L"\\SystemRoot\\pagefile.sys");
73
74 InitialSize.QuadPart = 50 * 4096;
75 MaximumSize.QuadPart = 80 * 4096;
76
77 Status = NtCreatePagingFile(&FileName,
78 &InitialSize,
79 &MaximumSize,
80 0);
81 if (!NT_SUCCESS(Status))
82 {
83 PrintString("SM: Failed to create paging file (Status was 0x%.8X)\n", Status);
84 }
85 }
86
87
88 static VOID
89 SmInitDosDevices(VOID)
90 {
91 OBJECT_ATTRIBUTES ObjectAttributes;
92 UNICODE_STRING DeviceName;
93 UNICODE_STRING LinkName;
94 HANDLE LinkHandle;
95 #if 0
96 HANDLE DeviceHandle;
97 IO_STATUS_BLOCK StatusBlock;
98 #endif
99 NTSTATUS Status;
100 WCHAR LinkBuffer[80];
101
102 PLINKDATA LinkPtr;
103 LINKDATA LinkData[] =
104 {{L"\\Device\\NamedPipe", L"PIPE"},
105 {L"\\Device\\Null", L"NUL"},
106 {L"\\Device\\Mup", L"UNC"},
107 {L"\\Device\\MailSlot", L"MAILSLOT"},
108 {L"\\DosDevices\\COM1", L"AUX"},
109 {L"\\DosDevices\\LPT1", L"PRN"},
110 {NULL, NULL}};
111
112 /* FIXME: Read the list of symbolic links from the registry!! */
113
114 LinkPtr = &LinkData[0];
115 while (LinkPtr->DeviceName != NULL)
116 {
117 swprintf(LinkBuffer, L"\\??\\%s",
118 LinkPtr->LinkName);
119 RtlInitUnicodeString(&LinkName,
120 LinkBuffer);
121 RtlInitUnicodeString(&DeviceName,
122 LinkPtr->DeviceName);
123
124 #if 0
125 /* check if target device exists (can be opened) */
126 InitializeObjectAttributes(&ObjectAttributes,
127 &DeviceName,
128 0,
129 NULL,
130 NULL);
131
132 Status = NtOpenFile(&DeviceHandle,
133 0x10001,
134 &ObjectAttributes,
135 &StatusBlock,
136 1,
137 FILE_SYNCHRONOUS_IO_NONALERT);
138 if (NT_SUCCESS(Status))
139 {
140 NtClose(DeviceHandle);
141 #endif
142 /* create symbolic link */
143 InitializeObjectAttributes(&ObjectAttributes,
144 &LinkName,
145 OBJ_PERMANENT,
146 NULL,
147 NULL);
148
149 Status = NtCreateSymbolicLinkObject(&LinkHandle,
150 SYMBOLIC_LINK_ALL_ACCESS,
151 &ObjectAttributes,
152 &DeviceName);
153 if (!NT_SUCCESS(Status))
154 {
155 PrintString("SM: NtCreateSymbolicLink( %wZ --> %wZ ) failed!\n",
156 &LinkName,
157 &DeviceName);
158 }
159 NtClose(LinkHandle);
160 #if 0
161 }
162 #endif
163 LinkPtr++;
164 }
165 }
166
167
168 static VOID
169 SmSetEnvironmentVariables (VOID)
170 {
171 UNICODE_STRING EnvVariable;
172 UNICODE_STRING EnvValue;
173 UNICODE_STRING EnvExpandedValue;
174 ULONG ExpandedLength;
175 WCHAR ExpandBuffer[512];
176 WCHAR ValueBuffer[MAX_PATH];
177 PKUSER_SHARED_DATA SharedUserData =
178 (PKUSER_SHARED_DATA)USER_SHARED_DATA_BASE;
179
180 /*
181 * The following environment variables are read from the registry.
182 * Because the registry does not work yet, the environment variables
183 * are set one by one, using information from the shared user page.
184 *
185 * Variables (example):
186 * SystemRoot = C:\reactos
187 * SystemDrive = C:
188 *
189 * OS = ReactOS
190 * Path = %SystemRoot%\system32;%SystemRoot%
191 * windir = %SystemRoot%
192 */
193
194 /* copy system root into value buffer */
195 wcscpy (ValueBuffer, SharedUserData->NtSystemRoot);
196
197 /* set "SystemRoot = C:\reactos" */
198 RtlInitUnicodeString (&EnvVariable,
199 L"SystemRoot");
200 RtlInitUnicodeString (&EnvValue,
201 ValueBuffer);
202 RtlSetEnvironmentVariable (&SmSystemEnvironment,
203 &EnvVariable,
204 &EnvValue);
205
206 /* cut off trailing path */
207 ValueBuffer[2] = 0;
208
209 /* Set "SystemDrive = C:" */
210 RtlInitUnicodeString (&EnvVariable,
211 L"SystemDrive");
212 RtlInitUnicodeString (&EnvValue,
213 ValueBuffer);
214 RtlSetEnvironmentVariable (&SmSystemEnvironment,
215 &EnvVariable,
216 &EnvValue);
217
218
219 /* Set "OS = ReactOS" */
220 RtlInitUnicodeString (&EnvVariable,
221 L"OS");
222 RtlInitUnicodeString (&EnvValue,
223 L"ReactOS");
224 RtlSetEnvironmentVariable (&SmSystemEnvironment,
225 &EnvVariable,
226 &EnvValue);
227
228
229 /* Set "Path = %SystemRoot%\system32;%SystemRoot%" */
230 RtlInitUnicodeString (&EnvVariable,
231 L"Path");
232 RtlInitUnicodeString (&EnvValue,
233 L"%SystemRoot%\\system32;%SystemRoot%");
234 EnvExpandedValue.Length = 0;
235 EnvExpandedValue.MaximumLength = 512 * sizeof(WCHAR);
236 EnvExpandedValue.Buffer = ExpandBuffer;
237 *ExpandBuffer = 0;
238 RtlExpandEnvironmentStrings_U (SmSystemEnvironment,
239 &EnvValue,
240 &EnvExpandedValue,
241 &ExpandedLength);
242 RtlSetEnvironmentVariable (&SmSystemEnvironment,
243 &EnvVariable,
244 &EnvExpandedValue);
245
246 /* Set "windir = %SystemRoot%" */
247 RtlInitUnicodeString (&EnvVariable,
248 L"windir");
249 RtlInitUnicodeString (&EnvValue,
250 L"%SystemRoot%");
251 EnvExpandedValue.Length = 0;
252 EnvExpandedValue.MaximumLength = 512 * sizeof(WCHAR);
253 EnvExpandedValue.Buffer = ExpandBuffer;
254 *ExpandBuffer = 0;
255 RtlExpandEnvironmentStrings_U (SmSystemEnvironment,
256 &EnvValue,
257 &EnvExpandedValue,
258 &ExpandedLength);
259 RtlSetEnvironmentVariable (&SmSystemEnvironment,
260 &EnvVariable,
261 &EnvExpandedValue);
262 }
263
264
265 BOOL InitSessionManager (HANDLE Children[])
266 {
267 NTSTATUS Status;
268 UNICODE_STRING UnicodeString;
269 OBJECT_ATTRIBUTES ObjectAttributes;
270 UNICODE_STRING CmdLineW;
271 PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
272 RTL_PROCESS_INFO ProcessInfo;
273 HANDLE CsrssInitEvent;
274 HANDLE WindowsDirectory;
275 WCHAR UnicodeBuffer[MAX_PATH];
276 PKUSER_SHARED_DATA SharedUserData =
277 (PKUSER_SHARED_DATA)USER_SHARED_DATA_BASE;
278
279 /*
280 * FIXME: The '\Windows' directory is created by csrss.exe but
281 * win32k.sys needs it at intialization and it is loaded
282 * before csrss.exe
283 */
284
285 /*
286 * Create the '\Windows' directory
287 */
288 RtlInitUnicodeString(&UnicodeString,
289 L"\\Windows");
290
291 InitializeObjectAttributes(&ObjectAttributes,
292 &UnicodeString,
293 0,
294 NULL,
295 NULL);
296
297 Status = ZwCreateDirectoryObject(&WindowsDirectory,
298 0,
299 &ObjectAttributes);
300 if (!NT_SUCCESS(Status))
301 {
302 DisplayString(L"SM: Could not create \\Windows directory!\n");
303 return FALSE;
304 }
305
306 /* Create the "\SmApiPort" object (LPC) */
307 RtlInitUnicodeString(&UnicodeString,
308 L"\\SmApiPort");
309 InitializeObjectAttributes(&ObjectAttributes,
310 &UnicodeString,
311 PORT_ALL_ACCESS,
312 NULL,
313 NULL);
314
315 Status = NtCreatePort(&SmApiPort,
316 &ObjectAttributes,
317 0,
318 0,
319 0);
320 if (!NT_SUCCESS(Status))
321 {
322 return FALSE;
323 }
324
325 #ifndef NDEBUG
326 DisplayString (L"SM: \\SmApiPort created...\n");
327 #endif
328
329 /* Create two threads for "\SmApiPort" */
330 RtlCreateUserThread(NtCurrentProcess(),
331 NULL,
332 FALSE,
333 0,
334 NULL,
335 NULL,
336 (PTHREAD_START_ROUTINE)SmApiThread,
337 (PVOID)SmApiPort,
338 NULL,
339 NULL);
340
341 RtlCreateUserThread (NtCurrentProcess (),
342 NULL,
343 FALSE,
344 0,
345 NULL,
346 NULL,
347 (PTHREAD_START_ROUTINE)SmApiThread,
348 (PVOID)SmApiPort,
349 NULL,
350 NULL);
351
352 /* Create the system environment */
353 Status = RtlCreateEnvironment(FALSE,
354 &SmSystemEnvironment);
355 if (!NT_SUCCESS(Status))
356 {
357 return FALSE;
358 }
359 #ifndef NDEBUG
360 DisplayString (L"SM: System Environment created\n");
361 #endif
362
363 /* Define symbolic links to kernel devices (MS-DOS names) */
364 SmInitDosDevices();
365
366 /* FIXME: Run all programs in the boot execution list */
367 // SmRunBootApps();
368
369 /* FIXME: Process the file rename list */
370 // SmProcessFileRenameList();
371
372 /* FIXME: Load the well known DLLs */
373 // SmPreloadDlls();
374
375 /* Create paging files */
376 SmCreatePagingFiles();
377
378 /* Load remaining registry hives */
379 NtInitializeRegistry(FALSE);
380
381 /* Set environment variables from registry */
382 SmSetEnvironmentVariables();
383
384 /* Load the kernel mode driver win32k.sys */
385 RtlInitUnicodeString(&CmdLineW,
386 L"\\SystemRoot\\system32\\drivers\\win32k.sys");
387 Status = NtLoadDriver(&CmdLineW);
388 #if 0
389 if (!NT_SUCCESS(Status))
390 {
391 return FALSE;
392 }
393 #endif
394
395 /* Run csrss.exe */
396 RtlInitUnicodeString(&UnicodeString,
397 L"\\CsrssInitDone");
398 InitializeObjectAttributes(&ObjectAttributes,
399 &UnicodeString,
400 EVENT_ALL_ACCESS,
401 0,
402 NULL);
403 Status = NtCreateEvent(&CsrssInitEvent,
404 EVENT_ALL_ACCESS,
405 &ObjectAttributes,
406 TRUE,
407 FALSE);
408 if (!NT_SUCCESS(Status))
409 {
410 DbgPrint("Failed to create csrss notification event\n");
411 }
412
413 /*
414 * Start the Win32 subsystem (csrss.exe)
415 */
416
417 /* initialize executable path */
418 wcscpy(UnicodeBuffer, L"\\??\\");
419 wcscat(UnicodeBuffer, SharedUserData->NtSystemRoot);
420 wcscat(UnicodeBuffer, L"\\system32\\csrss.exe");
421 RtlInitUnicodeString(&UnicodeString,
422 UnicodeBuffer);
423
424 RtlCreateProcessParameters(&ProcessParameters,
425 &UnicodeString,
426 NULL,
427 NULL,
428 NULL,
429 SmSystemEnvironment,
430 NULL,
431 NULL,
432 NULL,
433 NULL);
434
435 Status = RtlCreateUserProcess(&UnicodeString,
436 OBJ_CASE_INSENSITIVE,
437 ProcessParameters,
438 NULL,
439 NULL,
440 NULL,
441 FALSE,
442 NULL,
443 NULL,
444 &ProcessInfo);
445
446 RtlDestroyProcessParameters (ProcessParameters);
447
448 if (!NT_SUCCESS(Status))
449 {
450 DisplayString(L"SM: Loading csrss.exe failed!\n");
451 return FALSE;
452 }
453
454 NtWaitForSingleObject(CsrssInitEvent,
455 FALSE,
456 NULL);
457
458 Children[CHILD_CSRSS] = ProcessInfo.ProcessHandle;
459
460 /*
461 * Start the logon process (winlogon.exe)
462 */
463
464 /* initialize executable path */
465 wcscpy(UnicodeBuffer, L"\\??\\");
466 wcscat(UnicodeBuffer, SharedUserData->NtSystemRoot);
467 wcscat(UnicodeBuffer, L"\\system32\\winlogon.exe");
468 RtlInitUnicodeString(&UnicodeString,
469 UnicodeBuffer);
470
471 RtlCreateProcessParameters(&ProcessParameters,
472 &UnicodeString,
473 NULL,
474 NULL,
475 NULL,
476 SmSystemEnvironment,
477 NULL,
478 NULL,
479 NULL,
480 NULL);
481
482 Status = RtlCreateUserProcess(&UnicodeString,
483 OBJ_CASE_INSENSITIVE,
484 ProcessParameters,
485 NULL,
486 NULL,
487 NULL,
488 FALSE,
489 NULL,
490 NULL,
491 &ProcessInfo);
492
493 RtlDestroyProcessParameters(ProcessParameters);
494
495 if (!NT_SUCCESS(Status))
496 {
497 DisplayString(L"SM: Loading winlogon.exe failed!\n");
498 NtTerminateProcess(Children[CHILD_CSRSS],
499 0);
500 return FALSE;
501 }
502 Children[CHILD_WINLOGON] = ProcessInfo.ProcessHandle;
503
504 /* Create the \DbgSsApiPort object (LPC) */
505 RtlInitUnicodeString(&UnicodeString,
506 L"\\DbgSsApiPort");
507 InitializeObjectAttributes(&ObjectAttributes,
508 &UnicodeString,
509 PORT_ALL_ACCESS,
510 NULL,
511 NULL);
512
513 Status = NtCreatePort(&DbgSsApiPort,
514 &ObjectAttributes,
515 0,
516 0,
517 0);
518
519 if (!NT_SUCCESS(Status))
520 {
521 return FALSE;
522 }
523 #ifndef NDEBUG
524 DisplayString(L"SM: DbgSsApiPort created...\n");
525 #endif
526
527 /* Create the \DbgUiApiPort object (LPC) */
528 RtlInitUnicodeString(&UnicodeString,
529 L"\\DbgUiApiPort");
530 InitializeObjectAttributes(&ObjectAttributes,
531 &UnicodeString,
532 PORT_ALL_ACCESS,
533 NULL,
534 NULL);
535
536 Status = NtCreatePort(&DbgUiApiPort,
537 &ObjectAttributes,
538 0,
539 0,
540 0);
541 if (!NT_SUCCESS(Status))
542 {
543 return FALSE;
544 }
545 #ifndef NDEBUG
546 DisplayString (L"SM: DbgUiApiPort created...\n");
547 #endif
548
549 return TRUE;
550 }
551
552 /* EOF */