d3d8: Remove D3DFMT_R8G8B8 special handling.
[wine.git] / dlls / userenv / userenv_main.c
blob89fedabadae8116b7d3be788c9fadf27cfbf913d
1 /*
2 * Implementation of userenv.dll
4 * Copyright 2006 Mike McCormack for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #include "ntstatus.h"
24 #define WIN32_NO_STATUS
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winreg.h"
28 #include "winternl.h"
29 #include "winnls.h"
30 #include "sddl.h"
31 #include "userenv.h"
33 #include "wine/debug.h"
34 #include "wine/unicode.h"
36 WINE_DEFAULT_DEBUG_CHANNEL( userenv );
38 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
40 TRACE("%p %d %p\n", hinstDLL, fdwReason, lpvReserved);
42 switch (fdwReason)
44 case DLL_WINE_PREATTACH:
45 return FALSE; /* prefer native version */
46 case DLL_PROCESS_ATTACH:
47 DisableThreadLibraryCalls(hinstDLL);
48 break;
49 case DLL_PROCESS_DETACH:
50 break;
52 return TRUE;
55 static BOOL get_reg_value(WCHAR *env, HKEY hkey, const WCHAR *name, WCHAR *val, DWORD size)
57 DWORD type, res_size=0;
59 if (RegQueryValueExW(hkey, name, 0, &type, NULL, &res_size) != ERROR_SUCCESS)
60 return FALSE;
62 if (type == REG_SZ)
64 if (res_size > size)
65 return FALSE;
67 return RegQueryValueExW(hkey, name, 0, NULL, (BYTE*)val, &size) == ERROR_SUCCESS;
69 else if (type == REG_EXPAND_SZ)
71 UNICODE_STRING us_buf, us_expanded;
72 WCHAR *buf = HeapAlloc(GetProcessHeap(), 0, res_size);
73 if (!buf)
74 return FALSE;
76 if (RegQueryValueExW(hkey, name, 0, NULL, (BYTE*)buf, &res_size) != ERROR_SUCCESS)
78 HeapFree(GetProcessHeap(), 0, buf);
79 return FALSE;
82 RtlInitUnicodeString(&us_buf, buf);
83 us_expanded.Buffer = val;
84 us_expanded.MaximumLength = size;
85 if (RtlExpandEnvironmentStrings_U(env, &us_buf, &us_expanded, &size) != STATUS_SUCCESS)
87 HeapFree(GetProcessHeap(), 0, buf);
88 return FALSE;
91 HeapFree(GetProcessHeap(), 0, buf);
92 return TRUE;
95 return FALSE;
98 static void set_registry_variables(WCHAR **env, HKEY hkey, DWORD type, BOOL set_path)
100 static const WCHAR SystemRootW[] = {'S','y','s','t','e','m','R','o','o','t',0};
101 static const WCHAR SystemDriveW[] = {'S','y','s','t','e','m','D','r','i','v','e',0};
102 static const WCHAR PATHW[] = {'P','A','T','H'};
104 UNICODE_STRING us_name, us_value;
105 WCHAR name[1024], value[1024];
106 DWORD ret, index, size;
108 for (index = 0; ; index++)
110 size = sizeof(name)/sizeof(WCHAR);
111 ret = RegEnumValueW(hkey, index, name, &size, NULL, NULL, NULL, NULL);
112 if (ret != ERROR_SUCCESS)
113 break;
115 if (!memicmpW(name, SystemRootW, sizeof(SystemRootW)/sizeof(WCHAR)))
116 continue;
117 if (!memicmpW(name, SystemDriveW, sizeof(SystemDriveW)/sizeof(WCHAR)))
118 continue;
120 RtlInitUnicodeString(&us_name, name);
121 us_value.Buffer = value;
122 us_value.MaximumLength = sizeof(value);
123 if (!memicmpW(name, PATHW, sizeof(PATHW)/sizeof(WCHAR)) &&
124 !RtlQueryEnvironmentVariable_U(*env, &us_name, &us_value))
126 if (!set_path)
127 continue;
129 size = strlenW(value)+1;
130 if (!get_reg_value(*env, hkey, name, value+size,
131 sizeof(value)-size*sizeof(WCHAR)))
132 continue;
134 value[size] = ';';
135 RtlInitUnicodeString(&us_value, value);
136 RtlSetEnvironmentVariable(env, &us_name, &us_value);
137 continue;
140 if (!get_reg_value(*env, hkey, name, value, sizeof(value)))
141 continue;
143 if(!value[0])
144 continue;
146 RtlInitUnicodeString(&us_value, value);
147 RtlSetEnvironmentVariable(env, &us_name, &us_value);
151 static void set_wow64_environment(WCHAR **env)
153 static const WCHAR versionW[] = {'S','o','f','t','w','a','r','e','\\',
154 'M','i','c','r','o','s','o','f','t','\\',
155 'W','i','n','d','o','w','s','\\',
156 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',0};
157 static const WCHAR progdirW[] = {'P','r','o','g','r','a','m','F','i','l','e','s','D','i','r',0};
158 static const WCHAR progdir86W[] = {'P','r','o','g','r','a','m','F','i','l','e','s','D','i','r',' ','(','x','8','6',')',0};
159 static const WCHAR progfilesW[] = {'P','r','o','g','r','a','m','F','i','l','e','s',0};
160 static const WCHAR progw6432W[] = {'P','r','o','g','r','a','m','W','6','4','3','2',0};
161 static const WCHAR commondirW[] = {'C','o','m','m','o','n','F','i','l','e','s','D','i','r',0};
162 static const WCHAR commondir86W[] = {'C','o','m','m','o','n','F','i','l','e','s','D','i','r',' ','(','x','8','6',')',0};
163 static const WCHAR commonfilesW[] = {'C','o','m','m','o','n','P','r','o','g','r','a','m','F','i','l','e','s',0};
164 static const WCHAR commonw6432W[] = {'C','o','m','m','o','n','P','r','o','g','r','a','m','W','6','4','3','2',0};
166 UNICODE_STRING nameW, valueW;
167 WCHAR buf[64];
168 HKEY hkey;
169 BOOL is_win64 = (sizeof(void *) > sizeof(int));
170 BOOL is_wow64;
172 IsWow64Process( GetCurrentProcess(), &is_wow64 );
174 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, versionW, 0,
175 KEY_READ|KEY_WOW64_64KEY, &hkey))
176 return;
178 /* set the ProgramFiles variables */
180 if (get_reg_value(*env, hkey, progdirW, buf, sizeof(buf)))
182 if (is_win64 || is_wow64)
184 RtlInitUnicodeString(&nameW, progw6432W);
185 RtlInitUnicodeString(&valueW, buf);
186 RtlSetEnvironmentVariable(env, &nameW, &valueW);
188 if (is_win64 || !is_wow64)
190 RtlInitUnicodeString(&nameW, progfilesW);
191 RtlInitUnicodeString(&valueW, buf);
192 RtlSetEnvironmentVariable(env, &nameW, &valueW);
195 if (is_wow64 && get_reg_value(*env, hkey, progdir86W, buf, sizeof(buf)))
197 RtlInitUnicodeString(&nameW, progfilesW);
198 RtlInitUnicodeString(&valueW, buf);
199 RtlSetEnvironmentVariable(env, &nameW, &valueW);
202 /* set the CommonProgramFiles variables */
204 if (get_reg_value(*env, hkey, commondirW, buf, sizeof(buf)))
206 if (is_win64 || is_wow64)
208 RtlInitUnicodeString(&nameW, commonw6432W);
209 RtlInitUnicodeString(&valueW, buf);
210 RtlSetEnvironmentVariable(env, &nameW, &valueW);
212 if (is_win64 || !is_wow64)
214 RtlInitUnicodeString(&nameW, commonfilesW);
215 RtlInitUnicodeString(&valueW, buf);
216 RtlSetEnvironmentVariable(env, &nameW, &valueW);
219 if (is_wow64 && get_reg_value(*env, hkey, commondir86W, buf, sizeof(buf)))
221 RtlInitUnicodeString(&nameW, commonfilesW);
222 RtlInitUnicodeString(&valueW, buf);
223 RtlSetEnvironmentVariable(env, &nameW, &valueW);
226 RegCloseKey(hkey);
229 BOOL WINAPI CreateEnvironmentBlock( LPVOID* lpEnvironment,
230 HANDLE hToken, BOOL bInherit )
232 static const WCHAR env_keyW[] = {'S','y','s','t','e','m','\\',
233 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
234 'C','o','n','t','r','o','l','\\',
235 'S','e','s','s','i','o','n',' ','M','a','n','a','g','e','r','\\',
236 'E','n','v','i','r','o','n','m','e','n','t',0};
237 static const WCHAR profile_keyW[] = {'S','o','f','t','w','a','r','e','\\',
238 'M','i','c','r','o','s','o','f','t','\\',
239 'W','i','n','d','o','w','s',' ','N','T','\\',
240 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
241 'P','r','o','f','i','l','e','L','i','s','t',0};
242 static const WCHAR envW[] = {'E','n','v','i','r','o','n','m','e','n','t',0};
243 static const WCHAR volatile_envW[] = {'V','o','l','a','t','i','l','e',' ','E','n','v','i','r','o','n','m','e','n','t',0};
244 static const WCHAR ProfilesDirectoryW[] = {'P','r','o','f','i','l','e','s','D','i','r','e','c','t','o','r','y',0};
246 static const WCHAR SystemRootW[] = {'S','y','s','t','e','m','R','o','o','t',0};
247 static const WCHAR SystemDriveW[] = {'S','y','s','t','e','m','D','r','i','v','e',0};
248 static const WCHAR AllUsersProfileW[] = {'A','l','l','U','s','e','r','s','P','r','o','f','i','l','e',0};
249 static const WCHAR ALLUSERSPROFILEW[] = {'A','L','L','U','S','E','R','S','P','R','O','F','I','L','E',0};
250 static const WCHAR USERNAMEW[] = {'U','S','E','R','N','A','M','E',0};
251 static const WCHAR USERPROFILEW[] = {'U','S','E','R','P','R','O','F','I','L','E',0};
252 static const WCHAR DefaultW[] = {'D','e','f','a','u','l','t',0};
253 static const WCHAR COMPUTERNAMEW[] = {'C','O','M','P','U','T','E','R','N','A','M','E',0};
255 WCHAR *env, buf[UNICODE_STRING_MAX_CHARS], profiles_dir[MAX_PATH];
256 UNICODE_STRING us_name, us_val;
257 DWORD len;
258 HKEY hkey, hsubkey;
260 TRACE("%p %p %d\n", lpEnvironment, hToken, bInherit );
262 if (!lpEnvironment)
263 return FALSE;
265 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, env_keyW, 0, KEY_READ, &hkey) != ERROR_SUCCESS)
266 return FALSE;
268 if (RtlCreateEnvironment(bInherit, &env) != STATUS_SUCCESS)
270 RegCloseKey(hkey);
271 return FALSE;
274 if (!GetEnvironmentVariableW(SystemRootW, buf, UNICODE_STRING_MAX_CHARS))
276 if (!get_reg_value(env, hkey, SystemRootW, buf, UNICODE_STRING_MAX_CHARS))
278 buf[0] = 0;
279 WARN("SystemRoot variable not set\n");
282 RtlInitUnicodeString(&us_name, SystemRootW);
283 RtlInitUnicodeString(&us_val, buf);
284 RtlSetEnvironmentVariable(&env, &us_name, &us_val);
286 if (!GetEnvironmentVariableW(SystemDriveW, buf, UNICODE_STRING_MAX_CHARS))
288 if (!get_reg_value(env, hkey, SystemRootW, buf, UNICODE_STRING_MAX_CHARS))
290 buf[0] = 0;
291 WARN("SystemDrive variable not set\n");
294 RtlInitUnicodeString(&us_name, SystemDriveW);
295 RtlInitUnicodeString(&us_val, buf);
296 RtlSetEnvironmentVariable(&env, &us_name, &us_val);
298 set_registry_variables(&env, hkey, REG_SZ, !bInherit);
299 set_registry_variables(&env, hkey, REG_EXPAND_SZ, !bInherit);
301 if (RegOpenKeyExW(hkey, envW, 0, KEY_READ, &hsubkey) == ERROR_SUCCESS)
303 set_registry_variables(&env, hsubkey, REG_SZ, !bInherit);
304 set_registry_variables(&env, hsubkey, REG_EXPAND_SZ, !bInherit);
305 RegCloseKey(hsubkey);
308 if (RegOpenKeyExW(hkey, volatile_envW, 0, KEY_READ, &hsubkey) == ERROR_SUCCESS)
310 set_registry_variables(&env, hsubkey, REG_SZ, !bInherit);
311 set_registry_variables(&env, hsubkey, REG_EXPAND_SZ, !bInherit);
312 RegCloseKey(hsubkey);
314 RegCloseKey(hkey);
316 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, profile_keyW, 0, KEY_READ, &hkey) == ERROR_SUCCESS)
318 if (get_reg_value(env, hkey, ProfilesDirectoryW, profiles_dir, MAX_PATH-sizeof(WCHAR)))
320 len = strlenW(profiles_dir);
321 if (profiles_dir[len-1] != '\\')
323 profiles_dir[len++] = '\\';
324 profiles_dir[len] = '\0';
327 memcpy(buf, profiles_dir, len*sizeof(WCHAR));
328 if (get_reg_value(env, hkey, AllUsersProfileW, buf+len, UNICODE_STRING_MAX_CHARS-len))
330 RtlInitUnicodeString(&us_name, ALLUSERSPROFILEW);
331 RtlInitUnicodeString(&us_val, buf);
332 RtlSetEnvironmentVariable(&env, &us_name, &us_val);
335 else
337 profiles_dir[0] = 0;
340 RegCloseKey(hkey);
343 len = sizeof(buf)/sizeof(WCHAR);
344 if (GetComputerNameW(buf, &len))
346 RtlInitUnicodeString(&us_name, COMPUTERNAMEW);
347 RtlInitUnicodeString(&us_val, buf);
348 RtlSetEnvironmentVariable(&env, &us_name, &us_val);
351 set_wow64_environment(&env);
353 if (!hToken)
355 if (profiles_dir[0])
357 len = strlenW(profiles_dir);
358 if (len*sizeof(WCHAR)+sizeof(DefaultW) < sizeof(buf))
360 memcpy(buf, profiles_dir, len*sizeof(WCHAR));
361 memcpy(buf+len, DefaultW, sizeof(DefaultW));
362 RtlInitUnicodeString(&us_name, USERPROFILEW);
363 RtlInitUnicodeString(&us_val, buf);
364 RtlSetEnvironmentVariable(&env, &us_name, &us_val);
368 buf[0] = '.';
369 memcpy(buf+1, DefaultW, sizeof(DefaultW));
371 else
373 TOKEN_USER *token_user = NULL;
374 SID_NAME_USE use;
375 WCHAR *sidW;
376 DWORD size, tmp=0;
378 if (GetTokenInformation(hToken, TokenUser, NULL, 0, &len) ||
379 GetLastError()!=ERROR_INSUFFICIENT_BUFFER ||
380 !(token_user = HeapAlloc(GetProcessHeap(), 0, len)) ||
381 !GetTokenInformation(hToken, TokenUser, token_user, len, &len) ||
382 !ConvertSidToStringSidW(token_user->User.Sid, &sidW))
384 HeapFree(GetProcessHeap(), 0, token_user);
385 RtlDestroyEnvironment(env);
386 return FALSE;
389 len = strlenW(profiles_dir);
390 memcpy(buf, profiles_dir, len*sizeof(WCHAR));
392 size = UNICODE_STRING_MAX_CHARS-len;
393 if (LookupAccountSidW(NULL, token_user->User.Sid,
394 buf+len, &size, NULL, &tmp, &use))
396 RtlInitUnicodeString(&us_name, USERNAMEW);
397 RtlInitUnicodeString(&us_val, buf+len);
398 RtlSetEnvironmentVariable(&env, &us_name, &us_val);
400 if (len)
402 RtlInitUnicodeString(&us_name, USERPROFILEW);
403 RtlInitUnicodeString(&us_val, buf);
404 RtlSetEnvironmentVariable(&env, &us_name, &us_val);
408 HeapFree(GetProcessHeap(), 0, token_user);
409 strcpyW(buf, sidW);
410 LocalFree(sidW);
413 if (RegOpenKeyExW(HKEY_USERS, buf, 0, KEY_READ, &hkey) == ERROR_SUCCESS)
415 if (RegOpenKeyExW(hkey, envW, 0, KEY_READ, &hsubkey) == ERROR_SUCCESS)
417 set_registry_variables(&env, hsubkey, REG_SZ, !bInherit);
418 set_registry_variables(&env, hsubkey, REG_EXPAND_SZ, !bInherit);
419 RegCloseKey(hsubkey);
422 if (RegOpenKeyExW(hkey, volatile_envW, 0, KEY_READ, &hsubkey) == ERROR_SUCCESS)
424 set_registry_variables(&env, hsubkey, REG_SZ, !bInherit);
425 set_registry_variables(&env, hsubkey, REG_EXPAND_SZ, !bInherit);
426 RegCloseKey(hsubkey);
428 RegCloseKey(hkey);
431 *lpEnvironment = env;
432 return TRUE;
435 BOOL WINAPI DestroyEnvironmentBlock(LPVOID lpEnvironment)
437 NTSTATUS r;
439 TRACE("%p\n", lpEnvironment);
440 r = RtlDestroyEnvironment(lpEnvironment);
441 if (r == STATUS_SUCCESS)
442 return TRUE;
443 return FALSE;
446 BOOL WINAPI ExpandEnvironmentStringsForUserA( HANDLE hToken, LPCSTR lpSrc,
447 LPSTR lpDest, DWORD dwSize )
449 BOOL ret;
451 TRACE("%p %s %p %d\n", hToken, debugstr_a(lpSrc), lpDest, dwSize);
453 ret = ExpandEnvironmentStringsA( lpSrc, lpDest, dwSize );
454 TRACE("<- %s\n", debugstr_a(lpDest));
455 return ret;
458 BOOL WINAPI ExpandEnvironmentStringsForUserW( HANDLE hToken, LPCWSTR lpSrc,
459 LPWSTR lpDest, DWORD dwSize )
461 BOOL ret;
463 TRACE("%p %s %p %d\n", hToken, debugstr_w(lpSrc), lpDest, dwSize);
465 ret = ExpandEnvironmentStringsW( lpSrc, lpDest, dwSize );
466 TRACE("<- %s\n", debugstr_w(lpDest));
467 return ret;
470 BOOL WINAPI GetDefaultUserProfileDirectoryA( LPSTR lpProfileDir, LPDWORD lpcchSize )
472 FIXME("%p %p\n", lpProfileDir, lpcchSize );
473 return FALSE;
476 BOOL WINAPI GetDefaultUserProfileDirectoryW( LPWSTR lpProfileDir, LPDWORD lpcchSize )
478 FIXME("%p %p\n", lpProfileDir, lpcchSize );
479 return FALSE;
482 BOOL WINAPI GetUserProfileDirectoryA( HANDLE hToken, LPSTR lpProfileDir,
483 LPDWORD lpcchSize )
485 BOOL ret;
486 WCHAR *dirW = NULL;
488 TRACE( "%p %p %p\n", hToken, lpProfileDir, lpcchSize );
490 if (!lpProfileDir || !lpcchSize)
492 SetLastError( ERROR_INVALID_PARAMETER );
493 return FALSE;
495 if (!(dirW = HeapAlloc( GetProcessHeap(), 0, *lpcchSize * sizeof(WCHAR) )))
496 return FALSE;
498 if ((ret = GetUserProfileDirectoryW( hToken, dirW, lpcchSize )))
499 WideCharToMultiByte( CP_ACP, 0, dirW, *lpcchSize, lpProfileDir, *lpcchSize, NULL, NULL );
501 HeapFree( GetProcessHeap(), 0, dirW );
502 return ret;
505 BOOL WINAPI GetUserProfileDirectoryW( HANDLE hToken, LPWSTR lpProfileDir,
506 LPDWORD lpcchSize )
508 static const WCHAR slashW[] = {'\\',0};
509 TOKEN_USER *t;
510 WCHAR *userW = NULL, *dirW = NULL;
511 DWORD len, dir_len, domain_len;
512 SID_NAME_USE use;
513 BOOL ret = FALSE;
515 TRACE( "%p %p %p\n", hToken, lpProfileDir, lpcchSize );
517 if (!lpcchSize)
519 SetLastError( ERROR_INVALID_PARAMETER );
520 return FALSE;
523 len = 0;
524 GetTokenInformation( hToken, TokenUser, NULL, 0, &len );
525 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE;
526 if (!(t = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE;
527 if (!GetTokenInformation( hToken, TokenUser, t, len, &len )) goto done;
529 len = domain_len = 0;
530 LookupAccountSidW( NULL, t->User.Sid, NULL, &len, NULL, &domain_len, NULL );
531 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) goto done;
532 if (!(userW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) goto done;
533 if (!LookupAccountSidW( NULL, t->User.Sid, userW, &len, NULL, &domain_len, &use )) goto done;
535 dir_len = 0;
536 GetProfilesDirectoryW( NULL, &dir_len );
537 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) goto done;
538 if (!(dirW = HeapAlloc( GetProcessHeap(), 0, (dir_len + 1) * sizeof(WCHAR) ))) goto done;
539 if (!GetProfilesDirectoryW( dirW, &dir_len )) goto done;
541 len += dir_len + 2;
542 if (*lpcchSize < len)
544 SetLastError( ERROR_INSUFFICIENT_BUFFER );
545 *lpcchSize = len;
546 goto done;
548 strcpyW( lpProfileDir, dirW );
549 strcatW( lpProfileDir, slashW );
550 strcatW( lpProfileDir, userW );
551 *lpcchSize = len;
552 ret = TRUE;
554 done:
555 HeapFree( GetProcessHeap(), 0, t );
556 HeapFree( GetProcessHeap(), 0, userW );
557 HeapFree( GetProcessHeap(), 0, dirW );
558 return ret;
561 static const char ProfileListA[] = "Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList";
563 BOOL WINAPI GetProfilesDirectoryA( LPSTR lpProfilesDir, LPDWORD lpcchSize )
565 static const char ProfilesDirectory[] = "ProfilesDirectory";
566 LONG l;
567 HKEY key;
568 BOOL ret = FALSE;
569 DWORD len = 0, expanded_len;
570 LPSTR unexpanded_profiles_dir = NULL;
572 TRACE("%p %p\n", lpProfilesDir, lpcchSize );
574 if (!lpProfilesDir || !lpcchSize)
576 SetLastError(ERROR_INVALID_PARAMETER);
577 return FALSE;
580 l = RegOpenKeyExA(HKEY_LOCAL_MACHINE, ProfileListA, 0, KEY_READ, &key);
581 if (l)
583 SetLastError(l);
584 return FALSE;
586 l = RegQueryValueExA(key, ProfilesDirectory, NULL, NULL, NULL, &len);
587 if (l)
589 SetLastError(l);
590 goto end;
592 unexpanded_profiles_dir = HeapAlloc(GetProcessHeap(), 0, len);
593 if (!unexpanded_profiles_dir)
595 SetLastError(ERROR_OUTOFMEMORY);
596 goto end;
598 l = RegQueryValueExA(key, ProfilesDirectory, NULL, NULL,
599 (BYTE *)unexpanded_profiles_dir, &len);
600 if (l)
602 SetLastError(l);
603 goto end;
605 expanded_len = ExpandEnvironmentStringsA(unexpanded_profiles_dir, NULL, 0);
606 /* The returned length doesn't include the NULL terminator. */
607 if (*lpcchSize < expanded_len - 1)
609 *lpcchSize = expanded_len - 1;
610 SetLastError(ERROR_INSUFFICIENT_BUFFER);
611 goto end;
613 *lpcchSize = expanded_len - 1;
614 /* The return value is also the expected length. */
615 ret = ExpandEnvironmentStringsA(unexpanded_profiles_dir, lpProfilesDir,
616 expanded_len) - 1;
617 end:
618 HeapFree(GetProcessHeap(), 0, unexpanded_profiles_dir);
619 RegCloseKey(key);
620 return ret;
623 static const WCHAR ProfileListW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','P','r','o','f','i','l','e','L','i','s','t',0};
625 BOOL WINAPI GetProfilesDirectoryW( LPWSTR lpProfilesDir, LPDWORD lpcchSize )
627 static const WCHAR ProfilesDirectory[] = {'P','r','o','f','i','l','e','s','D','i','r','e','c','t','o','r','y',0};
628 LONG l;
629 HKEY key;
630 BOOL ret = FALSE;
631 DWORD len = 0, expanded_len;
632 LPWSTR unexpanded_profiles_dir = NULL;
634 TRACE("%p %p\n", lpProfilesDir, lpcchSize );
636 if (!lpcchSize)
638 SetLastError(ERROR_INVALID_PARAMETER);
639 return FALSE;
642 l = RegOpenKeyExW(HKEY_LOCAL_MACHINE, ProfileListW, 0, KEY_READ, &key);
643 if (l)
645 SetLastError(l);
646 return FALSE;
648 l = RegQueryValueExW(key, ProfilesDirectory, NULL, NULL, NULL, &len);
649 if (l)
651 SetLastError(l);
652 goto end;
654 unexpanded_profiles_dir = HeapAlloc(GetProcessHeap(), 0, len);
655 if (!unexpanded_profiles_dir)
657 SetLastError(ERROR_OUTOFMEMORY);
658 goto end;
660 l = RegQueryValueExW(key, ProfilesDirectory, NULL, NULL,
661 (BYTE *)unexpanded_profiles_dir, &len);
662 if (l)
664 SetLastError(l);
665 goto end;
667 expanded_len = ExpandEnvironmentStringsW(unexpanded_profiles_dir, NULL, 0);
668 /* The returned length doesn't include the NULL terminator. */
669 if (*lpcchSize < expanded_len - 1 || !lpProfilesDir)
671 *lpcchSize = expanded_len - 1;
672 SetLastError(ERROR_INSUFFICIENT_BUFFER);
673 goto end;
675 *lpcchSize = expanded_len - 1;
676 /* The return value is also the expected length. */
677 ret = ExpandEnvironmentStringsW(unexpanded_profiles_dir, lpProfilesDir,
678 expanded_len) - 1;
679 end:
680 HeapFree(GetProcessHeap(), 0, unexpanded_profiles_dir);
681 RegCloseKey(key);
682 return ret;
685 BOOL WINAPI GetAllUsersProfileDirectoryA( LPSTR lpProfileDir, LPDWORD lpcchSize )
687 FIXME("%p %p\n", lpProfileDir, lpcchSize);
688 return FALSE;
691 BOOL WINAPI GetAllUsersProfileDirectoryW( LPWSTR lpProfileDir, LPDWORD lpcchSize )
693 FIXME("%p %p\n", lpProfileDir, lpcchSize);
694 return FALSE;
697 BOOL WINAPI GetProfileType( DWORD *pdwFlags )
699 FIXME("%p\n", pdwFlags );
700 *pdwFlags = 0;
701 return TRUE;
704 BOOL WINAPI LoadUserProfileA( HANDLE hToken, LPPROFILEINFOA lpProfileInfo )
706 FIXME("%p %p\n", hToken, lpProfileInfo );
707 lpProfileInfo->hProfile = HKEY_CURRENT_USER;
708 return TRUE;
711 BOOL WINAPI LoadUserProfileW( HANDLE hToken, LPPROFILEINFOW lpProfileInfo )
713 FIXME("%p %p\n", hToken, lpProfileInfo );
714 lpProfileInfo->hProfile = HKEY_CURRENT_USER;
715 return TRUE;
718 BOOL WINAPI RegisterGPNotification( HANDLE event, BOOL machine )
720 FIXME("%p %d\n", event, machine );
721 return TRUE;
724 BOOL WINAPI UnregisterGPNotification( HANDLE event )
726 FIXME("%p\n", event );
727 return TRUE;
730 BOOL WINAPI UnloadUserProfile( HANDLE hToken, HANDLE hProfile )
732 FIXME("(%p, %p): stub\n", hToken, hProfile);
733 return FALSE;
736 /******************************************************************************
737 * USERENV.138
739 * Create .lnk file
741 * PARAMETERS
742 * int csidl [in] well-known directory location to create link in
743 * LPCSTR lnk_dir [in] directory (relative to directory specified by csidl) to create link in
744 * LPCSTR lnk_filename [in] filename of the link file without .lnk extension
745 * LPCSTR lnk_target [in] file/directory pointed to by link
746 * LPCSTR lnk_iconfile [in] link icon resource filename
747 * DWORD lnk_iconid [in] link icon resource id in file referred by lnk_iconfile
748 * LPCSTR work_directory [in] link target's work directory
749 * WORD hotkey [in] link hotkey (virtual key id)
750 * DWORD win_state [in] initial window size (SW_SHOWMAXIMIZED to start maximized,
751 * SW_SHOWMINNOACTIVE to start minimized, everything else is default state)
752 * LPCSTR comment [in] comment - link's comment
753 * LPCSTR loc_filename_resfile [in] resource file which holds localized filename for this link file
754 * DWORD loc_filename_resid [in] resource id for this link file's localized filename
756 * RETURNS
757 * TRUE: Link file was successfully created
758 * FALSE: Link file was not created
760 BOOL WINAPI USERENV_138( int csidl, LPCSTR lnk_dir, LPCSTR lnk_filename,
761 LPCSTR lnk_target, LPCSTR lnk_iconfile, DWORD lnk_iconid,
762 LPCSTR work_directory, WORD hotkey, DWORD win_state, LPCSTR comment,
763 LPCSTR loc_filename_resfile, DWORD loc_filename_resid)
765 FIXME("(%d,%s,%s,%s,%s,%d,%s,0x%x,%d,%s,%s,%d) - stub\n", csidl, debugstr_a(lnk_dir),
766 debugstr_a(lnk_filename), debugstr_a(lnk_target), debugstr_a(lnk_iconfile),
767 lnk_iconid, debugstr_a(work_directory), hotkey, win_state,
768 debugstr_a(comment), debugstr_a(loc_filename_resfile), loc_filename_resid );
770 return FALSE;