branch update for HEAD-2003050101
[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 <napi/lpc.h>
35
36 #include "smss.h"
37
38 #define NDEBUG
39
40
41 /* GLOBALS ******************************************************************/
42
43 HANDLE DbgSsApiPort = INVALID_HANDLE_VALUE;
44 HANDLE DbgUiApiPort = INVALID_HANDLE_VALUE;
45
46 PWSTR SmSystemEnvironment = NULL;
47
48
49 /* FUNCTIONS ****************************************************************/
50
51 static NTSTATUS STDCALL
52 SmObjectDirectoryQueryRoutine(PWSTR ValueName,
53                               ULONG ValueType,
54                               PVOID ValueData,
55                               ULONG ValueLength,
56                               PVOID Context,
57                               PVOID EntryContext)
58 {
59   OBJECT_ATTRIBUTES ObjectAttributes;
60   UNICODE_STRING UnicodeString;
61   HANDLE WindowsDirectory;
62   NTSTATUS Status = STATUS_SUCCESS;
63
64 #ifndef NDEBUG
65   PrintString("ValueName '%S'  Type %lu  Length %lu\n", ValueName, ValueType, ValueLength);
66   PrintString("ValueData '%S'\n", (PWSTR)ValueData);
67 #endif
68   if (ValueType != REG_SZ)
69     {
70       return(STATUS_SUCCESS);
71     }
72
73   RtlInitUnicodeString(&UnicodeString,
74                        (PWSTR)ValueData);
75
76   InitializeObjectAttributes(&ObjectAttributes,
77                              &UnicodeString,
78                              0,
79                              NULL,
80                              NULL);
81
82   Status = ZwCreateDirectoryObject(&WindowsDirectory,
83                                    0,
84                                    &ObjectAttributes);
85
86   return(Status);
87 }
88
89
90 static NTSTATUS
91 SmCreateObjectDirectories(VOID)
92 {
93   RTL_QUERY_REGISTRY_TABLE QueryTable[2];
94   NTSTATUS Status;
95
96   RtlZeroMemory(&QueryTable,
97                 sizeof(QueryTable));
98
99   QueryTable[0].Name = L"ObjectDirectories";
100   QueryTable[0].QueryRoutine = SmObjectDirectoryQueryRoutine;
101
102   Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
103                                   L"\\Session Manager",
104                                   QueryTable,
105                                   NULL,
106                                   NULL);
107
108   return(Status);
109 }
110
111
112 static NTSTATUS STDCALL
113 SmDosDevicesQueryRoutine(PWSTR ValueName,
114                          ULONG ValueType,
115                          PVOID ValueData,
116                          ULONG ValueLength,
117                          PVOID Context,
118                          PVOID EntryContext)
119 {
120   OBJECT_ATTRIBUTES ObjectAttributes;
121   UNICODE_STRING DeviceName;
122   UNICODE_STRING LinkName;
123   HANDLE LinkHandle;
124   WCHAR LinkBuffer[80];
125   NTSTATUS Status;
126
127 #ifndef NDEBUG
128   PrintString("ValueName '%S'  Type %lu  Length %lu\n", ValueName, ValueType, ValueLength);
129   PrintString("ValueData '%S'\n", (PWSTR)ValueData);
130 #endif
131
132   if (ValueType != REG_SZ)
133     {
134       return(STATUS_SUCCESS);
135     }
136
137   swprintf(LinkBuffer,
138            L"\\??\\%s",
139            ValueName);
140   RtlInitUnicodeString(&LinkName,
141                        LinkBuffer);
142   RtlInitUnicodeString(&DeviceName,
143                        (PWSTR)ValueData);
144
145 #ifndef NDEBUG
146   PrintString("SM: Linking %wZ --> %wZ\n",
147               &LinkName,
148               &DeviceName);
149 #endif
150
151   /* create symbolic link */
152   InitializeObjectAttributes(&ObjectAttributes,
153                              &LinkName,
154                              OBJ_PERMANENT,
155                              NULL,
156                              NULL);
157   Status = NtCreateSymbolicLinkObject(&LinkHandle,
158                                       SYMBOLIC_LINK_ALL_ACCESS,
159                                       &ObjectAttributes,
160                                       &DeviceName);
161   if (!NT_SUCCESS(Status))
162     {
163       PrintString("SmDosDevicesQueryRoutine: NtCreateSymbolicLink( %wZ --> %wZ ) failed!\n",
164                   &LinkName,
165                   &DeviceName);
166     }
167   NtClose(LinkHandle);
168
169   return(Status);
170 }
171
172
173 static NTSTATUS
174 SmInitDosDevices(VOID)
175 {
176   RTL_QUERY_REGISTRY_TABLE QueryTable[2];
177   NTSTATUS Status;
178
179   RtlZeroMemory(&QueryTable,
180                 sizeof(QueryTable));
181
182   QueryTable[0].QueryRoutine = SmDosDevicesQueryRoutine;
183
184   Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
185                                   L"\\Session Manager\\DOS Devices",
186                                   QueryTable,
187                                   NULL,
188                                   NULL);
189   return(Status);
190 }
191
192
193 static NTSTATUS STDCALL
194 SmRunBootAppsQueryRoutine(PWSTR ValueName,
195                           ULONG ValueType,
196                           PVOID ValueData,
197                           ULONG ValueLength,
198                           PVOID Context,
199                           PVOID EntryContext)
200 {
201   PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
202   RTL_PROCESS_INFO ProcessInfo;
203   UNICODE_STRING ImagePathString;
204   UNICODE_STRING CommandLineString;
205   WCHAR Description[256];
206   WCHAR ImageName[256];
207   WCHAR ImagePath[256];
208   WCHAR CommandLine[256];
209   PWSTR p1, p2;
210   ULONG len;
211   NTSTATUS Status;
212
213 #ifndef NDEBUG
214   PrintString("ValueName '%S'  Type %lu  Length %lu\n", ValueName, ValueType, ValueLength);
215   PrintString("ValueData '%S'\n", (PWSTR)ValueData);
216 #endif
217
218   if (ValueType != REG_SZ)
219     {
220       return(STATUS_SUCCESS);
221     }
222
223   /* Extract the description */
224   p1 = wcschr((PWSTR)ValueData, L' ');
225   len = p1 - (PWSTR)ValueData;
226   memcpy(Description,ValueData, len * sizeof(WCHAR));
227   Description[len] = 0;
228
229   /* Extract the image name */
230   p1++;
231   p2 = wcschr(p1, L' ');
232   if (p2 != NULL)
233     len = p2 - p1;
234   else
235     len = wcslen(p1);
236   memcpy(ImageName, p1, len * sizeof(WCHAR));
237   ImageName[len] = 0;
238
239   /* Extract the command line */
240   if (p2 == NULL)
241     {
242       CommandLine[0] = 0;
243     }
244   else
245     {
246       p2++;
247       wcscpy(CommandLine, p2);
248     }
249
250   PrintString("Running %S...\n", Description);
251 #ifndef NDEBUG
252   PrintString("ImageName: '%S'\n", ImageName);
253   PrintString("CommandLine: '%S'\n", CommandLine);
254 #endif
255
256   /* initialize executable path */
257   wcscpy(ImagePath, L"\\SystemRoot\\system32\\");
258   wcscat(ImagePath, ImageName);
259   wcscat(ImagePath, L".exe");
260
261   RtlInitUnicodeString(&ImagePathString,
262                        ImagePath);
263
264   RtlInitUnicodeString(&CommandLineString,
265                        CommandLine);
266
267   RtlCreateProcessParameters(&ProcessParameters,
268                              &ImagePathString,
269                              NULL,
270                              NULL,
271                              &CommandLineString,
272                              NULL,
273                              NULL,
274                              NULL,
275                              NULL,
276                              NULL);
277
278   Status = RtlCreateUserProcess(&ImagePathString,
279                                 OBJ_CASE_INSENSITIVE,
280                                 ProcessParameters,
281                                 NULL,
282                                 NULL,
283                                 NULL,
284                                 FALSE,
285                                 NULL,
286                                 NULL,
287                                 &ProcessInfo);
288   if (!NT_SUCCESS(Status))
289     {
290       PrintString("Running %s failed (Status %lx)\n", Description, Status);
291       return(STATUS_SUCCESS);
292     }
293
294   RtlDestroyProcessParameters(ProcessParameters);
295
296   /* Wait for process termination */
297   NtWaitForSingleObject(ProcessInfo.ProcessHandle,
298                         FALSE,
299                         NULL);
300
301   NtClose(ProcessInfo.ThreadHandle);
302   NtClose(ProcessInfo.ProcessHandle);
303
304   return(STATUS_SUCCESS);
305 }
306
307
308 /*
309  * Run native applications listed in the registry.
310  *
311  *  Key:
312  *    \Registry\Machine\SYSTEM\CurrentControlSet\Control\Session Manager
313  *
314  *  Value (format: "<description> <executable> <command line>":
315  *    BootExecute = "autocheck autochk *"
316  */
317 static NTSTATUS
318 SmRunBootApps(VOID)
319 {
320   RTL_QUERY_REGISTRY_TABLE QueryTable[2];
321   NTSTATUS Status;
322
323   RtlZeroMemory(&QueryTable,
324                 sizeof(QueryTable));
325
326   QueryTable[0].Name = L"BootExecute";
327   QueryTable[0].QueryRoutine = SmRunBootAppsQueryRoutine;
328
329   Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
330                                   L"\\Session Manager",
331                                   QueryTable,
332                                   NULL,
333                                   NULL);
334   if (!NT_SUCCESS(Status))
335     {
336       PrintString("SmRunBootApps: RtlQueryRegistryValues() failed! (Status %lx)\n", Status);
337     }
338
339   return(Status);
340 }
341
342
343 static NTSTATUS
344 SmProcessFileRenameList(VOID)
345 {
346 #ifndef NDEBUG
347   PrintString("SmProcessFileRenameList() called\n");
348 #endif
349
350   /* FIXME: implement it! */
351
352 #ifndef NDEBUG
353   PrintString("SmProcessFileRenameList() done\n");
354 #endif
355
356   return(STATUS_SUCCESS);
357 }
358
359
360 static NTSTATUS
361 SmPreloadDlls(VOID)
362 {
363 #ifndef NDEBUG
364   PrintString("SmPreloadDlls() called\n");
365 #endif
366
367   /* FIXME: implement it! */
368
369 #ifndef NDEBUG
370   PrintString("SmPreloadDlls() done\n");
371 #endif
372
373   return(STATUS_SUCCESS);
374 }
375
376
377 static NTSTATUS STDCALL
378 SmPagingFilesQueryRoutine(PWSTR ValueName,
379                           ULONG ValueType,
380                           PVOID ValueData,
381                           ULONG ValueLength,
382                           PVOID Context,
383                           PVOID EntryContext)
384 {
385   UNICODE_STRING FileName;
386   LARGE_INTEGER InitialSize;
387   LARGE_INTEGER MaximumSize;
388   NTSTATUS Status;
389   LPWSTR p;
390
391 #ifndef NDEBUG
392   PrintString("ValueName '%S'  Type %lu  Length %lu\n", ValueName, ValueType, ValueLength);
393   PrintString("ValueData '%S'\n", (PWSTR)ValueData);
394 #endif
395
396   if (ValueType != REG_SZ)
397     {
398       return(STATUS_SUCCESS);
399     }
400
401   /*
402    * Format: "<path>[ <initial_size>[ <maximum_size>]]"
403    */
404   if ((p = wcschr(ValueData, ' ')) != NULL)
405     {
406       *p = L'\0';
407       InitialSize.QuadPart = wcstoul(p + 1, &p, 0) * 256 * 4096;
408       if (*p == ' ')
409         {
410           MaximumSize.QuadPart = wcstoul(p + 1, NULL, 0) * 256 * 4096;
411         }
412       else
413         MaximumSize = InitialSize;
414     }
415   else
416     {
417       InitialSize.QuadPart = 50 * 4096;
418       MaximumSize.QuadPart = 80 * 4096;
419     }
420
421   if (!RtlDosPathNameToNtPathName_U ((LPWSTR)ValueData, 
422                                      &FileName,
423                                      NULL,
424                                      NULL))
425     {
426       return (STATUS_SUCCESS);
427     }  
428
429   DbgPrint("SMSS: Created paging file %wZ with size %dKB\n", 
430            &FileName, InitialSize.QuadPart / 1024);
431   Status = NtCreatePagingFile(&FileName,
432                               &InitialSize,
433                               &MaximumSize,
434                               0);
435
436   RtlFreeUnicodeString(&FileName);
437
438   return(STATUS_SUCCESS);
439 }
440
441
442 static NTSTATUS
443 SmCreatePagingFiles(VOID)
444 {
445   RTL_QUERY_REGISTRY_TABLE QueryTable[2];
446   NTSTATUS Status;
447
448   RtlZeroMemory(&QueryTable,
449                 sizeof(QueryTable));
450
451   QueryTable[0].Name = L"PagingFiles";
452   QueryTable[0].QueryRoutine = SmPagingFilesQueryRoutine;
453
454   Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
455                                   L"\\Session Manager\\Memory Management",
456                                   QueryTable,
457                                   NULL,
458                                   NULL);
459
460   return(Status);
461 }
462
463
464 static NTSTATUS STDCALL
465 SmEnvironmentQueryRoutine(PWSTR ValueName,
466                           ULONG ValueType,
467                           PVOID ValueData,
468                           ULONG ValueLength,
469                           PVOID Context,
470                           PVOID EntryContext)
471 {
472   UNICODE_STRING EnvVariable;
473   UNICODE_STRING EnvValue;
474
475 #ifndef NDEBUG
476   PrintString("ValueName '%S'  Type %lu  Length %lu\n", ValueName, ValueType, ValueLength);
477   PrintString("ValueData '%S'\n", (PWSTR)ValueData);
478 #endif
479
480   if (ValueType != REG_SZ)
481     {
482       return(STATUS_SUCCESS);
483     }
484
485   RtlInitUnicodeString(&EnvVariable,
486                        ValueName);
487   RtlInitUnicodeString(&EnvValue,
488                        (PWSTR)ValueData);
489   RtlSetEnvironmentVariable(Context,
490                             &EnvVariable,
491                             &EnvValue);
492
493   return(STATUS_SUCCESS);
494 }
495
496
497 static NTSTATUS
498 SmSetEnvironmentVariables(VOID)
499 {
500   RTL_QUERY_REGISTRY_TABLE QueryTable[2];
501   UNICODE_STRING EnvVariable;
502   UNICODE_STRING EnvValue;
503   WCHAR ValueBuffer[MAX_PATH];
504   NTSTATUS Status;
505
506   /*
507    * The following environment variables must be set prior to reading
508    * other variables from the registry.
509    *
510    * Variables (example):
511    *    SystemRoot = "C:\reactos"
512    *    SystemDrive = "C:"
513    */
514
515   /* Copy system root into value buffer */
516   wcscpy(ValueBuffer,
517          SharedUserData->NtSystemRoot);
518
519   /* Cet SystemRoot = "C:\reactos" */
520   RtlInitUnicodeStringFromLiteral(&EnvVariable,
521                        L"SystemRoot");
522   RtlInitUnicodeString(&EnvValue,
523                        ValueBuffer);
524   RtlSetEnvironmentVariable(&SmSystemEnvironment,
525                             &EnvVariable,
526                             &EnvValue);
527
528   /* Cut off trailing path */
529   ValueBuffer[2] = 0;
530
531   /* Set SystemDrive = "C:" */
532   RtlInitUnicodeStringFromLiteral(&EnvVariable,
533                        L"SystemDrive");
534   RtlInitUnicodeString(&EnvValue,
535                        ValueBuffer);
536   RtlSetEnvironmentVariable(&SmSystemEnvironment,
537                             &EnvVariable,
538                             &EnvValue);
539
540   /* Read system environment from the registry. */
541   RtlZeroMemory(&QueryTable,
542                 sizeof(QueryTable));
543
544   QueryTable[0].QueryRoutine = SmEnvironmentQueryRoutine;
545
546   Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
547                                   L"\\Session Manager\\Environment",
548                                   QueryTable,
549                                   &SmSystemEnvironment,
550                                   SmSystemEnvironment);
551
552   return(Status);
553 }
554
555
556 static NTSTATUS
557 SmLoadSubsystems(VOID)
558 {
559   SYSTEM_LOAD_AND_CALL_IMAGE ImageInfo;
560   NTSTATUS Status;
561
562   /* Load kernel mode subsystem (aka win32k.sys) */
563   RtlInitUnicodeStringFromLiteral(&ImageInfo.ModuleName,
564                        L"\\SystemRoot\\system32\\win32k.sys");
565
566   Status = NtSetSystemInformation(SystemLoadAndCallImage,
567                                   &ImageInfo,
568                                   sizeof(SYSTEM_LOAD_AND_CALL_IMAGE));
569
570   PrintString("SMSS: Loaded win32k.sys (Status %lx)\n", Status);
571 #if 0
572   if (!NT_SUCCESS(Status))
573     {
574       return(Status);
575     }
576 #endif
577
578   /* FIXME: load more subsystems (csrss!) */
579
580   return(Status);
581 }
582
583
584 NTSTATUS
585 InitSessionManager(HANDLE Children[])
586 {
587   NTSTATUS Status;
588   UNICODE_STRING UnicodeString;
589   OBJECT_ATTRIBUTES ObjectAttributes;
590   UNICODE_STRING CmdLineW;
591   PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
592   RTL_PROCESS_INFO ProcessInfo;
593   HANDLE CsrssInitEvent;
594   WCHAR UnicodeBuffer[MAX_PATH];
595
596   /* Create object directories */
597   Status = SmCreateObjectDirectories();
598   if (!NT_SUCCESS(Status))
599     {
600       PrintString("SM: Failed to create object directories (Status %lx)\n", Status);
601       return(Status);
602     }
603
604   /* Create the SmApiPort object (LPC) */
605   Status = SmCreateApiPort();
606   if (!NT_SUCCESS(Status))
607     {
608       PrintString("SM: Failed to create SmApiPort (Status %lx)\n", Status);
609       return(Status);
610     }
611
612   /* Create the system environment */
613   Status = RtlCreateEnvironment(FALSE,
614                                 &SmSystemEnvironment);
615   if (!NT_SUCCESS(Status))
616     {
617       PrintString("SM: Failed to create the system environment (Status %lx)\n", Status);
618       return(Status);
619     }
620
621   /* Define symbolic links to kernel devices (MS-DOS names) */
622   Status = SmInitDosDevices();
623   if (!NT_SUCCESS(Status))
624     {
625       PrintString("SM: Failed to create dos device links (Status %lx)\n", Status);
626       return(Status);
627     }
628
629   /* Run all programs in the boot execution list */
630   Status = SmRunBootApps();
631   if (!NT_SUCCESS(Status))
632     {
633       PrintString("SM: Failed to run boot applications (Status %lx)\n", Status);
634       return(Status);
635     }
636
637   /* Process the file rename list */
638   Status = SmProcessFileRenameList();
639   if (!NT_SUCCESS(Status))
640     {
641       PrintString("SM: Failed to process the file rename list (Status %lx)\n", Status);
642       return(Status);
643     }
644
645   /* Load the well known DLLs */
646   Status = SmPreloadDlls();
647   if (!NT_SUCCESS(Status))
648     {
649       PrintString("SM: Failed to preload system DLLs (Status %lx)\n", Status);
650       return(Status);
651     }
652
653   /* Create paging files */
654   Status = SmCreatePagingFiles();
655   if (!NT_SUCCESS(Status))
656     {
657       PrintString("SM: Failed to create paging files (Status %lx)\n", Status);
658       return(Status);
659     }
660
661   /* Load remaining registry hives */
662   NtInitializeRegistry(FALSE);
663
664   /* Set environment variables from registry */
665   Status = SmSetEnvironmentVariables();
666   if (!NT_SUCCESS(Status))
667     {
668       PrintString("SM: Failed to set system environment variables (Status %lx)\n", Status);
669       return(Status);
670     }
671
672   /* Load the subsystems */
673   Status = SmLoadSubsystems();
674   if (!NT_SUCCESS(Status))
675     {
676       PrintString("SM: Failed to load subsystems (Status %lx)\n", Status);
677       return(Status);
678     }
679
680   /* Run csrss.exe */
681   RtlInitUnicodeStringFromLiteral(&UnicodeString,
682                        L"\\CsrssInitDone");
683   InitializeObjectAttributes(&ObjectAttributes,
684                              &UnicodeString,
685                              EVENT_ALL_ACCESS,
686                              0,
687                              NULL);
688   Status = NtCreateEvent(&CsrssInitEvent,
689                          EVENT_ALL_ACCESS,
690                          &ObjectAttributes,
691                          TRUE,
692                          FALSE);
693   if (!NT_SUCCESS(Status))
694     {
695       DbgPrint("Failed to create csrss notification event\n");
696     }
697
698   /*
699    * Start the Win32 subsystem (csrss.exe)
700    */
701
702   /* initialize executable path */
703   wcscpy(UnicodeBuffer, L"\\??\\");
704   wcscat(UnicodeBuffer, SharedUserData->NtSystemRoot);
705   wcscat(UnicodeBuffer, L"\\system32\\csrss.exe");
706   RtlInitUnicodeString(&UnicodeString,
707                        UnicodeBuffer);
708
709   RtlCreateProcessParameters(&ProcessParameters,
710                              &UnicodeString,
711                              NULL,
712                              NULL,
713                              NULL,
714                              SmSystemEnvironment,
715                              NULL,
716                              NULL,
717                              NULL,
718                              NULL);
719
720   Status = RtlCreateUserProcess(&UnicodeString,
721                                 OBJ_CASE_INSENSITIVE,
722                                 ProcessParameters,
723                                 NULL,
724                                 NULL,
725                                 NULL,
726                                 FALSE,
727                                 NULL,
728                                 NULL,
729                                 &ProcessInfo);
730
731   RtlDestroyProcessParameters (ProcessParameters);
732
733   if (!NT_SUCCESS(Status))
734     {
735       DisplayString(L"SM: Loading csrss.exe failed!\n");
736       return(Status);
737     }
738
739   NtWaitForSingleObject(CsrssInitEvent,
740                         FALSE,
741                         NULL);
742
743   Children[CHILD_CSRSS] = ProcessInfo.ProcessHandle;
744
745   /*
746    * Start the logon process (winlogon.exe)
747    */
748
749   /* initialize executable path */
750   wcscpy(UnicodeBuffer, L"\\??\\");
751   wcscat(UnicodeBuffer, SharedUserData->NtSystemRoot);
752   wcscat(UnicodeBuffer, L"\\system32\\winlogon.exe");
753   RtlInitUnicodeString(&UnicodeString,
754                        UnicodeBuffer);
755
756   RtlCreateProcessParameters(&ProcessParameters,
757                              &UnicodeString,
758                              NULL,
759                              NULL,
760                              NULL,
761                              SmSystemEnvironment,
762                              NULL,
763                              NULL,
764                              NULL,
765                              NULL);
766
767   Status = RtlCreateUserProcess(&UnicodeString,
768                                 OBJ_CASE_INSENSITIVE,
769                                 ProcessParameters,
770                                 NULL,
771                                 NULL,
772                                 NULL,
773                                 FALSE,
774                                 NULL,
775                                 NULL,
776                                 &ProcessInfo);
777
778   RtlDestroyProcessParameters(ProcessParameters);
779
780   if (!NT_SUCCESS(Status))
781     {
782       DisplayString(L"SM: Loading winlogon.exe failed!\n");
783       NtTerminateProcess(Children[CHILD_CSRSS],
784                          0);
785       return(Status);
786     }
787   Children[CHILD_WINLOGON] = ProcessInfo.ProcessHandle;
788
789   /* Create the \DbgSsApiPort object (LPC) */
790   RtlInitUnicodeStringFromLiteral(&UnicodeString,
791                        L"\\DbgSsApiPort");
792   InitializeObjectAttributes(&ObjectAttributes,
793                              &UnicodeString,
794                              PORT_ALL_ACCESS,
795                              NULL,
796                              NULL);
797
798   Status = NtCreatePort(&DbgSsApiPort,
799                         &ObjectAttributes,
800                         0,
801                         0,
802                         0);
803
804   if (!NT_SUCCESS(Status))
805     {
806       return(Status);
807     }
808 #ifndef NDEBUG
809   DisplayString(L"SM: DbgSsApiPort created...\n");
810 #endif
811
812   /* Create the \DbgUiApiPort object (LPC) */
813   RtlInitUnicodeStringFromLiteral(&UnicodeString,
814                        L"\\DbgUiApiPort");
815   InitializeObjectAttributes(&ObjectAttributes,
816                              &UnicodeString,
817                              PORT_ALL_ACCESS,
818                              NULL,
819                              NULL);
820
821   Status = NtCreatePort(&DbgUiApiPort,
822                         &ObjectAttributes,
823                         0,
824                         0,
825                         0);
826   if (!NT_SUCCESS(Status))
827     {
828       return(Status);
829     }
830 #ifndef NDEBUG
831   DisplayString (L"SM: DbgUiApiPort created...\n");
832 #endif
833
834   return(STATUS_SUCCESS);
835 }
836
837 /* EOF */