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.

553 lines
14 KiB

  1. //-----------------------------------------------------------------------//
  2. //
  3. // File: query.cpp
  4. // Created: Jan 1997
  5. // By: Martin Holladay (a-martih)
  6. // Purpose: Registry Query Support for REG.CPP
  7. // Modification History:
  8. // Created - Jan 1997 (a-martih)
  9. // Aug 1997 (John Whited) Implemented a Binary output function for
  10. // REG_BINARY
  11. // Oct 1997 (martinho) fixed output for REG_MULTI_SZ \0 delimited strings
  12. // April 1998 - MartinHo - Incremented to 1.05 for REG_MULTI_SZ bug fixes.
  13. // Correct support for displaying query REG_MULTI_SZ of. Fix AV.
  14. // April 1999 Zeyong Xu: re-design, revision -> version 2.0
  15. //
  16. //------------------------------------------------------------------------//
  17. #include "stdafx.h"
  18. #include "reg.h"
  19. //-----------------------------------------------------------------------//
  20. //
  21. // QueryRegistry()
  22. //
  23. //-----------------------------------------------------------------------//
  24. LONG QueryRegistry(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
  25. {
  26. LONG nResult;
  27. HKEY hKey;
  28. //
  29. // Parse the cmd-line
  30. //
  31. nResult = ParseQueryCmdLine(pAppVars, argc, argv);
  32. if (nResult != ERROR_SUCCESS)
  33. {
  34. return nResult;
  35. }
  36. //
  37. // Connect to the Remote Machine(s) - if applicable
  38. //
  39. nResult = RegConnectMachine(pAppVars);
  40. if (nResult != ERROR_SUCCESS)
  41. {
  42. return nResult;
  43. }
  44. //
  45. // Open the registry key
  46. //
  47. nResult = RegOpenKeyEx(pAppVars->hRootKey,
  48. pAppVars->szSubKey,
  49. 0,
  50. KEY_READ,
  51. &hKey);
  52. if(nResult != ERROR_SUCCESS)
  53. return nResult;
  54. MyTPrintf(stdout,_T("\r\n! REG.EXE VERSION %s\r\n"), REG_EXE_FILEVERSION);
  55. //
  56. // if query a single registry value
  57. //
  58. if(pAppVars->szValueName)
  59. {
  60. // first print the key name
  61. MyTPrintf(stdout,_T("\r\n%s\r\n"), pAppVars->szFullKey);
  62. nResult = QueryValue(hKey, pAppVars->szValueName);
  63. MyTPrintf(stdout,_T("\r\n"));
  64. }
  65. else // query a registry key
  66. {
  67. nResult = QueryEnumerateKey(hKey,
  68. pAppVars->szFullKey,
  69. pAppVars->bRecurseSubKeys);
  70. }
  71. RegCloseKey(hKey);
  72. return nResult;
  73. }
  74. //------------------------------------------------------------------------//
  75. //
  76. // ParseQueryCmdLine()
  77. //
  78. //------------------------------------------------------------------------//
  79. REG_STATUS ParseQueryCmdLine(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
  80. {
  81. REG_STATUS nResult;
  82. UINT i;
  83. if(argc < 3)
  84. {
  85. return REG_STATUS_TOFEWPARAMS;
  86. }
  87. else if(argc > 5)
  88. {
  89. return REG_STATUS_TOMANYPARAMS;
  90. }
  91. // Machine Name and Registry key
  92. //
  93. nResult = BreakDownKeyString(argv[2], pAppVars);
  94. if(nResult != ERROR_SUCCESS)
  95. return nResult;
  96. // parsing
  97. for(i=3; i<argc; i++)
  98. {
  99. if(!_tcsicmp(argv[i], _T("/v")))
  100. {
  101. if(pAppVars->szValueName || pAppVars->bRecurseSubKeys)
  102. return REG_STATUS_INVALIDPARAMS;
  103. i++;
  104. if(i<argc)
  105. {
  106. pAppVars->szValueName = (TCHAR*) calloc(_tcslen(argv[i]) + 1,
  107. sizeof(TCHAR));
  108. if (!pAppVars->szValueName) {
  109. return ERROR_NOT_ENOUGH_MEMORY;
  110. }
  111. _tcscpy(pAppVars->szValueName, argv[i]);
  112. }
  113. else
  114. return REG_STATUS_TOFEWPARAMS;
  115. }
  116. else if(!_tcsicmp(argv[i], _T("/ve")))
  117. {
  118. if(pAppVars->szValueName || pAppVars->bRecurseSubKeys)
  119. return REG_STATUS_INVALIDPARAMS;
  120. pAppVars->szValueName = (TCHAR*) calloc(1, sizeof(TCHAR));
  121. if (!pAppVars->szValueName) {
  122. return ERROR_NOT_ENOUGH_MEMORY;
  123. }
  124. }
  125. else if(!_tcsicmp(argv[i], _T("/s")))
  126. {
  127. if(pAppVars->szValueName)
  128. return REG_STATUS_INVALIDPARAMS;
  129. pAppVars->bRecurseSubKeys = TRUE;
  130. }
  131. else
  132. return REG_STATUS_INVALIDPARAMS;
  133. }
  134. return ERROR_SUCCESS;
  135. }
  136. //-----------------------------------------------------------------------//
  137. //
  138. // GetTypeStr()
  139. //
  140. //-----------------------------------------------------------------------//
  141. void GetTypeStrFromType(TCHAR *szTypeStr, DWORD dwType)
  142. {
  143. switch (dwType)
  144. {
  145. case REG_BINARY:
  146. _tcscpy(szTypeStr, STR_REG_BINARY);
  147. break;
  148. case REG_DWORD:
  149. _tcscpy(szTypeStr, STR_REG_DWORD);
  150. break;
  151. case REG_DWORD_BIG_ENDIAN:
  152. _tcscpy(szTypeStr, STR_REG_DWORD_BIG_ENDIAN);
  153. break;
  154. case REG_EXPAND_SZ:
  155. _tcscpy(szTypeStr, STR_REG_EXPAND_SZ);
  156. break;
  157. case REG_LINK:
  158. _tcscpy(szTypeStr, STR_REG_LINK);
  159. break;
  160. case REG_MULTI_SZ:
  161. _tcscpy(szTypeStr, STR_REG_MULTI_SZ);
  162. break;
  163. case REG_NONE:
  164. _tcscpy(szTypeStr, STR_REG_NONE);
  165. break;
  166. case REG_RESOURCE_LIST:
  167. _tcscpy(szTypeStr, STR_REG_RESOURCE_LIST);
  168. break;
  169. case REG_SZ:
  170. _tcscpy(szTypeStr, STR_REG_SZ);
  171. break;
  172. default:
  173. _tcscpy(szTypeStr, STR_REG_NONE);
  174. break;
  175. }
  176. }
  177. //-----------------------------------------------------------------------//
  178. //
  179. // QueryValue()
  180. //
  181. //-----------------------------------------------------------------------//
  182. LONG QueryValue(HKEY hKey, TCHAR* szValueName)
  183. {
  184. LONG nResult;
  185. TCHAR szTypeStr[25];
  186. DWORD dwType;
  187. DWORD dwSize = 1;
  188. UINT i;
  189. BYTE* pBuff;
  190. TCHAR szEmptyString[ 2 ] = L"";
  191. if ( szValueName == NULL )
  192. {
  193. szValueName = szEmptyString;
  194. }
  195. //
  196. // First find out how much memory to allocate.
  197. //
  198. nResult = RegQueryValueEx(hKey,
  199. szValueName,
  200. 0,
  201. &dwType,
  202. NULL,
  203. &dwSize);
  204. if (nResult != ERROR_SUCCESS)
  205. {
  206. return nResult;
  207. }
  208. // to avoid problems with corrupted registry data --
  209. // always allocate memory of even no. of bytes
  210. dwSize += ( dwSize % 2 );
  211. pBuff = (BYTE*) calloc(dwSize + 2, sizeof(BYTE));
  212. if (!pBuff) {
  213. return ERROR_NOT_ENOUGH_MEMORY;
  214. }
  215. //
  216. // Now get the data
  217. //
  218. nResult = RegQueryValueEx(hKey,
  219. szValueName,
  220. 0,
  221. &dwType,
  222. (LPBYTE) pBuff,
  223. &dwSize);
  224. if (nResult != ERROR_SUCCESS)
  225. {
  226. free(pBuff);
  227. return nResult;
  228. }
  229. //
  230. // Now list the ValueName\tType\tData
  231. //
  232. GetTypeStrFromType(szTypeStr, dwType);
  233. MyTPrintf(stdout,
  234. _T(" %s\t%s\t"),
  235. (_tcslen(szValueName) == 0) // no name
  236. ? g_NoName
  237. : szValueName,
  238. szTypeStr);
  239. switch (dwType)
  240. {
  241. default:
  242. case REG_BINARY:
  243. for(i=0; i<dwSize; i++)
  244. {
  245. MyTPrintf(stdout,_T("%02X"),pBuff[i]);
  246. }
  247. break;
  248. case REG_SZ:
  249. case REG_EXPAND_SZ:
  250. MyTPrintf(stdout,_T("%s"), (LPCWSTR)pBuff );
  251. break;
  252. case REG_DWORD:
  253. case REG_DWORD_BIG_ENDIAN:
  254. MyTPrintf(stdout,_T("0x%x"), *((DWORD*)pBuff) );
  255. break;
  256. case REG_MULTI_SZ:
  257. {
  258. //
  259. // Replace '\0' with "\0" for MULTI_SZ
  260. //
  261. TCHAR* pEnd = (TCHAR*) pBuff;
  262. while( (BYTE*)pEnd < pBuff + dwSize )
  263. {
  264. if(*pEnd == 0)
  265. {
  266. MyTPrintf(stdout,_T("\\0"));
  267. pEnd++;
  268. }
  269. else
  270. {
  271. MyTPrintf(stdout,_T("%s"), pEnd);
  272. pEnd += _tcslen(pEnd);
  273. }
  274. }
  275. }
  276. break;
  277. }
  278. MyTPrintf(stdout,_T("\r\n"));
  279. if(pBuff)
  280. free(pBuff);
  281. return ERROR_SUCCESS;
  282. }
  283. //-----------------------------------------------------------------------//
  284. //
  285. // EnumerateKey() - Recursive
  286. //
  287. //-----------------------------------------------------------------------//
  288. LONG QueryEnumerateKey(HKEY hKey,
  289. TCHAR* szFullKey,
  290. BOOL bRecurseSubKeys)
  291. {
  292. DWORD nResult;
  293. UINT i;
  294. DWORD dwSize;
  295. HKEY hSubKey;
  296. TCHAR* szNameBuf;
  297. TCHAR* szTempName;
  298. // query source key info
  299. DWORD dwLenOfKeyName;
  300. DWORD dwLenOfValueName;
  301. nResult = RegQueryInfoKey(hKey,
  302. NULL,
  303. NULL,
  304. NULL,
  305. NULL,
  306. &dwLenOfKeyName,
  307. NULL,
  308. NULL,
  309. &dwLenOfValueName,
  310. NULL,
  311. NULL,
  312. NULL);
  313. if (nResult != ERROR_SUCCESS)
  314. {
  315. return nResult;
  316. }
  317. #ifndef REG_FOR_WIN2000 // ansi version for win98
  318. // fix API bugs: RegQueryInfoKey() returns non-correct length values
  319. // on remote Win98
  320. if(dwLenOfKeyName < MAX_PATH)
  321. dwLenOfKeyName = MAX_PATH;
  322. if(dwLenOfValueName < MAX_PATH)
  323. dwLenOfValueName = MAX_PATH;
  324. #endif
  325. // create buffer
  326. dwLenOfValueName++;
  327. szNameBuf = (TCHAR*) calloc(dwLenOfValueName, sizeof(TCHAR));
  328. if (!szNameBuf) {
  329. return ERROR_NOT_ENOUGH_MEMORY;
  330. }
  331. // first print the key name
  332. MyTPrintf(stdout,_T("\r\n%s\r\n"), szFullKey);
  333. //
  334. // enumerate all of the values
  335. //
  336. i = 0;
  337. do
  338. {
  339. dwSize = dwLenOfValueName;
  340. nResult = RegEnumValue(hKey,
  341. i,
  342. szNameBuf,
  343. &dwSize,
  344. NULL,
  345. NULL,
  346. NULL,
  347. NULL);
  348. if (nResult == ERROR_SUCCESS)
  349. {
  350. nResult = QueryValue(hKey, szNameBuf);
  351. // continue to query
  352. if(nResult == ERROR_ACCESS_DENIED)
  353. {
  354. MyTPrintf(stderr,
  355. _T("Error: Access is denied in the value %s under")
  356. _T(" the key %s\r\n"),
  357. szNameBuf,
  358. szFullKey);
  359. nResult = ERROR_SUCCESS;
  360. }
  361. }
  362. i++;
  363. } while (nResult == ERROR_SUCCESS);
  364. if(szNameBuf)
  365. free(szNameBuf);
  366. if (nResult == ERROR_NO_MORE_ITEMS)
  367. nResult = ERROR_SUCCESS;
  368. if( nResult != ERROR_SUCCESS )
  369. return nResult;
  370. //
  371. // SPECIAL CASE:
  372. // -------------
  373. // For HKLM\SYSTEM\CONTROLSET002 it is found to be API returning value 0 for dwMaxLength
  374. // though there are subkeys underneath this -- to handle this, we are doing a workaround
  375. // by assuming the max registry key length
  376. //
  377. if ( dwLenOfKeyName == 0 )
  378. {
  379. dwLenOfKeyName = 256;
  380. }
  381. else if ( dwLenOfKeyName < 256 )
  382. {
  383. // always assume 100% more length than what is returned by API
  384. dwLenOfKeyName *= 2;
  385. }
  386. //
  387. // Now Enumerate all of the keys
  388. //
  389. dwLenOfKeyName++;
  390. szNameBuf = (TCHAR*) calloc(dwLenOfKeyName, sizeof(TCHAR));
  391. if (!szNameBuf) {
  392. return ERROR_NOT_ENOUGH_MEMORY;
  393. }
  394. i = 0;
  395. do
  396. {
  397. dwSize = dwLenOfKeyName;
  398. nResult = RegEnumKeyEx(hKey,
  399. i,
  400. szNameBuf,
  401. &dwSize,
  402. NULL,
  403. NULL,
  404. NULL,
  405. NULL);
  406. if (nResult != ERROR_SUCCESS)
  407. break;
  408. //
  409. // open up the subkey, and enumerate it
  410. //
  411. nResult = RegOpenKeyEx(hKey,
  412. szNameBuf,
  413. 0,
  414. KEY_READ,
  415. &hSubKey);
  416. //
  417. // Build up the needed string and go down enumerating again
  418. //
  419. szTempName = (TCHAR*) calloc(_tcslen(szFullKey) +
  420. _tcslen(szNameBuf) +
  421. 2,
  422. sizeof(TCHAR));
  423. if (!szTempName) {
  424. nResult = ERROR_NOT_ENOUGH_MEMORY;
  425. goto Cleanup;
  426. }
  427. _tcscpy(szTempName, szFullKey);
  428. _tcscat(szTempName, _T("\\"));
  429. _tcscat(szTempName, szNameBuf);
  430. if (bRecurseSubKeys && nResult == ERROR_SUCCESS)
  431. {
  432. // recursive query
  433. nResult = QueryEnumerateKey(hSubKey,
  434. szTempName,
  435. bRecurseSubKeys);
  436. }
  437. else
  438. {
  439. // print key
  440. MyTPrintf(stdout,_T("\r\n%s\r\n"), szTempName);
  441. if(nResult == ERROR_ACCESS_DENIED) // continue to query next key
  442. {
  443. MyTPrintf(stderr,
  444. _T("Error: Access is denied in the key %s\r\n"),
  445. szTempName);
  446. nResult = ERROR_SUCCESS;
  447. }
  448. }
  449. RegCloseKey(hSubKey);
  450. if(szTempName)
  451. free(szTempName);
  452. i++;
  453. } while (nResult == ERROR_SUCCESS);
  454. Cleanup:
  455. if(szNameBuf)
  456. free(szNameBuf);
  457. if (nResult == ERROR_NO_MORE_ITEMS)
  458. nResult = ERROR_SUCCESS;
  459. return nResult;
  460. }