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.

836 lines
25 KiB

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