0c2f338ffa8422ef43cb00a38a0873e4a374255b
[reactos.git] / reactos / subsys / smss / initss.c
1 /* $Id$
2 *
3 * initss.c - Load the subsystems
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
27
28 #include "smss.h"
29
30 #include <rosrtl/string.h>
31
32 #define NDEBUG
33 #include <debug.h>
34
35 /* SM handle for its own \SmApiPort */
36 HANDLE hSmApiPort = (HANDLE) 0;
37
38
39 /* TODO:
40 *
41 * a) look if a special option is set for smss.exe in
42 * HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
43 */
44
45 /**********************************************************************
46 * SmpRegisterSmss/0
47 *
48 * DESCRIPTION
49 * Make smss register with itself for IMAGE_SUBSYSTEM_NATIVE
50 * (programmatically). This also opens hSmApiPort to be used
51 * in loading required subsystems.
52 */
53
54 static NTSTATUS
55 SmpRegisterSmss(VOID)
56 {
57 NTSTATUS Status = STATUS_SUCCESS;
58 RTL_PROCESS_INFO ProcessInfo;
59
60
61 DPRINT("SM: %s called\n",__FUNCTION__);
62
63 RtlZeroMemory (& ProcessInfo, sizeof ProcessInfo);
64 ProcessInfo.Size = sizeof ProcessInfo;
65 ProcessInfo.ProcessHandle = (HANDLE) SmSsProcessId;
66 ProcessInfo.ClientId.UniqueProcess = (HANDLE) SmSsProcessId;
67 DPRINT("SM: %s: ProcessInfo.ProcessHandle=%lx\n",
68 __FUNCTION__,ProcessInfo.ProcessHandle);
69 Status = SmCreateClient (& ProcessInfo, L"Session Manager");
70 if (NT_SUCCESS(Status))
71 {
72 UNICODE_STRING SbApiPortName = {0,0,NULL};
73
74 RtlInitUnicodeString (& SbApiPortName, L"");
75 Status = SmConnectApiPort(& SbApiPortName,
76 (HANDLE) -1, /* SM has no SB port */
77 IMAGE_SUBSYSTEM_NATIVE,
78 & hSmApiPort);
79 if(!NT_SUCCESS(Status))
80 {
81 DPRINT("SM: %s: SMLIB!SmConnectApiPort failed (Status=0x%08lx)\n",
82 __FUNCTION__,Status);
83 return Status;
84 }
85 DPRINT("SM self registered\n");
86 }
87 else
88 {
89 DPRINT1("SM: %s: SmCreateClient failed (Status=0x%08lx)\n",
90 __FUNCTION__, Status);
91 }
92 /*
93 * Note that you don't need to call complete session
94 * because connection handling code autocompletes
95 * the client structure for IMAGE_SUBSYSTEM_NATIVE.
96 */
97 return Status;
98 }
99
100
101 /**********************************************************************
102 * SmpLoadKernelModeSubsystem/0
103 */
104 static NTSTATUS
105 SmpLoadKernelModeSubsystem (VOID)
106 {
107 NTSTATUS Status = STATUS_SUCCESS;
108 WCHAR Data [MAX_PATH + 1];
109 ULONG DataLength = sizeof Data;
110 ULONG DataType = 0;
111
112
113 DPRINT("SM: %s called\n", __FUNCTION__);
114
115 Status = SmLookupSubsystem (L"Kmode",
116 Data,
117 & DataLength,
118 & DataType,
119 TRUE);
120 if((STATUS_SUCCESS == Status) && (DataLength > sizeof Data[0]))
121 {
122 WCHAR ImagePath [MAX_PATH + 1] = {0};
123 SYSTEM_LOAD_AND_CALL_IMAGE ImageInfo;
124
125 wcscpy (ImagePath, L"\\??\\");
126 wcscat (ImagePath, Data);
127 RtlZeroMemory (& ImageInfo, sizeof ImageInfo);
128 RtlInitUnicodeString (& ImageInfo.ModuleName, ImagePath);
129 Status = NtSetSystemInformation(SystemLoadAndCallImage,
130 & ImageInfo,
131 sizeof ImageInfo);
132 if(!NT_SUCCESS(Status))
133 {
134 DPRINT("SM: %s: loading Kmode failed (Status=0x%08lx)\n",
135 __FUNCTION__, Status);
136 }
137 }
138 return Status;
139 }
140
141 /**********************************************************************
142 * SmpLoadRequiredSubsystems/0
143 */
144 static NTSTATUS
145 SmpLoadRequiredSubsystems (VOID)
146 {
147 NTSTATUS Status = STATUS_SUCCESS;
148 WCHAR Data [MAX_PATH + 1];
149 ULONG DataLength = sizeof Data;
150 ULONG DataType = 0;
151
152
153 DPRINT("SM: %s called\n", __FUNCTION__);
154
155 RtlZeroMemory (Data, DataLength);
156 Status = SmLookupSubsystem (L"Required",
157 Data,
158 & DataLength,
159 & DataType,
160 FALSE);
161 if((STATUS_SUCCESS == Status) && (DataLength > sizeof Data[0]))
162 {
163 PWCHAR Name = NULL;
164 ULONG Offset = 0;
165
166 for (Name = Data; (Offset < DataLength); )
167 {
168 if(L'\0' != *Name)
169 {
170 UNICODE_STRING Program;
171
172 /* Run the current program */
173 RtlInitUnicodeString (& Program, Name);
174 Status = SmExecuteProgram (hSmApiPort, & Program);
175 if(!NT_SUCCESS(Status))
176 {
177 DPRINT1("SM: %s failed to run '%S' program (Status=0x%08lx)\n",
178 __FUNCTION__, Name, Status);
179 }
180 /* Look for the next program */
181 while ((L'\0' != *Name) && (Offset < DataLength))
182 {
183 ++ Name;
184 ++ Offset;
185 }
186 }
187 ++ Name;
188 ++ Offset;
189 }
190 }
191
192 return Status;
193 }
194
195 /**********************************************************************
196 * SmLoadSubsystems/0
197 */
198 NTSTATUS
199 SmLoadSubsystems(VOID)
200 {
201 NTSTATUS Status = STATUS_SUCCESS;
202
203
204 DPRINT("SM: loading subsystems\n");
205
206 /* SM self registers */
207 Status = SmpRegisterSmss();
208 if(!NT_SUCCESS(Status)) return Status;
209 /* Load Kmode subsystem (aka win32k.sys) */
210 Status = SmpLoadKernelModeSubsystem();
211 if(!NT_SUCCESS(Status)) return Status;
212 /* Load Required subsystems (Debug Windows) */
213 Status = SmpLoadRequiredSubsystems();
214 if(!NT_SUCCESS(Status)) return Status;
215 /* done */
216 return Status;
217 }
218
219 /* EOF */