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.

406 lines
9.6 KiB

  1. // Copyright (c) 1998-1999 Microsoft Corporation
  2. /******************************************************************************
  3. *
  4. * ACREGL.C
  5. *
  6. * Application Compatibility Registry Lookup Helper Program
  7. *
  8. *
  9. *******************************************************************************/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. // #include <winreg.h>
  13. #define MAXLEN 512
  14. // Options
  15. // The strip char option will strip the rightmost n instances
  16. // of the specified character from the output. If the count
  17. // is omitted, then a single instance is removed.
  18. //
  19. // Example: STRIPCHAR\3 will change
  20. // C:\WINNT40\Profiles\All Users\Start Menu to
  21. // C:\WINNT40
  22. #define OPTION_STRIP_CHAR L"STRIPCHAR"
  23. // The strip path option strips off the path.
  24. //
  25. // Example: STRIPPATH will change
  26. // C:\WINNT40\Profiles\All Users\Start Menu to
  27. // Start Menu
  28. #define OPTION_STRIP_PATH L"STRIPPATH"
  29. // The get path option gets the common paths
  30. //
  31. // Example: GETPATHS will return
  32. //
  33. #define OPTION_GET_PATHS L"GETPATHS"
  34. // Define the strings used for setting the user/common paths
  35. #define COMMON_STARTUP L"COMMON_STARTUP"
  36. #define COMMON_START_MENU L"COMMON_START_MENU"
  37. #define COMMON_PROGRAMS L"COMMON_PROGRAMS"
  38. #define USER_START_MENU L"USER_START_MENU"
  39. #define USER_STARTUP L"USER_STARTUP"
  40. #define USER_PROGRAMS L"USER_PROGRAMS"
  41. #define MY_DOCUMENTS L"MY_DOCUMENTS"
  42. #define TEMPLATES L"TEMPLATES"
  43. #define APP_DATA L"APP_DATA"
  44. // Option Block.
  45. // Scan Options will populate
  46. // this struct.
  47. typedef struct
  48. {
  49. WCHAR stripChar; // Character to strip.
  50. int stripNthChar; // Strip nth occurrence from the right.
  51. int stripPath; // Strip path.
  52. int getPaths; // Get the common paths
  53. } OptionBlock;
  54. //
  55. // Strip quotes from argument if they exist, convert to unicode, and expand
  56. // environment variables.
  57. //
  58. int ParseArg(CHAR *inarg, WCHAR *outarg)
  59. {
  60. WCHAR T[MAXLEN+1], wcin[MAXLEN+1];
  61. int retval;
  62. // Convert to Ansi
  63. OEM2ANSIA(inarg, (USHORT)strlen(inarg));
  64. wsprintf(wcin, L"%S", inarg);
  65. if (wcin[0] == L'"')
  66. {
  67. wcscpy(T, &wcin[1]);
  68. if (T[wcslen(T)-1] == L'"')
  69. T[wcslen(T)-1] = UNICODE_NULL;
  70. else
  71. return(-1); // Mismatched quotes
  72. }
  73. else
  74. wcscpy(T, wcin);
  75. retval = ExpandEnvironmentStrings(T, outarg, MAXLEN);
  76. if ((retval == 0) || (retval > MAXLEN))
  77. return(-1);
  78. return(retval);
  79. }
  80. //
  81. // See comment above OPTION_STRIP_CHAR definition.
  82. //
  83. void StripChar(WCHAR *s, WCHAR c, int num)
  84. {
  85. if(s)
  86. {
  87. WCHAR *p = s + wcslen(s) + 1;
  88. while ((num != 0) && (p != s))
  89. {
  90. p--;
  91. if (*p == c)
  92. num--;
  93. }
  94. *p = 0;
  95. }
  96. }
  97. //
  98. // Strips the path from the
  99. // specified string.
  100. //
  101. void StripPath(WCHAR *s)
  102. {
  103. WCHAR *p = wcsrchr(s, L'\\');
  104. if (p != 0)
  105. wcscpy(s, p+1);
  106. }
  107. //
  108. // Populates option block.
  109. //
  110. int ScanOptions(WCHAR *optionString, OptionBlock* options)
  111. {
  112. WCHAR *curOption;
  113. WCHAR temp[MAXLEN+1];
  114. // Clear out option block.
  115. memset(options, 0, sizeof(OptionBlock));
  116. // Trivial Reject.
  117. if (*optionString == 0)
  118. return 0;
  119. // Uppercase a copy of the option string.
  120. wcscpy(temp, optionString);
  121. _wcsupr(temp);
  122. // Look for strip char option.
  123. curOption = wcsstr(temp, OPTION_STRIP_CHAR);
  124. if (curOption != 0)
  125. {
  126. // Change current option so it points into the original
  127. // option, not the uppercased copy.
  128. curOption = (WCHAR*)((INT_PTR)optionString + ((INT_PTR)curOption - (INT_PTR)temp));
  129. // Get parameters after strip specifier.
  130. // If there are not any then error.
  131. curOption += (sizeof(OPTION_STRIP_CHAR)/sizeof(WCHAR)) - 1;
  132. if (*curOption == UNICODE_NULL || *curOption == L' ')
  133. return 1;
  134. // Get the character to strip.
  135. options->stripChar = *curOption++;
  136. // Get the number of occurrrences.
  137. // If not specified then assume 1.
  138. if (*curOption == UNICODE_NULL || *curOption == L' ')
  139. options->stripNthChar = 1;
  140. else
  141. options->stripNthChar = _wtoi(curOption);
  142. }
  143. // Look for leaf option.
  144. curOption = wcsstr(temp, OPTION_STRIP_PATH);
  145. if (curOption != UNICODE_NULL)
  146. options->stripPath = 1;
  147. // Look get paths option
  148. curOption = wcsstr(temp, OPTION_GET_PATHS);
  149. if (curOption != UNICODE_NULL)
  150. options->getPaths = 1;
  151. return 0;
  152. }
  153. //
  154. // Outputs the common directories into the temp file
  155. // Input: file (input) pointer to open handle for the batch file
  156. // Returns: 0 - success
  157. // 1 - failure
  158. //
  159. int GetPaths(FILE *file)
  160. {
  161. WCHAR szPath[MAX_PATH+1];
  162. if( !GetWindowsDirectory(szPath, MAX_PATH) ){
  163. return (1);
  164. }
  165. if (SHGetFolderPath(NULL, CSIDL_COMMON_STARTMENU, NULL, 0, szPath) == S_OK) {
  166. fwprintf(file, L"SET %s=%s\n", COMMON_START_MENU, szPath);
  167. } else {
  168. return(1);
  169. }
  170. if (SHGetFolderPath(NULL, CSIDL_COMMON_STARTUP, NULL, 0, szPath) == S_OK) {
  171. fwprintf(file, L"SET %s=%s\n", COMMON_STARTUP, szPath);
  172. } else {
  173. return(1);
  174. }
  175. if (SHGetFolderPath(NULL, CSIDL_COMMON_PROGRAMS, NULL, 0, szPath) == S_OK) {
  176. fwprintf(file, L"SET %s=%s\n", COMMON_PROGRAMS, szPath);
  177. } else {
  178. return(1);
  179. }
  180. if (SHGetFolderPath(NULL, CSIDL_STARTMENU, NULL, 0, szPath) == S_OK) {
  181. fwprintf(file, L"SET %s=%s\n", USER_START_MENU, szPath);
  182. } else {
  183. return(1);
  184. }
  185. if (SHGetFolderPath(NULL, CSIDL_STARTUP, NULL, 0, szPath) == S_OK) {
  186. fwprintf(file, L"SET %s=%s\n", USER_STARTUP, szPath);
  187. } else {
  188. return(1);
  189. }
  190. if (SHGetFolderPath(NULL, CSIDL_PROGRAMS, NULL, 0, szPath) == S_OK) {
  191. fwprintf(file, L"SET %s=%s\n", USER_PROGRAMS, szPath);
  192. } else {
  193. return(1);
  194. }
  195. // MY_DOCUMENTS should only be the last component of the path
  196. if (SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, szPath) == S_OK) {
  197. StripPath(szPath);
  198. fwprintf(file, L"SET %s=%s\n", MY_DOCUMENTS, szPath);
  199. } else {
  200. return(1);
  201. }
  202. // TEMPLATES should only be the last component of the path
  203. if (SHGetFolderPath(NULL, CSIDL_TEMPLATES, NULL, 0, szPath) == S_OK) {
  204. StripPath(szPath);
  205. fwprintf(file, L"SET %s=%s\n", TEMPLATES, szPath);
  206. } else {
  207. return(1);
  208. }
  209. // APP_DATA should only be the last component of the path
  210. if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, szPath) == S_OK) {
  211. StripPath(szPath);
  212. fwprintf(file, L"SET %s=%s\n", APP_DATA, szPath);
  213. } else {
  214. return(1);
  215. }
  216. return(0);
  217. }
  218. int __cdecl main(INT argc, CHAR **argv)
  219. {
  220. FILE *OutFP;
  221. WCHAR OutFN[MAXLEN+1];
  222. WCHAR EVName[MAXLEN+1];
  223. WCHAR KeyName[MAXLEN+1];
  224. WCHAR ValName[MAXLEN+1];
  225. WCHAR Temp[MAXLEN+1];
  226. WCHAR Opts[MAXLEN+1];
  227. struct HKEY__ *Hive;
  228. DWORD RetType, RetSize;
  229. HKEY TargetKey;
  230. LONG Ret;
  231. OptionBlock options;
  232. int rc=0;
  233. //
  234. // Process the command line arguments. We expect:
  235. //
  236. // acregl FileName EnvVarName KeyName ValueName Options
  237. //
  238. // The program uses exit code 0 to indicate success or
  239. // exit code 1 for failure.
  240. //
  241. if (argc != 6)
  242. return(1);
  243. setlocale(LC_ALL, ".OCP");
  244. if (ParseArg(argv[1], OutFN) <= 0)
  245. return(1);
  246. if (ParseArg(argv[2], EVName) <= 0)
  247. return(1);
  248. if (ParseArg(argv[3], Temp) <= 0)
  249. return(1);
  250. if (_wcsnicmp(L"HKLM\\", Temp, 5) == 0)
  251. Hive = HKEY_LOCAL_MACHINE;
  252. else if (_wcsnicmp(L"HKCU\\", Temp, 5) == 0)
  253. Hive = HKEY_CURRENT_USER;
  254. else
  255. return(1);
  256. wcscpy(KeyName,&Temp[5]);
  257. if (ParseArg(argv[4], ValName) < 0) // Ok if 0 is returned
  258. return(1);
  259. if (ParseArg(argv[5], Opts) <= 0)
  260. return(1);
  261. if (ScanOptions(Opts, &options) != 0)
  262. return 1;
  263. // wprintf(L"OutFN <%ws>\n",OutFN);
  264. // wprintf(L"EVName <%ws>\n",EVName);
  265. // wprintf(L"KeyName <%ws>, Hive 0x%x\n",KeyName, Hive);
  266. // wprintf(L"ValName <%ws>\n",ValName);
  267. // wprintf(L"Opts <%ws>\n",Opts);
  268. // If the GETPATHS option isn't specified, open the reg keys
  269. if (options.getPaths == 0) {
  270. //
  271. // Read the specified key and value from the registry. The ANSI
  272. // registry functions are used because the command line arguments
  273. // are in ANSI and when we write the data out it also needs to be
  274. // in ANSI.
  275. //
  276. Ret = RegOpenKeyEx(Hive, KeyName, 0, KEY_READ, &TargetKey);
  277. if (Ret != ERROR_SUCCESS)
  278. return(1);
  279. RetSize = MAXLEN;
  280. Ret = RegQueryValueEx(TargetKey, ValName, 0, &RetType, (LPBYTE) &Temp,
  281. &RetSize);
  282. if (Ret != ERROR_SUCCESS)
  283. return(1);
  284. //Now we need to procedd DWORDs too
  285. if(RetType == REG_DWORD)
  286. {
  287. DWORD dwTmp = (DWORD)(*Temp);
  288. _itow((int)dwTmp,Temp,10);
  289. }
  290. RegCloseKey(TargetKey);
  291. }
  292. //
  293. // Process Options
  294. //
  295. //
  296. // Write a SET statement to the specified file. The file can be
  297. // executed from a script which will set the indicated environment
  298. // variable. This is a round-about method, but there appears to be
  299. // no easy method for setting environment variables in the parent's
  300. // environment.
  301. //
  302. // wprintf(L"SET %s=%s\n",EVName,Temp);
  303. OutFP = _wfopen(OutFN, L"w");
  304. if (OutFP == NULL)
  305. return(1);
  306. if (options.stripNthChar != 0)
  307. StripChar(Temp, options.stripChar, options.stripNthChar);
  308. if (options.stripPath != 0)
  309. StripPath(Temp);
  310. if (options.getPaths != 0) {
  311. if (GetPaths(OutFP)) {
  312. rc = 1;
  313. }
  314. } else {
  315. fwprintf(OutFP, L"SET %s=%s\n", EVName, Temp);
  316. }
  317. fclose(OutFP);
  318. return(rc);
  319. }