- partially implemented RegisterGPNotification() and UnregisterGPNotification() ...
[reactos.git] / reactos / lib / userenv / setup.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2004 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 /* $Id$
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS system libraries
23 * FILE: lib/userenv/setup.c
24 * PURPOSE: Profile setup functions
25 * PROGRAMMER: Eric Kohl
26 */
27
28 #include <precomp.h>
29
30 #define NDEBUG
31 #include <debug.h>
32
33
34 typedef struct _FOLDERDATA
35 {
36 LPWSTR lpValueName;
37 LPWSTR lpPath;
38 UINT uId;
39 BOOL bHidden;
40 BOOL bShellFolder;
41 BOOL bUserShellFolder;
42 } FOLDERDATA, *PFOLDERDATA;
43
44
45 static FOLDERDATA
46 UserShellFolders[] =
47 {
48 {L"AppData", L"Application Data", IDS_APPDATA, TRUE, TRUE, TRUE},
49 {L"Desktop", L"Desktop", IDS_DESKTOP, FALSE, TRUE, TRUE},
50 {L"Favorites", L"Favorites", IDS_FAVORITES, FALSE, TRUE, TRUE},
51 {L"Personal", L"My Documents", IDS_MYDOCUMENTS, FALSE, TRUE, TRUE},
52 {L"My Pictures", L"My Documents\\My Pictures", IDS_MYPICTURES, FALSE, TRUE, TRUE},
53 {L"My Music", L"My Documents\\My Music", IDS_MYMUSIC, FALSE, TRUE, TRUE},
54 {L"My Video", L"My Documents\\My Videos", IDS_MYVIDEOS, FALSE, TRUE, TRUE},
55 {L"NetHood", L"NetHood", IDS_NETHOOD, TRUE, TRUE, TRUE},
56 {L"PrintHood", L"PrintHood", IDS_PRINTHOOD, TRUE, TRUE, TRUE},
57 {L"Recent", L"Recent", IDS_RECENT, TRUE, TRUE, TRUE},
58 {L"SendTo", L"SendTo", IDS_SENDTO, FALSE, TRUE, TRUE},
59 {L"Templates", L"Templates", IDS_TEMPLATES, FALSE, TRUE, TRUE},
60 {L"Start Menu", L"Start Menu", IDS_STARTMENU, FALSE, TRUE, TRUE},
61 {L"Programs", L"Start Menu\\Programs", IDS_PROGRAMS, FALSE, TRUE, TRUE},
62 {L"Startup", L"Start Menu\\Programs\\Startup", IDS_STARTUP, FALSE, TRUE, TRUE},
63 {L"Local Settings", L"Local Settings", IDS_LOCALSETTINGS, TRUE, TRUE, TRUE},
64 {L"Local AppData", L"Local Settings\\Application Data", IDS_LOCALAPPDATA, TRUE, TRUE, TRUE},
65 {L"Temp", L"Local Settings\\Temp", IDS_TEMP, FALSE, FALSE, FALSE},
66 {L"Cache", L"Local Settings\\Temporary Internet Files", IDS_CACHE, FALSE, TRUE, TRUE},
67 {L"History", L"Local Settings\\History", IDS_HISTORY, FALSE, TRUE, TRUE},
68 {L"Cookies", L"Cookies", IDS_COOKIES, FALSE, TRUE, TRUE},
69 {NULL, NULL, -1, FALSE, FALSE, FALSE}
70 };
71
72
73 static FOLDERDATA
74 CommonShellFolders[] =
75 {
76 {L"Common AppData", L"Application Data", IDS_APPDATA, TRUE, TRUE, TRUE},
77 {L"Common Desktop", L"Desktop", IDS_DESKTOP, FALSE, TRUE, TRUE},
78 {L"Common Favorites", L"Favorites", IDS_FAVORITES, FALSE, TRUE, TRUE},
79 {L"Common Start Menu", L"Start Menu", IDS_STARTMENU, FALSE, TRUE, TRUE},
80 {L"Common Programs", L"Start Menu\\Programs", IDS_PROGRAMS, FALSE, TRUE, TRUE},
81 {L"Common Administrative Tools", L"Start Menu\\Programs\\Administrative Tools", IDS_ADMINTOOLS, FALSE, TRUE, FALSE},
82 {L"Common Startup", L"Start Menu\\Programs\\Startup", IDS_STARTUP, FALSE, TRUE, TRUE},
83 {L"Common Templates", L"Templates", IDS_TEMPLATES, TRUE, TRUE, TRUE},
84 {L"Common Documents", L"My Documents", IDS_MYDOCUMENTS, FALSE, TRUE, TRUE},
85 {L"CommonPictures", L"My Documents\\My Pictures", IDS_MYPICTURES, FALSE, TRUE, TRUE},
86 {L"CommonMusic", L"My Documents\\My Music", IDS_MYMUSIC, FALSE, TRUE, TRUE},
87 {L"CommonVideo", L"My Documents\\My Videos", IDS_MYVIDEOS, FALSE, TRUE, TRUE},
88 {NULL, NULL, -1, FALSE, FALSE, FALSE}
89 };
90
91
92 void
93 DebugPrint(char* fmt,...)
94 {
95 char buffer[512];
96 va_list ap;
97
98 va_start(ap, fmt);
99 vsprintf(buffer, fmt, ap);
100 va_end(ap);
101
102 OutputDebugStringA(buffer);
103 }
104
105
106 BOOL WINAPI
107 InitializeProfiles (VOID)
108 {
109 WCHAR szProfilesPath[MAX_PATH];
110 WCHAR szProfilePath[MAX_PATH];
111 WCHAR szBuffer[MAX_PATH];
112 DWORD dwLength;
113 PFOLDERDATA lpFolderData;
114 HKEY hKey;
115
116 /* Load profiles directory path */
117 if (!LoadStringW(hInstance,
118 IDS_PROFILEPATH,
119 szBuffer,
120 MAX_PATH))
121 {
122 DPRINT1("Error: %lu\n", GetLastError());
123 return FALSE;
124 }
125
126 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
127 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
128 0,
129 KEY_ALL_ACCESS,
130 &hKey))
131 {
132 DPRINT1("Error: %lu\n", GetLastError());
133 return FALSE;
134 }
135
136 /* Store profiles directory path */
137 dwLength = (wcslen (szBuffer) + 1) * sizeof(WCHAR);
138 if (RegSetValueExW (hKey,
139 L"ProfilesDirectory",
140 0,
141 REG_EXPAND_SZ,
142 (LPBYTE)szBuffer,
143 dwLength))
144 {
145 DPRINT1("Error: %lu\n", GetLastError());
146 RegCloseKey (hKey);
147 return FALSE;
148 }
149
150 /* Expand it */
151 if (!ExpandEnvironmentStringsW (szBuffer,
152 szProfilesPath,
153 MAX_PATH))
154 {
155 DPRINT1("Error: %lu\n", GetLastError());
156 RegCloseKey (hKey);
157 return FALSE;
158 }
159
160 /* Create profiles directory */
161 if (!CreateDirectoryW (szProfilesPath, NULL))
162 {
163 if (GetLastError () != ERROR_ALREADY_EXISTS)
164 {
165 DPRINT1("Error: %lu\n", GetLastError());
166 RegCloseKey (hKey);
167 return FALSE;
168 }
169 }
170
171 /* Set 'DefaultUserProfile' value */
172 wcscpy (szBuffer, L"Default User");
173 if (!AppendSystemPostfix (szBuffer, MAX_PATH))
174 {
175 DPRINT1("AppendSystemPostfix() failed\n", GetLastError());
176 RegCloseKey (hKey);
177 return FALSE;
178 }
179
180 dwLength = (wcslen (szBuffer) + 1) * sizeof(WCHAR);
181 if (RegSetValueExW (hKey,
182 L"DefaultUserProfile",
183 0,
184 REG_SZ,
185 (LPBYTE)szBuffer,
186 dwLength))
187 {
188 DPRINT1("Error: %lu\n", GetLastError());
189 RegCloseKey (hKey);
190 return FALSE;
191 }
192
193 RegCloseKey (hKey);
194
195 /* Create 'Default User' profile directory */
196 wcscpy (szProfilePath, szProfilesPath);
197 wcscat (szProfilePath, L"\\");
198 wcscat (szProfilePath, szBuffer);
199 if (!CreateDirectoryW (szProfilePath, NULL))
200 {
201 if (GetLastError () != ERROR_ALREADY_EXISTS)
202 {
203 DPRINT1("Error: %lu\n", GetLastError());
204 return FALSE;
205 }
206 }
207
208 /* Set current user profile */
209 SetEnvironmentVariableW(L"USERPROFILE", szProfilePath);
210
211 /* Create 'Default User' subdirectories */
212 /* FIXME: Get these paths from the registry */
213 lpFolderData = &UserShellFolders[0];
214 while (lpFolderData->lpValueName != NULL)
215 {
216 wcscpy(szBuffer, szProfilePath);
217 wcscat(szBuffer, L"\\");
218
219 /* Append the folder name */
220 dwLength = wcslen(szBuffer);
221 if (!LoadStringW(hInstance,
222 lpFolderData->uId,
223 &szBuffer[dwLength],
224 MAX_PATH - dwLength))
225 {
226 /* Use the default name instead */
227 wcscat(szBuffer, lpFolderData->lpPath);
228 }
229
230 if (!CreateDirectoryW(szBuffer, NULL))
231 {
232 if (GetLastError() != ERROR_ALREADY_EXISTS)
233 {
234 DPRINT1("Error: %lu\n", GetLastError());
235 return FALSE;
236 }
237 }
238
239 if (lpFolderData->bHidden == TRUE)
240 {
241 SetFileAttributesW(szBuffer,
242 FILE_ATTRIBUTE_HIDDEN);
243 }
244
245 lpFolderData++;
246 }
247
248 /* Set default 'Shell Folders' values */
249 if (RegOpenKeyExW(HKEY_USERS,
250 L".Default\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
251 0,
252 KEY_ALL_ACCESS,
253 &hKey))
254 {
255 DPRINT1("Error: %lu\n", GetLastError());
256 return FALSE;
257 }
258
259 lpFolderData = &UserShellFolders[0];
260 while (lpFolderData->lpValueName != NULL)
261 {
262 if (lpFolderData->bShellFolder)
263 {
264 wcscpy(szBuffer, szProfilePath);
265 wcscat(szBuffer, L"\\");
266
267 /* Append the folder name */
268 dwLength = wcslen(szBuffer);
269 if (!LoadStringW(hInstance,
270 lpFolderData->uId,
271 &szBuffer[dwLength],
272 MAX_PATH - dwLength))
273 {
274 /* Use the default name instead */
275 wcscat(szBuffer, lpFolderData->lpPath);
276 }
277
278 dwLength = (wcslen(szBuffer) + 1) * sizeof(WCHAR);
279 if (RegSetValueExW(hKey,
280 lpFolderData->lpValueName,
281 0,
282 REG_SZ,
283 (LPBYTE)szBuffer,
284 dwLength))
285 {
286 DPRINT1("Error: %lu\n", GetLastError());
287 RegCloseKey(hKey);
288 return FALSE;
289 }
290 }
291
292 lpFolderData++;
293 }
294
295 /* Set 'Fonts' folder path */
296 GetWindowsDirectoryW(szBuffer, MAX_PATH);
297 wcscat(szBuffer, L"\\media\\fonts");
298
299 dwLength = (wcslen(szBuffer) + 1) * sizeof(WCHAR);
300 if (RegSetValueExW(hKey,
301 L"Fonts",
302 0,
303 REG_SZ,
304 (LPBYTE)szBuffer,
305 dwLength))
306 {
307 DPRINT1("Error: %lu\n", GetLastError());
308 RegCloseKey(hKey);
309 return FALSE;
310 }
311
312 RegCloseKey(hKey);
313
314 /* Set default 'User Shell Folders' values */
315 if (RegOpenKeyExW(HKEY_USERS,
316 L".Default\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
317 0,
318 KEY_ALL_ACCESS,
319 &hKey))
320 {
321 DPRINT1("Error: %lu\n", GetLastError());
322 return FALSE;
323 }
324
325 lpFolderData = &UserShellFolders[0];
326 while (lpFolderData->lpValueName != NULL)
327 {
328 if (lpFolderData->bUserShellFolder)
329 {
330 wcscpy(szBuffer, L"%USERPROFILE%\\");
331
332 /* Append the folder name */
333 dwLength = wcslen(szBuffer);
334 if (!LoadStringW(hInstance,
335 lpFolderData->uId,
336 &szBuffer[dwLength],
337 MAX_PATH - dwLength))
338 {
339 /* Use the default name instead */
340 wcscat(szBuffer, lpFolderData->lpPath);
341 }
342
343 dwLength = (wcslen(szBuffer) + 1) * sizeof(WCHAR);
344 if (RegSetValueExW(hKey,
345 lpFolderData->lpValueName,
346 0,
347 REG_EXPAND_SZ,
348 (LPBYTE)szBuffer,
349 dwLength))
350 {
351 DPRINT1("Error: %lu\n", GetLastError());
352 RegCloseKey(hKey);
353 return FALSE;
354 }
355 }
356
357 lpFolderData++;
358 }
359
360 RegCloseKey(hKey);
361
362
363 /* Set 'AllUsersProfile' value */
364 wcscpy(szBuffer, L"All Users");
365 if (!AppendSystemPostfix(szBuffer, MAX_PATH))
366 {
367 DPRINT1("AppendSystemPostfix() failed\n", GetLastError());
368 return FALSE;
369 }
370
371 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
372 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
373 0,
374 KEY_ALL_ACCESS,
375 &hKey))
376 {
377 DPRINT1("Error: %lu\n", GetLastError());
378 return FALSE;
379 }
380
381 dwLength = (wcslen(szBuffer) + 1) * sizeof(WCHAR);
382 if (RegSetValueExW(hKey,
383 L"AllUsersProfile",
384 0,
385 REG_SZ,
386 (LPBYTE)szBuffer,
387 dwLength))
388 {
389 DPRINT1("Error: %lu\n", GetLastError());
390 RegCloseKey (hKey);
391 return FALSE;
392 }
393
394 RegCloseKey(hKey);
395
396
397 /* Create 'All Users' profile directory */
398 wcscpy(szProfilePath, szProfilesPath);
399 wcscat(szProfilePath, L"\\");
400 wcscat(szProfilePath, szBuffer);
401 if (!CreateDirectoryW(szProfilePath, NULL))
402 {
403 if (GetLastError() != ERROR_ALREADY_EXISTS)
404 {
405 DPRINT1("Error: %lu\n", GetLastError());
406 return FALSE;
407 }
408 }
409
410 /* Set 'All Users' profile */
411 SetEnvironmentVariableW(L"ALLUSERSPROFILE", szProfilePath);
412
413 /* Create 'All Users' subdirectories */
414 /* FIXME: Take these paths from the registry */
415 lpFolderData = &CommonShellFolders[0];
416 while (lpFolderData->lpValueName != NULL)
417 {
418 wcscpy(szBuffer, szProfilePath);
419 wcscat(szBuffer, L"\\");
420
421 /* Append the folder name */
422 dwLength = wcslen(szBuffer);
423 if (!LoadStringW(hInstance,
424 lpFolderData->uId,
425 &szBuffer[dwLength],
426 MAX_PATH - dwLength))
427 {
428 /* Use the default name instead */
429 wcscat(szBuffer, lpFolderData->lpPath);
430 }
431
432 if (!CreateDirectoryW(szBuffer, NULL))
433 {
434 if (GetLastError() != ERROR_ALREADY_EXISTS)
435 {
436 DPRINT1("Error: %lu\n", GetLastError());
437 return FALSE;
438 }
439 }
440
441 if (lpFolderData->bHidden)
442 {
443 SetFileAttributesW(szBuffer,
444 FILE_ATTRIBUTE_HIDDEN);
445 }
446
447 lpFolderData++;
448 }
449
450 /* Set common 'Shell Folders' values */
451 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
452 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
453 0,
454 KEY_ALL_ACCESS,
455 &hKey))
456 {
457 DPRINT1("Error: %lu\n", GetLastError());
458 return FALSE;
459 }
460
461 lpFolderData = &CommonShellFolders[0];
462 while (lpFolderData->lpValueName != NULL)
463 {
464 if (lpFolderData->bShellFolder)
465 {
466 wcscpy(szBuffer, szProfilePath);
467 wcscat(szBuffer, L"\\");
468
469 /* Append the folder name */
470 dwLength = wcslen(szBuffer);
471 if (!LoadStringW(hInstance,
472 lpFolderData->uId,
473 &szBuffer[dwLength],
474 MAX_PATH - dwLength))
475 {
476 /* Use the default name instead */
477 wcscat(szBuffer, lpFolderData->lpPath);
478 }
479
480 dwLength = (wcslen(szBuffer) + 1) * sizeof(WCHAR);
481 if (RegSetValueExW(hKey,
482 lpFolderData->lpValueName,
483 0,
484 REG_SZ,
485 (LPBYTE)szBuffer,
486 dwLength))
487 {
488 DPRINT1("Error: %lu\n", GetLastError());
489 RegCloseKey(hKey);
490 return FALSE;
491 }
492 }
493
494 lpFolderData++;
495 }
496
497 RegCloseKey(hKey);
498
499 /* Set common 'User Shell Folders' values */
500 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
501 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders",
502 0,
503 KEY_ALL_ACCESS,
504 &hKey))
505 {
506 DPRINT1("Error: %lu\n", GetLastError());
507 return FALSE;
508 }
509
510 lpFolderData = &CommonShellFolders[0];
511 while (lpFolderData->lpValueName != NULL)
512 {
513 if (lpFolderData->bUserShellFolder)
514 {
515 wcscpy(szBuffer, L"%ALLUSERSPROFILE%\\");
516
517 /* Append the folder name */
518 dwLength = wcslen(szBuffer);
519 if (!LoadStringW(hInstance,
520 lpFolderData->uId,
521 &szBuffer[dwLength],
522 MAX_PATH - dwLength))
523 {
524 /* Use the default name instead */
525 wcscat(szBuffer, lpFolderData->lpPath);
526 }
527
528 dwLength = (wcslen(szBuffer) + 1) * sizeof(WCHAR);
529 if (RegSetValueExW(hKey,
530 lpFolderData->lpValueName,
531 0,
532 REG_EXPAND_SZ,
533 (LPBYTE)szBuffer,
534 dwLength))
535 {
536 DPRINT1("Error: %lu\n", GetLastError());
537 RegCloseKey(hKey);
538 return FALSE;
539 }
540 }
541
542 lpFolderData++;
543 }
544
545 RegCloseKey(hKey);
546
547 /* Load 'Program Files' location */
548 if (!LoadStringW(hInstance,
549 IDS_PROGRAMFILES,
550 szBuffer,
551 MAX_PATH))
552 {
553 DPRINT1("Error: %lu\n", GetLastError());
554 return FALSE;
555 }
556
557 /* Expand it */
558 if (!ExpandEnvironmentStringsW (szBuffer,
559 szProfilesPath,
560 MAX_PATH))
561 {
562 DPRINT1("Error: %lu\n", GetLastError());
563 RegCloseKey (hKey);
564 return FALSE;
565 }
566
567 /* Store it */
568 if (RegOpenKeyExW (HKEY_LOCAL_MACHINE,
569 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion",
570 0,
571 KEY_ALL_ACCESS,
572 &hKey))
573 {
574 DPRINT1("Error: %lu\n", GetLastError());
575 return FALSE;
576 }
577
578 dwLength = (wcslen (szProfilesPath) + 1) * sizeof(WCHAR);
579 if (RegSetValueExW (hKey,
580 L"ProgramFilesDir",
581 0,
582 REG_SZ,
583 (LPBYTE)szProfilesPath,
584 dwLength))
585 {
586 DPRINT1("Error: %lu\n", GetLastError());
587 RegCloseKey (hKey);
588 return FALSE;
589 }
590
591 RegCloseKey (hKey);
592
593 /* Create directory */
594 if (!CreateDirectoryW (szProfilesPath, NULL))
595 {
596 if (GetLastError () != ERROR_ALREADY_EXISTS)
597 {
598 DPRINT1("Error: %lu\n", GetLastError());
599 return FALSE;
600 }
601 }
602
603
604 DPRINT("Success\n");
605
606 return TRUE;
607 }
608
609
610 BOOL
611 UpdateUsersShellFolderSettings(LPCWSTR lpUserProfilePath,
612 HKEY hUserKey)
613 {
614 WCHAR szBuffer[MAX_PATH];
615 DWORD dwLength;
616 PFOLDERDATA lpFolderData;
617 HKEY hFoldersKey;
618
619 DPRINT("UpdateUsersShellFolderSettings() called\n");
620
621 DPRINT("User profile path: %S\n", lpUserProfilePath);
622
623 if (RegOpenKeyExW(hUserKey,
624 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
625 0,
626 KEY_ALL_ACCESS,
627 &hFoldersKey))
628 {
629 DPRINT1("Error: %lu\n", GetLastError());
630 return FALSE;
631 }
632
633 lpFolderData = &UserShellFolders[0];
634 while (lpFolderData->lpValueName != NULL)
635 {
636 if (lpFolderData->bShellFolder)
637 {
638 wcscpy(szBuffer, lpUserProfilePath);
639 wcscat(szBuffer, L"\\");
640
641 /* Append the folder name */
642 dwLength = wcslen(szBuffer);
643 if (!LoadStringW(hInstance,
644 lpFolderData->uId,
645 &szBuffer[dwLength],
646 MAX_PATH - dwLength))
647 {
648 /* Use the default name instead */
649 wcscat(szBuffer, lpFolderData->lpPath);
650 }
651
652 DPRINT("%S: %S\n", lpFolderData->lpValueName, szBuffer);
653
654 dwLength = (wcslen(szBuffer) + 1) * sizeof(WCHAR);
655 if (RegSetValueExW(hFoldersKey,
656 lpFolderData->lpValueName,
657 0,
658 REG_SZ,
659 (LPBYTE)szBuffer,
660 dwLength))
661 {
662 DPRINT1("Error: %lu\n", GetLastError());
663 RegCloseKey(hFoldersKey);
664 return FALSE;
665 }
666 }
667
668 lpFolderData++;
669 }
670
671 RegCloseKey(hFoldersKey);
672
673 DPRINT("UpdateUsersShellFolderSettings() done\n");
674
675 return TRUE;
676 }
677
678 /* EOF */