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.

938 lines
30 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. grabmiapi.c
  5. Abstract:
  6. Code for generating matching information for files in a given
  7. directory and its subdirectories.
  8. Author:
  9. jdoherty created sometime in 2000
  10. Revision History:
  11. several people contributed (vadimb, clupu, ...)
  12. --*/
  13. #include "sdbp.h"
  14. #include <time.h>
  15. #define GRABMI_BUFFER_SIZE 4096
  16. #define MAX_MISC_FILES_PER_LEVEL 10
  17. #define MAX_LEVELS_OF_DIRECTORIES 3
  18. static UCHAR UNICODE_MARKER[2] = { 0xFF, 0xFE }; // will hold special characters to specify
  19. // a UNICODE File
  20. TCHAR* g_szFilterDesc[] = {
  21. TEXT("GRABMI_FILTER_NORMAL"),
  22. TEXT("GRABMI_FILTER_PRIVACY"),
  23. TEXT("GRABMI_FILTER_DRIVERS"),
  24. TEXT("GRABMI_FILTER_VERBOSE"),
  25. TEXT("GRABMI_FILTER_SYSTEM"),
  26. TEXT("GRABMI_FILTER_THISFILEONLY"),
  27. TEXT("")
  28. };
  29. TCHAR* g_szGrabmiFilterNormal[] = {
  30. TEXT(".exe"),
  31. TEXT(".icd"),
  32. TEXT("._mp"),
  33. TEXT(".msi"),
  34. TEXT(".dll"),
  35. TEXT("")
  36. };
  37. TCHAR* g_szGrabmiFilterSystem[] = {
  38. TEXT("ntdll.dll"),
  39. TEXT("user32.dll"),
  40. TEXT("kernel32.dll"),
  41. TEXT("gdi32.dll"),
  42. TEXT("wininet.dll"),
  43. TEXT("winsock.dll"),
  44. TEXT("advapi32.dll"),
  45. TEXT("shell32.dll"),
  46. TEXT("ole32.dll"),
  47. TEXT("advapi32.dll"),
  48. TEXT("oleaut32.dll"),
  49. TEXT("repcrt32.dll"),
  50. TEXT("")
  51. };
  52. typedef struct tagRECINFO {
  53. LPVOID lpvCallbackParameter;
  54. PFNGMIProgressCallback pfnCallback;
  55. ULONG MaxFiles; // limit the number of files
  56. ULONG FileCount; // count the files
  57. BOOL bNewStorageFile;
  58. } RECINFO, *PRECINFO;
  59. #define GRABMI_FLAGS_MASK 0xFFFF0000
  60. GMI_RESULT
  61. SdbpGrabMatchingInfoDir(
  62. HANDLE hStorageFile, // handle to a file we are writing
  63. PRECINFO pinfo, // pointer to extra info
  64. DWORD dwFilterAndFlags, // specifies the types of files to be added for matching
  65. LPCTSTR lpszRoot, // root directory for our search (pointer to the buffer)
  66. LPTSTR lpszOriginalExe, // pointer to the relative portion
  67. LPTSTR lpszRelative, // never null -- pointer to the relative portion
  68. int nLevel // current directory level for matching information
  69. )
  70. /*++
  71. Function Name:
  72. SdbpGrabMatchingInfoDir
  73. Function Description:
  74. This function traverses a directory and its subdirectories gathering matching
  75. information and writes it to the specified file.
  76. Return Value:
  77. BOOL: TRUE if Successful
  78. History:
  79. 04/26/2001 jdoherty Created
  80. SdbpGrabMatchingInfoDir pointer definition:
  81. c:\foo\bar\soap\relativepath\
  82. ^- lpszRoot ^- lpszRelative
  83. --*/
  84. {
  85. HRESULT hr;
  86. HANDLE hSearch = INVALID_HANDLE_VALUE; // handle for FindFileFirst and FindFileNext
  87. WIN32_FIND_DATA FindFileData; // structure containing file information
  88. LPTSTR lpchFilePart; // points to a file part in szSearchPath
  89. LPTSTR pchExt; // extension of current file
  90. BOOL bMiscFile;
  91. INT nch, nchBuffer, i;
  92. INT nLen;
  93. size_t cchRemaining;
  94. INT cbFileCounter = 0; // running count of misc files added to matching.
  95. #ifdef WIN32A_MODE
  96. int cchWideChar = 0; // The amount of WideChars converted.
  97. #endif
  98. size_t cchBufferRemaining; // The amount of space left in lpszRoot.
  99. DWORD dwBufferSize = GRABMI_BUFFER_SIZE; // initialize me with the alloc size for lpData
  100. LPTSTR lpData = NULL; // INITIALIZE ME WITH MALLOC!!!
  101. LPTSTR lpBuffer = NULL; // points within lpData
  102. LPWSTR lpUnicodeBuffer = NULL; // INITIALIZE ME WITH MALLOC!!!
  103. DWORD dwFilter = (dwFilterAndFlags & ~GRABMI_FLAGS_MASK);
  104. DWORD dwFilterFlags = (dwFilterAndFlags & GRABMI_FLAGS_MASK);
  105. PATTRINFO pAttrInfo; // attribute information structure
  106. DWORD dwBytesWritten = 0;
  107. DWORD dwAttrCount;
  108. GMI_RESULT Result = GMI_FAILED; // these two variables control return Result
  109. // is set as a return from callback or nested call
  110. //
  111. // Only want to grab information for the file(s) specified which
  112. // should reside in the root directory specified.
  113. //
  114. if (nLevel != 0 &&
  115. (dwFilter == GRABMI_FILTER_THISFILEONLY ||
  116. dwFilter == GRABMI_FILTER_SYSTEM)) {
  117. goto eh;
  118. }
  119. lpData = (LPTSTR)SdbAlloc(dwBufferSize * sizeof(TCHAR));
  120. if (lpData == NULL) {
  121. DBGPRINT((sdlError,
  122. "SdbpGrabMatchingInfoDir",
  123. "Unable to allocate %d bytes.\n",
  124. dwBufferSize * sizeof(TCHAR)));
  125. goto eh;
  126. }
  127. #ifdef WIN32A_MODE
  128. lpUnicodeBuffer = (LPWSTR)SdbAlloc(dwBufferSize * sizeof(WCHAR));
  129. if (lpUnicodeBuffer == NULL) {
  130. DBGPRINT((sdlError,
  131. "SdbpGrabMatchingInfoDir",
  132. "Unable to allocate %d bytes.\n",
  133. dwBufferSize * sizeof(WCHAR)));
  134. goto eh;
  135. }
  136. #endif // WIN32A_MODE
  137. lpchFilePart = lpszRelative + _tcslen(lpszRelative);
  138. //
  139. // The calculation below tells us how much is left in the buffer.
  140. //
  141. cchBufferRemaining = GRABMI_BUFFER_SIZE - (lpchFilePart - lpszRoot);
  142. assert(lpchFilePart == lpszRoot || *(lpchFilePart - 1) == TEXT('\\'));
  143. if (dwFilter == GRABMI_FILTER_THISFILEONLY) {
  144. StringCchCopy(lpchFilePart, cchBufferRemaining, lpszOriginalExe);
  145. } else {
  146. StringCchCopy(lpchFilePart, cchBufferRemaining, TEXT("*"));
  147. }
  148. //
  149. // Pass one. Grab all the file matching info we can.
  150. //
  151. hSearch = FindFirstFile(lpszRoot, &FindFileData);
  152. if (hSearch == INVALID_HANDLE_VALUE) {
  153. DBGPRINT((sdlError,
  154. "SdbpGrabMatchingInfoDir",
  155. "FindFirstFile Failed on [%s].\n",
  156. lpszRoot));
  157. goto eh;
  158. }
  159. //
  160. // Comment in hStorage file where the root of the matching information is
  161. //
  162. if (nLevel == 0 && pinfo->bNewStorageFile) {
  163. *lpchFilePart = TEXT('\0');
  164. hr = StringCchPrintf(lpData,
  165. dwBufferSize,
  166. TEXT("<?xml version=\"1.0\" encoding=\"UTF-16\"?>\r\n<DATABASE>\r\n"));
  167. if (FAILED(hr)) {
  168. //
  169. // lpData is too small to store information
  170. //
  171. DBGPRINT((sdlError, "SdbpGrabMatchingInforDir", "lpData is too small\n"));
  172. goto eh;
  173. }
  174. #ifndef WIN32A_MODE
  175. lpUnicodeBuffer = lpData;
  176. #else
  177. cchWideChar = MultiByteToWideChar(CP_ACP,
  178. 0,
  179. lpData,
  180. -1,
  181. lpUnicodeBuffer,
  182. dwBufferSize);
  183. if (cchWideChar == 0) {
  184. DBGPRINT((sdlError,
  185. "SdbpGrabMatchingInforDir",
  186. "lpUnicodeBuffer is too small for conversion\n"));
  187. goto eh;
  188. }
  189. #endif
  190. WriteFile(hStorageFile, UNICODE_MARKER, 2, &dwBytesWritten, NULL);
  191. WriteFile(hStorageFile,
  192. lpUnicodeBuffer,
  193. (DWORD)wcslen(lpUnicodeBuffer) * sizeof(WCHAR),
  194. &dwBytesWritten,
  195. NULL);
  196. }
  197. if (nLevel == 0) {
  198. if (dwFilter == GRABMI_FILTER_SYSTEM) {
  199. StringCchCopy(lpszOriginalExe, _tcslen(lpszOriginalExe) + 1, TEXT("SYSTEM INFO"));
  200. }
  201. hr = StringCchPrintfEx(lpData,
  202. dwBufferSize,
  203. NULL,
  204. &cchRemaining,
  205. 0,
  206. TEXT("<EXE NAME=\""));
  207. if (FAILED(hr)) {
  208. DBGPRINT((sdlError, "SdbpGrabMatchingInforDir", "lpData is to small\n"));
  209. goto eh;
  210. }
  211. nch = (int)dwBufferSize - (int)cchRemaining;
  212. if (!SdbpSanitizeXML(lpData + nch, dwBufferSize - nch, lpszOriginalExe)) {
  213. goto eh;
  214. }
  215. // if we are here, we need to attach a few more things
  216. nLen = (int)_tcslen(lpData);
  217. hr = StringCchPrintfEx(lpData + nLen,
  218. dwBufferSize - nLen,
  219. NULL,
  220. &cchRemaining,
  221. 0,
  222. TEXT("\" FILTER=\"%s\">\r\n"),
  223. g_szFilterDesc[dwFilter]);
  224. if (FAILED(hr)) {
  225. goto eh;
  226. }
  227. nch = dwBufferSize - nLen - (int)cchRemaining;
  228. nch += nLen;
  229. #ifndef WIN32A_MODE
  230. lpUnicodeBuffer = lpData;
  231. #else
  232. cchWideChar = MultiByteToWideChar(CP_ACP,
  233. 0,
  234. lpData,
  235. -1,
  236. lpUnicodeBuffer,
  237. dwBufferSize);
  238. if (cchWideChar == 0) {
  239. DBGPRINT((sdlError,
  240. "SdbpGrabMatchingInforDir",
  241. "lpUnicodeBuffer is too small for conversion\n"));
  242. goto eh;
  243. }
  244. #endif // WIN32A_MODE
  245. WriteFile(hStorageFile,
  246. lpUnicodeBuffer,
  247. (DWORD)wcslen(lpUnicodeBuffer) * sizeof(WCHAR),
  248. &dwBytesWritten,
  249. NULL);
  250. }
  251. switch (dwFilter) {
  252. case GRABMI_FILTER_PRIVACY:
  253. case GRABMI_FILTER_THISFILEONLY:
  254. case GRABMI_FILTER_SYSTEM:
  255. cbFileCounter = MAX_MISC_FILES_PER_LEVEL;
  256. break;
  257. }
  258. do {
  259. //
  260. // Check for directories including . and ..
  261. //
  262. if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  263. continue;
  264. }
  265. //
  266. // Make a relative path with our buffer.
  267. //
  268. StringCchCopy(lpchFilePart,
  269. cchBufferRemaining,
  270. FindFileData.cFileName);
  271. //
  272. // lpszRelative points to the relative path
  273. // lpszRoot points to the full path
  274. bMiscFile = FALSE;
  275. //
  276. // Check to see if there is version information for the specified file and whether
  277. // it is a .exe, .icd, ._MP, .msi, or .dll. If so print the information to the file.
  278. // Otherwise, add the information if cbFileCounter is less than MAX_MISC_FILES_PER_LEVEL.
  279. //
  280. pchExt = PathFindExtension(lpszRoot);
  281. switch (dwFilter) {
  282. case GRABMI_FILTER_NORMAL:
  283. case GRABMI_FILTER_PRIVACY:
  284. for (i = 0; *g_szGrabmiFilterNormal[i] != 0; i++) {
  285. if (_tcsicmp(pchExt, g_szGrabmiFilterNormal[i]) == 0) {
  286. break;
  287. }
  288. }
  289. bMiscFile = (*g_szGrabmiFilterNormal[i] == 0);
  290. break;
  291. case GRABMI_FILTER_SYSTEM:
  292. for (i = 0; *g_szGrabmiFilterSystem[i] != 0; i++) {
  293. if (_tcsicmp(FindFileData.cFileName, g_szGrabmiFilterSystem[i]) == 0) {
  294. break;
  295. }
  296. }
  297. bMiscFile = (*g_szGrabmiFilterSystem[i] == 0);
  298. break;
  299. case GRABMI_FILTER_THISFILEONLY:
  300. bMiscFile = _tcsicmp(FindFileData.cFileName, lpszOriginalExe);
  301. break;
  302. case GRABMI_FILTER_DRIVERS:
  303. bMiscFile = _tcsicmp(pchExt, TEXT(".sys"));
  304. break;
  305. default:
  306. break;
  307. }
  308. if (bMiscFile) {
  309. if (cbFileCounter < MAX_MISC_FILES_PER_LEVEL) {
  310. ++cbFileCounter;
  311. } else {
  312. continue;
  313. }
  314. }
  315. //
  316. // List relative data here.
  317. //
  318. lpBuffer = lpData;
  319. if (dwFilter == GRABMI_FILTER_DRIVERS) {
  320. hr = StringCchPrintfEx(lpBuffer,
  321. dwBufferSize,
  322. NULL,
  323. &cchRemaining,
  324. 0,
  325. TEXT(" <SYS NAME=\""));
  326. } else {
  327. hr = StringCchPrintfEx(lpBuffer,
  328. dwBufferSize,
  329. NULL,
  330. &cchRemaining,
  331. 0,
  332. TEXT(" <MATCHING_FILE NAME=\""));
  333. }
  334. if (FAILED(hr)) {
  335. goto eh;
  336. }
  337. nch = (int)dwBufferSize - (int)cchRemaining;
  338. if (!SdbpSanitizeXML(lpBuffer + nch, dwBufferSize - nch, lpszRelative)) {
  339. goto eh;
  340. }
  341. nLen = (int)_tcslen(lpBuffer);
  342. hr = StringCchPrintfEx(lpBuffer + nLen,
  343. dwBufferSize - nLen,
  344. NULL,
  345. &cchRemaining,
  346. 0,
  347. TEXT("\" "));
  348. if (FAILED(hr)) {
  349. goto eh;
  350. }
  351. nch = (int)dwBufferSize - nLen - (int)cchRemaining;
  352. //
  353. // Now we add the length -- and we're ready
  354. //
  355. nch += nLen;
  356. lpBuffer += nch;
  357. nchBuffer = nch; // amount of characters in lpBuffer already
  358. //
  359. // Call the attribute manager to get all the attributes for this file.
  360. //
  361. pAttrInfo = NULL;
  362. if (SdbGetFileAttributes(lpszRoot, &pAttrInfo, &dwAttrCount)) {
  363. //
  364. // Loop through all the attributes and add the ones that are available.
  365. //
  366. for (i = 0; (DWORD)i < dwAttrCount; ++i) {
  367. if (SdbFormatAttribute(&pAttrInfo[i], lpBuffer, dwBufferSize - nchBuffer)) {
  368. //
  369. // lpBuffer has XML for this attribute
  370. //
  371. // insert space
  372. nch = (int)_tcslen(lpBuffer) + 1; // for space
  373. if (dwFilter == GRABMI_FILTER_DRIVERS) {
  374. switch (pAttrInfo[i].tAttrID) {
  375. case TAG_BIN_PRODUCT_VERSION:
  376. case TAG_UPTO_BIN_PRODUCT_VERSION:
  377. case TAG_LINK_DATE:
  378. case TAG_UPTO_LINK_DATE:
  379. break;
  380. default:
  381. continue;
  382. }
  383. }
  384. if (nchBuffer + nch >= (int)dwBufferSize) {
  385. //
  386. // lpBuffer is not large enough to hold the information
  387. //
  388. DBGPRINT((sdlError,
  389. "SdbGetMatchingInfoDir",
  390. "lpBuffer is too small to handle attributes for %s.\n",
  391. lpszRelative));
  392. }
  393. StringCchCat(lpBuffer, dwBufferSize, TEXT(" "));
  394. lpBuffer += nch;
  395. nchBuffer += nch;
  396. }
  397. }
  398. }
  399. hr = StringCchPrintf(lpBuffer,
  400. dwBufferSize,
  401. TEXT("/>\r\n"));
  402. if (FAILED(hr)) {
  403. //
  404. // Buffer is too small.
  405. //
  406. DBGPRINT((sdlError,
  407. "SdbGrabMatchingInfoDir",
  408. "lpBuffer is too small to handle attributes for %s.\n",
  409. lpszRelative));
  410. continue;
  411. }
  412. //
  413. // Check to see if using unicode or not. If not, convert
  414. // to unicode.
  415. //
  416. #ifndef WIN32A_MODE
  417. lpUnicodeBuffer = lpData;
  418. #else
  419. cchWideChar = MultiByteToWideChar(CP_ACP,
  420. 0,
  421. lpData,
  422. -1,
  423. lpUnicodeBuffer,
  424. dwBufferSize);
  425. if (cchWideChar == 0) {
  426. //
  427. // Buffer is not large enough for conversion.
  428. //
  429. DBGPRINT((sdlError,
  430. "SdbpGrabMatchingInforDir",
  431. "lpUnicodeBuffer is not large enough for conversion\n"));
  432. goto eh;
  433. }
  434. #endif // WIN32A_MODE
  435. if (pinfo->pfnCallback) {
  436. if (!pinfo->pfnCallback(pinfo->lpvCallbackParameter,
  437. lpszRoot, // give straight name
  438. lpszRelative, // relative name
  439. pAttrInfo, // pointer to the attributes
  440. lpUnicodeBuffer)) { // xml output
  441. Result = GMI_CANCELLED;
  442. }
  443. }
  444. WriteFile(hStorageFile,
  445. lpUnicodeBuffer,
  446. (DWORD)wcslen(lpUnicodeBuffer) * sizeof(WCHAR),
  447. &dwBytesWritten,
  448. NULL);
  449. if (pAttrInfo) {
  450. SdbFreeFileAttributes(pAttrInfo);
  451. pAttrInfo = NULL; // make sure we do not free it twice
  452. }
  453. //
  454. // Check to see whether we have reached the file limit
  455. //
  456. if (pinfo->MaxFiles && ++pinfo->FileCount >= pinfo->MaxFiles && Result != GMI_CANCELLED) {
  457. Result = GMI_SUCCESS; // limit reached, grabmi cancelled
  458. nLevel = MAX_LEVELS_OF_DIRECTORIES; // this is so that we bail out
  459. break;
  460. }
  461. } while (FindNextFile(hSearch, &FindFileData) && (Result != GMI_CANCELLED));
  462. FindClose(hSearch);
  463. hSearch = INVALID_HANDLE_VALUE;
  464. if (Result == GMI_CANCELLED) {
  465. goto CloseTags;
  466. }
  467. if (dwFilter != GRABMI_FILTER_SYSTEM && dwFilter != GRABMI_FILTER_THISFILEONLY) {
  468. if (nLevel >= MAX_LEVELS_OF_DIRECTORIES || (dwFilterFlags & GRABMI_FILTER_NORECURSE)) {
  469. Result = GMI_SUCCESS; // not a failure, just a limiting case
  470. goto eh; // done
  471. }
  472. //
  473. // Replace the filename in szSearchFile with "*" -- hack!
  474. //
  475. StringCchCopy(lpchFilePart, cchBufferRemaining, TEXT("*"));
  476. hSearch = FindFirstFile(lpszRoot, &FindFileData);
  477. if (INVALID_HANDLE_VALUE == hSearch) {
  478. //
  479. // lpszRoot does not contain any matching files
  480. //
  481. DBGPRINT((sdlError,
  482. "SdbGrabMatchingInfoDir",
  483. "%s contains no matching files!\n",
  484. lpszRoot));
  485. goto eh;
  486. }
  487. //
  488. // Now go through the subdirectories and grab that information.
  489. //
  490. do {
  491. if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  492. continue;
  493. }
  494. if ((_tcscmp(FindFileData.cFileName, TEXT(".")) == 0) ||
  495. (_tcscmp( FindFileData.cFileName, TEXT("..")) == 0)) {
  496. continue;
  497. }
  498. //
  499. // Form relative path here by copying lpszRelative and appending cFileName and '\\'
  500. //
  501. StringCchCopy(lpchFilePart, cchBufferRemaining, FindFileData.cFileName);
  502. StringCchCat(lpchFilePart, cchBufferRemaining, TEXT("\\"));
  503. //
  504. // Recursive call. Check return result for having been cancelled !!!
  505. //
  506. Result = SdbpGrabMatchingInfoDir(hStorageFile,
  507. pinfo,
  508. dwFilterAndFlags,
  509. lpszRoot,
  510. NULL,
  511. lpszRelative,
  512. nLevel + 1);
  513. if (Result == GMI_CANCELLED) {
  514. //
  515. // We are cancelled. Write out a valid database code to close
  516. // this if we have the option set.
  517. //
  518. break;
  519. }
  520. } while (FindNextFile(hSearch, &FindFileData));
  521. }
  522. CloseTags:
  523. //
  524. // This is where we close the tags if instructed to do so.
  525. //
  526. if (nLevel == 0) {
  527. StringCchCopyW(lpUnicodeBuffer, dwBufferSize, L"</EXE>\r\n");
  528. if (!(dwFilterFlags & GRABMI_FILTER_NOCLOSE)) {
  529. StringCchCatW(lpUnicodeBuffer, dwBufferSize, L"</DATABASE>\r\n");
  530. }
  531. WriteFile(hStorageFile,
  532. lpUnicodeBuffer,
  533. (DWORD)wcslen(lpUnicodeBuffer) * sizeof(WCHAR),
  534. &dwBytesWritten,
  535. NULL);
  536. }
  537. //
  538. // Check how we got here -- was it via the cancel route ?
  539. //
  540. if (Result == GMI_CANCELLED) {
  541. goto eh;
  542. }
  543. //
  544. // Information gathered successfully.
  545. //
  546. Result = GMI_SUCCESS;
  547. eh:
  548. if (INVALID_HANDLE_VALUE != hSearch) {
  549. FindClose(hSearch);
  550. }
  551. if (lpData != NULL) {
  552. SdbFree(lpData);
  553. }
  554. #ifdef WIN32A_MODE
  555. if (lpUnicodeBuffer != NULL) {
  556. SdbFree(lpUnicodeBuffer);
  557. }
  558. #endif // WIN32A_MODE
  559. return Result;
  560. }
  561. BOOL
  562. SDBAPI
  563. SdbGrabMatchingInfo(
  564. IN LPCTSTR pszMatchingPath,
  565. IN DWORD dwFilter,
  566. IN LPCTSTR pszFile
  567. )
  568. /*++
  569. Routine Description:
  570. Routine that stubs to SdbGrabMatchingInfoEx.
  571. Arguments:
  572. [IN] pszMatchingPath - Path where we being gathering information.
  573. [IN] dwFilterAndFlags - Specifies filters that control what files
  574. we collect information about.
  575. [IN] pszFile - Full path to the file where matching information
  576. will be stored.
  577. Return Value:
  578. On success, returns TRUE. On failure, returns FALSE.
  579. --*/
  580. {
  581. return SdbGrabMatchingInfoEx(pszMatchingPath,
  582. dwFilter,
  583. pszFile,
  584. NULL,
  585. NULL) == GMI_SUCCESS;
  586. }
  587. GMI_RESULT
  588. SDBAPI
  589. SdbGrabMatchingInfoEx(
  590. IN LPCTSTR szMatchingPath,
  591. IN DWORD dwFilterAndFlags,
  592. IN LPCTSTR szFile,
  593. IN PFNGMIProgressCallback pfnCallback OPTIONAL,
  594. IN LPVOID lpvCallbackParameter OPTIONAL
  595. )
  596. /*++
  597. Routine Description:
  598. Routine that performs some necessary work prior to calling the main
  599. routine, SdbpGrabMatchingInfoDir.
  600. Arguments:
  601. [IN] szMatchingPath - Path where we being gathering information.
  602. [IN] dwFilterAndFlags - Specifies filters and flags that control
  603. what files we collect information about.
  604. [IN] szFile - Full path to the file where matching information
  605. will be stored.
  606. [IN] pfnCallback - Optional pointer a user-supplied callback function.
  607. [IN] lpvCallbackParameter - Optional parameter to pass to the callback.
  608. Return Value:
  609. On success, returns GMI_SUCCESS. On failure, returns GMI_FAILED.
  610. --*/
  611. {
  612. HANDLE hStorageFile = INVALID_HANDLE_VALUE;
  613. LPTSTR lpRootDirectory = NULL;
  614. LPTSTR pchBackslash;
  615. LPTSTR lpRelative;
  616. TCHAR szOriginalExe[MAX_PATH] = {TEXT("Exe Not Specified")};
  617. int nDirLen, nLevel = 0;
  618. UINT cchSize;
  619. DWORD dwAttributes;
  620. GMI_RESULT Result = GMI_FAILED;
  621. DWORD dwFilter = (dwFilterAndFlags & ~GRABMI_FLAGS_MASK);
  622. DWORD dwFilterFlags = (dwFilterAndFlags & GRABMI_FLAGS_MASK);
  623. RECINFO info;
  624. //
  625. // Check to see if dwFilter is a know value
  626. //
  627. if (dwFilter != GRABMI_FILTER_NORMAL &&
  628. dwFilter != GRABMI_FILTER_PRIVACY &&
  629. dwFilter != GRABMI_FILTER_DRIVERS &&
  630. dwFilter != GRABMI_FILTER_VERBOSE &&
  631. dwFilter != GRABMI_FILTER_SYSTEM &&
  632. dwFilter != GRABMI_FILTER_THISFILEONLY) {
  633. //
  634. // Unknown filter specified.
  635. //
  636. DBGPRINT((sdlError,
  637. "SdbGrabMatchingInfo",
  638. "dwFilter is not a recognized filter.\n"));
  639. goto eh;
  640. }
  641. RtlZeroMemory(&info, sizeof(info));
  642. info.pfnCallback = pfnCallback;
  643. info.lpvCallbackParameter = lpvCallbackParameter;
  644. info.MaxFiles = (dwFilterFlags & GRABMI_FILTER_LIMITFILES) ? GRABMI_IMPOSED_FILE_LIMIT : 0;
  645. info.FileCount = 0;
  646. info.bNewStorageFile = TRUE;
  647. lpRootDirectory = (LPTSTR)SdbAlloc(GRABMI_BUFFER_SIZE * sizeof(TCHAR));
  648. if (lpRootDirectory == NULL) {
  649. DBGPRINT((sdlError,
  650. "SdbGrabMatchingInfo",
  651. "Unable to allocate memory for lpRootDirectory."));
  652. goto eh;
  653. }
  654. if (dwFilter == GRABMI_FILTER_SYSTEM) {
  655. cchSize = GetSystemDirectory(lpRootDirectory, MAX_PATH);
  656. if (cchSize > MAX_PATH || cchSize == 0) {
  657. goto eh;
  658. }
  659. StringCchCat(lpRootDirectory, GRABMI_BUFFER_SIZE, TEXT("\\"));
  660. } else {
  661. dwAttributes = GetFileAttributes(szMatchingPath);
  662. if (dwAttributes == (DWORD)-1) {
  663. DBGPRINT((sdlError,
  664. "SdbGrabMatchingInfo",
  665. "GetFileAttributes failed or %s is not a valid path",
  666. szMatchingPath));
  667. goto eh;
  668. }
  669. StringCchCopy(lpRootDirectory, GRABMI_BUFFER_SIZE, szMatchingPath);
  670. nDirLen = (int)_tcslen(lpRootDirectory);
  671. //
  672. // See if location specified exists and if so determine
  673. // whether its a file or directory
  674. //
  675. if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  676. //
  677. // Is this a directory ?
  678. //
  679. if (nDirLen > 0 && lpRootDirectory[nDirLen-1] != TEXT('\\')) {
  680. StringCchCat(lpRootDirectory, GRABMI_BUFFER_SIZE, TEXT("\\"));
  681. }
  682. } else {
  683. //
  684. // A path containing a file name was passed as szMatchingPath.
  685. // Determine what the containing dir is.
  686. //
  687. pchBackslash = _tcsrchr(lpRootDirectory, TEXT('\\'));
  688. if (NULL == pchBackslash) {
  689. StringCchCopy(szOriginalExe, CHARCOUNT(szOriginalExe), lpRootDirectory);
  690. GetCurrentDirectory (MAX_PATH*16, lpRootDirectory);
  691. StringCchCat(lpRootDirectory, GRABMI_BUFFER_SIZE, TEXT("\\"));
  692. } else {
  693. pchBackslash = CharNext(pchBackslash);
  694. StringCchCopy(szOriginalExe, CHARCOUNT(szOriginalExe), pchBackslash);
  695. *pchBackslash = TEXT('\0');
  696. }
  697. }
  698. }
  699. lpRelative = lpRootDirectory + _tcslen(lpRootDirectory);
  700. //
  701. // Check to see if szOriginalExe is not NULL if
  702. // GRABMI_FILTER_THISFILEONLY was selected.
  703. //
  704. if (dwFilter == GRABMI_FILTER_THISFILEONLY && szOriginalExe == '\0' ) {
  705. DBGPRINT((sdlError,
  706. "SdbGrabMatchingInfo",
  707. "GRABMI_FILTER_THISFILEONLY specified but passed in a directory: %s.",
  708. lpRootDirectory));
  709. goto eh;
  710. } else if (dwFilterFlags & GRABMI_FILTER_APPEND) {
  711. //
  712. // Open the file where the information will be stored.
  713. //
  714. hStorageFile = CreateFile(szFile,
  715. GENERIC_WRITE,
  716. 0,
  717. NULL,
  718. OPEN_ALWAYS,
  719. FILE_ATTRIBUTE_NORMAL,
  720. NULL);
  721. if (ERROR_ALREADY_EXISTS == GetLastError()) {
  722. SetFilePointer (hStorageFile, 0, NULL, FILE_END);
  723. info.bNewStorageFile = FALSE;
  724. }
  725. } else {
  726. //
  727. // Open the file where the information will be stored.
  728. //
  729. hStorageFile = CreateFile(szFile,
  730. GENERIC_WRITE,
  731. 0,
  732. NULL,
  733. CREATE_ALWAYS,
  734. FILE_ATTRIBUTE_NORMAL,
  735. NULL);
  736. }
  737. if (hStorageFile == INVALID_HANDLE_VALUE) {
  738. DBGPRINT((sdlError, "SdbGrabMatchingInfo", "Unable to open the storage file."));
  739. goto eh;
  740. }
  741. //
  742. // Call the API which does the bulk of the work
  743. //
  744. Result = SdbpGrabMatchingInfoDir(hStorageFile,
  745. &info,
  746. dwFilterAndFlags,
  747. lpRootDirectory,
  748. szOriginalExe,
  749. lpRelative,
  750. nLevel);
  751. eh:
  752. if (hStorageFile != INVALID_HANDLE_VALUE) {
  753. CloseHandle(hStorageFile);
  754. }
  755. if (lpRootDirectory) {
  756. SdbFree(lpRootDirectory);
  757. }
  758. return Result;
  759. }