Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

750 lines
26 KiB

  1. //*************************************************************
  2. //
  3. // Global Variables
  4. //
  5. // Microsoft Confidential
  6. // Copyright (c) Microsoft Corporation 1995
  7. // All rights reserved
  8. //
  9. //*************************************************************
  10. #include "uenv.h"
  11. #include <winfoldr.h>
  12. #include "strsafe.h"
  13. HINSTANCE g_hDllInstance;
  14. DWORD g_dwBuildNumber;
  15. NTPRODUCTTYPE g_ProductType;
  16. HANDLE g_hProfileSetup = NULL;
  17. DWORD g_dwNumShellFolders;
  18. DWORD g_dwNumCommonShellFolders;
  19. HANDLE g_hPolicyCritMutexMach = NULL;
  20. HANDLE g_hPolicyCritMutexUser = NULL;
  21. HANDLE g_hRegistryPolicyCritMutexMach = NULL;
  22. HANDLE g_hRegistryPolicyCritMutexUser = NULL;
  23. HANDLE g_hPolicyNotifyEventMach = NULL;
  24. HANDLE g_hPolicyNotifyEventUser = NULL;
  25. HANDLE g_hPolicyNeedFGEventMach = NULL;
  26. HANDLE g_hPolicyNeedFGEventUser = NULL;
  27. HANDLE g_hPolicyDoneEventMach = NULL;
  28. HANDLE g_hPolicyDoneEventUser = NULL;
  29. HANDLE g_hPolicyForegroundDoneEventMach = 0;
  30. HANDLE g_hPolicyForegroundDoneEventUser = 0;
  31. const TCHAR c_szStarDotStar[] = TEXT("*.*");
  32. const TCHAR c_szSlash[] = TEXT("\\");
  33. const TCHAR c_szDot[] = TEXT(".");
  34. const TCHAR c_szDotDot[] = TEXT("..");
  35. const TCHAR c_szMAN[] = TEXT(".man");
  36. const TCHAR c_szUSR[] = TEXT(".usr");
  37. const TCHAR c_szLog[] = TEXT(".log");
  38. const TCHAR c_szPDS[] = TEXT(".pds");
  39. const TCHAR c_szPDM[] = TEXT(".pdm");
  40. const TCHAR c_szLNK[] = TEXT(".lnk");
  41. const TCHAR c_szBAK[] = TEXT(".bak");
  42. const TCHAR c_szNTUserTmp[] = TEXT("ntuser.tmp");
  43. const TCHAR c_szNTUserMan[] = TEXT("ntuser.man");
  44. const TCHAR c_szNTUserDat[] = TEXT("ntuser.dat");
  45. const TCHAR c_szNTUserIni[] = TEXT("ntuser.ini");
  46. const TCHAR c_szRegistryPol[] = TEXT("registry.pol");
  47. const TCHAR c_szNTUserStar[] = TEXT("ntuser.*");
  48. const TCHAR c_szUserStar[] = TEXT("user.*");
  49. const TCHAR c_szSpace[] = TEXT(" ");
  50. const TCHAR c_szDotPif[] = TEXT(".pif");
  51. const TCHAR c_szNULL[] = TEXT("");
  52. const TCHAR c_szCommonGroupsLocation[] = TEXT("Software\\Program Groups");
  53. TCHAR c_szRegistryExtName[64];
  54. //
  55. // Registry Extension guid
  56. //
  57. GUID guidRegistryExt = REGISTRY_EXTENSION_GUID;
  58. //
  59. // Special folders
  60. //
  61. FOLDER_INFO c_ShellFolders[] =
  62. {
  63. //Hidden Local Add New Within Folder Folder Folder Folder Folder
  64. // Dir? Dir CSIDl? NT5? Local Resource ID Name Location Resource Resource
  65. // Settings DLL ID
  66. {TRUE, FALSE, TRUE, FALSE, FALSE, IDS_SH_APPDATA, TEXT("AppData"), {0}, TEXT("shell32.dll"), IDS_LOCALGDN_FLD_APP_DATA}, // AppData
  67. {TRUE, FALSE, TRUE, TRUE, FALSE, IDS_SH_COOKIES, TEXT("Cookies"), {0}, TEXT("shell32.dll"), 0}, // Cookies
  68. {FALSE, FALSE, TRUE, FALSE, FALSE, IDS_SH_DESKTOP, TEXT("Desktop"), {0}, TEXT("shell32.dll"), 0}, // Desktop
  69. {FALSE, FALSE, TRUE, FALSE, FALSE, IDS_SH_FAVORITES, TEXT("Favorites"), {0}, TEXT("shell32.dll"), 0}, // Favorites
  70. {TRUE, FALSE, TRUE, FALSE, FALSE, IDS_SH_NETHOOD, TEXT("NetHood"), {0}, TEXT("shell32.dll"), 0}, // NetHood
  71. {FALSE, FALSE, TRUE, FALSE, FALSE, IDS_SH_PERSONAL, TEXT("Personal"), {0}, TEXT("shell32.dll"), 0}, // My Documents
  72. {TRUE, FALSE, TRUE, FALSE, FALSE, IDS_SH_PRINTHOOD, TEXT("PrintHood"), {0}, TEXT("shell32.dll"), 0}, // PrintHood
  73. {TRUE, FALSE, TRUE, FALSE, FALSE, IDS_SH_RECENT, TEXT("Recent"), {0}, TEXT("shell32.dll"), 0}, // Recent
  74. {TRUE, FALSE, TRUE, FALSE, FALSE, IDS_SH_SENDTO, TEXT("SendTo"), {0}, TEXT("shell32.dll"), 0}, // SendTo
  75. {FALSE, FALSE, TRUE, FALSE, FALSE, IDS_SH_STARTMENU, TEXT("Start Menu"), {0}, TEXT("shell32.dll"), IDS_LOCALGDN_FLD_START_MENU}, // Start Menu
  76. {TRUE, FALSE, TRUE, TRUE, FALSE, IDS_SH_TEMPLATES, TEXT("Templates"), {0}, TEXT("shell32.dll"), 0}, // Templates
  77. {FALSE, FALSE, TRUE, FALSE, FALSE, IDS_SH_PROGRAMS, TEXT("Programs"), {0}, TEXT("shell32.dll"), IDS_LOCALGDN_FLD_PROGRAMS}, // Programs
  78. {FALSE, FALSE, TRUE, FALSE, FALSE, IDS_SH_STARTUP, TEXT("Startup"), {0}, TEXT("shell32.dll"), IDS_LOCALGDN_FLD_STARTUP}, // Startup
  79. {TRUE, TRUE, TRUE, TRUE, FALSE, IDS_SH_LOCALSETTINGS, TEXT("Local Settings"), {0}, TEXT("shell32.dll"), IDS_LOCALGDN_FLD_LOCALSETTINGS}, // Local Settings
  80. {TRUE, TRUE, TRUE, TRUE, TRUE, IDS_SH_LOCALAPPDATA, TEXT("Local AppData"), {0}, TEXT("shell32.dll"), 0}, // Local AppData
  81. {TRUE, TRUE, TRUE, TRUE, TRUE, IDS_SH_CACHE, TEXT("Cache"), {0}, TEXT("shell32.dll"), 0}, // Temporary Internet Files
  82. {TRUE, TRUE, TRUE, TRUE, TRUE, IDS_SH_HISTORY, TEXT("History"), {0}, TEXT("shell32.dll"), 0}, // History
  83. {FALSE, TRUE, FALSE, TRUE, TRUE, IDS_SH_TEMP, TEXT("Temp"), {0}, TEXT("shell32.dll"), 0}, // Temp
  84. };
  85. FOLDER_INFO c_CommonShellFolders[] =
  86. {
  87. {FALSE, TRUE, TRUE, FALSE, FALSE, IDS_SH_DESKTOP, TEXT("Common Desktop"), {0}, TEXT("shell32.dll"), 0}, // Common Desktop
  88. {FALSE, TRUE, TRUE, FALSE, FALSE, IDS_SH_STARTMENU, TEXT("Common Start Menu"), {0}, TEXT("shell32.dll"), IDS_LOCALGDN_FLD_START_MENU}, // Common Start Menu
  89. {FALSE, TRUE, TRUE, FALSE, FALSE, IDS_SH_PROGRAMS, TEXT("Common Programs"), {0}, TEXT("shell32.dll"), IDS_LOCALGDN_FLD_PROGRAMS}, // Common Programs
  90. {FALSE, TRUE, TRUE, FALSE, FALSE, IDS_SH_STARTUP, TEXT("Common Startup"), {0}, TEXT("shell32.dll"), IDS_LOCALGDN_FLD_STARTUP}, // Common Startup
  91. {TRUE, TRUE, TRUE, TRUE, FALSE, IDS_SH_APPDATA, TEXT("Common AppData"), {0}, TEXT("shell32.dll"), IDS_LOCALGDN_FLD_APP_DATA}, // Common Application Data
  92. {TRUE, TRUE, TRUE, TRUE, FALSE, IDS_SH_TEMPLATES, TEXT("Common Templates"), {0}, TEXT("shell32.dll"), 0}, // Common Templates
  93. {FALSE, TRUE, TRUE, TRUE, FALSE, IDS_SH_FAVORITES, TEXT("Common Favorites"), {0}, TEXT("shell32.dll"), 0}, // Common Favorites
  94. {FALSE, TRUE, TRUE, TRUE, FALSE, IDS_SH_SHAREDDOCS, TEXT("Common Documents"), {0}, TEXT("shell32.dll"), IDS_LOCALGDN_FLD_SHARED_DOC}, // Common Documents
  95. };
  96. //
  97. // Function proto-types
  98. //
  99. void InitializeProductType (void);
  100. BOOL DetermineLocalSettingsLocation(LPTSTR szLocalSettings, DWORD cchLocalSettings);
  101. //*************************************************************
  102. //
  103. // PatchLocalSettings()
  104. //
  105. // Purpose: Initializes the LocalSettingsFolder correctly
  106. //
  107. // Parameters: hInstance - DLL instance handle
  108. //
  109. // Return: void
  110. //
  111. // Comments:
  112. //
  113. // History: Date Author Comment
  114. // 10/13/95 ushaji Created
  115. //
  116. //
  117. // Comments:
  118. // Should remove this post NT5 and restructure to take care of the
  119. // NT4 Localisation Problems
  120. //
  121. //*************************************************************
  122. void PatchLocalAppData(HANDLE hToken)
  123. {
  124. TCHAR szLocalSettingsPath[MAX_PATH];
  125. TCHAR szLocalAppData[MAX_PATH];
  126. LPTSTR lpEnd = NULL, lpLocalAppDataFolder;
  127. HANDLE hTokenOld=NULL;
  128. HKEY hKeyRoot, hKey;
  129. DWORD dwIndex;
  130. DWORD cchEnd;
  131. BOOL bGotLocalPath = FALSE;
  132. if (!ImpersonateUser (hToken, &hTokenOld))
  133. return;
  134. if (RegOpenCurrentUser(KEY_READ, &hKeyRoot) == ERROR_SUCCESS) {
  135. if (RegOpenKeyEx (hKeyRoot, USER_SHELL_FOLDERS,
  136. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  137. if (RegQueryValueEx (hKey, TEXT("Local AppData"), NULL, NULL,
  138. NULL, NULL) == ERROR_SUCCESS) {
  139. RegCloseKey(hKey);
  140. RegCloseKey(hKeyRoot);
  141. RevertToUser(&hTokenOld);
  142. return;
  143. }
  144. RegCloseKey(hKey);
  145. }
  146. RegCloseKey(hKeyRoot);
  147. }
  148. //
  149. // Impersonate and determine the user's localsettings
  150. //
  151. bGotLocalPath = DetermineLocalSettingsLocation(szLocalSettingsPath, ARRAYSIZE(szLocalSettingsPath));
  152. RevertToUser(&hTokenOld);
  153. if (!bGotLocalPath)
  154. return;
  155. StringCchCopy(szLocalAppData, ARRAYSIZE(szLocalAppData), TEXT("%userprofile%"));
  156. //
  157. // Set the Local AppData Folder after %userprofile% so that we
  158. // we can update the global variable below.
  159. //
  160. lpLocalAppDataFolder = CheckSlashEx(szLocalAppData, ARRAYSIZE(szLocalAppData), NULL);
  161. if (SUCCEEDED(StringCchCat(szLocalAppData, ARRAYSIZE(szLocalAppData), szLocalSettingsPath)))
  162. {
  163. lpEnd = CheckSlashEx(szLocalAppData, ARRAYSIZE(szLocalAppData), &cchEnd);
  164. if (lpEnd)
  165. {
  166. LoadString(g_hDllInstance, IDS_SH_LOCALAPPDATA, lpEnd, cchEnd);
  167. //
  168. // Construct the path and let it be set.
  169. //
  170. SetFolderPath(CSIDL_LOCAL_APPDATA | CSIDL_FLAG_DONT_UNEXPAND, hToken, szLocalAppData);
  171. //
  172. // the global variable should be reset by the time it gets used.
  173. // No Need to reset it here, but let us be safer.
  174. //
  175. for (dwIndex = 0; dwIndex < g_dwNumShellFolders; dwIndex++)
  176. if (c_ShellFolders[dwIndex].iFolderID == IDS_SH_LOCALAPPDATA)
  177. StringCchCopy(c_ShellFolders[dwIndex].szFolderLocation, MAX_FOLDER_SIZE, lpLocalAppDataFolder);
  178. }
  179. }
  180. }
  181. //*************************************************************
  182. //
  183. // LoadStringWithLangid()
  184. //
  185. // Purpose: MUI version requires load the folder name in the
  186. // default UI language. Standard LoadString() doesn't
  187. // support the language id.
  188. //
  189. // Parameters: hInstance - handle to resource module
  190. // uID - resource identifier
  191. // lpBuffer - result string resource buffer
  192. // nBufferMax - size of buffer
  193. // idLang - language id
  194. //
  195. // Return: number of chars copied to the buffer, 0 means failed.
  196. //
  197. // Comments:
  198. //
  199. // History: Date Author Comment
  200. // 10/12/01 mingzhu Created
  201. //
  202. //*************************************************************
  203. int LoadStringWithLangid(HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax, LANGID idLang)
  204. {
  205. int cchstr = 0;
  206. UINT block, num, i;
  207. HRSRC hResInfo;
  208. HGLOBAL hRes;
  209. LPWSTR lpwstrRes;
  210. if (!hInstance || !lpBuffer)
  211. goto Exit;
  212. block = (uID >>4)+1;
  213. num = uID & 0xf;
  214. // Load the resource block which contains up to 16 length-counted strings.
  215. hResInfo = FindResourceEx (hInstance, RT_STRING, MAKEINTRESOURCE(block), idLang);
  216. if (!hResInfo)
  217. goto Exit;
  218. if ((hRes = LoadResource(hInstance, hResInfo)) == NULL)
  219. goto Exit;
  220. if ((lpwstrRes = (LPWSTR)LockResource(hRes)) == NULL)
  221. goto Exit;
  222. // Seek to the string using the length
  223. for(i = 0; i < num; i++)
  224. lpwstrRes += *lpwstrRes + 1;
  225. // Get the length
  226. cchstr = *lpwstrRes;
  227. #ifdef UNICODE
  228. if (cchstr > nBufferMax - 1)
  229. cchstr = nBufferMax - 1;
  230. CopyMemory(lpBuffer, lpwstrRes+1, cchstr * sizeof(WCHAR));
  231. #else
  232. cchstr = WideCharToMultiByte(CP_ACP, 0, lpwstrRes+1, cchstr, lpBuffer, nBufferMax-1, 0, 0);
  233. #endif
  234. Exit:
  235. // Add the terminating null char
  236. lpBuffer[cchstr]= (TCHAR)0x0;
  237. return cchstr;
  238. }
  239. //*************************************************************
  240. //
  241. // InitializeGlobals()
  242. //
  243. // Purpose: Initializes all the globals variables
  244. // at DLL load time.
  245. //
  246. // Parameters: hInstance - DLL instance handle
  247. //
  248. // Return: void
  249. //
  250. // Comments:
  251. //
  252. // History: Date Author Comment
  253. // 10/13/95 ericflo Created
  254. //
  255. //*************************************************************
  256. void InitializeGlobals (HINSTANCE hInstance)
  257. {
  258. OSVERSIONINFO ver;
  259. DWORD dwIndex, dwSize, dwType;
  260. HKEY hKey, hKeyRoot;
  261. TCHAR szTemp[MAX_PATH];
  262. TCHAR szTemp2[MAX_PATH];
  263. TCHAR szTemp3[MAX_PATH];
  264. SECURITY_DESCRIPTOR sd;
  265. SECURITY_ATTRIBUTES sa;
  266. LPTSTR lpEnd;
  267. SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
  268. PACL pAcl = NULL;
  269. PSID pSidAdmin = NULL, pSidSystem = NULL;
  270. DWORD cbAcl;
  271. BOOL bDefaultSecurity = FALSE;
  272. LANGID idDefLang;
  273. DWORD cchEnd;
  274. //
  275. // Save the instance handle
  276. //
  277. g_hDllInstance = hInstance;
  278. //
  279. // Save the number of shell folders
  280. //
  281. g_dwNumShellFolders = ARRAYSIZE(c_ShellFolders);
  282. g_dwNumCommonShellFolders = ARRAYSIZE(c_CommonShellFolders);
  283. //
  284. // Query the build number
  285. //
  286. ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  287. GetVersionEx(&ver);
  288. g_dwBuildNumber = (DWORD) LOWORD(ver.dwBuildNumber);
  289. //
  290. // Initialize the product type
  291. //
  292. InitializeProductType ();
  293. //
  294. // Open the user profile setup event. This event is set to non-signalled
  295. // anytime the default user profile is being updated. This blocks
  296. // LoadUserProfile until the update is finished.
  297. //
  298. if (!g_hProfileSetup) {
  299. //
  300. // Get the system sid
  301. //
  302. if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
  303. 0, 0, 0, 0, 0, 0, 0, &pSidSystem)) {
  304. DebugMsg((DM_WARNING, TEXT("InitializeGlobals: Failed to initialize system sid. Error = %d"), GetLastError()));
  305. bDefaultSecurity = TRUE;
  306. goto DefaultSecurity;
  307. }
  308. //
  309. // Get the Admin sid
  310. //
  311. if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
  312. DOMAIN_ALIAS_RID_ADMINS, 0, 0,
  313. 0, 0, 0, 0, &pSidAdmin)) {
  314. DebugMsg((DM_WARNING, TEXT("InitializeGlobals: Failed to initialize admin sid. Error = %d"), GetLastError()));
  315. bDefaultSecurity = TRUE;
  316. goto DefaultSecurity;
  317. }
  318. cbAcl = (GetLengthSid (pSidSystem)) +
  319. (GetLengthSid (pSidAdmin)) +
  320. sizeof(ACL) +
  321. (2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
  322. pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
  323. if (!pAcl) {
  324. DebugMsg((DM_WARNING, TEXT("InitializeGlobals: Failed to allocate memory for acl. Error = %d"), GetLastError()));
  325. bDefaultSecurity = TRUE;
  326. goto DefaultSecurity;
  327. }
  328. if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
  329. DebugMsg((DM_WARNING, TEXT("InitializeGlobals: Failed to initialize acl. Error = %d"), GetLastError()));
  330. bDefaultSecurity = TRUE;
  331. goto DefaultSecurity;
  332. }
  333. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, pSidSystem)) {
  334. DebugMsg((DM_WARNING, TEXT("InitializeGlobals: Failed to add system ace. Error = %d"), GetLastError()));
  335. bDefaultSecurity = TRUE;
  336. goto DefaultSecurity;
  337. }
  338. if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, pSidAdmin)) {
  339. DebugMsg((DM_WARNING, TEXT("InitializeGlobals: Failed to add builtin admin ace. Error = %d"), GetLastError()));
  340. bDefaultSecurity = TRUE;
  341. goto DefaultSecurity;
  342. }
  343. //
  344. // Put together the security descriptor
  345. //
  346. InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
  347. SetSecurityDescriptorDacl (
  348. &sd,
  349. TRUE, // Dacl present
  350. pAcl, // Dacl
  351. FALSE // Not defaulted
  352. );
  353. DefaultSecurity:
  354. sa.nLength = sizeof(sa);
  355. sa.bInheritHandle = FALSE;
  356. if (bDefaultSecurity) {
  357. sa.lpSecurityDescriptor = NULL;
  358. }
  359. else {
  360. sa.lpSecurityDescriptor = &sd;
  361. }
  362. g_hProfileSetup = CreateEvent (&sa, TRUE, TRUE, USER_PROFILE_SETUP_EVENT);
  363. if (!g_hProfileSetup) {
  364. DebugMsg((DM_VERBOSE, TEXT("InitializeGlobals: Failed to create profile setup event with %d"), GetLastError()));
  365. }
  366. if (pAcl) {
  367. GlobalFree (pAcl);
  368. }
  369. if (pSidSystem) {
  370. FreeSid(pSidSystem);
  371. }
  372. if (pSidAdmin) {
  373. FreeSid(pSidAdmin);
  374. }
  375. }
  376. //
  377. // Now load the directory names that match the special folders
  378. // MUI version requires the resources in the installed language (SystemDefaultUILanguage)
  379. //
  380. idDefLang = GetSystemDefaultUILanguage();
  381. for (dwIndex = 0; dwIndex < g_dwNumShellFolders; dwIndex++) {
  382. int cchFolder = LoadStringWithLangid(
  383. hInstance,
  384. c_ShellFolders[dwIndex].iFolderID,
  385. c_ShellFolders[dwIndex].szFolderLocation,
  386. MAX_FOLDER_SIZE,
  387. idDefLang);
  388. // If we failed to load string using default language, use the resource in current binary
  389. if (cchFolder == 0) {
  390. cchFolder = LoadString(
  391. hInstance,
  392. c_ShellFolders[dwIndex].iFolderID,
  393. c_ShellFolders[dwIndex].szFolderLocation,
  394. MAX_FOLDER_SIZE);
  395. }
  396. }
  397. for (dwIndex = 0; dwIndex < g_dwNumCommonShellFolders; dwIndex++) {
  398. int cchFolder = LoadStringWithLangid(
  399. hInstance,
  400. c_CommonShellFolders[dwIndex].iFolderID,
  401. c_CommonShellFolders[dwIndex].szFolderLocation,
  402. MAX_FOLDER_SIZE,
  403. idDefLang);
  404. // If we failed to load string using default language, use the resource in current binary
  405. if (cchFolder == 0) {
  406. cchFolder = LoadString(
  407. hInstance,
  408. c_CommonShellFolders[dwIndex].iFolderID,
  409. c_CommonShellFolders[dwIndex].szFolderLocation,
  410. MAX_FOLDER_SIZE);
  411. }
  412. }
  413. //
  414. // Special case for the Personal / My Documents folder. NT4 used a folder
  415. // called "Personal" for document storage. NT5 renamed this folder to
  416. // My Documents. In the upgrade case from NT4 to NT5, if the user already
  417. // had information in "Personal", that name was preserved (for compatibility
  418. // reasons) and the My Pictures folder is created inside of Personal.
  419. // We need to make sure and fix up the My Documents and My Pictures entries
  420. // in the global array so they have the correct directory names.
  421. //
  422. if (RegOpenCurrentUser(KEY_READ, &hKeyRoot) == ERROR_SUCCESS) {
  423. if (RegOpenKeyEx (hKeyRoot, USER_SHELL_FOLDERS,
  424. 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  425. dwSize = sizeof(szTemp3);
  426. szTemp3[0] = TEXT('\0');
  427. if (RegQueryValueEx (hKey, TEXT("Personal"), NULL, &dwType,
  428. (LPBYTE) szTemp3, &dwSize) == ERROR_SUCCESS) {
  429. LoadString (g_hDllInstance, IDS_SH_PERSONAL2, szTemp2, ARRAYSIZE(szTemp2));
  430. StringCchCopy (szTemp, ARRAYSIZE(szTemp), TEXT("%USERPROFILE%\\"));
  431. StringCchCat (szTemp, ARRAYSIZE(szTemp), szTemp2);
  432. if (lstrcmpi(szTemp, szTemp3) == 0) {
  433. LoadString(hInstance, IDS_SH_PERSONAL2,
  434. c_ShellFolders[5].szFolderLocation, MAX_FOLDER_SIZE);
  435. }
  436. }
  437. //
  438. // Special Case for Local Settings.
  439. // Due to localisations LocalSettings can be pointing to different places in nt4 and rc might
  440. // not be in sync with the current value. Read the LocalSettings value first and then
  441. // update everything else afterwards.
  442. //
  443. dwSize = sizeof(szTemp2);
  444. *szTemp = *szTemp2 = TEXT('\0');
  445. //
  446. // Read the value from the registry if it is available
  447. //
  448. if (RegQueryValueEx (hKey, TEXT("Local Settings"), NULL, &dwType,
  449. (LPBYTE) szTemp2, &dwSize) != ERROR_SUCCESS) {
  450. //
  451. // if the value is not present load it from the rc file
  452. //
  453. LoadString(hInstance, IDS_SH_LOCALSETTINGS, szTemp, MAX_FOLDER_SIZE);
  454. DebugMsg((DM_VERBOSE, TEXT("InitializeGlobals: local settings folder from the rc is %s"), szTemp));
  455. }
  456. else {
  457. //
  458. // The registry value read from the registry is the full unexpanded path.
  459. //
  460. if (lstrlen(szTemp2) > lstrlen(TEXT("%userprofile%"))) {
  461. StringCchCopy(szTemp, ARRAYSIZE(szTemp), szTemp2+(lstrlen(TEXT("%userprofile%"))+1));
  462. DebugMsg((DM_VERBOSE, TEXT("InitializeGlobals: local settings folder from the reigtry is %s"), szTemp));
  463. }
  464. else {
  465. LoadString(hInstance, IDS_SH_LOCALSETTINGS, szTemp, MAX_FOLDER_SIZE);
  466. DebugMsg((DM_VERBOSE, TEXT("InitializeGlobals: local settings folder(2) from the rc is %s"), szTemp));
  467. }
  468. }
  469. lpEnd = CheckSlashEx(szTemp, ARRAYSIZE(szTemp), &cchEnd);
  470. for (dwIndex = 0; dwIndex < g_dwNumShellFolders; dwIndex++) {
  471. //
  472. // Fix up all LocalSettings related shfolders
  473. //
  474. if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE,
  475. c_ShellFolders[dwIndex].lpFolderName, -1,
  476. TEXT("Local Settings"), -1) == CSTR_EQUAL)
  477. {
  478. //
  479. // Don't copy the final slash
  480. //
  481. *lpEnd = TEXT('\0');
  482. c_ShellFolders[dwIndex].szFolderLocation[0] = TEXT('\0');
  483. StringCchCatN(c_ShellFolders[dwIndex].szFolderLocation, MAX_FOLDER_SIZE, szTemp, lstrlen(szTemp) - 1);
  484. }
  485. if (c_ShellFolders[dwIndex].bLocalSettings) {
  486. LoadString(hInstance, c_ShellFolders[dwIndex].iFolderID, szTemp3, ARRAYSIZE(szTemp3));
  487. //
  488. // Append localsetting value read above to the end of %userprofile%
  489. // before putting on the shell folder itself
  490. //
  491. StringCchCopy(lpEnd, cchEnd, szTemp3);
  492. StringCchCopy(c_ShellFolders[dwIndex].szFolderLocation, MAX_FOLDER_SIZE, szTemp);
  493. DebugMsg((DM_VERBOSE, TEXT("InitializeGlobals: Shell folder %s is %s"), c_ShellFolders[dwIndex].lpFolderName,
  494. c_ShellFolders[dwIndex].szFolderLocation));
  495. }
  496. }
  497. RegCloseKey (hKey);
  498. }
  499. RegCloseKey (hKeyRoot);
  500. }
  501. //
  502. // Get string version of registry extension guid
  503. //
  504. GuidToString( &guidRegistryExt, c_szRegistryExtName);
  505. }
  506. //*************************************************************
  507. //
  508. // InitializeProductType()
  509. //
  510. // Purpose: Determines the current product type and
  511. // sets the g_ProductType global variable.
  512. //
  513. // Parameters: void
  514. //
  515. // Return: void
  516. //
  517. // Comments:
  518. //
  519. // History: Date Author Comment
  520. // 4/08/96 ericflo Created
  521. //
  522. //*************************************************************
  523. void InitializeProductType (void)
  524. {
  525. #ifdef WINNT
  526. HKEY hkey;
  527. LONG lResult;
  528. TCHAR szProductType[50];
  529. DWORD dwType, dwSize;
  530. //
  531. // Default product type is workstation.
  532. //
  533. g_ProductType = PT_WORKSTATION;
  534. //
  535. // Query the registry for the product type.
  536. //
  537. lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  538. TEXT("System\\CurrentControlSet\\Control\\ProductOptions"),
  539. 0,
  540. KEY_READ,
  541. &hkey);
  542. if (lResult != ERROR_SUCCESS) {
  543. DebugMsg((DM_WARNING, TEXT("InitializeProductType: Failed to open registry (%d)"), lResult));
  544. goto Exit;
  545. }
  546. dwSize = 50;
  547. szProductType[0] = TEXT('\0');
  548. lResult = RegQueryValueEx (hkey,
  549. TEXT("ProductType"),
  550. NULL,
  551. &dwType,
  552. (LPBYTE) szProductType,
  553. &dwSize);
  554. RegCloseKey (hkey);
  555. if (lResult != ERROR_SUCCESS) {
  556. DebugMsg((DM_WARNING, TEXT("InitializeProductType: Failed to query product type (%d)"), lResult));
  557. goto Exit;
  558. }
  559. //
  560. // Map the product type string to the enumeration value.
  561. //
  562. if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, szProductType, -1, TEXT("WinNT") , -1) == CSTR_EQUAL ) {
  563. g_ProductType = PT_WORKSTATION;
  564. } else if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, szProductType, -1, TEXT("ServerNT") , -1) == CSTR_EQUAL ) {
  565. g_ProductType = PT_SERVER;
  566. } else if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, szProductType, -1, TEXT("LanmanNT") , -1) == CSTR_EQUAL ) {
  567. g_ProductType = PT_DC;
  568. } else {
  569. DebugMsg((DM_WARNING, TEXT("InitializeProductType: Unknown product type! <%s>"), szProductType));
  570. }
  571. Exit:
  572. DebugMsg((DM_VERBOSE, TEXT("InitializeProductType: Product Type: %d"), g_ProductType));
  573. #else // WINNT
  574. //
  575. // Windows only has 1 product type
  576. //
  577. g_ProductType = PT_WINDOWS;
  578. #endif
  579. }