* fixed some warnings
[reactos.git] / reactos / base / system / userinit / userinit.c
1 /*
2 * ReactOS applications
3 * Copyright (C) 2001, 2002 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS Userinit Logon Application
22 * FILE: subsys/system/userinit/userinit.c
23 * PROGRAMMERS: Thomas Weidenmueller (w3seek@users.sourceforge.net)
24 * Hervé Poussineau (hpoussin@reactos.org)
25 */
26 #include <windows.h>
27 #include <cfgmgr32.h>
28 #include <regstr.h>
29 #include <shlobj.h>
30 #include "resource.h"
31
32 #define CMP_MAGIC 0x01234567
33
34 /* GLOBALS ******************************************************************/
35
36 /* FUNCTIONS ****************************************************************/
37
38 static LONG
39 ReadRegSzKey(
40 IN HKEY hKey,
41 IN LPCWSTR pszKey,
42 OUT LPWSTR* pValue)
43 {
44 LONG rc;
45 DWORD dwType;
46 DWORD cbData = 0;
47 LPWSTR Value;
48
49 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
50 if (rc != ERROR_SUCCESS)
51 return rc;
52 if (dwType != REG_SZ)
53 return ERROR_FILE_NOT_FOUND;
54 Value = (WCHAR*) HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
55 if (!Value)
56 return ERROR_NOT_ENOUGH_MEMORY;
57 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
58 if (rc != ERROR_SUCCESS)
59 {
60 HeapFree(GetProcessHeap(), 0, Value);
61 return rc;
62 }
63 /* NULL-terminate the string */
64 Value[cbData / sizeof(WCHAR)] = '\0';
65
66 *pValue = Value;
67 return ERROR_SUCCESS;
68 }
69
70 static
71 BOOL IsConsoleShell(void)
72 {
73 HKEY ControlKey = NULL;
74 LPWSTR SystemStartOptions = NULL;
75 LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
76 LONG rc;
77 BOOL ret = FALSE;
78
79 rc = RegOpenKeyEx(
80 HKEY_LOCAL_MACHINE,
81 REGSTR_PATH_CURRENT_CONTROL_SET,
82 0,
83 KEY_QUERY_VALUE,
84 &ControlKey);
85
86 rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
87 if (rc != ERROR_SUCCESS)
88 goto cleanup;
89
90 /* Check for CMDCONS in SystemStartOptions */
91 CurrentOption = SystemStartOptions;
92 while (CurrentOption)
93 {
94 NextOption = wcschr(CurrentOption, L' ');
95 if (NextOption)
96 *NextOption = L'\0';
97 if (wcsicmp(CurrentOption, L"CMDCONS") == 0)
98 {
99 ret = TRUE;
100 goto cleanup;
101 }
102 CurrentOption = NextOption ? NextOption + 1 : NULL;
103 }
104
105 cleanup:
106 if (ControlKey != NULL)
107 RegCloseKey(ControlKey);
108 HeapFree(GetProcessHeap(), 0, SystemStartOptions);
109 return ret;
110 }
111
112 static
113 BOOL GetShell(WCHAR *CommandLine, HKEY hRootKey)
114 {
115 HKEY hKey;
116 DWORD Type, Size;
117 WCHAR Shell[MAX_PATH];
118 BOOL Ret = FALSE;
119 BOOL ConsoleShell = IsConsoleShell();
120
121 if(RegOpenKeyEx(hRootKey,
122 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", /* FIXME: should be REGSTR_PATH_WINLOGON */
123 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
124 {
125 Size = MAX_PATH * sizeof(WCHAR);
126 if(RegQueryValueEx(hKey,
127 ConsoleShell ? L"ConsoleShell" : L"Shell",
128 NULL,
129 &Type,
130 (LPBYTE)Shell,
131 &Size) == ERROR_SUCCESS)
132 {
133 if((Type == REG_SZ) || (Type == REG_EXPAND_SZ))
134 {
135 wcscpy(CommandLine, Shell);
136 Ret = TRUE;
137 }
138 }
139 RegCloseKey(hKey);
140 }
141
142 return Ret;
143 }
144
145 static VOID
146 StartAutoApplications(int clsid)
147 {
148 WCHAR szPath[MAX_PATH] = {0};
149 HRESULT hResult;
150 HANDLE hFind;
151 WIN32_FIND_DATAW findData;
152 SHELLEXECUTEINFOW ExecInfo;
153 size_t len;
154
155 hResult = SHGetFolderPathW(NULL, clsid, NULL, SHGFP_TYPE_CURRENT, szPath);
156 len = wcslen(szPath);
157 if (!SUCCEEDED(hResult) || len == 0)
158 {
159 return;
160 }
161
162 wcscat(szPath, L"\\*");
163 hFind = FindFirstFileW(szPath, &findData);
164 if (hFind == INVALID_HANDLE_VALUE)
165 {
166 return;
167 }
168 szPath[len] = L'\0';
169
170 do
171 {
172 if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (findData.nFileSizeHigh || findData.nFileSizeLow))
173 {
174 memset(&ExecInfo, 0x0, sizeof(SHELLEXECUTEINFOW));
175 ExecInfo.cbSize = sizeof(ExecInfo);
176 ExecInfo.lpVerb = L"open";
177 ExecInfo.lpFile = findData.cFileName;
178 ExecInfo.lpDirectory = szPath;
179 ShellExecuteExW(&ExecInfo);
180 }
181 }while(FindNextFileW(hFind, &findData));
182 FindClose(hFind);
183 }
184
185
186 static BOOL
187 TryToStartShell(LPCWSTR Shell)
188 {
189 STARTUPINFO si;
190 PROCESS_INFORMATION pi;
191 WCHAR ExpandedShell[MAX_PATH];
192
193 ZeroMemory(&si, sizeof(STARTUPINFO));
194 si.cb = sizeof(STARTUPINFO);
195 ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
196
197 ExpandEnvironmentStrings(Shell, ExpandedShell, MAX_PATH);
198
199 if(!CreateProcess(NULL,
200 ExpandedShell,
201 NULL,
202 NULL,
203 FALSE,
204 NORMAL_PRIORITY_CLASS,
205 NULL,
206 NULL,
207 &si,
208 &pi))
209 return FALSE;
210
211 StartAutoApplications(CSIDL_STARTUP);
212 StartAutoApplications(CSIDL_COMMON_STARTUP);
213 WaitForSingleObject(pi.hProcess, INFINITE);
214 CloseHandle(pi.hProcess);
215 CloseHandle(pi.hThread);
216 return TRUE;
217 }
218
219 static
220 void StartShell(void)
221 {
222 WCHAR Shell[MAX_PATH];
223 TCHAR szMsg[RC_STRING_MAX_SIZE];
224
225 /* Try to run shell in user key */
226 if (GetShell(Shell, HKEY_CURRENT_USER) && TryToStartShell(Shell))
227 return;
228
229 /* Try to run shell in local machine key */
230 if (GetShell(Shell, HKEY_LOCAL_MACHINE) && TryToStartShell(Shell))
231 return;
232
233 /* Try default shell */
234 if (IsConsoleShell())
235 {
236 if(GetSystemDirectory(Shell, MAX_PATH - 8))
237 wcscat(Shell, L"\\cmd.exe");
238 else
239 wcscpy(Shell, L"cmd.exe");
240 }
241 else
242 {
243 if(GetWindowsDirectory(Shell, MAX_PATH - 13))
244 wcscat(Shell, L"\\explorer.exe");
245 else
246 wcscpy(Shell, L"explorer.exe");
247 }
248 if (!TryToStartShell(Shell))
249 {
250 LoadString( GetModuleHandle(NULL), STRING_USERINIT_FAIL, szMsg, sizeof(szMsg) / sizeof(szMsg[0]));
251 MessageBox(0, szMsg, NULL, 0);
252 }
253 }
254
255 static
256 void SetUserSettings(void)
257 {
258 HKEY hKey;
259 DWORD Type, Size;
260 WCHAR szWallpaper[MAX_PATH + 1];
261
262 if(RegOpenKeyEx(HKEY_CURRENT_USER,
263 REGSTR_PATH_DESKTOP,
264 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
265 {
266 Size = sizeof(szWallpaper);
267 if(RegQueryValueEx(hKey,
268 L"Wallpaper",
269 NULL,
270 &Type,
271 (LPBYTE)szWallpaper,
272 &Size) == ERROR_SUCCESS
273 && Type == REG_SZ)
274 {
275 /* Load and change the wallpaper */
276 SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, szWallpaper, SPIF_SENDCHANGE);
277 }
278 else
279 {
280 /* remove the wallpaper */
281 SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, NULL, SPIF_SENDCHANGE);
282 }
283 RegCloseKey(hKey);
284 }
285 }
286
287
288 typedef DWORD (WINAPI *PCMP_REPORT_LOGON)(DWORD, DWORD);
289
290 static VOID
291 NotifyLogon(VOID)
292 {
293 HINSTANCE hModule;
294 PCMP_REPORT_LOGON CMP_Report_LogOn;
295
296 hModule = LoadLibrary(L"setupapi.dll");
297 if (hModule)
298 {
299 CMP_Report_LogOn = (PCMP_REPORT_LOGON)GetProcAddress(hModule, "CMP_Report_LogOn");
300 if (CMP_Report_LogOn)
301 CMP_Report_LogOn(CMP_MAGIC, GetCurrentProcessId());
302
303 FreeLibrary(hModule);
304 }
305 }
306
307
308
309 #ifdef _MSC_VER
310 #pragma warning(disable : 4100)
311 #endif /* _MSC_VER */
312
313 int WINAPI
314 WinMain(HINSTANCE hInst,
315 HINSTANCE hPrevInstance,
316 LPSTR lpszCmdLine,
317 int nCmdShow)
318 {
319 NotifyLogon();
320 SetUserSettings();
321 StartShell();
322 return 0;
323 }
324
325 /* EOF */