Source code of Windows XP (NT5)
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.

950 lines
29 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. sgmutil.c
  5. Abstract:
  6. Implements basic utilities used for source data gathering.
  7. Author:
  8. Jim Schmidt (jimschm) 14-May-2000
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. //
  13. // Includes
  14. //
  15. #include "pch.h"
  16. #include "v1p.h"
  17. #define DBG_FOO "Foo"
  18. //
  19. // Strings
  20. //
  21. // None
  22. //
  23. // Constants
  24. //
  25. // None
  26. //
  27. // Macros
  28. //
  29. // None
  30. //
  31. // Types
  32. //
  33. // None
  34. //
  35. // Globals
  36. //
  37. // None
  38. //
  39. // Macro expansion list
  40. //
  41. #define USER_SHELL_FOLDERS \
  42. DEFMAC(CSIDL_APPDATA, TEXT("AppData"), TEXT("CSIDL_APPDATA")) \
  43. DEFMAC(CSIDL_APPDATA, TEXT("AppData"), TEXT("APPDATA")) \
  44. DEFMAC(CSIDL_ADMINTOOLS, TEXT("Administrative Tools"), TEXT("CSIDL_ADMINTOOLS")) \
  45. DEFMAC(CSIDL_ALTSTARTUP, TEXT("AltStartup"), TEXT("CSIDL_ALTSTARTUP")) \
  46. DEFMAC(CSIDL_BITBUCKET, TEXT("RecycleBinFolder"), TEXT("CSIDL_BITBUCKET")) \
  47. DEFMAC(CSIDL_CONTROLS, TEXT("ControlPanelFolder"), TEXT("CSIDL_CONTROLS")) \
  48. DEFMAC(CSIDL_COOKIES, TEXT("Cookies"), TEXT("CSIDL_COOKIES")) \
  49. DEFMAC(CSIDL_DESKTOP, TEXT("Desktop"), TEXT("CSIDL_DESKTOP")) \
  50. DEFMAC(CSIDL_DESKTOPDIRECTORY, TEXT("Desktop"), TEXT("CSIDL_DESKTOPDIRECTORY")) \
  51. DEFMAC(CSIDL_DRIVES, TEXT("DriveFolder"), TEXT("CSIDL_DRIVES")) \
  52. DEFMAC(CSIDL_FAVORITES, TEXT("Favorites"), TEXT("CSIDL_FAVORITES")) \
  53. DEFMAC(CSIDL_FONTS, TEXT("Fonts"), TEXT("CSIDL_FONTS")) \
  54. DEFMAC(CSIDL_HISTORY, TEXT("History"), TEXT("CSIDL_HISTORY")) \
  55. DEFMAC(CSIDL_INTERNET, TEXT("InternetFolder"), TEXT("CSIDL_INTERNET")) \
  56. DEFMAC(CSIDL_INTERNET_CACHE, TEXT("Cache"), TEXT("CSIDL_INTERNET_CACHE")) \
  57. DEFMAC(CSIDL_LOCAL_APPDATA, TEXT("Local AppData"), TEXT("CSIDL_LOCAL_APPDATA")) \
  58. DEFMAC(CSIDL_MYPICTURES, TEXT("My Pictures"), TEXT("CSIDL_MYPICTURES")) \
  59. DEFMAC(CSIDL_NETHOOD, TEXT("NetHood"), TEXT("CSIDL_NETHOOD")) \
  60. DEFMAC(CSIDL_NETWORK, TEXT("NetworkFolder"), TEXT("CSIDL_NETWORK")) \
  61. DEFMAC(CSIDL_PERSONAL, TEXT("Personal"), TEXT("CSIDL_PERSONAL")) \
  62. DEFMAC(CSIDL_PROFILE, TEXT("Profile"), TEXT("CSIDL_PROFILE")) \
  63. DEFMAC(CSIDL_PROGRAM_FILES, TEXT("ProgramFiles"), TEXT("CSIDL_PROGRAM_FILES")) \
  64. DEFMAC(CSIDL_PROGRAM_FILES, TEXT("ProgramFiles"), TEXT("PROGRAMFILES")) \
  65. DEFMAC(CSIDL_PROGRAM_FILES_COMMON, TEXT("CommonProgramFiles"), TEXT("CSIDL_PROGRAM_FILES_COMMON")) \
  66. DEFMAC(CSIDL_PROGRAM_FILES_COMMON, TEXT("CommonProgramFiles"), TEXT("COMMONPROGRAMFILES")) \
  67. DEFMAC(CSIDL_PROGRAMS, TEXT("Programs"), TEXT("CSIDL_PROGRAMS")) \
  68. DEFMAC(CSIDL_RECENT, TEXT("Recent"), TEXT("CSIDL_RECENT")) \
  69. DEFMAC(CSIDL_SENDTO, TEXT("SendTo"), TEXT("CSIDL_SENDTO")) \
  70. DEFMAC(CSIDL_STARTMENU, TEXT("Start Menu"), TEXT("CSIDL_STARTMENU")) \
  71. DEFMAC(CSIDL_STARTUP, TEXT("Startup"), TEXT("CSIDL_STARTUP")) \
  72. DEFMAC(CSIDL_SYSTEM, TEXT("System"), TEXT("CSIDL_SYSTEM")) \
  73. DEFMAC(CSIDL_TEMPLATES, TEXT("Templates"), TEXT("CSIDL_TEMPLATES")) \
  74. DEFMAC(CSIDL_WINDOWS, TEXT("Windows"), TEXT("CSIDL_WINDOWS")) \
  75. DEFMAC(CSIDL_MYDOCUMENTS, TEXT("My Documents"), TEXT("CSIDL_MYDOCUMENTS")) \
  76. DEFMAC(CSIDL_MYMUSIC, TEXT("My Music"), TEXT("CSIDL_MYMUSIC")) \
  77. DEFMAC(CSIDL_MYVIDEO, TEXT("My Video"), TEXT("CSIDL_MYVIDEO")) \
  78. DEFMAC(CSIDL_SYSTEMX86, TEXT("SystemX86"), TEXT("CSIDL_SYSTEMX86")) \
  79. DEFMAC(CSIDL_PROGRAM_FILESX86, TEXT("ProgramFilesX86"), TEXT("CSIDL_PROGRAM_FILESX86")) \
  80. DEFMAC(CSIDL_PROGRAM_FILES_COMMONX86, TEXT("CommonProgramFilesX86"), TEXT("CSIDL_PROGRAM_FILES_COMMONX86")) \
  81. DEFMAC(CSIDL_CONNECTIONS, TEXT("ConnectionsFolder"), TEXT("CSIDL_CONNECTIONS")) \
  82. #define COMMON_SHELL_FOLDERS \
  83. DEFMAC(CSIDL_COMMON_ADMINTOOLS, TEXT("Common Administrative Tools"), TEXT("CSIDL_COMMON_ADMINTOOLS")) \
  84. DEFMAC(CSIDL_COMMON_ALTSTARTUP, TEXT("Common AltStartup"), TEXT("CSIDL_COMMON_ALTSTARTUP")) \
  85. DEFMAC(CSIDL_COMMON_APPDATA, TEXT("Common AppData"), TEXT("CSIDL_COMMON_APPDATA")) \
  86. DEFMAC(CSIDL_COMMON_DESKTOPDIRECTORY, TEXT("Common Desktop"), TEXT("CSIDL_COMMON_DESKTOPDIRECTORY")) \
  87. DEFMAC(CSIDL_COMMON_DOCUMENTS, TEXT("Common Documents"), TEXT("CSIDL_COMMON_DOCUMENTS")) \
  88. DEFMAC(CSIDL_COMMON_FAVORITES, TEXT("Common Favorites"), TEXT("CSIDL_COMMON_FAVORITES")) \
  89. DEFMAC(CSIDL_COMMON_PROGRAMS, TEXT("Common Programs"), TEXT("CSIDL_COMMON_PROGRAMS")) \
  90. DEFMAC(CSIDL_COMMON_STARTMENU, TEXT("Common Start Menu"), TEXT("CSIDL_COMMON_STARTMENU")) \
  91. DEFMAC(CSIDL_COMMON_STARTUP, TEXT("Common Startup"), TEXT("CSIDL_COMMON_STARTUP")) \
  92. DEFMAC(CSIDL_COMMON_TEMPLATES, TEXT("Common Templates"), TEXT("CSIDL_COMMON_TEMPLATES")) \
  93. #define ENVIRONMENT_VARIABLES \
  94. DEFMAC(TEXT("WINDIR")) \
  95. DEFMAC(TEXT("SYSTEMROOT")) \
  96. DEFMAC(TEXT("SYSTEM16")) \
  97. DEFMAC(TEXT("SYSTEM32")) \
  98. DEFMAC(TEXT("SYSTEM")) \
  99. DEFMAC(TEXT("ALLUSERSPROFILE")) \
  100. DEFMAC(TEXT("USERPROFILE")) \
  101. DEFMAC(TEXT("PROFILESFOLDER")) \
  102. DEFMAC(TEXT("APPDATA")) \
  103. DEFMAC(TEXT("CSIDL_APPDATA")) \
  104. DEFMAC(TEXT("CSIDL_ADMINTOOLS")) \
  105. DEFMAC(TEXT("CSIDL_ALTSTARTUP")) \
  106. DEFMAC(TEXT("CSIDL_BITBUCKET")) \
  107. DEFMAC(TEXT("CSIDL_COMMON_ADMINTOOLS")) \
  108. DEFMAC(TEXT("CSIDL_COMMON_ALTSTARTUP")) \
  109. DEFMAC(TEXT("CSIDL_COMMON_APPDATA")) \
  110. DEFMAC(TEXT("CSIDL_COMMON_DESKTOPDIRECTORY")) \
  111. DEFMAC(TEXT("CSIDL_COMMON_DOCUMENTS")) \
  112. DEFMAC(TEXT("CSIDL_COMMON_FAVORITES")) \
  113. DEFMAC(TEXT("CSIDL_COMMON_PROGRAMS")) \
  114. DEFMAC(TEXT("CSIDL_COMMON_STARTMENU")) \
  115. DEFMAC(TEXT("CSIDL_COMMON_STARTUP")) \
  116. DEFMAC(TEXT("CSIDL_COMMON_TEMPLATES")) \
  117. DEFMAC(TEXT("CSIDL_CONTROLS")) \
  118. DEFMAC(TEXT("CSIDL_COOKIES")) \
  119. DEFMAC(TEXT("CSIDL_DESKTOP")) \
  120. DEFMAC(TEXT("CSIDL_DESKTOPDIRECTORY")) \
  121. DEFMAC(TEXT("CSIDL_DRIVES")) \
  122. DEFMAC(TEXT("CSIDL_FAVORITES")) \
  123. DEFMAC(TEXT("CSIDL_FONTS")) \
  124. DEFMAC(TEXT("CSIDL_HISTORY")) \
  125. DEFMAC(TEXT("CSIDL_INTERNET")) \
  126. DEFMAC(TEXT("CSIDL_INTERNET_CACHE")) \
  127. DEFMAC(TEXT("CSIDL_LOCAL_APPDATA")) \
  128. DEFMAC(TEXT("CSIDL_MYPICTURES")) \
  129. DEFMAC(TEXT("CSIDL_NETHOOD")) \
  130. DEFMAC(TEXT("CSIDL_NETWORK")) \
  131. DEFMAC(TEXT("CSIDL_PERSONAL")) \
  132. DEFMAC(TEXT("CSIDL_PRINTERS")) \
  133. DEFMAC(TEXT("CSIDL_PRINTHOOD")) \
  134. DEFMAC(TEXT("CSIDL_PROFILE")) \
  135. DEFMAC(TEXT("CSIDL_PROGRAM_FILES")) \
  136. DEFMAC(TEXT("ProgramFiles")) \
  137. DEFMAC(TEXT("CSIDL_PROGRAM_FILES_COMMON")) \
  138. DEFMAC(TEXT("CommonProgramFiles")) \
  139. DEFMAC(TEXT("CSIDL_PROGRAMS")) \
  140. DEFMAC(TEXT("CSIDL_RECENT")) \
  141. DEFMAC(TEXT("CSIDL_SENDTO")) \
  142. DEFMAC(TEXT("CSIDL_STARTMENU")) \
  143. DEFMAC(TEXT("CSIDL_STARTUP")) \
  144. DEFMAC(TEXT("CSIDL_SYSTEM")) \
  145. DEFMAC(TEXT("CSIDL_TEMPLATES")) \
  146. DEFMAC(TEXT("CSIDL_WINDOWS")) \
  147. DEFMAC(TEXT("CSIDL_MYDOCUMENTS")) \
  148. DEFMAC(TEXT("CSIDL_MYMUSIC")) \
  149. DEFMAC(TEXT("CSIDL_MYVIDEO")) \
  150. DEFMAC(TEXT("CSIDL_SYSTEMX86")) \
  151. DEFMAC(TEXT("CSIDL_PROGRAM_FILESX86")) \
  152. DEFMAC(TEXT("CSIDL_PROGRAM_FILES_COMMONX86")) \
  153. DEFMAC(TEXT("CSIDL_CONNECTIONS")) \
  154. DEFMAC(TEXT("TEMP")) \
  155. DEFMAC(TEXT("TMP")) \
  156. //
  157. // Private function prototypes
  158. //
  159. // None
  160. //
  161. // Macro expansion definition
  162. //
  163. // None
  164. //
  165. // Code
  166. //
  167. /*++
  168. The shell folder functions here are duplicates of the RAS code. This is not
  169. a good solution (we have two copies of the same code), but the designed
  170. solution requires engine scope support. Scopes are the mechanism in which
  171. major groups of data are separated from each other, such as the separation
  172. of multiple users. A scope provides properties that affect objects within
  173. the scope. For example, a user scope has properties such as domain name,
  174. profile path, sid, and so on.
  175. In order not to duplicate this code but still maintain modularity and system
  176. independence, a scope module is needed for users. So instead of the code
  177. below, the code would be something like
  178. property = IsmGetScopeProperty ("userprofile");
  179. This will be implemented if we want to (A) support multiple scopes, (B)
  180. eliminate physical system access in non-type modules, or (C) clean up this
  181. duplicated code.
  182. --*/
  183. typedef HRESULT (WINAPI SHGETFOLDERPATH)(HWND hwndOwner, int nFolder, HANDLE hToken, DWORD dwFlags, PTSTR pszPath);
  184. typedef SHGETFOLDERPATH * PSHGETFOLDERPATH;
  185. HANDLE
  186. pGetShFolderLib (
  187. VOID
  188. )
  189. {
  190. static HANDLE lib;
  191. if (lib) {
  192. return lib;
  193. }
  194. lib = LoadLibrary (TEXT("shfolder.dll"));
  195. if (!lib) {
  196. LOG ((LOG_ERROR, (PCSTR) MSG_SHFOLDER_LOAD_ERROR));
  197. }
  198. return lib;
  199. }
  200. PTSTR
  201. pFindSfPath (
  202. IN PCTSTR FolderStr,
  203. IN BOOL UserFolder
  204. )
  205. {
  206. HKEY key;
  207. REGSAM prevMode;
  208. PCTSTR data;
  209. PCTSTR result = NULL;
  210. if (!result) {
  211. if (UserFolder) {
  212. prevMode = SetRegOpenAccessMode (KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS);
  213. key = OpenRegKeyStr (TEXT("HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders"));
  214. SetRegOpenAccessMode (prevMode);
  215. } else {
  216. prevMode = SetRegOpenAccessMode (KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS);
  217. key = OpenRegKeyStr (TEXT("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders"));
  218. SetRegOpenAccessMode (prevMode);
  219. }
  220. if (key) {
  221. data = GetRegValueString (key, FolderStr);
  222. if (data) {
  223. result = DuplicatePathString (data, 0);
  224. FreeAlloc (data);
  225. }
  226. CloseRegKey (key);
  227. }
  228. }
  229. if (!result) {
  230. if (UserFolder) {
  231. prevMode = SetRegOpenAccessMode (KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS);
  232. key = OpenRegKeyStr (TEXT("HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"));
  233. SetRegOpenAccessMode (prevMode);
  234. } else {
  235. prevMode = SetRegOpenAccessMode (KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS);
  236. key = OpenRegKeyStr (TEXT("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"));
  237. SetRegOpenAccessMode (prevMode);
  238. }
  239. if (key) {
  240. data = GetRegValueString (key, FolderStr);
  241. if (data) {
  242. result = DuplicatePathString (data, 0);
  243. FreeAlloc (data);
  244. }
  245. CloseRegKey (key);
  246. }
  247. }
  248. return (PTSTR) result;
  249. }
  250. PCTSTR
  251. GetShellFolderPath (
  252. IN INT Folder,
  253. IN PCTSTR FolderStr,
  254. IN BOOL UserFolder,
  255. OUT PTSTR Buffer
  256. )
  257. {
  258. HRESULT result;
  259. LPITEMIDLIST pidl;
  260. BOOL b;
  261. LPMALLOC mallocFn;
  262. HANDLE lib;
  263. PSHGETFOLDERPATH shGetFolderPath;
  264. PCTSTR sfPath = NULL;
  265. PCTSTR expandedPath = NULL;
  266. PTSTR endPtr = NULL;
  267. TCHAR currUserProfile[MAX_TCHAR_PATH];
  268. MIG_USERDATA userData;
  269. result = SHGetMalloc (&mallocFn);
  270. if (result != S_OK) {
  271. return NULL;
  272. }
  273. if (FolderStr) {
  274. //
  275. // First try to find this in Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
  276. //
  277. sfPath = pFindSfPath (FolderStr, UserFolder);
  278. if (sfPath && *sfPath) {
  279. //
  280. // We found it.
  281. //
  282. StringCopyTcharCount (Buffer, sfPath, MAX_PATH);
  283. expandedPath = IsmExpandEnvironmentString (IsmGetRealPlatform (), S_SYSENVVAR_GROUP, sfPath, NULL);
  284. FreePathString (sfPath);
  285. sfPath = NULL;
  286. if (expandedPath && *expandedPath) {
  287. StringCopyTcharCount (Buffer, expandedPath, MAX_PATH);
  288. }
  289. if (expandedPath) {
  290. IsmReleaseMemory (expandedPath);
  291. }
  292. if (IsmGetMappedUserData (&userData)) {
  293. // we have a mapped user, try to build it's default shell folder location
  294. GetUserProfileRootPath (currUserProfile);
  295. if (StringIMatch (currUserProfile, Buffer)) {
  296. StringCopyTcharCount (Buffer, userData.UserProfileRoot, MAX_PATH);
  297. } else {
  298. AppendWack (currUserProfile);
  299. if (StringIMatchTcharCount (currUserProfile, Buffer, TcharCount (currUserProfile))) {
  300. endPtr = Buffer + TcharCount (currUserProfile);
  301. sfPath = JoinPaths (userData.UserProfileRoot, endPtr);
  302. StringCopyTcharCount (Buffer, sfPath, MAX_PATH);
  303. FreePathString (sfPath);
  304. }
  305. }
  306. }
  307. return Buffer;
  308. }
  309. if (sfPath) {
  310. FreePathString (sfPath);
  311. }
  312. lib = pGetShFolderLib ();
  313. if (lib) {
  314. #ifdef UNICODE
  315. (FARPROC) shGetFolderPath = GetProcAddress (lib, "SHGetFolderPathW");
  316. #else
  317. (FARPROC) shGetFolderPath = GetProcAddress (lib, "SHGetFolderPathA");
  318. #endif
  319. if (shGetFolderPath) {
  320. result = shGetFolderPath (NULL, Folder, NULL, 1, Buffer);
  321. if (result != S_OK) {
  322. return NULL;
  323. }
  324. expandedPath = IsmExpandEnvironmentString (IsmGetRealPlatform (), S_SYSENVVAR_GROUP, Buffer, NULL);
  325. if (expandedPath && *expandedPath) {
  326. StringCopyTcharCount (Buffer, expandedPath, MAX_PATH);
  327. }
  328. if (expandedPath) {
  329. IsmReleaseMemory (expandedPath);
  330. expandedPath = NULL;
  331. }
  332. if (IsmGetMappedUserData (&userData)) {
  333. // we have a mapped user, try to build it's default shell folder location
  334. GetUserProfileRootPath (currUserProfile);
  335. if (StringIMatch (currUserProfile, Buffer)) {
  336. StringCopyTcharCount (Buffer, userData.UserProfileRoot, MAX_PATH);
  337. } else {
  338. AppendWack (currUserProfile);
  339. if (StringIMatchTcharCount (currUserProfile, Buffer, TcharCount (currUserProfile))) {
  340. endPtr = Buffer + TcharCount (currUserProfile);
  341. sfPath = JoinPaths (userData.UserProfileRoot, endPtr);
  342. StringCopyTcharCount (Buffer, sfPath, MAX_PATH);
  343. FreePathString (sfPath);
  344. }
  345. }
  346. return Buffer;
  347. } else {
  348. // no mapped user, use the current user's path
  349. result = shGetFolderPath (NULL, Folder, NULL, 0, Buffer);
  350. }
  351. if (result != S_OK) {
  352. return NULL;
  353. }
  354. expandedPath = IsmExpandEnvironmentString (IsmGetRealPlatform (), S_SYSENVVAR_GROUP, Buffer, NULL);
  355. if (expandedPath && *expandedPath) {
  356. StringCopyTcharCount (Buffer, expandedPath, MAX_PATH);
  357. }
  358. if (expandedPath) {
  359. IsmReleaseMemory (expandedPath);
  360. expandedPath = NULL;
  361. }
  362. return Buffer;
  363. } else {
  364. result = SHGetSpecialFolderLocation (NULL, Folder, &pidl);
  365. }
  366. } else {
  367. result = SHGetSpecialFolderLocation (NULL, Folder, &pidl);
  368. }
  369. if (result != S_OK) {
  370. return NULL;
  371. }
  372. b = SHGetPathFromIDList (pidl, Buffer);
  373. } else {
  374. result = SHGetSpecialFolderLocation (NULL, Folder, &pidl);
  375. if (result != S_OK) {
  376. return NULL;
  377. }
  378. b = SHGetPathFromIDList (pidl, Buffer);
  379. }
  380. IMalloc_Free (mallocFn, pidl);
  381. return b ? Buffer : NULL;
  382. }
  383. PCTSTR
  384. GetAllUsersProfilePath (
  385. OUT PTSTR Buffer
  386. )
  387. {
  388. HKEY key;
  389. REGSAM prevMode;
  390. PCTSTR data;
  391. PCTSTR expData;
  392. prevMode = SetRegOpenAccessMode (KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS);
  393. key = OpenRegKeyStr (TEXT("HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList"));
  394. SetRegOpenAccessMode (prevMode);
  395. if (key) {
  396. data = GetRegValueString (key, TEXT("ProfilesDirectory"));
  397. if (data) {
  398. expData = IsmExpandEnvironmentString (IsmGetRealPlatform (), S_SYSENVVAR_GROUP, data, NULL);
  399. StringCopyByteCount (Buffer, expData, MAX_PATH);
  400. IsmReleaseMemory (expData);
  401. FreeAlloc (data);
  402. } else {
  403. GetWindowsDirectory (Buffer, MAX_PATH);
  404. StringCopy (AppendWack (Buffer), TEXT("Profiles"));
  405. }
  406. data = GetRegValueString (key, TEXT("AllUsersProfile"));
  407. if (data) {
  408. StringCopy (AppendWack (Buffer), data);
  409. FreeAlloc (data);
  410. } else {
  411. StringCopy (AppendWack (Buffer), TEXT("All Users"));
  412. }
  413. CloseRegKey (key);
  414. return Buffer;
  415. }
  416. GetWindowsDirectory (Buffer, MAX_PATH);
  417. return Buffer;
  418. }
  419. PCTSTR
  420. GetProfilesFolderPath (
  421. OUT PTSTR Buffer
  422. )
  423. {
  424. HKEY key;
  425. REGSAM prevMode;
  426. PCTSTR data;
  427. PCTSTR expData;
  428. prevMode = SetRegOpenAccessMode (KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS);
  429. key = OpenRegKeyStr (TEXT("HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList"));
  430. SetRegOpenAccessMode (prevMode);
  431. if (key) {
  432. data = GetRegValueString (key, TEXT("ProfilesDirectory"));
  433. if (data) {
  434. expData = IsmExpandEnvironmentString (IsmGetRealPlatform (), S_SYSENVVAR_GROUP, data, NULL);
  435. StringCopyByteCount (Buffer, expData, MAX_PATH);
  436. IsmReleaseMemory (expData);
  437. FreeAlloc (data);
  438. } else {
  439. GetWindowsDirectory (Buffer, MAX_PATH);
  440. StringCopy (AppendWack (Buffer), TEXT("Profiles"));
  441. }
  442. CloseRegKey (key);
  443. return Buffer;
  444. }
  445. GetWindowsDirectory (Buffer, MAX_PATH);
  446. return Buffer;
  447. }
  448. PCTSTR
  449. GetUserProfileRootPath (
  450. OUT PTSTR Buffer
  451. )
  452. {
  453. HKEY key;
  454. REGSAM prevMode;
  455. PDWORD data;
  456. DWORD size;
  457. //
  458. // For Win2k and higher, use the shell
  459. //
  460. if (GetShellFolderPath (CSIDL_PROFILE, NULL, FALSE, Buffer)) {
  461. return Buffer;
  462. }
  463. //
  464. // For NT 4, use the environment
  465. //
  466. if (GetEnvironmentVariable (TEXT("USERPROFILE"), Buffer, MAX_PATH)) {
  467. return Buffer;
  468. }
  469. //
  470. // For Win9x, are profiles enabled? If so, return %windir%\profiles\%user%.
  471. // If not, return %windir%.
  472. //
  473. GetWindowsDirectory (Buffer, MAX_PATH);
  474. prevMode = SetRegOpenAccessMode (KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS);
  475. key = OpenRegKeyStr (TEXT("HKLM\\Network\\Logon"));
  476. SetRegOpenAccessMode (prevMode);
  477. if (key) {
  478. data = GetRegValueDword (key, TEXT("UserProfiles"));
  479. if (data && *data) {
  480. StringCat (Buffer, TEXT("\\Profiles\\"));
  481. size = MAX_PATH;
  482. GetUserName (GetEndOfString (Buffer), &size);
  483. FreeAlloc (data);
  484. }
  485. CloseRegKey (key);
  486. }
  487. return Buffer;
  488. }
  489. PCTSTR
  490. IsValidUncPath (
  491. IN PCTSTR Path
  492. )
  493. {
  494. BOOL needNonWack = FALSE;
  495. BOOL wackRequired = TRUE;
  496. INT wacks = 0;
  497. while (*Path) {
  498. if (_tcsnextc (Path) == TEXT('\\')) {
  499. if (needNonWack) {
  500. break;
  501. }
  502. wacks++;
  503. if (wacks != 1) {
  504. needNonWack = TRUE;
  505. wackRequired = FALSE;
  506. }
  507. Path++;
  508. } else {
  509. //
  510. // Note: it would be nice to validate the non-wack characters against the
  511. // legal unc charset
  512. //
  513. if (needNonWack) {
  514. if (wacks == 3) {
  515. //
  516. // Found \\x\x syntax; it's a UNC path
  517. //
  518. do {
  519. Path = _tcsinc (Path);
  520. } while (*Path && _tcsnextc (Path) != TEXT('\\'));
  521. MYASSERT (*Path == 0 || *Path == TEXT('\\'));
  522. return Path;
  523. }
  524. needNonWack = FALSE;
  525. }
  526. if (wackRequired) {
  527. break;
  528. }
  529. Path = _tcsinc (Path);
  530. }
  531. }
  532. return NULL;
  533. }
  534. BOOL
  535. IsValidFileSpec (
  536. IN PCTSTR FileSpec
  537. )
  538. {
  539. CHARTYPE ch;
  540. BOOL result = TRUE;
  541. for (;;) {
  542. ch = (CHARTYPE) _tcsnextc (FileSpec);
  543. if (ch == TEXT('*')) {
  544. //
  545. // Really can't say what the validity is!
  546. //
  547. break;
  548. }
  549. if (!_istalpha (ch) && ch != TEXT('?')) {
  550. result = FALSE;
  551. break;
  552. }
  553. ch = (CHARTYPE) _tcsnextc (FileSpec + 1);
  554. if (ch == TEXT('*')) {
  555. break;
  556. }
  557. if (ch != TEXT(':') && ch != TEXT('?')) {
  558. result = FALSE;
  559. break;
  560. }
  561. ch = (CHARTYPE) _tcsnextc (FileSpec + 2);
  562. if (ch == 0) {
  563. // this is something like "d:", it's valid
  564. break;
  565. }
  566. if (ch == TEXT('*')) {
  567. break;
  568. }
  569. if (ch != TEXT('\\') && ch != TEXT('?')) {
  570. result = FALSE;
  571. break;
  572. }
  573. break;
  574. }
  575. if (!result) {
  576. result = (IsValidUncPath (FileSpec) != NULL);
  577. }
  578. return result;
  579. }
  580. VOID
  581. pSetEnvironmentVar (
  582. IN PMAPSTRUCT Map,
  583. IN PMAPSTRUCT UndefMap, OPTIONAL
  584. IN BOOL MapSourceToDest,
  585. IN PCTSTR VariableName,
  586. IN PCTSTR VariableData OPTIONAL
  587. )
  588. {
  589. TCHAR encodedVariableName[128];
  590. TCHAR buffer[MAX_TCHAR_PATH];
  591. PCTSTR undefText;
  592. //
  593. // VariableData is NULL when VariableName is not present on the machine
  594. //
  595. if (MapSourceToDest) {
  596. //
  597. // MapSourceToDest tells us to map a source path (c:\windows) to
  598. // a destination path (d:\winnt).
  599. //
  600. if (VariableData) {
  601. if (IsmGetEnvironmentString (
  602. PLATFORM_SOURCE,
  603. S_SYSENVVAR_GROUP,
  604. VariableName,
  605. buffer,
  606. ARRAYSIZE(buffer),
  607. NULL
  608. )) {
  609. AddStringMappingPair (Map, buffer, VariableData);
  610. }
  611. }
  612. return;
  613. }
  614. //
  615. // MapSourceToDest is FALSE when we want to map environment variables
  616. // to the actual path.
  617. //
  618. //
  619. // VariableName length is hard-coded, so we know it does not exceed our
  620. // buffer
  621. //
  622. wsprintf (encodedVariableName, TEXT("%%%s%%"), VariableName);
  623. if (VariableData) {
  624. IsmSetEnvironmentString (IsmGetRealPlatform (), S_SYSENVVAR_GROUP, VariableName, VariableData);
  625. AddStringMappingPair (Map, encodedVariableName, VariableData);
  626. } else if (UndefMap) {
  627. //
  628. // If no variable data, then put environment variable in the
  629. // "undefined" variable mapping
  630. //
  631. undefText = JoinTextEx (NULL, TEXT("--> "), TEXT(" <--"), encodedVariableName, 0, NULL);
  632. AddStringMappingPair (UndefMap, encodedVariableName, undefText);
  633. FreeText (undefText);
  634. }
  635. }
  636. VOID
  637. AddRemappingEnvVar (
  638. IN PMAPSTRUCT Map,
  639. IN PMAPSTRUCT ReMap,
  640. IN PMAPSTRUCT UndefMap, OPTIONAL
  641. IN PCTSTR VariableName,
  642. IN PCTSTR VariableData
  643. )
  644. {
  645. pSetEnvironmentVar (Map, UndefMap, FALSE, VariableName, VariableData);
  646. pSetEnvironmentVar (ReMap, UndefMap, TRUE, VariableName, VariableData);
  647. }
  648. VOID
  649. SetIsmEnvironmentFromPhysicalMachine (
  650. IN PMAPSTRUCT Map,
  651. IN BOOL MapSourceToDest,
  652. IN PMAPSTRUCT UndefMap OPTIONAL
  653. )
  654. {
  655. TCHAR dir[MAX_TCHAR_PATH];
  656. PCTSTR path;
  657. PTSTR p;
  658. MIG_USERDATA userData;
  659. BOOL mappedUser = FALSE;
  660. mappedUser = IsmGetMappedUserData (&userData);
  661. //
  662. // Prepare ISM environment variables. The ones added last have the highest priority when
  663. // two or more variables map to the same path.
  664. //
  665. //
  666. // ...user profile
  667. //
  668. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("ALLUSERSPROFILE"), GetAllUsersProfilePath (dir));
  669. if (mappedUser) {
  670. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("USERPROFILE"), userData.UserProfileRoot);
  671. } else {
  672. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("USERPROFILE"), GetUserProfileRootPath (dir));
  673. }
  674. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("PROFILESFOLDER"), GetProfilesFolderPath (dir));
  675. //
  676. // ...temp dir
  677. //
  678. if (GetTempPath (MAX_PATH, dir)) {
  679. p = (PTSTR) FindLastWack (dir);
  680. if (p) {
  681. if (p[1] == 0) {
  682. *p = 0;
  683. }
  684. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("TEMP"), dir);
  685. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("TMP"), dir);
  686. }
  687. }
  688. //
  689. // ...windows directory env variable
  690. //
  691. GetWindowsDirectory (dir, ARRAYSIZE(dir));
  692. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("WINDIR"), dir);
  693. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("SYSTEMROOT"), dir);
  694. //
  695. // ...16-bit system directory. We invent SYSTEM16 and SYSTEM32 for use
  696. // in scripts.
  697. //
  698. path = JoinPaths (dir, TEXT("system"));
  699. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("SYSTEM16"), path);
  700. FreePathString (path);
  701. path = JoinPaths (dir, TEXT("system32"));
  702. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("SYSTEM32"), path);
  703. FreePathString (path);
  704. //
  705. // ...platform-specific system directory
  706. //
  707. GetSystemDirectory (dir, ARRAYSIZE(dir));
  708. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("SYSTEM"), dir);
  709. //
  710. // ...shell folders -- we invent all variables with the CSIDL_ prefix
  711. //
  712. #define DEFMAC(id,folder_str,var_name) \
  713. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, var_name, \
  714. GetShellFolderPath (id, folder_str, TRUE, dir));
  715. USER_SHELL_FOLDERS
  716. #undef DEFMAC
  717. #define DEFMAC(id,folder_str,var_name) \
  718. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, var_name, \
  719. GetShellFolderPath (id, folder_str, FALSE, dir));
  720. COMMON_SHELL_FOLDERS
  721. #undef DEFMAC
  722. }
  723. VOID
  724. pTransferEnvPath (
  725. IN PCTSTR IsmVariableName,
  726. IN PMAPSTRUCT DirectMap,
  727. IN PMAPSTRUCT ReverseMap,
  728. IN PMAPSTRUCT UndefMap
  729. )
  730. {
  731. TCHAR dir[MAX_TCHAR_PATH];
  732. TCHAR encodedVariableName[128];
  733. PCTSTR undefText;
  734. wsprintf (encodedVariableName, TEXT("%%%s%%"), IsmVariableName);
  735. if (IsmGetEnvironmentString (PLATFORM_SOURCE, S_SYSENVVAR_GROUP, IsmVariableName, dir, sizeof(dir)/sizeof((dir)[0]), NULL)) {
  736. if (DirectMap) {
  737. AddStringMappingPair (DirectMap, encodedVariableName, dir);
  738. }
  739. if (ReverseMap) {
  740. AddStringMappingPair (ReverseMap, dir, encodedVariableName);
  741. }
  742. } else {
  743. undefText = JoinTextEx (NULL, TEXT("--> "), TEXT(" <--"), encodedVariableName, 0, NULL);
  744. if (UndefMap) {
  745. AddStringMappingPair (UndefMap, encodedVariableName, undefText);
  746. }
  747. FreeText (undefText);
  748. }
  749. }
  750. VOID
  751. SetIsmEnvironmentFromVirtualMachine (
  752. IN PMAPSTRUCT DirectMap,
  753. IN PMAPSTRUCT ReverseMap,
  754. IN PMAPSTRUCT UndefMap
  755. )
  756. {
  757. //
  758. // Need to transfer ISM environment into our string mapping
  759. //
  760. #define DEFMAC(name) pTransferEnvPath(name, DirectMap, ReverseMap, UndefMap);
  761. ENVIRONMENT_VARIABLES
  762. #undef DEFMAC
  763. }