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.

900 lines
31 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 = NULL;
  260. BOOL b = FALSE;
  261. LPMALLOC mallocFn = NULL;
  262. HANDLE lib;
  263. PSHGETFOLDERPATH shGetFolderPath = NULL;
  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. // we didn't find it yet, let's try shfolder.dll
  313. lib = pGetShFolderLib ();
  314. if (lib) {
  315. #ifdef UNICODE
  316. (FARPROC) shGetFolderPath = GetProcAddress (lib, "SHGetFolderPathW");
  317. #else
  318. (FARPROC) shGetFolderPath = GetProcAddress (lib, "SHGetFolderPathA");
  319. #endif
  320. if (shGetFolderPath) {
  321. result = shGetFolderPath (NULL, Folder, NULL, 1, Buffer);
  322. if (result == S_OK) {
  323. expandedPath = IsmExpandEnvironmentString (IsmGetRealPlatform (), S_SYSENVVAR_GROUP, Buffer, NULL);
  324. if (expandedPath && *expandedPath) {
  325. StringCopyTcharCount (Buffer, expandedPath, MAX_PATH);
  326. }
  327. if (expandedPath) {
  328. IsmReleaseMemory (expandedPath);
  329. expandedPath = NULL;
  330. }
  331. if (IsmGetMappedUserData (&userData)) {
  332. // we have a mapped user, try to build it's default shell folder location
  333. GetUserProfileRootPath (currUserProfile);
  334. if (StringIMatch (currUserProfile, Buffer)) {
  335. StringCopyTcharCount (Buffer, userData.UserProfileRoot, MAX_PATH);
  336. } else {
  337. AppendWack (currUserProfile);
  338. if (StringIMatchTcharCount (currUserProfile, Buffer, TcharCount (currUserProfile))) {
  339. endPtr = Buffer + TcharCount (currUserProfile);
  340. sfPath = JoinPaths (userData.UserProfileRoot, endPtr);
  341. StringCopyTcharCount (Buffer, sfPath, MAX_PATH);
  342. FreePathString (sfPath);
  343. }
  344. }
  345. return Buffer;
  346. } else {
  347. // no mapped user, use the current user's path
  348. result = shGetFolderPath (NULL, Folder, NULL, 0, Buffer);
  349. if (result != S_OK) {
  350. // no current path, use default one
  351. result = shGetFolderPath (NULL, Folder, NULL, 1, Buffer);
  352. }
  353. }
  354. if (result == S_OK) {
  355. expandedPath = IsmExpandEnvironmentString (IsmGetRealPlatform (), S_SYSENVVAR_GROUP, Buffer, NULL);
  356. if (expandedPath && *expandedPath) {
  357. StringCopyTcharCount (Buffer, expandedPath, MAX_PATH);
  358. }
  359. if (expandedPath) {
  360. IsmReleaseMemory (expandedPath);
  361. expandedPath = NULL;
  362. }
  363. return Buffer;
  364. }
  365. }
  366. } else {
  367. result = SHGetSpecialFolderLocation (NULL, Folder, &pidl);
  368. }
  369. } else {
  370. result = SHGetSpecialFolderLocation (NULL, Folder, &pidl);
  371. }
  372. if (result == S_OK) {
  373. b = SHGetPathFromIDList (pidl, Buffer);
  374. } else {
  375. b = FALSE;
  376. }
  377. } else {
  378. result = SHGetSpecialFolderLocation (NULL, Folder, &pidl);
  379. if (result == S_OK) {
  380. b = SHGetPathFromIDList (pidl, Buffer);
  381. } else {
  382. b = FALSE;
  383. }
  384. }
  385. IMalloc_Free (mallocFn, pidl);
  386. if (!b && (Folder == CSIDL_PROGRAM_FILES)) {
  387. PCTSTR defProgramFiles = NULL;
  388. PTSTR buffPtr = NULL;
  389. // Special case for %ProgramFiles%.
  390. // This is a very important CSIDL, and some legacy OS's
  391. // like some NT4 don't detect it properly. We are going
  392. // to build it from %windir%
  393. if (GetWindowsDirectory (Buffer, MAX_PATH)) {
  394. // find the first wack
  395. buffPtr = _tcschr (Buffer, TEXT('\\'));
  396. if (buffPtr) {
  397. buffPtr = _tcsinc (buffPtr);
  398. if (buffPtr) {
  399. defProgramFiles = GetStringResource (PROGRAM_FILES_PATH);
  400. if (defProgramFiles) {
  401. StringCopyTcharCount (buffPtr, defProgramFiles, MAX_PATH - 3);
  402. FreeStringResource (defProgramFiles);
  403. b = TRUE;
  404. }
  405. }
  406. }
  407. }
  408. }
  409. if (!b && (Folder == CSIDL_PROGRAM_FILES_COMMON)) {
  410. PCTSTR defProgramFiles = NULL;
  411. PTSTR buffPtr = NULL;
  412. // Special case for %ProgramFiles%.
  413. // This is a very important CSIDL, and some legacy OS's
  414. // like some NT4 don't detect it properly. We are going
  415. // to build it from %windir%
  416. if (GetWindowsDirectory (Buffer, MAX_PATH)) {
  417. // find the first wack
  418. buffPtr = _tcschr (Buffer, TEXT('\\'));
  419. if (buffPtr) {
  420. buffPtr = _tcsinc (buffPtr);
  421. if (buffPtr) {
  422. defProgramFiles = GetStringResource (PROGRAM_FILES_COMMON_PATH);
  423. if (defProgramFiles) {
  424. StringCopyTcharCount (buffPtr, defProgramFiles, MAX_PATH - 3);
  425. FreeStringResource (defProgramFiles);
  426. b = TRUE;
  427. }
  428. }
  429. }
  430. }
  431. }
  432. return b ? Buffer : NULL;
  433. }
  434. PCTSTR
  435. GetAllUsersProfilePath (
  436. OUT PTSTR Buffer
  437. )
  438. {
  439. HKEY key;
  440. REGSAM prevMode;
  441. PCTSTR data;
  442. PCTSTR expData;
  443. prevMode = SetRegOpenAccessMode (KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS);
  444. key = OpenRegKeyStr (TEXT("HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList"));
  445. SetRegOpenAccessMode (prevMode);
  446. if (key) {
  447. data = GetRegValueString (key, TEXT("ProfilesDirectory"));
  448. if (data) {
  449. expData = IsmExpandEnvironmentString (IsmGetRealPlatform (), S_SYSENVVAR_GROUP, data, NULL);
  450. StringCopyByteCount (Buffer, expData, MAX_PATH);
  451. IsmReleaseMemory (expData);
  452. FreeAlloc (data);
  453. } else {
  454. GetWindowsDirectory (Buffer, MAX_PATH);
  455. StringCopy (AppendWack (Buffer), TEXT("Profiles"));
  456. }
  457. data = GetRegValueString (key, TEXT("AllUsersProfile"));
  458. if (data) {
  459. StringCopy (AppendWack (Buffer), data);
  460. FreeAlloc (data);
  461. } else {
  462. StringCopy (AppendWack (Buffer), TEXT("All Users"));
  463. }
  464. CloseRegKey (key);
  465. return Buffer;
  466. }
  467. GetWindowsDirectory (Buffer, MAX_PATH);
  468. return Buffer;
  469. }
  470. PCTSTR
  471. GetProfilesFolderPath (
  472. OUT PTSTR Buffer
  473. )
  474. {
  475. HKEY key;
  476. REGSAM prevMode;
  477. PCTSTR data;
  478. PCTSTR expData;
  479. prevMode = SetRegOpenAccessMode (KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS);
  480. key = OpenRegKeyStr (TEXT("HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList"));
  481. SetRegOpenAccessMode (prevMode);
  482. if (key) {
  483. data = GetRegValueString (key, TEXT("ProfilesDirectory"));
  484. if (data) {
  485. expData = IsmExpandEnvironmentString (IsmGetRealPlatform (), S_SYSENVVAR_GROUP, data, NULL);
  486. StringCopyByteCount (Buffer, expData, MAX_PATH);
  487. IsmReleaseMemory (expData);
  488. FreeAlloc (data);
  489. } else {
  490. GetWindowsDirectory (Buffer, MAX_PATH);
  491. StringCopy (AppendWack (Buffer), TEXT("Profiles"));
  492. }
  493. CloseRegKey (key);
  494. return Buffer;
  495. }
  496. GetWindowsDirectory (Buffer, MAX_PATH);
  497. return Buffer;
  498. }
  499. PCTSTR
  500. GetUserProfileRootPath (
  501. OUT PTSTR Buffer
  502. )
  503. {
  504. HKEY key;
  505. REGSAM prevMode;
  506. PDWORD data;
  507. DWORD size;
  508. //
  509. // For Win2k and higher, use the shell
  510. //
  511. if (GetShellFolderPath (CSIDL_PROFILE, NULL, FALSE, Buffer)) {
  512. return Buffer;
  513. }
  514. //
  515. // For NT 4, use the environment
  516. //
  517. if (GetEnvironmentVariable (TEXT("USERPROFILE"), Buffer, MAX_PATH)) {
  518. return Buffer;
  519. }
  520. //
  521. // For Win9x, are profiles enabled? If so, return %windir%\profiles\%user%.
  522. // If not, return %windir%.
  523. //
  524. GetWindowsDirectory (Buffer, MAX_PATH);
  525. prevMode = SetRegOpenAccessMode (KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS);
  526. key = OpenRegKeyStr (TEXT("HKLM\\Network\\Logon"));
  527. SetRegOpenAccessMode (prevMode);
  528. if (key) {
  529. data = GetRegValueDword (key, TEXT("UserProfiles"));
  530. if (data && *data) {
  531. StringCat (Buffer, TEXT("\\Profiles\\"));
  532. size = MAX_PATH;
  533. GetUserName (GetEndOfString (Buffer), &size);
  534. FreeAlloc (data);
  535. }
  536. CloseRegKey (key);
  537. }
  538. return Buffer;
  539. }
  540. VOID
  541. pSetEnvironmentVar (
  542. IN PMAPSTRUCT Map,
  543. IN PMAPSTRUCT UndefMap, OPTIONAL
  544. IN BOOL MapSourceToDest,
  545. IN PCTSTR VariableName,
  546. IN PCTSTR VariableData OPTIONAL
  547. )
  548. {
  549. PTSTR encodedVariableName;
  550. TCHAR buffer[MAX_TCHAR_PATH];
  551. PCTSTR undefText;
  552. //
  553. // VariableData is NULL when VariableName is not present on the machine
  554. //
  555. if (MapSourceToDest) {
  556. //
  557. // MapSourceToDest tells us to map a source path (c:\windows) to
  558. // a destination path (d:\winnt).
  559. //
  560. if (VariableData) {
  561. if (IsmGetEnvironmentString (
  562. PLATFORM_SOURCE,
  563. S_SYSENVVAR_GROUP,
  564. VariableName,
  565. buffer,
  566. ARRAYSIZE(buffer),
  567. NULL
  568. )) {
  569. AddStringMappingPair (Map, buffer, VariableData);
  570. }
  571. }
  572. return;
  573. }
  574. //
  575. // MapSourceToDest is FALSE when we want to map environment variables
  576. // to the actual path.
  577. //
  578. encodedVariableName = AllocPathString (TcharCount (VariableName) + 3);
  579. if (encodedVariableName) {
  580. wsprintf (encodedVariableName, TEXT("%%%s%%"), VariableName);
  581. if (VariableData) {
  582. IsmSetEnvironmentString (IsmGetRealPlatform (), S_SYSENVVAR_GROUP, VariableName, VariableData);
  583. if (Map) {
  584. AddStringMappingPair (Map, encodedVariableName, VariableData);
  585. }
  586. } else if (UndefMap) {
  587. //
  588. // If no variable data, then put environment variable in the
  589. // "undefined" variable mapping
  590. //
  591. undefText = JoinTextEx (NULL, TEXT("--> "), TEXT(" <--"), encodedVariableName, 0, NULL);
  592. AddStringMappingPair (UndefMap, encodedVariableName, undefText);
  593. FreeText (undefText);
  594. }
  595. FreePathString (encodedVariableName);
  596. }
  597. }
  598. VOID
  599. AddRemappingEnvVar (
  600. IN PMAPSTRUCT Map,
  601. IN PMAPSTRUCT ReMap,
  602. IN PMAPSTRUCT UndefMap, OPTIONAL
  603. IN PCTSTR VariableName,
  604. IN PCTSTR VariableData
  605. )
  606. {
  607. pSetEnvironmentVar (Map, UndefMap, FALSE, VariableName, VariableData);
  608. pSetEnvironmentVar (ReMap, UndefMap, TRUE, VariableName, VariableData);
  609. }
  610. VOID
  611. SetIsmEnvironmentFromPhysicalMachine (
  612. IN PMAPSTRUCT Map,
  613. IN BOOL MapSourceToDest,
  614. IN PMAPSTRUCT UndefMap OPTIONAL
  615. )
  616. {
  617. TCHAR dir[MAX_TCHAR_PATH];
  618. PCTSTR path;
  619. PTSTR p;
  620. MIG_USERDATA userData;
  621. BOOL mappedUser = FALSE;
  622. mappedUser = IsmGetMappedUserData (&userData);
  623. //
  624. // Prepare ISM environment variables. The ones added last have the highest priority when
  625. // two or more variables map to the same path.
  626. //
  627. //
  628. // ...user profile
  629. //
  630. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("ALLUSERSPROFILE"), GetAllUsersProfilePath (dir));
  631. if (mappedUser) {
  632. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("USERPROFILE"), userData.UserProfileRoot);
  633. p = _tcschr (userData.UserProfileRoot, TEXT('\\'));
  634. if (p) {
  635. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("HOMEPATH"), p);
  636. }
  637. } else {
  638. GetUserProfileRootPath (dir);
  639. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("USERPROFILE"), dir);
  640. p = _tcschr (dir, TEXT('\\'));
  641. if (p) {
  642. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("HOMEPATH"), p);
  643. }
  644. }
  645. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("PROFILESFOLDER"), GetProfilesFolderPath (dir));
  646. //
  647. // ...temp dir
  648. //
  649. if (GetTempPath (MAX_PATH, dir)) {
  650. p = (PTSTR) FindLastWack (dir);
  651. if (p) {
  652. if (p[1] == 0) {
  653. *p = 0;
  654. }
  655. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("TEMP"), dir);
  656. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("TMP"), dir);
  657. }
  658. }
  659. //
  660. // ...windows directory env variable
  661. //
  662. GetWindowsDirectory (dir, ARRAYSIZE(dir));
  663. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("WINDIR"), dir);
  664. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("SYSTEMROOT"), dir);
  665. //
  666. // ...16-bit system directory. We invent SYSTEM16 and SYSTEM32 for use
  667. // in scripts.
  668. //
  669. path = JoinPaths (dir, TEXT("system"));
  670. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("SYSTEM16"), path);
  671. FreePathString (path);
  672. path = JoinPaths (dir, TEXT("system32"));
  673. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("SYSTEM32"), path);
  674. FreePathString (path);
  675. //
  676. // ...platform-specific system directory
  677. //
  678. GetSystemDirectory (dir, ARRAYSIZE(dir));
  679. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, TEXT("SYSTEM"), dir);
  680. //
  681. // ...shell folders -- we invent all variables with the CSIDL_ prefix
  682. //
  683. #define DEFMAC(id,folder_str,var_name) \
  684. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, var_name, \
  685. GetShellFolderPath (id, folder_str, TRUE, dir));
  686. USER_SHELL_FOLDERS
  687. #undef DEFMAC
  688. #define DEFMAC(id,folder_str,var_name) \
  689. pSetEnvironmentVar (Map, UndefMap, MapSourceToDest, var_name, \
  690. GetShellFolderPath (id, folder_str, FALSE, dir));
  691. COMMON_SHELL_FOLDERS
  692. #undef DEFMAC
  693. }
  694. VOID
  695. pTransferEnvPath (
  696. IN PCTSTR IsmVariableName,
  697. IN PMAPSTRUCT DirectMap,
  698. IN PMAPSTRUCT ReverseMap,
  699. IN PMAPSTRUCT UndefMap
  700. )
  701. {
  702. TCHAR dir[MAX_TCHAR_PATH];
  703. PTSTR encodedVariableName;
  704. PCTSTR undefText;
  705. encodedVariableName = AllocPathString (TcharCount (IsmVariableName) + 3);
  706. if (encodedVariableName) {
  707. wsprintf (encodedVariableName, TEXT("%%%s%%"), IsmVariableName);
  708. if (IsmGetEnvironmentString (PLATFORM_SOURCE, S_SYSENVVAR_GROUP, IsmVariableName, dir, sizeof(dir)/sizeof((dir)[0]), NULL)) {
  709. if (DirectMap) {
  710. AddStringMappingPair (DirectMap, encodedVariableName, dir);
  711. }
  712. if (ReverseMap) {
  713. AddStringMappingPair (ReverseMap, dir, encodedVariableName);
  714. }
  715. } else {
  716. undefText = JoinTextEx (NULL, TEXT("--> "), TEXT(" <--"), encodedVariableName, 0, NULL);
  717. if (UndefMap) {
  718. AddStringMappingPair (UndefMap, encodedVariableName, undefText);
  719. }
  720. FreeText (undefText);
  721. }
  722. FreePathString (encodedVariableName);
  723. }
  724. }
  725. VOID
  726. SetIsmEnvironmentFromVirtualMachine (
  727. IN PMAPSTRUCT DirectMap,
  728. IN PMAPSTRUCT ReverseMap,
  729. IN PMAPSTRUCT UndefMap
  730. )
  731. {
  732. //
  733. // Need to transfer ISM environment into our string mapping
  734. //
  735. #define DEFMAC(name) pTransferEnvPath(name, DirectMap, ReverseMap, UndefMap);
  736. ENVIRONMENT_VARIABLES
  737. #undef DEFMAC
  738. }