xref: /reactos/dll/win32/userenv/setup.c (revision c2c66aff)
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