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.

428 lines
15 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2000
  5. //
  6. // File: GrabMI.cpp
  7. //
  8. // Contents: Code for generating matching information for files in a given
  9. // directory and it's subdirectories.
  10. //
  11. // History: 18-Jul-00 jdoherty Created.
  12. // 16-Dec-00 jdoherty Modified to use SDBAPI routines.
  13. // 29-Dec-00 prashkud Modified to take space in the filepath
  14. //
  15. //
  16. //
  17. //---------------------------------------------------------------------------
  18. #include <windows.h>
  19. #include <TCHAR.h>
  20. #include <stdio.h>
  21. #include <conio.h>
  22. #ifdef __cplusplus
  23. extern "C" {
  24. #include "shimdb.h"
  25. typedef BOOL
  26. (SDBAPI*PFNSdbGrabMatchingInfoA)(
  27. LPCSTR szMatchingPath,
  28. DWORD dwFilter,
  29. LPCSTR szFile
  30. );
  31. typedef BOOL
  32. (SDBAPI*PFNSdbGrabMatchingInfoW)(
  33. LPCWSTR szMatchingPath,
  34. DWORD dwFilter,
  35. LPCWSTR szFile
  36. );
  37. }
  38. #endif
  39. typedef GMI_RESULT
  40. (SDBAPI *PFNSdbGrabMatchingInfoExA)(
  41. LPCSTR szMatchingPath, // path to begin gathering information
  42. DWORD dwFilterAndFlags, // specifies the types of files to be added to matching
  43. LPCSTR szFile, // full path to file where information will be stored
  44. PFNGMIProgressCallback pfnCallback,
  45. LPVOID lpvCallbackParameter
  46. );
  47. typedef GMI_RESULT
  48. (SDBAPI *PFNSdbGrabMatchingInfoExW)(
  49. LPCWSTR szMatchingPath, // path to begin gathering information
  50. DWORD dwFilterAndFlags, // specifies the types of files to be added to matching
  51. LPCWSTR szFile, // full path to file where information will be stored
  52. PFNGMIProgressCallback pfnCallback,
  53. LPVOID lpvCallbackParameter
  54. );
  55. //
  56. // Filters needed for SdbGrabMatchingInfo
  57. //
  58. /*
  59. #define GRABMI_FILTER_NORMAL 0
  60. #define GRABMI_FILTER_PRIVACY 1
  61. #define GRABMI_FILTER_DRIVERS 2
  62. #define GRABMI_FILTER_VERBOSE 3
  63. #define GRABMI_FILTER_SYSTEM 4
  64. #define GRABMI_FILTER_THISFILEONLY 5
  65. */
  66. void ProperUsage();
  67. BOOL CALLBACK _GrabmiCallback(
  68. LPVOID lpvCallbackParam, // application-defined parameter
  69. LPCTSTR lpszRoot, // root directory path
  70. LPCTSTR lpszRelative, // relative path
  71. PATTRINFO pAttrInfo, // attributes
  72. LPCWSTR pwszXML // resulting xml
  73. )
  74. {
  75. static int State = 0;
  76. static TCHAR szIcon[] = TEXT("||//--\\\\");
  77. State = ++State % (ARRAYSIZE(szIcon)-1);
  78. _tcprintf(TEXT("%c\r"), szIcon[State]);
  79. return TRUE;
  80. }
  81. int __cdecl main(int argc, TCHAR* argv[])
  82. {
  83. TCHAR szRootDir[MAX_PATH] = {'\0'}; // original root directory for matching
  84. TCHAR szFile[MAX_PATH] = {'\0'}; // File to store information to
  85. TCHAR szCommandLine[MAX_PATH]={'\0'}; // command line passed to winexec
  86. TCHAR szMessage[MAX_PATH]={'\0'}; // error message to display
  87. DWORD dwFilter = GRABMI_FILTER_NORMAL; // specifies filter for matching
  88. DWORD dwFilterFlags = 0;
  89. BOOL bDestinationSelected = FALSE;
  90. BOOL bDisplayFile = TRUE;
  91. OSVERSIONINFO VersionInfo;
  92. int iRetCode = 0;
  93. BOOL bUseApphelp = FALSE;
  94. static int Cnt = 0;
  95. PFNSdbGrabMatchingInfoExA pfnGrabA = NULL;
  96. PFNSdbGrabMatchingInfoExW pfnGrabW = NULL;
  97. HMODULE hLib;
  98. VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  99. if (GetVersionEx(&VersionInfo) == FALSE) {
  100. wsprintf (szMessage, TEXT("Unable to get version info.\n"));
  101. goto eh;
  102. }
  103. // check OS version to load the correct version
  104. // of sdbapi
  105. // set to debug 9x binaries on WinXP
  106. // VersionInfo.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
  107. switch (VersionInfo.dwPlatformId) {
  108. case VER_PLATFORM_WIN32_NT:
  109. if (VersionInfo.dwMajorVersion >= 5) {
  110. if (VersionInfo.dwMajorVersion == 5) { // Check minor version for WinXP
  111. bUseApphelp = VersionInfo.dwMinorVersion >= 1;
  112. } else {
  113. bUseApphelp = TRUE;
  114. }
  115. }
  116. hLib = LoadLibrary(bUseApphelp ? TEXT("apphelp.dll") : TEXT("sdbapiu.dll"));
  117. if (hLib == NULL) {
  118. wsprintf (szMessage, TEXT("Could not load sdbapiu.dll.\n"));
  119. goto eh;
  120. }
  121. pfnGrabW = (PFNSdbGrabMatchingInfoExW)GetProcAddress(hLib, TEXT("SdbGrabMatchingInfoEx"));
  122. if (pfnGrabW == NULL) {
  123. wsprintf (szMessage, TEXT("Unable to get proc address for SdbGrabMatchingInfo\n"));
  124. goto eh;
  125. }
  126. break;
  127. case VER_PLATFORM_WIN32_WINDOWS:
  128. hLib = LoadLibraryA(TEXT("sdbapi.dll"));
  129. if (hLib == NULL) {
  130. wsprintf (szMessage, TEXT("Could not load sdbapi.dll.\n"));
  131. goto eh;
  132. }
  133. pfnGrabA = (PFNSdbGrabMatchingInfoExA)GetProcAddress(hLib, TEXT("SdbGrabMatchingInfoEx"));
  134. if (pfnGrabA == NULL) {
  135. wsprintf (szMessage, TEXT("Unable to get proc address for SdbGrabMatchingInfo\n"));
  136. goto eh;
  137. }
  138. break;
  139. default:
  140. wsprintf (szMessage, TEXT("Unknown platform\n"));
  141. goto eh;
  142. }
  143. // Parse the command line for flags
  144. if( argc >= 2) {
  145. int i = 1;
  146. while (i < argc){
  147. LPCTSTR pch = argv[i];
  148. TCHAR ch = *pch;
  149. if (ch == TEXT('-') || ch == TEXT('/')) {
  150. ch = *++pch;
  151. ++pch;
  152. switch(_totupper(ch)) {
  153. case TEXT('F'):
  154. if (*pch == TEXT('\0')) {
  155. ++i;
  156. if (i < argc && _istalnum(*argv[i])) {
  157. pch = argv[i];
  158. } else {
  159. // error - missing filename
  160. wsprintf (szMessage, TEXT("You must provide a file with a .txt extension to save to.\n") );
  161. goto HandleUsage;
  162. }
  163. }
  164. lstrcpy(szFile, pch);
  165. bDestinationSelected=TRUE;
  166. break;
  167. case TEXT('?'):
  168. case TEXT('H'): // help ?
  169. HandleUsage:
  170. ProperUsage();
  171. goto eh;
  172. case TEXT('D'):
  173. dwFilter = GRABMI_FILTER_DRIVERS;
  174. break;
  175. case TEXT('O'):
  176. dwFilter = GRABMI_FILTER_THISFILEONLY;
  177. break;
  178. case TEXT('V'):
  179. dwFilter = GRABMI_FILTER_VERBOSE;
  180. break;
  181. case TEXT('Q'):
  182. bDisplayFile = FALSE;
  183. break;
  184. case TEXT('P'):
  185. dwFilter = GRABMI_FILTER_PRIVACY;
  186. break;
  187. case TEXT('S'):
  188. dwFilter = GRABMI_FILTER_SYSTEM;
  189. break;
  190. case TEXT('A'):
  191. dwFilterFlags |= GRABMI_FILTER_APPEND;
  192. break;
  193. case TEXT('N'):
  194. dwFilterFlags |= GRABMI_FILTER_NOCLOSE;
  195. break;
  196. default:
  197. // unrecognized arg goes here
  198. wsprintf(szMessage, TEXT("Unrecognized argument, RTFM: %s\n"), argv[i]);
  199. goto HandleUsage;
  200. break;
  201. }
  202. } else {
  203. // unnamed argument
  204. if (++Cnt > 1) {
  205. // error - more than one file specified -- we do not support it for now
  206. //
  207. wsprintf(szMessage, TEXT("More than one file specified %s\n"), argv[i]);
  208. goto HandleUsage;
  209. }
  210. lstrcpy(szRootDir, argv[i]);
  211. }
  212. ++i;
  213. }
  214. }
  215. if (!bDestinationSelected) {
  216. GetSystemDirectory( szFile, MAX_PATH );
  217. LPTSTR pchBackslash;
  218. pchBackslash = _tcschr(szFile, TEXT('\\'));
  219. lstrcpy (pchBackslash, TEXT("\\matchinginfo.txt"));
  220. bDestinationSelected=TRUE;
  221. }
  222. if ( (_tcsicmp(szRootDir ,TEXT(".")) == 0) || szRootDir[0] == '\0' ) {
  223. // The root path wasn't specified. Get the current path or
  224. // the path to the drivers depending on command line
  225. if (dwFilter == GRABMI_FILTER_DRIVERS && (_tcsicmp(szRootDir ,TEXT(".")) != 0)) {
  226. GetSystemDirectory( szRootDir, MAX_PATH );
  227. lstrcat( szRootDir, TEXT("\\drivers") );
  228. } else {
  229. GetCurrentDirectory( MAX_PATH, szRootDir );
  230. }
  231. }
  232. // if we are using sdbapiu.dll we need to call it with
  233. // unicode parameters
  234. if (VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
  235. WCHAR wszRootDir[MAX_PATH] ={'\0'};
  236. WCHAR wszFile[MAX_PATH] ={'\0'};
  237. int cchWideChar;
  238. cchWideChar = MultiByteToWideChar(
  239. CP_ACP,
  240. 0,
  241. szRootDir,
  242. -1,
  243. NULL,
  244. 0 );
  245. //
  246. // check for error!!!
  247. //
  248. if ((DWORD)cchWideChar > MAX_PATH) {
  249. wsprintf (szMessage, TEXT("Unable to convert szRootDir to wszRootDir.\n"));
  250. goto eh;
  251. }
  252. MultiByteToWideChar(
  253. CP_ACP,
  254. 0,
  255. szRootDir,
  256. -1,
  257. wszRootDir,
  258. cchWideChar );
  259. cchWideChar = MultiByteToWideChar(
  260. CP_ACP,
  261. 0,
  262. szFile,
  263. -1,
  264. NULL,
  265. 0 );
  266. //
  267. // check for error!!!
  268. //
  269. if ((DWORD)cchWideChar > MAX_PATH) {
  270. wsprintf (szMessage, TEXT("Unable to convert szFile to wszFile.\n"));
  271. goto eh;
  272. }
  273. MultiByteToWideChar(
  274. CP_ACP,
  275. 0,
  276. szFile,
  277. -1,
  278. wszFile,
  279. cchWideChar );
  280. // now make call to SdbGrabMatchingInfo with Unicode parameters
  281. if ((pfnGrabW (wszRootDir, dwFilter|dwFilterFlags, wszFile, _GrabmiCallback, NULL)) != GMI_SUCCESS) {
  282. wsprintf (szMessage, TEXT("Unable to grab matching information from %s.\n"), szRootDir);
  283. goto eh;
  284. }
  285. wsprintf (szMessage, TEXT("Matching information retrieved successfully.\n"));
  286. }
  287. else if (VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS){
  288. // otherwise call SdbGrabMatchingInfo as normal
  289. if ((pfnGrabA (szRootDir, dwFilter|dwFilterFlags, szFile, _GrabmiCallback, NULL)) != GMI_SUCCESS) {
  290. wsprintf (szMessage, TEXT("Unable to grab matching information from %s.\n"), szRootDir);
  291. goto eh;
  292. }
  293. wsprintf (szMessage, TEXT("Matching information retrieved successfully.\n"));
  294. }
  295. else {
  296. wsprintf (szMessage, TEXT("Unknown OS Platform.\n"));
  297. goto eh;
  298. }
  299. if (bDisplayFile) {
  300. if (VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
  301. lstrcpy (szCommandLine, TEXT("notepad "));
  302. }
  303. else {
  304. lstrcpy (szCommandLine, TEXT("write "));
  305. }
  306. lstrcat (szCommandLine, szFile);
  307. WinExec (szCommandLine, SW_SHOW);
  308. }
  309. eh:
  310. if (*szMessage) {
  311. _tprintf (TEXT("%s"), szMessage);
  312. iRetCode = 1;
  313. }
  314. return iRetCode;
  315. }
  316. /*++
  317. Function Description:
  318. This function simply prints out the proper usage for GrabMI.
  319. Arguments:
  320. Return Value:
  321. VOID.
  322. History:
  323. jdoherty Created 8/2/00
  324. --*/
  325. void ProperUsage()
  326. {
  327. _tprintf (TEXT("\nGrabMI can be used in one of the following ways:\n")
  328. TEXT(" *** The following flags can be used with other flags: \n")
  329. TEXT(" -f, -a, -n, and -h \n")
  330. TEXT(" otherwise the last flag specified will be the one used.\n")
  331. TEXT(" *** By default information will be stored in %%systemdrive%%\\matchinginfo.txt\n\n")
  332. TEXT(" grabmi [path to start generating info ie. c:\\progs]\n")
  333. TEXT(" Grabs matching information from the path specified. Limits the\n")
  334. TEXT(" information gathered to 10 miscellaneous files per directory,\n")
  335. TEXT(" and includes all files with extensions .icd, .exe, .dll, \n")
  336. TEXT(" .msi, ._mp\n\n")
  337. TEXT(" grabmi [-d]\n")
  338. TEXT(" Grabs matching information from %%windir%%\\system32\\drivers. \n")
  339. TEXT(" The format of the information is slightly different in this case\n")
  340. TEXT(" and only information for *.sys files will be grabbed.\n\n")
  341. TEXT(" grabmi [-f drive:\\filename.txt]\n")
  342. TEXT(" The matching information is stored in a file specified by the user.\n\n")
  343. TEXT(" grabmi [-h or -?]\n")
  344. TEXT(" Displays this help.\n\n")
  345. TEXT(" grabmi [-o]\n")
  346. TEXT(" Grabs information for the file specified. If a file was not specified \n")
  347. TEXT(" the call will fail. If the destination file exists then the information\n")
  348. TEXT(" will be concatenated to the end of the existing file.\n\n")
  349. TEXT(" grabmi [-p]\n")
  350. TEXT(" Grabs information for files with .icd, .exe, .dll, .msi, ._mp extensions. \n")
  351. TEXT(" No more, no less.\n\n")
  352. TEXT(" grabmi [-q]\n")
  353. TEXT(" Grabs matching information and does not display the file when completed.\n\n")
  354. TEXT(" grabmi [-s]\n")
  355. TEXT(" Grabs information for the following system files: \n")
  356. TEXT(" advapi32.dll, gdi32.dll, ntdll.dll, kernel32.dll, winsock.dll\n")
  357. TEXT(" ole32.dll, oleaut32.dll, shell32.dll, user32.dll, and wininet.dll \n\n")
  358. TEXT(" grabmi [-v]\n")
  359. TEXT(" Grabs matching information for all files. \n\n")
  360. TEXT(" grabmi [-a]\n")
  361. TEXT(" Appends new matching information to the existing matching\n")
  362. TEXT(" information file. \n\n")
  363. TEXT(" grabmi [-n]\n")
  364. TEXT(" Allows to append more information to the file later (see -a). \n\n")
  365. TEXT("Grab Matching Information Help\n"));
  366. return;
  367. }