update for HEAD-2003091401
[reactos.git] / subsys / smss / init.c
1 /* $Id$
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
30 /* INCLUDES *****************************************************************/
31
32 #include <ntos.h>
33 #include <ntdll/rtl.h>
34 #include <ntdll/ldr.h>
35 #include <napi/lpc.h>
36
37 #include "smss.h"
38
39 #define NDEBUG
40 #include <debug.h>
41
42 /* GLOBALS ******************************************************************/
43
44 HANDLE DbgSsApiPort = INVALID_HANDLE_VALUE;
45 HANDLE DbgUiApiPort = INVALID_HANDLE_VALUE;
46
47 PWSTR SmSystemEnvironment = NULL;
48
49
50 /* FUNCTIONS ****************************************************************/
51
52 static NTSTATUS STDCALL
53 SmObjectDirectoryQueryRoutine(PWSTR ValueName,
54                               ULONG ValueType,
55                               PVOID ValueData,
56                               ULONG ValueLength,
57                               PVOID Context,
58                               PVOID EntryContext)
59 {
60   OBJECT_ATTRIBUTES ObjectAttributes;
61   UNICODE_STRING UnicodeString;
62   HANDLE WindowsDirectory;
63   NTSTATUS Status = STATUS_SUCCESS;
64
65 #ifndef NDEBUG
66   DbgPrint("ValueName '%S'  Type %lu  Length %lu\n", ValueName, ValueType, ValueLength);
67   DbgPrint("ValueData '%S'\n", (PWSTR)ValueData);
68 #endif
69   if (ValueType != REG_SZ)
70     {
71       return(STATUS_SUCCESS);
72     }
73
74   RtlInitUnicodeString(&UnicodeString,
75                        (PWSTR)ValueData);
76
77   InitializeObjectAttributes(&ObjectAttributes,
78                              &UnicodeString,
79                              0,
80                              NULL,
81                              NULL);
82
83   Status = ZwCreateDirectoryObject(&WindowsDirectory,
84                                    0,
85                                    &ObjectAttributes);
86
87   return(Status);
88 }
89
90
91 static NTSTATUS
92 SmCreateObjectDirectories(VOID)
93 {
94   RTL_QUERY_REGISTRY_TABLE QueryTable[2];
95   NTSTATUS Status;
96
97   RtlZeroMemory(&QueryTable,
98                 sizeof(QueryTable));
99
100   QueryTable[0].Name = L"ObjectDirectories";
101   QueryTable[0].QueryRoutine = SmObjectDirectoryQueryRoutine;
102
103   Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
104                                   L"\\Session Manager",
105                                   QueryTable,
106                                   NULL,
107                                   NULL);
108
109   return(Status);
110 }
111
112
113 static NTSTATUS STDCALL
114 SmDosDevicesQueryRoutine(PWSTR ValueName,
115                          ULONG ValueType,
116                          PVOID ValueData,
117                          ULONG ValueLength,
118                          PVOID Context,
119                          PVOID EntryContext)
120 {
121   OBJECT_ATTRIBUTES ObjectAttributes;
122   UNICODE_STRING DeviceName;
123   UNICODE_STRING LinkName;
124   HANDLE LinkHandle;
125   WCHAR LinkBuffer[80];
126   NTSTATUS Status;
127
128   DPRINT("ValueName '%S'  Type %lu  Length %lu\n", ValueName, ValueType, ValueLength);
129   DPRINT("ValueData '%S'\n", (PWSTR)ValueData);
130
131   if (ValueType != REG_SZ)
132     {
133       return(STATUS_SUCCESS);
134     }
135
136   swprintf(LinkBuffer,
137            L"\\??\\%s",
138            ValueName);
139   RtlInitUnicodeString(&LinkName,
140                        LinkBuffer);
141   RtlInitUnicodeString(&DeviceName,
142                        (PWSTR)ValueData);
143
144   DPRINT("SM: Linking %wZ --> %wZ\n",
145               &LinkName,
146               &DeviceName);
147
148   /* create symbolic link */
149   InitializeObjectAttributes(&ObjectAttributes,
150                              &LinkName,
151                              OBJ_PERMANENT,
152                              NULL,
153                              NULL);
154   Status = NtCreateSymbolicLinkObject(&LinkHandle,
155                                       SYMBOLIC_LINK_ALL_ACCESS,
156                                       &ObjectAttributes,
157                                       &DeviceName);
158   if (!NT_SUCCESS(Status))
159     {
160       DPRINT1("SmDosDevicesQueryRoutine: NtCreateSymbolicLink( %wZ --> %wZ ) failed!\n",
161                   &LinkName,
162                   &DeviceName);
163     }
164   NtClose(LinkHandle);
165
166   return(Status);
167 }
168
169
170 static NTSTATUS
171 SmInitDosDevices(VOID)
172 {
173   RTL_QUERY_REGISTRY_TABLE QueryTable[2];
174   NTSTATUS Status;
175
176   RtlZeroMemory(&QueryTable,
177                 sizeof(QueryTable));
178
179   QueryTable[0].QueryRoutine = SmDosDevicesQueryRoutine;
180
181   Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
182                                   L"\\Session Manager\\DOS Devices",
183                                   QueryTable,
184                                   NULL,
185                                   NULL);
186   return(Status);
187 }
188
189
190 static NTSTATUS STDCALL
191 SmRunBootAppsQueryRoutine(PWSTR ValueName,
192                           ULONG ValueType,
193                           PVOID ValueData,
194                           ULONG ValueLength,
195                           PVOID Context,
196                           PVOID EntryContext)
197 {
198   PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
199   RTL_PROCESS_INFO ProcessInfo;
200   UNICODE_STRING ImagePathString;
201   UNICODE_STRING CommandLineString;
202   WCHAR Description[256];
203   WCHAR ImageName[256];
204   WCHAR ImagePath[256];
205   WCHAR CommandLine[256];
206   PWSTR p1, p2;
207   ULONG len;
208   NTSTATUS Status;
209
210   DPRINT("ValueName '%S'  Type %lu  Length %lu\n", ValueName, ValueType, ValueLength);
211   DPRINT("ValueData '%S'\n", (PWSTR)ValueData);
212
213   if (ValueType != REG_SZ)
214     {
215       return(STATUS_SUCCESS);
216     }
217
218   /* Extract the description */
219   p1 = wcschr((PWSTR)ValueData, L' ');
220   len = p1 - (PWSTR)ValueData;
221   memcpy(Description,ValueData, len * sizeof(WCHAR));
222   Description[len] = 0;
223
224   /* Extract the image name */
225   p1++;
226   p2 = wcschr(p1, L' ');
227   if (p2 != NULL)
228     len = p2 - p1;
229   else
230     len = wcslen(p1);
231   memcpy(ImageName, p1, len * sizeof(WCHAR));
232   ImageName[len] = 0;
233
234   /* Extract the command line */
235   if (p2 == NULL)
236     {
237       CommandLine[0] = 0;
238     }
239   else
240     {
241       p2++;
242       wcscpy(CommandLine, p2);
243     }
244
245   DPRINT("Running %S...\n", Description);
246   DPRINT("ImageName: '%S'\n", ImageName);
247   DPRINT("CommandLine: '%S'\n", CommandLine);
248
249   /* initialize executable path */
250   wcscpy(ImagePath, L"\\SystemRoot\\system32\\");
251   wcscat(ImagePath, ImageName);
252   wcscat(ImagePath, L".exe");
253
254   RtlInitUnicodeString(&ImagePathString,
255                        ImagePath);
256
257   RtlInitUnicodeString(&CommandLineString,
258                        CommandLine);
259
260   RtlCreateProcessParameters(&ProcessParameters,
261                              &ImagePathString,
262                              NULL,
263                              NULL,
264                              &CommandLineString,
265                              NULL,
266                              NULL,
267                              NULL,
268                              NULL,
269                              NULL);
270
271   Status = RtlCreateUserProcess(&ImagePathString,
272                                 OBJ_CASE_INSENSITIVE,
273                                 ProcessParameters,
274                                 NULL,
275                                 NULL,
276                                 NULL,
277                                 FALSE,
278                                 NULL,
279                                 NULL,
280                                 &ProcessInfo);
281   if (!NT_SUCCESS(Status))
282     {
283       DPRINT1("Running %s failed (Status %lx)\n", Description, Status);
284       return(STATUS_SUCCESS);
285     }
286
287   RtlDestroyProcessParameters(ProcessParameters);
288
289   /* Wait for process termination */
290   NtWaitForSingleObject(ProcessInfo.ProcessHandle,
291                         FALSE,
292                         NULL);
293
294   NtClose(ProcessInfo.ThreadHandle);
295   NtClose(ProcessInfo.ProcessHandle);
296
297   return(STATUS_SUCCESS);
298 }
299
300
301 /*
302  * Run native applications listed in the registry.
303  *
304  *  Key:
305  *    \Registry\Machine\SYSTEM\CurrentControlSet\Control\Session Manager
306  *
307  *  Value (format: "<description> <executable> <command line>":
308  *    BootExecute = "autocheck autochk *"
309  */
310 static NTSTATUS
311 SmRunBootApps(VOID)
312 {
313   RTL_QUERY_REGISTRY_TABLE QueryTable[2];
314   NTSTATUS Status;
315
316   RtlZeroMemory(&QueryTable,
317                 sizeof(QueryTable));
318
319   QueryTable[0].Name = L"BootExecute";
320   QueryTable[0].QueryRoutine = SmRunBootAppsQueryRoutine;
321
322   Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
323                                   L"\\Session Manager",
324                                   QueryTable,
325                                   NULL,
326                                   NULL);
327   if (!NT_SUCCESS(Status))
328     {
329       DPRINT1("SmRunBootApps: RtlQueryRegistryValues() failed! (Status %lx)\n", Status);
330     }
331
332   return(Status);
333 }
334
335
336 static NTSTATUS
337 SmProcessFileRenameList(VOID)
338 {
339   DPRINT("SmProcessFileRenameList() called\n");
340
341   /* FIXME: implement it! */
342
343   DPRINT("SmProcessFileRenameList() done\n");
344
345   return(STATUS_SUCCESS);
346 }
347
348
349 static NTSTATUS STDCALL
350 SmKnownDllsQueryRoutine(PWSTR ValueName,
351                         ULONG ValueType,
352                         PVOID ValueData,
353                         ULONG ValueLength,
354                         PVOID Context,
355                         PVOID EntryContext)
356 {
357   OBJECT_ATTRIBUTES ObjectAttributes;
358   IO_STATUS_BLOCK IoStatusBlock;
359   UNICODE_STRING ImageName;
360   HANDLE FileHandle;
361   HANDLE SectionHandle;
362   NTSTATUS Status;
363
364   DPRINT("ValueName '%S'  Type %lu  Length %lu\n", ValueName, ValueType, ValueLength);
365   DPRINT("ValueData '%S'  Context %p  EntryContext %p\n", (PWSTR)ValueData, Context, EntryContext);
366
367   /* Ignore the 'DllDirectory' value */
368   if (!_wcsicmp(ValueName, L"DllDirectory"))
369     return STATUS_SUCCESS;
370
371   /* Open the DLL image file */
372   RtlInitUnicodeString(&ImageName,
373                        ValueData);
374   InitializeObjectAttributes(&ObjectAttributes,
375                              &ImageName,
376                              OBJ_CASE_INSENSITIVE,
377                              (HANDLE)Context,
378                              NULL);
379   Status = NtOpenFile(&FileHandle,
380                       SYNCHRONIZE | FILE_EXECUTE,
381                       &ObjectAttributes,
382                       &IoStatusBlock,
383                       FILE_SHARE_READ,
384                       FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
385   if (!NT_SUCCESS(Status))
386     {
387       DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
388       return STATUS_SUCCESS;
389     }
390
391   DPRINT("Opened file %wZ successfully\n", &ImageName);
392
393   /* Check for valid image checksum */
394   Status = LdrVerifyImageMatchesChecksum (FileHandle,
395                                           0,
396                                           0,
397                                           0);
398   if (Status == STATUS_IMAGE_CHECKSUM_MISMATCH)
399     {
400       /* Raise a hard error (crash the system/BSOD) */
401       NtRaiseHardError (Status,
402                         0,
403                         0,
404                         0,
405                         0,
406                         0);
407     }
408   else if (!NT_SUCCESS(Status))
409     {
410       DPRINT1("Failed to check the image checksum\n");
411
412       NtClose(SectionHandle);
413       NtClose(FileHandle);
414
415       return STATUS_SUCCESS;
416     }
417
418   InitializeObjectAttributes(&ObjectAttributes,
419                              &ImageName,
420                              OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
421                              (HANDLE)EntryContext,
422                              NULL);
423   Status = NtCreateSection(&SectionHandle,
424                            SECTION_ALL_ACCESS,
425                            &ObjectAttributes,
426                            NULL,
427                            PAGE_EXECUTE,
428                            SEC_IMAGE,
429                            FileHandle);
430   if (NT_SUCCESS(Status))
431     {
432       DPRINT("Created section successfully\n");
433       NtClose(SectionHandle);
434     }
435
436   NtClose(FileHandle);
437
438   return STATUS_SUCCESS;
439 }
440
441
442 static NTSTATUS
443 SmLoadKnownDlls(VOID)
444 {
445   RTL_QUERY_REGISTRY_TABLE QueryTable[2];
446   OBJECT_ATTRIBUTES ObjectAttributes;
447   IO_STATUS_BLOCK IoStatusBlock;
448   UNICODE_STRING DllDosPath;
449   UNICODE_STRING DllNtPath;
450   UNICODE_STRING Name;
451   HANDLE ObjectDirHandle;
452   HANDLE FileDirHandle;
453   HANDLE SymlinkHandle;
454   NTSTATUS Status;
455
456   DPRINT("SmLoadKnownDlls() called\n");
457
458   /* Create 'KnownDlls' object directory */
459   RtlInitUnicodeString(&Name,
460                        L"\\KnownDlls");
461   InitializeObjectAttributes(&ObjectAttributes,
462                              &Name,
463                              OBJ_PERMANENT | OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
464                              NULL,
465                              NULL);
466   Status = NtCreateDirectoryObject(&ObjectDirHandle,
467                                    DIRECTORY_ALL_ACCESS,
468                                    &ObjectAttributes);
469   if (!NT_SUCCESS(Status))
470     {
471       DPRINT1("NtCreateDirectoryObject() failed (Status %lx)\n", Status);
472       return Status;
473     }
474
475   RtlInitUnicodeString(&DllDosPath, NULL);
476
477   RtlZeroMemory(&QueryTable,
478                 sizeof(QueryTable));
479
480   QueryTable[0].Name = L"DllDirectory";
481   QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
482   QueryTable[0].EntryContext = &DllDosPath;
483
484   Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
485                                   L"\\Session Manager\\KnownDlls",
486                                   QueryTable,
487                                   NULL,
488                                   SmSystemEnvironment);
489   if (!NT_SUCCESS(Status))
490     {
491       DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
492       return Status;
493     }
494
495   DPRINT("DllDosPath: '%wZ'\n", &DllDosPath);
496
497   if (!RtlDosPathNameToNtPathName_U(DllDosPath.Buffer,
498                                     &DllNtPath,
499                                     NULL,
500                                     NULL))
501     {
502       DPRINT1("RtlDosPathNameToNtPathName_U() failed\n");
503       return STATUS_OBJECT_NAME_INVALID;
504     }
505
506   DPRINT("DllNtPath: '%wZ'\n", &DllNtPath);
507
508   /* Open the dll path directory */
509   InitializeObjectAttributes(&ObjectAttributes,
510                              &DllNtPath,
511                              OBJ_CASE_INSENSITIVE,
512                              NULL,
513                              NULL);
514   Status = NtOpenFile(&FileDirHandle,
515                       SYNCHRONIZE | FILE_READ_DATA,
516                       &ObjectAttributes,
517                       &IoStatusBlock,
518                       FILE_SHARE_READ | FILE_SHARE_WRITE,
519                       FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE);
520   if (!NT_SUCCESS(Status))
521     {
522       DPRINT("NtOpenFile() failed (Status %lx)\n", Status);
523       return Status;
524     }
525
526   /* Link 'KnownDllPath' the dll path directory */
527   RtlInitUnicodeString(&Name,
528                        L"KnownDllPath");
529   InitializeObjectAttributes(&ObjectAttributes,
530                              &Name,
531                              OBJ_PERMANENT | OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
532                              ObjectDirHandle,
533                              NULL);
534   Status = NtCreateSymbolicLinkObject(&SymlinkHandle,
535                                       SYMBOLIC_LINK_ALL_ACCESS,
536                                       &ObjectAttributes,
537                                       &DllDosPath);
538   if (!NT_SUCCESS(Status))
539     {
540       DPRINT1("NtCreateSymbolicLink() failed (Status %lx)\n", Status);
541       return Status;
542     }
543
544   NtClose(SymlinkHandle);
545
546   RtlZeroMemory(&QueryTable,
547                 sizeof(QueryTable));
548
549   QueryTable[0].QueryRoutine = SmKnownDllsQueryRoutine;
550   QueryTable[0].EntryContext = ObjectDirHandle;
551
552   Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
553                                   L"\\Session Manager\\KnownDlls",
554                                   QueryTable,
555                                   (PVOID)FileDirHandle,
556                                   NULL);
557   if (!NT_SUCCESS(Status))
558     {
559       DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
560     }
561
562   DPRINT("SmLoadKnownDlls() done\n");
563
564   return Status;
565 }
566
567
568 static NTSTATUS STDCALL
569 SmPagingFilesQueryRoutine(PWSTR ValueName,
570                           ULONG ValueType,
571                           PVOID ValueData,
572                           ULONG ValueLength,
573                           PVOID Context,
574                           PVOID EntryContext)
575 {
576   UNICODE_STRING FileName;
577   LARGE_INTEGER InitialSize;
578   LARGE_INTEGER MaximumSize;
579   NTSTATUS Status;
580   LPWSTR p;
581
582   DPRINT("ValueName '%S'  Type %lu  Length %lu\n", ValueName, ValueType, ValueLength);
583   DPRINT("ValueData '%S'\n", (PWSTR)ValueData);
584
585   if (ValueType != REG_SZ)
586     {
587       return(STATUS_SUCCESS);
588     }
589
590   /*
591    * Format: "<path>[ <initial_size>[ <maximum_size>]]"
592    */
593   if ((p = wcschr(ValueData, ' ')) != NULL)
594     {
595       *p = L'\0';
596       InitialSize.QuadPart = wcstoul(p + 1, &p, 0) * 256 * 4096;
597       if (*p == ' ')
598         {
599           MaximumSize.QuadPart = wcstoul(p + 1, NULL, 0) * 256 * 4096;
600         }
601       else
602         MaximumSize = InitialSize;
603     }
604   else
605     {
606       InitialSize.QuadPart = 50 * 4096;
607       MaximumSize.QuadPart = 80 * 4096;
608     }
609
610   if (!RtlDosPathNameToNtPathName_U ((LPWSTR)ValueData,
611                                      &FileName,
612                                      NULL,
613                                      NULL))
614     {
615       return (STATUS_SUCCESS);
616     }
617
618   DbgPrint("SMSS: Created paging file %wZ with size %dKB\n",
619            &FileName, InitialSize.QuadPart / 1024);
620   Status = NtCreatePagingFile(&FileName,
621                               &InitialSize,
622                               &MaximumSize,
623                               0);
624
625   RtlFreeUnicodeString(&FileName);
626
627   return(STATUS_SUCCESS);
628 }
629
630
631 static NTSTATUS
632 SmCreatePagingFiles(VOID)
633 {
634   RTL_QUERY_REGISTRY_TABLE QueryTable[2];
635   NTSTATUS Status;
636
637   RtlZeroMemory(&QueryTable,
638                 sizeof(QueryTable));
639
640   QueryTable[0].Name = L"PagingFiles";
641   QueryTable[0].QueryRoutine = SmPagingFilesQueryRoutine;
642
643   Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
644                                   L"\\Session Manager\\Memory Management",
645                                   QueryTable,
646                                   NULL,
647                                   NULL);
648
649   return(Status);
650 }
651
652
653 static NTSTATUS STDCALL
654 SmEnvironmentQueryRoutine(PWSTR ValueName,
655                           ULONG ValueType,
656                           PVOID ValueData,
657                           ULONG ValueLength,
658                           PVOID Context,
659                           PVOID EntryContext)
660 {
661   UNICODE_STRING EnvVariable;
662   UNICODE_STRING EnvValue;
663
664   DPRINT("ValueName '%S'  Type %lu  Length %lu\n", ValueName, ValueType, ValueLength);
665   DPRINT("ValueData '%S'\n", (PWSTR)ValueData);
666
667   if (ValueType != REG_SZ)
668     {
669       return(STATUS_SUCCESS);
670     }
671
672   RtlInitUnicodeString(&EnvVariable,
673                        ValueName);
674   RtlInitUnicodeString(&EnvValue,
675                        (PWSTR)ValueData);
676   RtlSetEnvironmentVariable(Context,
677                             &EnvVariable,
678                             &EnvValue);
679
680   return(STATUS_SUCCESS);
681 }
682
683
684 static NTSTATUS
685 SmSetEnvironmentVariables(VOID)
686 {
687   RTL_QUERY_REGISTRY_TABLE QueryTable[2];
688   UNICODE_STRING EnvVariable;
689   UNICODE_STRING EnvValue;
690   WCHAR ValueBuffer[MAX_PATH];
691   NTSTATUS Status;
692
693   /*
694    * The following environment variables must be set prior to reading
695    * other variables from the registry.
696    *
697    * Variables (example):
698    *    SystemRoot = "C:\reactos"
699    *    SystemDrive = "C:"
700    */
701
702   /* Copy system root into value buffer */
703   wcscpy(ValueBuffer,
704          SharedUserData->NtSystemRoot);
705
706   /* Set SystemRoot = "C:\reactos" */
707   RtlInitUnicodeStringFromLiteral(&EnvVariable,
708                        L"SystemRoot");
709   RtlInitUnicodeString(&EnvValue,
710                        ValueBuffer);
711   RtlSetEnvironmentVariable(&SmSystemEnvironment,
712                             &EnvVariable,
713                             &EnvValue);
714
715   /* Cut off trailing path */
716   ValueBuffer[2] = 0;
717
718   /* Set SystemDrive = "C:" */
719   RtlInitUnicodeStringFromLiteral(&EnvVariable,
720                        L"SystemDrive");
721   RtlInitUnicodeString(&EnvValue,
722                        ValueBuffer);
723   RtlSetEnvironmentVariable(&SmSystemEnvironment,
724                             &EnvVariable,
725                             &EnvValue);
726
727   /* Read system environment from the registry. */
728   RtlZeroMemory(&QueryTable,
729                 sizeof(QueryTable));
730
731   QueryTable[0].QueryRoutine = SmEnvironmentQueryRoutine;
732
733   Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
734                                   L"\\Session Manager\\Environment",
735                                   QueryTable,
736                                   &SmSystemEnvironment,
737                                   SmSystemEnvironment);
738
739   return(Status);
740 }
741
742
743 static NTSTATUS
744 SmLoadSubsystems(VOID)
745 {
746   SYSTEM_LOAD_AND_CALL_IMAGE ImageInfo;
747   NTSTATUS Status;
748
749   /* Load kernel mode subsystem (aka win32k.sys) */
750   RtlInitUnicodeStringFromLiteral(&ImageInfo.ModuleName,
751                        L"\\SystemRoot\\system32\\win32k.sys");
752
753   Status = NtSetSystemInformation(SystemLoadAndCallImage,
754                                   &ImageInfo,
755                                   sizeof(SYSTEM_LOAD_AND_CALL_IMAGE));
756
757   DPRINT("SMSS: Loaded win32k.sys (Status %lx)\n", Status);
758 #if 0
759   if (!NT_SUCCESS(Status))
760     {
761       return(Status);
762     }
763 #endif
764
765   /* FIXME: load more subsystems (csrss!) */
766
767   return(Status);
768 }
769
770
771 static VOID
772 SignalInitEvent()
773 {
774   NTSTATUS Status;
775   OBJECT_ATTRIBUTES ObjectAttributes;
776   UNICODE_STRING UnicodeString;
777   HANDLE ReactOSInitEvent;
778
779   RtlInitUnicodeStringFromLiteral(&UnicodeString, L"\\ReactOSInitDone");
780   InitializeObjectAttributes(&ObjectAttributes,
781     &UnicodeString,
782     EVENT_ALL_ACCESS,
783     0,
784     NULL);
785   Status = NtOpenEvent(&ReactOSInitEvent,
786     EVENT_ALL_ACCESS,
787     &ObjectAttributes);
788   if (NT_SUCCESS(Status))
789     {
790       LARGE_INTEGER Timeout;
791       /* This will cause the boot screen image to go away (if displayed) */
792       NtPulseEvent(ReactOSInitEvent, NULL);
793
794       /* Wait for the display mode to be changed (if in graphics mode) */
795       Timeout.QuadPart = -50000000LL;  /* 5 second timeout */
796       NtWaitForSingleObject(ReactOSInitEvent, FALSE, &Timeout);
797
798       NtClose(ReactOSInitEvent);
799     }
800   else
801     {
802       /* We don't really care if this fails */
803       DPRINT1("SM: Failed to open ReactOS init notification event\n");
804     }
805 }
806
807
808 NTSTATUS
809 InitSessionManager(HANDLE Children[])
810 {
811   NTSTATUS Status;
812   UNICODE_STRING UnicodeString;
813   OBJECT_ATTRIBUTES ObjectAttributes;
814   UNICODE_STRING CmdLineW;
815   PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
816   RTL_PROCESS_INFO ProcessInfo;
817   HANDLE CsrssInitEvent;
818   WCHAR UnicodeBuffer[MAX_PATH];
819
820   /* Create object directories */
821   Status = SmCreateObjectDirectories();
822   if (!NT_SUCCESS(Status))
823     {
824       DPRINT1("SM: Failed to create object directories (Status %lx)\n", Status);
825       return(Status);
826     }
827
828   /* Create the SmApiPort object (LPC) */
829   Status = SmCreateApiPort();
830   if (!NT_SUCCESS(Status))
831     {
832       DPRINT1("SM: Failed to create SmApiPort (Status %lx)\n", Status);
833       return(Status);
834     }
835
836   /* Create the system environment */
837   Status = RtlCreateEnvironment(FALSE,
838                                 &SmSystemEnvironment);
839   if (!NT_SUCCESS(Status))
840     {
841       DPRINT1("SM: Failed to create the system environment (Status %lx)\n", Status);
842       return(Status);
843     }
844
845   /* Set environment variables */
846   Status = SmSetEnvironmentVariables();
847   if (!NT_SUCCESS(Status))
848     {
849       DPRINT1("SM: Failed to set system environment variables (Status %lx)\n", Status);
850       return(Status);
851     }
852
853   /* Define symbolic links to kernel devices (MS-DOS names) */
854   Status = SmInitDosDevices();
855   if (!NT_SUCCESS(Status))
856     {
857       DPRINT1("SM: Failed to create dos device links (Status %lx)\n", Status);
858       return(Status);
859     }
860
861   /* Run all programs in the boot execution list */
862   Status = SmRunBootApps();
863   if (!NT_SUCCESS(Status))
864     {
865       DPRINT1("SM: Failed to run boot applications (Status %lx)\n", Status);
866       return(Status);
867     }
868
869   /* Process the file rename list */
870   Status = SmProcessFileRenameList();
871   if (!NT_SUCCESS(Status))
872     {
873       DPRINT1("SM: Failed to process the file rename list (Status %lx)\n", Status);
874       return(Status);
875     }
876
877   DPRINT("SM: loading well-known DLLs\n");
878
879   /* Load the well known DLLs */
880   Status = SmLoadKnownDlls();
881   if (!NT_SUCCESS(Status))
882     {
883       DPRINT1("SM: Failed to preload system DLLs (Status %lx)\n", Status);
884       /* Don't crash ReactOS if DLLs cannot be loaded */
885     }
886
887   DPRINT("SM: creating system paging files\n");
888
889   /* Create paging files */
890   Status = SmCreatePagingFiles();
891   if (!NT_SUCCESS(Status))
892     {
893       DPRINT1("SM: Failed to create paging files (Status %lx)\n", Status);
894       return(Status);
895     }
896
897   DPRINT("SM: initializing registry\n");
898
899   /* Load remaining registry hives */
900   NtInitializeRegistry(FALSE);
901
902   /* Set environment variables from registry */
903 #if 0
904   Status = SmUpdateEnvironment();
905   if (!NT_SUCCESS(Status))
906     {
907       DPRINT1("SM: Failed to update environment variables (Status %lx)\n", Status);
908       return(Status);
909     }
910 #endif
911
912   DPRINT("SM: loading subsystems\n");
913
914   /* Load the subsystems */
915   Status = SmLoadSubsystems();
916   if (!NT_SUCCESS(Status))
917     {
918       DPRINT1("SM: Failed to load subsystems (Status %lx)\n", Status);
919       return(Status);
920     }
921
922
923   SignalInitEvent();
924
925
926   DPRINT("SM: initializing csrss\n");
927
928   /* Run csrss.exe */
929   RtlInitUnicodeStringFromLiteral(&UnicodeString,
930                                   L"\\CsrssInitDone");
931   InitializeObjectAttributes(&ObjectAttributes,
932                              &UnicodeString,
933                              EVENT_ALL_ACCESS,
934                              0,
935                              NULL);
936   Status = NtCreateEvent(&CsrssInitEvent,
937                          EVENT_ALL_ACCESS,
938                          &ObjectAttributes,
939                          TRUE,
940                          FALSE);
941   if (!NT_SUCCESS(Status))
942     {
943       DbgPrint("Failed to create csrss notification event\n");
944     }
945
946   /*
947    * Start the Win32 subsystem (csrss.exe)
948    */
949
950   /* initialize executable path */
951   wcscpy(UnicodeBuffer, L"\\??\\");
952   wcscat(UnicodeBuffer, SharedUserData->NtSystemRoot);
953   wcscat(UnicodeBuffer, L"\\system32\\csrss.exe");
954   RtlInitUnicodeString(&UnicodeString,
955                        UnicodeBuffer);
956
957   RtlCreateProcessParameters(&ProcessParameters,
958                              &UnicodeString,
959                              NULL,
960                              NULL,
961                              NULL,
962                              SmSystemEnvironment,
963                              NULL,
964                              NULL,
965                              NULL,
966                              NULL);
967
968   Status = RtlCreateUserProcess(&UnicodeString,
969                                 OBJ_CASE_INSENSITIVE,
970                                 ProcessParameters,
971                                 NULL,
972                                 NULL,
973                                 NULL,
974                                 FALSE,
975                                 NULL,
976                                 NULL,
977                                 &ProcessInfo);
978
979   RtlDestroyProcessParameters (ProcessParameters);
980
981   if (!NT_SUCCESS(Status))
982     {
983       DisplayString(L"SM: Loading csrss.exe failed!\n");
984       return(Status);
985     }
986
987   NtWaitForSingleObject(CsrssInitEvent,
988                         FALSE,
989                         NULL);
990
991   Children[CHILD_CSRSS] = ProcessInfo.ProcessHandle;
992
993   /*
994    * Start the logon process (winlogon.exe)
995    */
996
997   DPRINT("SM: starting winlogon\n");
998
999   /* initialize executable path */
1000   wcscpy(UnicodeBuffer, L"\\??\\");
1001   wcscat(UnicodeBuffer, SharedUserData->NtSystemRoot);
1002   wcscat(UnicodeBuffer, L"\\system32\\winlogon.exe");
1003   RtlInitUnicodeString(&UnicodeString,
1004                        UnicodeBuffer);
1005
1006   RtlCreateProcessParameters(&ProcessParameters,
1007                              &UnicodeString,
1008                              NULL,
1009                              NULL,
1010                              NULL,
1011                              SmSystemEnvironment,
1012                              NULL,
1013                              NULL,
1014                              NULL,
1015                              NULL);
1016
1017   Status = RtlCreateUserProcess(&UnicodeString,
1018                                 OBJ_CASE_INSENSITIVE,
1019                                 ProcessParameters,
1020                                 NULL,
1021                                 NULL,
1022                                 NULL,
1023                                 FALSE,
1024                                 NULL,
1025                                 NULL,
1026                                 &ProcessInfo);
1027
1028   RtlDestroyProcessParameters(ProcessParameters);
1029
1030   if (!NT_SUCCESS(Status))
1031     {
1032       DisplayString(L"SM: Loading winlogon.exe failed!\n");
1033       NtTerminateProcess(Children[CHILD_CSRSS],
1034                          0);
1035       return(Status);
1036     }
1037   Children[CHILD_WINLOGON] = ProcessInfo.ProcessHandle;
1038
1039   /* Create the \DbgSsApiPort object (LPC) */
1040   RtlInitUnicodeStringFromLiteral(&UnicodeString,
1041                        L"\\DbgSsApiPort");
1042   InitializeObjectAttributes(&ObjectAttributes,
1043                              &UnicodeString,
1044                              PORT_ALL_ACCESS,
1045                              NULL,
1046                              NULL);
1047
1048   Status = NtCreatePort(&DbgSsApiPort,
1049                         &ObjectAttributes,
1050                         0,
1051                         0,
1052                         0);
1053
1054   if (!NT_SUCCESS(Status))
1055     {
1056       return(Status);
1057     }
1058 #ifndef NDEBUG
1059   DisplayString(L"SM: DbgSsApiPort created...\n");
1060 #endif
1061
1062   /* Create the \DbgUiApiPort object (LPC) */
1063   RtlInitUnicodeStringFromLiteral(&UnicodeString,
1064                        L"\\DbgUiApiPort");
1065   InitializeObjectAttributes(&ObjectAttributes,
1066                              &UnicodeString,
1067                              PORT_ALL_ACCESS,
1068                              NULL,
1069                              NULL);
1070
1071   Status = NtCreatePort(&DbgUiApiPort,
1072                         &ObjectAttributes,
1073                         0,
1074                         0,
1075                         0);
1076   if (!NT_SUCCESS(Status))
1077     {
1078       return(Status);
1079     }
1080 #ifndef NDEBUG
1081   DisplayString (L"SM: DbgUiApiPort created...\n");
1082 #endif
1083
1084   return(STATUS_SUCCESS);
1085 }
1086
1087 /* EOF */