1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/userenv/setup.c
5 * PURPOSE: Profile setup functions
6 * PROGRAMMERS: Eric Kohl
7 * Hermes Belusca-Maito
8 */
9
10 #include "precomp.h"
11
12 #define NDEBUG
13 #include <debug.h>
14
15 #include "resources.h"
16
17 typedef struct _FOLDERDATA
18 {
19 LPWSTR lpValueName;
20 LPWSTR lpPath;
21 UINT uId;
22 BOOL bHidden;
23 BOOL bShellFolder;
24 BOOL bUserShellFolder;
25 } FOLDERDATA, *PFOLDERDATA;
26
27
28 static FOLDERDATA
29 UserShellFolders[] =
30 {
31 {L"AppData", L"Application Data", IDS_APPDATA, TRUE, TRUE, TRUE},
32 {L"Desktop", L"Desktop", IDS_DESKTOP, FALSE, TRUE, TRUE},
33 {L"Favorites", L"Favorites", IDS_FAVORITES, FALSE, TRUE, TRUE},
34 {L"Personal", L"My Documents", IDS_MYDOCUMENTS, FALSE, TRUE, TRUE},
35 {L"NetHood", L"NetHood", IDS_NETHOOD, TRUE, TRUE, TRUE},
36 {L"PrintHood", L"PrintHood", IDS_PRINTHOOD, TRUE, TRUE, TRUE},
37 {L"Recent", L"Recent", IDS_RECENT, TRUE, TRUE, TRUE},
38 {L"SendTo", L"SendTo", IDS_SENDTO, FALSE, TRUE, TRUE},
39 {L"Templates", L"Templates", IDS_TEMPLATES, FALSE, TRUE, TRUE},
40 {L"Start Menu", L"Start Menu", IDS_STARTMENU, FALSE, TRUE, TRUE},
41 {L"Programs", L"Start Menu\\Programs", IDS_PROGRAMS, FALSE, TRUE, TRUE},
42 {L"Startup", L"Start Menu\\Programs\\Startup", IDS_STARTUP, FALSE, TRUE, TRUE},
43 {L"Local Settings", L"Local Settings", IDS_LOCALSETTINGS, TRUE, TRUE, TRUE},
44 {L"Local AppData", L"Local Settings\\Application Data", IDS_LOCALAPPDATA, TRUE, TRUE, TRUE},
45 {L"Temp", L"Local Settings\\Temp", IDS_TEMP, FALSE, FALSE, FALSE},
46 {L"Cache", L"Local Settings\\Temporary Internet Files", IDS_CACHE, FALSE, TRUE, TRUE},
47 {L"History", L"Local Settings\\History", IDS_HISTORY, FALSE, TRUE, TRUE},
48 {L"Cookies", L"Cookies", IDS_COOKIES, FALSE, TRUE, TRUE},
49 {NULL, NULL, -1, FALSE, FALSE, FALSE}
50 };
51
52
53 static FOLDERDATA
54 CommonShellFolders[] =
55 {
56 {L"Common AppData", L"Application Data", IDS_APPDATA, TRUE, TRUE, TRUE},
57 {L"Common Desktop", L"Desktop", IDS_DESKTOP, FALSE, TRUE, TRUE},
58 {L"Common Favorites", L"Favorites", IDS_FAVORITES, FALSE, TRUE, TRUE},
59 {L"Common Documents", L"My Documents", IDS_MYDOCUMENTS, FALSE, TRUE, TRUE},
60 {L"Common Templates", L"Templates", IDS_TEMPLATES, TRUE, TRUE, TRUE},
61 {L"Common Start Menu", L"Start Menu", IDS_STARTMENU, FALSE, TRUE, TRUE},
62 {L"Common Programs", L"Start Menu\\Programs", IDS_PROGRAMS, FALSE, TRUE, TRUE},
63 {L"Common Startup", L"Start Menu\\Programs\\Startup", IDS_STARTUP, FALSE, TRUE, TRUE},
64 {NULL, NULL, -1, FALSE, FALSE, FALSE}
65 };
66
67
68 typedef struct _PROFILEPARAMS
69 {
70 LPCWSTR pszProfileName;
71 LPCWSTR pszProfileRegValue;
72 LPCWSTR pszEnvVar;
73 LPCWSTR pszEnvVarProfilePath;
74 PFOLDERDATA pFolderList;
75 HKEY hRootKey;
76 LPCWSTR pszShellFoldersKey;
77 LPCWSTR pszUserShellFoldersKey;
78 } PROFILEPARAMS, *PPROFILEPARAMS;
79
80
81 static PROFILEPARAMS
82 StandardProfiles[] =
83 {
84 {
85 L"Default User", L"DefaultUserProfile",
86 L"USERPROFILE", L"%USERPROFILE%",
87 UserShellFolders,
88 HKEY_USERS,
89 L".Default\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
90 L".Default\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders"
91 },
92 {
93 L"All Users", L"AllUsersProfile",
94 L"ALLUSERSPROFILE", L"%ALLUSERSPROFILE%",
95 CommonShellFolders,
96 HKEY_LOCAL_MACHINE,
97 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
98 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders"
99 },
100 };
101
102
103 static
104 BOOL
CreateStandardProfile(IN LPCWSTR pszProfilesPath,IN HKEY hProfileListKey,IN PPROFILEPARAMS pProfileParams)105 CreateStandardProfile(IN LPCWSTR pszProfilesPath,
106 IN HKEY hProfileListKey,
107 IN PPROFILEPARAMS pProfileParams)
108 {
109 LONG Error;
110 PFOLDERDATA lpFolderData;
111 HKEY hKey;
112 DWORD dwLength;
113 WCHAR szProfilePath[MAX_PATH];
114 WCHAR szBuffer[MAX_PATH];
115
116 /*
117 * Create the standard profile main directory
118 */
119
120 StringCbCopyW(szBuffer, sizeof(szBuffer), pProfileParams->pszProfileName);
121
122 /* Build the profile directory path */
123 StringCbCopyW(szProfilePath, sizeof(szProfilePath), pszProfilesPath);
124 StringCbCatW(szProfilePath, sizeof(szProfilePath), L"\\");
125 StringCbCatW(szProfilePath, sizeof(szProfilePath), szBuffer);
126
127 /* Attempt profile directory creation */
128 // FIXME: Security!
129 if (!CreateDirectoryW(szProfilePath, NULL))
130 {
131 if (GetLastError() != ERROR_ALREADY_EXISTS)
132 {
133 DPRINT1("Error: %lu\n", GetLastError());
134 return FALSE;
135 }
136
137 /* Directory existed, let's try to append the postfix */
138 if (!AppendSystemPostfix(szBuffer, ARRAYSIZE(szBuffer)))
139 {
140 DPRINT1("AppendSystemPostfix() failed\n", GetLastError());
141 return FALSE;
142 }
143
144 /* Attempt again creation with appended postfix */
145 StringCbCopyW(szProfilePath, sizeof(szProfilePath), pszProfilesPath);
146 StringCbCatW(szProfilePath, sizeof(szProfilePath), L"\\");
147 StringCbCatW(szProfilePath, sizeof(szProfilePath), szBuffer);
148
149 // FIXME: Security!
150 if (!CreateDirectoryW(szProfilePath, NULL))
151 {
152 if (GetLastError() != ERROR_ALREADY_EXISTS)
153 {
154 DPRINT1("Error: %lu\n", GetLastError());
155 return FALSE;
156 }
157 }
158 }
159
160 /* Set 'DefaultUserProfile' / 'AllUsersProfile' value */
161 /* Store the default user / all users profile path in the registry */
162 dwLength = (wcslen(szBuffer) + 1) * sizeof(WCHAR);
163 Error = RegSetValueExW(hProfileListKey,
164 pProfileParams->pszProfileRegValue,
165 0,
166 REG_SZ,
167 (LPBYTE)szBuffer,
168 dwLength);
169 if (Error != ERROR_SUCCESS)
170 {
171 DPRINT1("Error: %lu\n", Error);
172 SetLastError((DWORD)Error);
173 return FALSE;
174 }
175
176 /* Set 'Default User' / 'All Users' profile */
177 SetEnvironmentVariableW(pProfileParams->pszEnvVar, szProfilePath);
178
179
180 /*
181 * Create the standard profile sub-directories and associated registry keys
182 */
183
184 /* Create 'Default User' / 'All Users' subdirectories */
185 /* FIXME: Take these paths from the registry */
186
187 lpFolderData = pProfileParams->pFolderList;
188 while (lpFolderData->lpValueName != NULL)
189 {
190 StringCbCopyW(szBuffer, sizeof(szBuffer), szProfilePath);
191 StringCbCatW(szBuffer, sizeof(szBuffer), L"\\");
192
193 /* Append the folder name */
194 dwLength = wcslen(szBuffer);
195 if (!LoadStringW(hInstance,
196 lpFolderData->uId,
197 &szBuffer[dwLength],
198 ARRAYSIZE(szBuffer) - dwLength))
199 {
200 /* Use the default name instead */
201 StringCbCatW(szBuffer, sizeof(szBuffer), lpFolderData->lpPath);
202 }
203
204 // FIXME: Security!
205 if (!CreateDirectoryW(szBuffer, NULL))
206 {
207 if (GetLastError() != ERROR_ALREADY_EXISTS)
208 {
209 DPRINT1("Error: %lu\n", GetLastError());
210 return FALSE;
211 }
212 }
213
214 if (lpFolderData->bHidden)
215 SetFileAttributesW(szBuffer, FILE_ATTRIBUTE_HIDDEN);
216
217 lpFolderData++;
218 }
219
220 /* Set 'Shell Folders' values */
221 Error = RegOpenKeyExW(pProfileParams->hRootKey,
222 pProfileParams->pszShellFoldersKey,
223 0,
224 KEY_SET_VALUE,
225 &hKey);
226 if (Error != ERROR_SUCCESS)
227 {
228 DPRINT1("Error: %lu\n", Error);
229 SetLastError((DWORD)Error);
230 return FALSE;
231 }
232
233 /*
234 * NOTE: This is identical to UpdateUsersShellFolderSettings().
235 */
236 lpFolderData = pProfileParams->pFolderList;
237 while (lpFolderData->lpValueName != NULL)
238 {
239 if (lpFolderData->bShellFolder)
240 {
241 StringCbCopyW(szBuffer, sizeof(szBuffer), szProfilePath);
242 StringCbCatW(szBuffer, sizeof(szBuffer), L"\\");
243
244 /* Append the folder name */
245 dwLength = wcslen(szBuffer);
246 if (!LoadStringW(hInstance,
247 lpFolderData->uId,
248 &szBuffer[dwLength],
249 ARRAYSIZE(szBuffer) - dwLength))
250 {
251 /* Use the default name instead */
252 StringCbCatW(szBuffer, sizeof(szBuffer), lpFolderData->lpPath);
253 }
254
255 dwLength = (wcslen(szBuffer) + 1) * sizeof(WCHAR);
256 Error = RegSetValueExW(hKey,
257 lpFolderData->lpValueName,
258 0,
259 REG_SZ,
260 (LPBYTE)szBuffer,
261 dwLength);
262 if (Error != ERROR_SUCCESS)
263 {
264 DPRINT1("Error: %lu\n", Error);
265 RegCloseKey(hKey);
266 SetLastError((DWORD)Error);
267 return FALSE;
268 }
269 }
270
271 lpFolderData++;
272 }
273
274 RegCloseKey(hKey);
275
276 /* Set 'User Shell Folders' values */
277 Error = RegOpenKeyExW(pProfileParams->hRootKey,
278 pProfileParams->pszUserShellFoldersKey,
279 0,
280 KEY_SET_VALUE,
281 &hKey);
282 if (Error != ERROR_SUCCESS)
283 {
284 DPRINT1("Error: %lu\n", Error);
285 SetLastError((DWORD)Error);
286 return FALSE;
287 }
288
289 lpFolderData = pProfileParams->pFolderList;
290 while (lpFolderData->lpValueName != NULL)
291 {
292 if (lpFolderData->bUserShellFolder)
293 {
294 StringCbCopyW(szBuffer, sizeof(szBuffer), pProfileParams->pszEnvVarProfilePath);
295 StringCbCatW(szBuffer, sizeof(szBuffer), L"\\");
296
297 /* Append the folder name */
298 dwLength = wcslen(szBuffer);
299 if (!LoadStringW(hInstance,
300 lpFolderData->uId,
301 &szBuffer[dwLength],
302 ARRAYSIZE(szBuffer) - dwLength))
303 {
304 /* Use the default name instead */
305 StringCbCatW(szBuffer, sizeof(szBuffer), lpFolderData->lpPath);
306 }
307
308 dwLength = (wcslen(szBuffer) + 1) * sizeof(WCHAR);
309 Error = RegSetValueExW(hKey,
310 lpFolderData->lpValueName,
311 0,
312 REG_EXPAND_SZ,
313 (LPBYTE)szBuffer,
314 dwLength);
315 if (Error != ERROR_SUCCESS)
316 {
317 DPRINT1("Error: %lu\n", Error);
318 RegCloseKey(hKey);
319 SetLastError((DWORD)Error);
320 return FALSE;
321 }
322 }
323
324 lpFolderData++;
325 }
326
327 RegCloseKey(hKey);
328
329 return TRUE;
330 }
331
332
333 BOOL
334 WINAPI
InitializeProfiles(VOID)335 InitializeProfiles(VOID)
336 {
337 LONG Error;
338 HKEY hKey;
339 DWORD dwLength;
340 WCHAR szProfilesPath[MAX_PATH];
341 WCHAR szBuffer[MAX_PATH];
342
343 DPRINT("InitializeProfiles()\n");
344
345 /* Load profiles directory path */
346 if (!LoadStringW(hInstance,
347 IDS_PROFILEPATH,
348 szBuffer,
349 ARRAYSIZE(szBuffer)))
350 {
351 DPRINT1("Error: %lu\n", GetLastError());
352 return FALSE;
353 }
354
355 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
356 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
357 0,
358 KEY_SET_VALUE,
359 &hKey);
360 if (Error != ERROR_SUCCESS)
361 {
362 DPRINT1("Error: %lu\n", Error);
363 SetLastError((DWORD)Error);
364 return FALSE;
365 }
366
367 /* Expand it */
368 if (!ExpandEnvironmentStringsW(szBuffer,
369 szProfilesPath,
370 ARRAYSIZE(szProfilesPath)))
371 {
372 DPRINT1("Error: %lu\n", GetLastError());
373 RegCloseKey(hKey);
374 return FALSE;
375 }
376
377 /* Create profiles directory */
378 // FIXME: Security!
379 if (!CreateDirectoryW(szProfilesPath, NULL))
380 {
381 if (GetLastError() != ERROR_ALREADY_EXISTS)
382 {
383 DPRINT1("Error: %lu\n", GetLastError());
384 RegCloseKey(hKey);
385 return FALSE;
386 }
387 }
388
389 /* Store the profiles directory path (unexpanded) in the registry */
390 dwLength = (wcslen(szBuffer) + 1) * sizeof(WCHAR);
391 Error = RegSetValueExW(hKey,
392 L"ProfilesDirectory",
393 0,
394 REG_EXPAND_SZ,
395 (LPBYTE)szBuffer,
396 dwLength);
397 if (Error != ERROR_SUCCESS)
398 {
399 DPRINT1("Error: %lu\n", Error);
400 RegCloseKey(hKey);
401 SetLastError((DWORD)Error);
402 return FALSE;
403 }
404
405 /* Create 'Default User' profile directory path */
406 if (!CreateStandardProfile(szProfilesPath, hKey, &StandardProfiles[0]))
407 {
408 DPRINT1("CreateStandardProfile(L\"%S\") failed.\n", StandardProfiles[0].pszProfileName);
409 RegCloseKey(hKey);
410 return FALSE;
411 }
412
413 /* Create 'All Users' profile directory path */
414 if (!CreateStandardProfile(szProfilesPath, hKey, &StandardProfiles[1]))
415 {
416 DPRINT1("CreateStandardProfile(L\"%S\") failed.\n", StandardProfiles[1].pszProfileName);
417 RegCloseKey(hKey);
418 return FALSE;
419 }
420
421 RegCloseKey(hKey);
422
423 DPRINT("Success\n");
424
425 return TRUE;
426 }
427
428
429 /*
430 * NOTE: See CreateStandardProfile() too.
431 * Used by registry.c!CreateUserHive()
432 */
433 BOOL
UpdateUsersShellFolderSettings(LPCWSTR lpUserProfilePath,HKEY hUserKey)434 UpdateUsersShellFolderSettings(LPCWSTR lpUserProfilePath,
435 HKEY hUserKey)
436 {
437 WCHAR szBuffer[MAX_PATH];
438 DWORD dwLength;
439 PFOLDERDATA lpFolderData;
440 HKEY hFoldersKey;
441 LONG Error;
442
443 DPRINT("UpdateUsersShellFolderSettings() called\n");
444
445 DPRINT("User profile path: %S\n", lpUserProfilePath);
446
447 Error = RegOpenKeyExW(hUserKey,
448 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
449 0,
450 KEY_SET_VALUE,
451 &hFoldersKey);
452 if (Error != ERROR_SUCCESS)
453 {
454 DPRINT1("Error: %lu\n", Error);
455 SetLastError((DWORD)Error);
456 return FALSE;
457 }
458
459 lpFolderData = &UserShellFolders[0];
460 while (lpFolderData->lpValueName != NULL)
461 {
462 if (lpFolderData->bShellFolder)
463 {
464 StringCbCopyW(szBuffer, sizeof(szBuffer), lpUserProfilePath);
465 StringCbCatW(szBuffer, sizeof(szBuffer), L"\\");
466
467 /* Append the folder name */
468 dwLength = wcslen(szBuffer);
469 if (!LoadStringW(hInstance,
470 lpFolderData->uId,
471 &szBuffer[dwLength],
472 ARRAYSIZE(szBuffer) - dwLength))
473 {
474 /* Use the default name instead */
475 StringCbCatW(szBuffer, sizeof(szBuffer), lpFolderData->lpPath);
476 }
477
478 DPRINT("%S: %S\n", lpFolderData->lpValueName, szBuffer);
479
480 dwLength = (wcslen(szBuffer) + 1) * sizeof(WCHAR);
481 Error = RegSetValueExW(hFoldersKey,
482 lpFolderData->lpValueName,
483 0,
484 REG_SZ,
485 (LPBYTE)szBuffer,
486 dwLength);
487 if (Error != ERROR_SUCCESS)
488 {
489 DPRINT1("Error: %lu\n", Error);
490 RegCloseKey(hFoldersKey);
491 SetLastError((DWORD)Error);
492 return FALSE;
493 }
494 }
495
496 lpFolderData++;
497 }
498
499 RegCloseKey(hFoldersKey);
500
501 DPRINT("UpdateUsersShellFolderSettings() done\n");
502
503 return TRUE;
504 }
505
506 /* EOF */
507