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