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.

1344 lines
34 KiB

  1. #include <assert.h>
  2. #include "symutil.h"
  3. #define PDB_LIBRARY
  4. #include "pdb.h"
  5. #include "dbghelp.h"
  6. #include "cvinfo.h"
  7. #include "cvexefmt.h"
  8. #include "exe_vxd.h"
  9. #include "share.h"
  10. #include "winbase.h"
  11. #include "symsrv.h"
  12. // Stuff for Checking symbols
  13. // Typedefs
  14. typedef struct _NB10I {
  15. DWORD dwSig; // NB10
  16. DWORD dwOffset; // offset, always 0
  17. SIG sig;
  18. AGE age;
  19. char szPDB[_MAX_PATH];
  20. }NB10I, *PNB10I;
  21. typedef struct _FILE_INFO {
  22. DWORD TimeDateStamp;
  23. DWORD CheckSum;
  24. TCHAR szName[MAX_PATH];
  25. } FILE_INFO, *PFILE_INFO;
  26. PIMAGE_SEPARATE_DEBUG_HEADER
  27. MapDbgHeader (
  28. LPTSTR szFileName,
  29. PHANDLE phFile
  30. );
  31. BOOL
  32. UnmapFile(
  33. LPCVOID phFileMap,
  34. HANDLE hFile
  35. );
  36. BOOL
  37. AddToReferenceCount(
  38. LPTSTR szDir, // Directory where refs.ptr belongs
  39. LPTSTR szFileName, // Full path and name of the file that is referenced.
  40. LPTSTR szPtrOrFile // Was a file or a pointer written
  41. );
  42. BOOL
  43. StoreFile(
  44. LPTSTR szDestDir,
  45. LPTSTR szFileName,
  46. LPTSTR szString2,
  47. LPTSTR szPtrFileName
  48. );
  49. BOOL
  50. StoreFilePtr(
  51. LPTSTR szDestDir,
  52. LPTSTR szString2,
  53. LPTSTR szPtrFileName
  54. );
  55. BOOL
  56. GetString2(
  57. LPTSTR szFileName,
  58. GUID *guid,
  59. DWORD dwNum1,
  60. DWORD dwNum2,
  61. LPTSTR szDirName
  62. );
  63. PIMAGE_DOS_HEADER
  64. MapFileHeader (
  65. LPTSTR szFileName,
  66. PHANDLE phFile
  67. );
  68. PIMAGE_NT_HEADERS
  69. GetNtHeader (
  70. PIMAGE_DOS_HEADER pDosHeader,
  71. HANDLE hDosFile
  72. );
  73. BOOL
  74. ResourceOnlyDll(
  75. PVOID pImageBase,
  76. BOOLEAN bMappedAsImage
  77. );
  78. PIMAGE_SEPARATE_DEBUG_HEADER
  79. MapDbgHeader (
  80. LPTSTR szFileName,
  81. PHANDLE phFile
  82. )
  83. {
  84. HANDLE hFileMap;
  85. PIMAGE_SEPARATE_DEBUG_HEADER pDbgHeader;
  86. (*phFile) = CreateFile( (LPCTSTR) szFileName,
  87. GENERIC_READ,
  88. FILE_SHARE_READ,
  89. NULL,
  90. OPEN_EXISTING,
  91. FILE_ATTRIBUTE_NORMAL,
  92. NULL
  93. );
  94. if (*phFile == INVALID_HANDLE_VALUE) {
  95. CloseHandle(*phFile);
  96. return(NULL);
  97. }
  98. hFileMap = CreateFileMapping( *phFile,
  99. NULL,
  100. PAGE_READONLY,
  101. 0,
  102. 0,
  103. NULL
  104. );
  105. if ( !hFileMap) {
  106. CloseHandle(*phFile);
  107. CloseHandle(hFileMap);
  108. return(NULL);
  109. }
  110. pDbgHeader = (PIMAGE_SEPARATE_DEBUG_HEADER) MapViewOfFile( hFileMap,
  111. FILE_MAP_READ,
  112. 0, // high
  113. 0, // low
  114. 0 // whole file
  115. );
  116. CloseHandle(hFileMap);
  117. if ( !pDbgHeader ) {
  118. UnmapFile((LPCVOID)pDbgHeader, *phFile);
  119. return(NULL);
  120. }
  121. return (pDbgHeader);
  122. }
  123. BOOL
  124. UnmapFile( LPCVOID phFileMap, HANDLE hFile )
  125. {
  126. if ((PHANDLE)phFileMap != NULL) {
  127. UnmapViewOfFile( phFileMap );
  128. }
  129. if (hFile) {
  130. CloseHandle(hFile);
  131. }
  132. return TRUE;
  133. }
  134. BOOL
  135. StoreDbg(
  136. LPTSTR szDestDir,
  137. LPTSTR szFileName,
  138. LPTSTR szPtrFileName
  139. )
  140. /* ++
  141. Routine Description:
  142. Stores this file as "szDestDir\szFileName\Checksum"
  143. Return Value:
  144. TRUE - file was stored successfully
  145. FALSE - file was not stored successfully
  146. -- */
  147. {
  148. PIMAGE_SEPARATE_DEBUG_HEADER pDbgHeader;
  149. HANDLE hFile;
  150. BOOL rc;
  151. TCHAR szString[_MAX_PATH];
  152. ZeroMemory(szString, _MAX_PATH * sizeof(TCHAR) );
  153. pDbgHeader = MapDbgHeader ( szFileName, &hFile );
  154. if (pDbgHeader == NULL) {
  155. printf("ERROR: StoreDbg(), %s was not opened successfully\n",szFileName);
  156. UnmapFile((LPCVOID)pDbgHeader, hFile);
  157. return FALSE;
  158. }
  159. GetString2( szFileName,
  160. NULL,
  161. (DWORD) pDbgHeader->TimeDateStamp,
  162. (DWORD) pDbgHeader->SizeOfImage,
  163. szString
  164. );
  165. rc = StoreFile( szDestDir,
  166. szFileName,
  167. szString,
  168. szPtrFileName );
  169. UnmapFile((LPCVOID)pDbgHeader, hFile);
  170. return rc;
  171. }
  172. BOOL
  173. StorePdb(
  174. LPTSTR szDestDir,
  175. LPTSTR szFileName,
  176. LPTSTR szPtrFileName
  177. )
  178. /*++
  179. Routine Description:
  180. Validates the PDB
  181. Return Value:
  182. TRUE PDB validates
  183. FALSE PDB doesn't validate
  184. --*/
  185. {
  186. BOOL rc;
  187. BOOL valid;
  188. PDB *pdb;
  189. EC ec;
  190. char szError[cbErrMax] = _T("");
  191. SIG sig;
  192. AGE age;
  193. SIG70 sig70;
  194. TCHAR szString[_MAX_PATH];
  195. DBI *pdbi;
  196. ZeroMemory( szString, _MAX_PATH * sizeof(TCHAR) );
  197. ZeroMemory( &sig70, sizeof(SIG70) );
  198. pdb=NULL;
  199. __try
  200. {
  201. valid = PDBOpen( szFileName,
  202. _T("r"),
  203. 0,
  204. &ec,
  205. szError,
  206. &pdb
  207. );
  208. }
  209. __except( EXCEPTION_EXECUTE_HANDLER )
  210. {
  211. valid=FALSE;
  212. }
  213. if ( !valid ) {
  214. return FALSE;
  215. }
  216. // The DBI age is created when the exe is created.
  217. // This age will not change if an operation is performed
  218. // on the PDB that increments its PDB age.
  219. if ( !PDBOpenDBI(pdb, pdbRead, NULL, &pdbi) ) {
  220. // OpenDBI failed
  221. DBIClose(pdbi);
  222. return FALSE;
  223. }
  224. sig = PDBQuerySignature(pdb);
  225. age = pdbi->QueryAge();
  226. rc = PDBQuerySignature2(pdb, &sig70);
  227. DBIClose(pdbi);
  228. PDBClose(pdb);
  229. if (rc) {
  230. GetString2( szFileName,
  231. &sig70,
  232. (DWORD) sig,
  233. (DWORD) age,
  234. szString );
  235. } else {
  236. GetString2( szFileName,
  237. NULL,
  238. (DWORD) sig,
  239. (DWORD) age,
  240. szString );
  241. }
  242. rc = StoreFile( szDestDir,
  243. szFileName,
  244. szString,
  245. szPtrFileName
  246. );
  247. return (rc);
  248. }
  249. P_LIST
  250. GetList(
  251. LPTSTR szFileName
  252. )
  253. {
  254. /* GetList gets the list and keeps the original file name which could
  255. * have included the path to the file
  256. * Note, it can be merged with GetExcludeList. I first created it for
  257. * use in creating the symbols CD, and didn't want to risk entering a
  258. * bug into symchk
  259. */
  260. P_LIST pList;
  261. FILE *fFile;
  262. TCHAR szCurFile[_MAX_FNAME+1], *c;
  263. TCHAR fname[_MAX_FNAME+1], ext[_MAX_EXT+1];
  264. DWORD i;
  265. LPTSTR szEndName;
  266. ULONG RetVal = FALSE;
  267. pList = (P_LIST)malloc(sizeof(LIST));
  268. if (pList)
  269. {
  270. pList->dNumFiles = 0;
  271. if ( (fFile = _tfopen(szFileName,_T("r") )) == NULL )
  272. {
  273. // printf( "Cannot open the exclude file %s\n",szFileName );
  274. }
  275. else
  276. {
  277. while ( _fgetts(szCurFile,_MAX_FNAME,fFile) ) {
  278. if ( szCurFile[0] == ';' ) continue;
  279. (pList->dNumFiles)++;
  280. }
  281. // Go back to the beginning of the file
  282. fseek(fFile,0,0);
  283. pList->List = (LIST_ELEM*)malloc( sizeof(LIST_ELEM) *
  284. (pList->dNumFiles));
  285. if (pList->List)
  286. {
  287. i = 0;
  288. while ( i < pList->dNumFiles )
  289. {
  290. memset(szCurFile,'\0',sizeof(TCHAR) * (_MAX_FNAME+1) );
  291. _fgetts(szCurFile,_MAX_FNAME,fFile);
  292. // Replace the \n with \0
  293. c = NULL;
  294. c = _tcschr(szCurFile, '\n');
  295. if ( c != NULL) *c='\0';
  296. if ( szCurFile[0] == ';' ) continue;
  297. if ( _tcslen(szCurFile) > _MAX_FNAME ) {
  298. printf("File %s has a string that is too large\n",szFileName);
  299. break;
  300. }
  301. // Allow for spaces and a ; after the file name
  302. // Move the '\0' back until it has erased the ';' and any
  303. // tabs and spaces that might come before it
  304. szEndName = _tcschr(szCurFile, ';');
  305. if (szEndName != NULL ) {
  306. while ( *szEndName == ';' || *szEndName == ' '
  307. || *szEndName == '\t' ){
  308. *szEndName = '\0';
  309. if ( szEndName > szCurFile ) szEndName--;
  310. }
  311. }
  312. _tcscpy(pList->List[i].Path,szCurFile);
  313. _tsplitpath(szCurFile,NULL,NULL,fname,ext);
  314. _tcscpy(pList->List[i].FName,fname);
  315. _tcscat(pList->List[i].FName,ext);
  316. i++;
  317. }
  318. if (i == pList->dNumFiles)
  319. {
  320. RetVal = TRUE;
  321. }
  322. else
  323. {
  324. free(pList->List);
  325. }
  326. }
  327. fclose(fFile);
  328. }
  329. if (!RetVal)
  330. {
  331. free(pList);
  332. pList = NULL;
  333. }
  334. }
  335. // Sort the List
  336. // qsort( (void*)pList->List, (size_t)pList->dNumFiles,
  337. // (size_t)sizeof(LIST_ELEM), SymComp2 );
  338. return (pList);
  339. }
  340. BOOL
  341. GetString2(
  342. LPTSTR szFileName,
  343. GUID *guid,
  344. DWORD dwNum1,
  345. DWORD dwNum2,
  346. LPTSTR szString
  347. )
  348. {
  349. TCHAR szFileNameOnly[_MAX_FNAME + _MAX_EXT];
  350. TCHAR szExt[_MAX_EXT];
  351. _tcscpy( szString, _T("") );
  352. _tsplitpath(szFileName, NULL, NULL, szFileNameOnly, szExt);
  353. _tcscat(szString, szFileNameOnly);
  354. _tcscat(szString, szExt);
  355. EnsureTrailingBackslash(szString);
  356. if (guid != NULL) {
  357. AppendHexStringWithGUID( szString, guid );
  358. } else {
  359. AppendHexStringWithDWORD( szString, dwNum1 );
  360. }
  361. AppendHexStringWithDWORD( szString, dwNum2 );
  362. return (TRUE);
  363. }
  364. BOOL
  365. StoreFile(
  366. LPTSTR szDestDir,
  367. LPTSTR szFileName,
  368. LPTSTR szString2,
  369. LPTSTR szPtrFileName
  370. )
  371. {
  372. TCHAR szPathName[_MAX_PATH + _MAX_FNAME + 2];
  373. TCHAR szFileNameOnly[_MAX_FNAME + _MAX_EXT];
  374. TCHAR szExt[_MAX_EXT];
  375. TCHAR szBuf[_MAX_PATH * 3];
  376. TCHAR szRefsDir[_MAX_PATH * 3];
  377. TCHAR szFileNameComp[_MAX_PATH * 3];
  378. TCHAR szPathNameComp[_MAX_PATH + _MAX_FNAME + 2];
  379. DWORD dwNumBytesToWrite;
  380. DWORD dwNumBytesWritten;
  381. BOOL rc;
  382. DWORD dwSizeDestDir;
  383. DWORD dwFileSizeLow;
  384. DWORD dwFileSizeHigh;
  385. DWORD dw;
  386. // If ADD_DONT_STORE, then write the function parameters
  387. // to a file so we can call this function exactly when
  388. // running ADD_STORE_FROM_FILE
  389. if ( StoreFlags == ADD_DONT_STORE ) {
  390. // Don't need to store szDestDir because it will
  391. // be given when adding from file
  392. dwFileSizeLow = GetFileSize(hTransFile, &dwFileSizeHigh);
  393. _stprintf(szBuf,"%s,%s,",
  394. szFileName+pArgs->ShareNameLength,
  395. szString2);
  396. if ( szPtrFileName != NULL ) {
  397. _tcscat(szBuf, szPtrFileName+pArgs->ShareNameLength);
  398. }
  399. _tcscat(szBuf, _T(",\r\n") );
  400. dwNumBytesToWrite = _tcslen(szBuf) * sizeof(TCHAR);
  401. WriteFile( hTransFile,
  402. (LPCVOID)szBuf,
  403. dwNumBytesToWrite,
  404. &dwNumBytesWritten,
  405. NULL
  406. );
  407. if ( dwNumBytesToWrite != dwNumBytesWritten ) {
  408. printf( "FAILED to write to %s, with GetLastError = %d\n",
  409. szPathName,
  410. GetLastError()
  411. );
  412. return (FALSE);
  413. } else {
  414. return (TRUE);
  415. }
  416. }
  417. if ( szPtrFileName != NULL ) {
  418. rc = StoreFilePtr ( szDestDir,
  419. szString2,
  420. szPtrFileName
  421. );
  422. return (rc);
  423. }
  424. _tsplitpath(szFileName, NULL, NULL, szFileNameOnly, szExt);
  425. _tcscat(szFileNameOnly, szExt);
  426. _stprintf( szPathName, "%s%s",
  427. szDestDir,
  428. szString2 );
  429. // Save a copy for writing refs.ptr
  430. _tcscpy(szRefsDir, szPathName);
  431. // Create the directory to store the file if its not already there
  432. EnsureTrailingBackslash(szPathName);
  433. if ( !MakeSureDirectoryPathExists( szPathName ) ) {
  434. printf("Could not create %s\n", szPathName);
  435. return (FALSE);
  436. }
  437. _tcscat( szPathName, szFileNameOnly );
  438. // Enter this into the log, skipping the Destination directory
  439. // at the beginning of szPathName
  440. //
  441. dwSizeDestDir = _tcslen(szDestDir);
  442. dwFileSizeLow = GetFileSize(hTransFile, &dwFileSizeHigh);
  443. if ( dwFileSizeLow == 0 && dwFileSizeHigh == 0 ) {
  444. _stprintf( szBuf,"%s,%s", szRefsDir+dwSizeDestDir, szFileName );
  445. } else {
  446. _stprintf( szBuf,"\n%s,%s", szRefsDir+dwSizeDestDir, szFileName );
  447. }
  448. dwNumBytesToWrite = _tcslen(szBuf) * sizeof(TCHAR);
  449. WriteFile( hTransFile,
  450. (LPCVOID)szBuf,
  451. dwNumBytesToWrite,
  452. &dwNumBytesWritten,
  453. NULL
  454. );
  455. if ( dwNumBytesToWrite != dwNumBytesWritten ) {
  456. printf( "FAILED to write to %s, with GetLastError = %d\n",
  457. szPathName,
  458. GetLastError()
  459. );
  460. return (FALSE);
  461. }
  462. rc = MyCopyFile(szFileName, szPathName);
  463. if (!rc) return (FALSE);
  464. EnsureTrailingBackslash(szRefsDir);
  465. rc = AddToReferenceCount(szRefsDir, szFileName, _T("file") );
  466. return (rc);
  467. }
  468. BOOL
  469. StoreFilePtr(
  470. LPTSTR szDestDir,
  471. LPTSTR szString2,
  472. LPTSTR szPtrFileName
  473. )
  474. {
  475. /*
  476. szPathName The full path with "file.ptr" appended to it.
  477. This is the path for storing file.ptr
  478. */
  479. TCHAR szPathName[_MAX_PATH + _MAX_FNAME + 2];
  480. TCHAR szRefsDir[_MAX_PATH * 3];
  481. HANDLE hFile;
  482. DWORD dwNumBytesToWrite;
  483. DWORD dwNumBytesWritten;
  484. DWORD rc;
  485. DWORD dwSizeDestDir;
  486. DWORD dwFileSizeLow;
  487. DWORD dwFileSizeHigh;
  488. DWORD timeout;
  489. DWORD First;
  490. WIN32_FIND_DATA FindFileData;
  491. _stprintf( szPathName, "%s%s",
  492. szDestDir,
  493. szString2 );
  494. // Save a copy for creating refs.ptr
  495. _tcscpy(szRefsDir, szPathName);
  496. EnsureTrailingBackslash( szPathName );
  497. _stprintf( szPathName, "%s%s", szPathName, _T("file.ptr") );
  498. if ( !MakeSureDirectoryPathExists( szPathName ) ) {
  499. printf("Could not create %s\n", szPathName);
  500. return (FALSE);
  501. }
  502. // Put this file into file.ptr. If file.ptr is already there, then
  503. // replace the contents with this pointer
  504. // Wait for the file to become available
  505. timeout=0;
  506. First = 1;
  507. do {
  508. hFile = CreateFile( szPathName,
  509. GENERIC_READ | GENERIC_WRITE,
  510. 0,
  511. NULL,
  512. CREATE_ALWAYS,
  513. FILE_ATTRIBUTE_NORMAL,
  514. NULL );
  515. // Only print this message the first time the loop
  516. // is repeated.
  517. if ( First && hFile == INVALID_HANDLE_VALUE ) {
  518. First = 0;
  519. printf("Failed to open %s for writing, with GetLastError = %d\n",
  520. szPathName,
  521. GetLastError()
  522. );
  523. }
  524. // Make sure that delete didn't come through and remove the directory
  525. if ( !MakeSureDirectoryPathExists( szPathName ) ) {
  526. printf("Could not create %s\n", szPathName);
  527. return (FALSE);
  528. }
  529. if ( hFile == INVALID_HANDLE_VALUE ) {
  530. SleepEx(1000,0);
  531. timeout++;
  532. }
  533. } while ( hFile == INVALID_HANDLE_VALUE && timeout <= 50 ) ;
  534. if ( timeout > 50 ) {
  535. printf("Timed out -- could not open %s\n", szPathName);
  536. return (1);
  537. }
  538. dwNumBytesToWrite = _tcslen(szPtrFileName) * sizeof(TCHAR);
  539. WriteFile( hFile,
  540. (LPCVOID)szPtrFileName,
  541. dwNumBytesToWrite,
  542. &dwNumBytesWritten,
  543. NULL
  544. );
  545. if ( dwNumBytesToWrite != dwNumBytesWritten ) {
  546. printf( "FAILED to write %s, with GetLastError = %d\n",
  547. szPathName,
  548. GetLastError()
  549. );
  550. CloseHandle(hFile);
  551. return (FALSE);
  552. }
  553. // Enter this into the log, skipping the first part that is the root
  554. // of the symbols server
  555. //
  556. dwSizeDestDir = _tcslen(szDestDir);
  557. dwFileSizeLow = GetFileSize(hTransFile, &dwFileSizeHigh);
  558. if ( dwFileSizeLow == 0 && dwFileSizeHigh == 0 ) {
  559. _stprintf( szPathName, "%s,%s", szRefsDir + dwSizeDestDir, szPtrFileName);
  560. } else {
  561. _stprintf( szPathName, "\n%s,%s", szRefsDir + dwSizeDestDir, szPtrFileName);
  562. }
  563. dwNumBytesToWrite = _tcslen(szPathName) * sizeof(TCHAR);
  564. WriteFile( hTransFile,
  565. (LPCVOID)(szPathName),
  566. dwNumBytesToWrite,
  567. &dwNumBytesWritten,
  568. NULL
  569. );
  570. if ( dwNumBytesToWrite != dwNumBytesWritten ) {
  571. printf( "FAILED to write to %s, with GetLastError = %d\n",
  572. szPathName,
  573. GetLastError()
  574. );
  575. return (FALSE);
  576. }
  577. // File.ptr was created successfully, now, add the contents of
  578. // szPathName to refs.ptr
  579. EnsureTrailingBackslash(szRefsDir);
  580. rc = AddToReferenceCount( szRefsDir, szPtrFileName, "ptr");
  581. if (!rc) {
  582. printf("AddToReferenceCount failed for %s,ptr,%s",
  583. szDestDir, szPtrFileName);
  584. }
  585. // If you close this handle sooner, there will be problems if add and
  586. // delete are running at the same time. The delete process can come in
  587. // and delete the directory before AddToReferenceCount gets called.
  588. // Then the CreateFile in there fails.
  589. CloseHandle(hFile);
  590. return (rc);
  591. }
  592. DWORD
  593. StoreFromFile(
  594. FILE *pStoreFromFile,
  595. LPTSTR szDestDir,
  596. PFILE_COUNTS pFileCounts
  597. ) {
  598. LPTSTR szFileName;
  599. DWORD dw1,dw2;
  600. LPTSTR szPtrFileName;
  601. LPTSTR szBuf;
  602. TCHAR szFullFileName[_MAX_PATH*2];
  603. TCHAR szFullPtrFileName[_MAX_PATH*2];
  604. TCHAR szString[_MAX_PATH];
  605. LPTSTR token2,token3,token4;
  606. ULONG i,comma_count,token_start;
  607. BOOL rc;
  608. ZeroMemory( szString,_MAX_PATH*sizeof(TCHAR) );
  609. // Read in each line of the file
  610. szBuf = (LPTSTR)malloc(_MAX_PATH * 4 * sizeof(TCHAR) );
  611. if (!szBuf) MallocFailed();
  612. while ( !feof( pStoreFromFile) ) {
  613. szFileName=NULL;
  614. szPtrFileName=NULL;
  615. _tcscpy(szBuf, _T("") );
  616. if (!fgets( szBuf, _MAX_PATH*4, pStoreFromFile))
  617. {
  618. break;
  619. }
  620. if (_tcscmp(szBuf, _T("") ) == 0 )
  621. {
  622. break;
  623. }
  624. _tcscpy( szFullFileName, pArgs->szShareName );
  625. _tcscpy( szFullPtrFileName, pArgs->szShareName );
  626. // Step through szBuf and count how many commas there are
  627. // If there are 3 commas, this is a new style file. If there
  628. // are 4 commas, this is an old style file.
  629. token2=NULL;
  630. token3=NULL;
  631. token4=NULL;
  632. comma_count=0;
  633. i=0;
  634. token_start=i;
  635. while ( szBuf[i] != _T('\0') && comma_count < 4 ) {
  636. if ( szBuf[i] == _T(',') ) {
  637. switch (comma_count)
  638. {
  639. case 0: szFileName=szBuf;
  640. break;
  641. case 1: token2=szBuf+token_start;
  642. break;
  643. case 2: token3=szBuf+token_start;
  644. break;
  645. case 3: token4=szBuf+token_start;
  646. break;
  647. default: break;
  648. }
  649. token_start=i+1;
  650. szBuf[i]=_T('\0');
  651. comma_count++;
  652. }
  653. i++;
  654. }
  655. _tcscat( szFullFileName, szFileName);
  656. if ( comma_count == 3 ) {
  657. //This is the new style
  658. _tcscpy( szString,token2);
  659. if ( *token3 != _T('\0') ) {
  660. szPtrFileName=token3;
  661. }
  662. } else {
  663. dw1=atoi(token2);
  664. dw2=atoi(token3);
  665. if ( *token4 != _T('\0') ) {
  666. szPtrFileName=token4;
  667. }
  668. GetString2( szFileName, NULL, dw1,dw2,szString );
  669. }
  670. if ( szPtrFileName != NULL ) {
  671. _tcscat( szFullPtrFileName, szPtrFileName);
  672. }
  673. if ( szFileName != NULL ) {
  674. if ( szPtrFileName == NULL ) {
  675. rc = StoreFile(szDestDir,szFullFileName,szString,NULL);
  676. } else {
  677. rc = StoreFile(szDestDir,szFullFileName,szString,szFullPtrFileName);
  678. }
  679. if (rc) {
  680. pFileCounts->NumPassedFiles++;
  681. } else {
  682. pFileCounts->NumFailedFiles++;
  683. }
  684. }
  685. }
  686. free(szBuf);
  687. return(pFileCounts->NumFailedFiles);
  688. }
  689. BOOL
  690. AddToReferenceCount(
  691. LPTSTR szDir, // Directory where refs.ptr belongs
  692. LPTSTR szFileName, // Full path and name of the file that is referenced.
  693. LPTSTR szPtrOrFile // Was a file or a pointer written
  694. )
  695. {
  696. HANDLE hFile;
  697. TCHAR szRefsEntry[_MAX_PATH * 3];
  698. TCHAR szRefsFileName[_MAX_PATH + 1];
  699. DWORD dwPtr=0;
  700. DWORD dwError=0;
  701. DWORD dwNumBytesToWrite=0;
  702. DWORD dwNumBytesWritten=0;
  703. BOOL FirstEntry = FALSE;
  704. DWORD First;
  705. _stprintf( szRefsFileName,"%s\\%s", szDir, _T("refs.ptr") );
  706. // Find out if this is the first entry in the file or not
  707. // First, try opening an existing file. If that doesn't work
  708. // then create a new one.
  709. First=1;
  710. do {
  711. FirstEntry = FALSE;
  712. hFile = CreateFile( szRefsFileName,
  713. GENERIC_READ | GENERIC_WRITE,
  714. 0,
  715. NULL,
  716. OPEN_EXISTING,
  717. FILE_ATTRIBUTE_NORMAL,
  718. NULL );
  719. if ( hFile == INVALID_HANDLE_VALUE ) {
  720. FirstEntry = TRUE;
  721. hFile = CreateFile( szRefsFileName,
  722. GENERIC_READ | GENERIC_WRITE,
  723. 0,
  724. NULL,
  725. CREATE_ALWAYS,
  726. FILE_ATTRIBUTE_NORMAL,
  727. NULL );
  728. }
  729. // Only print a message the first time through
  730. if ( First && hFile == INVALID_HANDLE_VALUE ) {
  731. First = 0;
  732. printf( "Trying to get write access to %s ...\n", szRefsFileName);
  733. }
  734. } while ( hFile == INVALID_HANDLE_VALUE);
  735. dwPtr = SetFilePointer( hFile,
  736. 0,
  737. NULL,
  738. FILE_END );
  739. if (dwPtr == INVALID_SET_FILE_POINTER) {
  740. // Obtain the error code.
  741. dwError = GetLastError() ;
  742. printf("Failed to move to the end of the file %s with GetLastError = %d\n",
  743. szRefsFileName, dwError);
  744. SetEndOfFile(hFile);
  745. CloseHandle(hFile);
  746. return(FALSE);
  747. }
  748. //
  749. // Put in a '\n' if this isn't the first entry
  750. //
  751. if ( FirstEntry ) {
  752. _stprintf( szRefsEntry, "%s,%s,%s", pTrans->szId, szPtrOrFile, szFileName);
  753. } else {
  754. _stprintf( szRefsEntry, "\n%s,%s,%s", pTrans->szId, szPtrOrFile, szFileName);
  755. }
  756. dwNumBytesToWrite = (_tcslen(szRefsEntry) ) * sizeof(TCHAR);
  757. WriteFile( hFile,
  758. (LPCVOID) szRefsEntry,
  759. dwNumBytesToWrite,
  760. &dwNumBytesWritten,
  761. NULL
  762. );
  763. if ( dwNumBytesToWrite != dwNumBytesWritten ) {
  764. printf( "FAILED to write %s, with GetLastError = %d\n",
  765. szRefsEntry,
  766. GetLastError()
  767. );
  768. SetEndOfFile(hFile);
  769. CloseHandle(hFile);
  770. return (FALSE);
  771. }
  772. SetEndOfFile(hFile);
  773. CloseHandle(hFile);
  774. return (TRUE);
  775. }
  776. BOOL
  777. DeleteAllFilesInDirectory(
  778. LPTSTR szDir
  779. )
  780. {
  781. HANDLE hFindFile;
  782. BOOL Found = FALSE;
  783. BOOL rc = TRUE;
  784. LPTSTR szBuf;
  785. LPTSTR szDir2;
  786. LPWIN32_FIND_DATA lpFindFileData;
  787. szDir2 = (LPTSTR)malloc( (_tcslen(szDir) + 4) * sizeof(TCHAR) );
  788. if (szDir2 == NULL) MallocFailed();
  789. _tcscpy( szDir2, szDir);
  790. _tcscat( szDir2, _T("*.*") );
  791. szBuf = (LPTSTR)malloc( ( _tcslen(szDir) + _MAX_FNAME + _MAX_EXT + 2 )
  792. * sizeof(TCHAR) );
  793. if (szBuf == NULL) MallocFailed();
  794. lpFindFileData = (LPWIN32_FIND_DATA) malloc (sizeof(WIN32_FIND_DATA) );
  795. if (!lpFindFileData) MallocFailed();
  796. Found = TRUE;
  797. hFindFile = FindFirstFile((LPCTSTR)szDir2, lpFindFileData);
  798. if ( hFindFile == INVALID_HANDLE_VALUE) {
  799. Found = FALSE;
  800. }
  801. while ( Found ) {
  802. if ( !(lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
  803. _stprintf(szBuf, "%s%s", szDir, lpFindFileData->cFileName);
  804. if (!DeleteFile(szBuf)) {
  805. rc = FALSE;
  806. }
  807. }
  808. Found = FindNextFile(hFindFile, lpFindFileData);
  809. }
  810. free(lpFindFileData);
  811. FindClose(hFindFile);
  812. free(szDir2);
  813. free(szBuf);
  814. return(rc);
  815. }
  816. BOOL
  817. StoreNtFile(
  818. LPTSTR szDestDir,
  819. LPTSTR szFileName,
  820. LPTSTR szPtrFileName,
  821. USHORT *rc
  822. )
  823. /*++
  824. Routine Description:
  825. Stores this file as "szDestDir\szFileName\Checksum"
  826. Return Value:
  827. TRUE - file was stored successfully
  828. FALSE - file was not stored successfully
  829. --*/
  830. {
  831. BOOL temp_rc;
  832. HANDLE DosFile = 0;
  833. PIMAGE_DOS_HEADER pDosHeader = NULL;
  834. PIMAGE_NT_HEADERS pNtHeader = NULL;
  835. ULONG TimeDateStamp;
  836. ULONG SizeOfImage;
  837. TCHAR szString[_MAX_PATH];
  838. ZeroMemory(szString, _MAX_PATH*sizeof(TCHAR) );
  839. pDosHeader = MapFileHeader( szFileName, &DosFile );
  840. if ( pDosHeader == NULL ) {
  841. *rc = FILE_SKIPPED;
  842. return FALSE;
  843. };
  844. pNtHeader = GetNtHeader( pDosHeader, DosFile);
  845. if ( pNtHeader == NULL ) {
  846. UnmapFile((LPCVOID)pDosHeader,DosFile);
  847. *rc = FILE_SKIPPED;
  848. return FALSE;
  849. }
  850. __try {
  851. // Resource Dll's shouldn't have symbols
  852. if ( ResourceOnlyDll((PVOID)pDosHeader, FALSE) ) {
  853. *rc = FILE_SKIPPED;
  854. return FALSE;
  855. }
  856. TimeDateStamp = pNtHeader->FileHeader.TimeDateStamp;
  857. if (pNtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  858. SizeOfImage = ((PIMAGE_NT_HEADERS32)pNtHeader)->OptionalHeader.SizeOfImage;
  859. } else {
  860. if (pNtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
  861. SizeOfImage = ((PIMAGE_NT_HEADERS64)pNtHeader)->OptionalHeader.SizeOfImage;
  862. } else {
  863. SizeOfImage = 0;
  864. }
  865. }
  866. } __finally {
  867. UnmapFile((LPCVOID)pDosHeader,DosFile);
  868. }
  869. GetString2( szFileName,
  870. NULL,
  871. (DWORD) TimeDateStamp,
  872. (DWORD) SizeOfImage,
  873. szString );
  874. temp_rc = StoreFile( szDestDir,
  875. szFileName,
  876. szString,
  877. szPtrFileName );
  878. if (temp_rc) {
  879. *rc = FILE_STORED;
  880. return (TRUE);
  881. }
  882. else {
  883. *rc = FILE_ERRORED;
  884. return (FALSE);
  885. }
  886. }
  887. PIMAGE_DOS_HEADER
  888. MapFileHeader (
  889. LPTSTR szFileName,
  890. PHANDLE phFile
  891. )
  892. {
  893. /*
  894. Creates a file mapping and returns Handle for the DOS_HEADER
  895. If the file does not have a DOS_HEADER, then it returns NULL.
  896. If it returns NULL, then this file needs to be skipped.
  897. */
  898. HANDLE hFileMap;
  899. PIMAGE_DOS_HEADER pDosHeader = NULL;
  900. // phFile map needs to be returned, so it can be closed later
  901. (*phFile) = CreateFile( (LPCTSTR) szFileName,
  902. GENERIC_READ,
  903. FILE_SHARE_READ,
  904. NULL,
  905. OPEN_EXISTING,
  906. FILE_ATTRIBUTE_NORMAL,
  907. NULL
  908. );
  909. if (*phFile == INVALID_HANDLE_VALUE) {
  910. return(NULL);
  911. }
  912. hFileMap = CreateFileMapping( *phFile,
  913. NULL,
  914. PAGE_READONLY,
  915. 0,
  916. 0,
  917. NULL
  918. );
  919. if ( !hFileMap) {
  920. CloseHandle(*phFile);
  921. return(NULL);
  922. }
  923. pDosHeader = (PIMAGE_DOS_HEADER) MapViewOfFile( hFileMap,
  924. FILE_MAP_READ,
  925. 0, // high
  926. 0, // low
  927. 0 // whole file
  928. );
  929. CloseHandle(hFileMap);
  930. if ( !pDosHeader ) {
  931. UnmapFile((LPCVOID)pDosHeader, *phFile);
  932. return(NULL);
  933. }
  934. //
  935. // Check to determine if this is an NT image (PE format)
  936. if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
  937. UnmapFile((LPCVOID)pDosHeader,*phFile);
  938. return(NULL);
  939. }
  940. return (pDosHeader);
  941. }
  942. PIMAGE_NT_HEADERS
  943. GetNtHeader ( PIMAGE_DOS_HEADER pDosHeader,
  944. HANDLE hDosFile
  945. )
  946. {
  947. /*
  948. Returns the pointer the address of the NT Header. If there isn't
  949. an NT header, it returns NULL
  950. */
  951. PIMAGE_NT_HEADERS pNtHeader = NULL;
  952. LPBY_HANDLE_FILE_INFORMATION lpFileInfo;
  953. if (lpFileInfo = (LPBY_HANDLE_FILE_INFORMATION) malloc
  954. (sizeof(BY_HANDLE_FILE_INFORMATION)))
  955. {
  956. //
  957. // If the image header is not aligned on a long boundary.
  958. // Report this as an invalid protect mode image.
  959. //
  960. if ( ((ULONG)(pDosHeader->e_lfanew) & 3) == 0)
  961. {
  962. if (GetFileInformationByHandle( hDosFile, lpFileInfo) &&
  963. ((ULONG)(pDosHeader->e_lfanew) <= lpFileInfo->nFileSizeLow))
  964. {
  965. pNtHeader = (PIMAGE_NT_HEADERS)((PCHAR)pDosHeader +
  966. (ULONG)pDosHeader->e_lfanew);
  967. if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
  968. {
  969. pNtHeader = NULL;
  970. }
  971. }
  972. }
  973. free(lpFileInfo);
  974. }
  975. return pNtHeader;
  976. }
  977. BOOL
  978. ResourceOnlyDll(
  979. PVOID pImageBase,
  980. BOOLEAN bMappedAsImage
  981. )
  982. /*++
  983. Routine Description:
  984. Returns true if the image is a resource only dll.
  985. --*/
  986. {
  987. PVOID pExports, pImports, pResources;
  988. DWORD dwExportSize, dwImportSize, dwResourceSize;
  989. pExports = ImageDirectoryEntryToData(pImageBase,
  990. bMappedAsImage,
  991. IMAGE_DIRECTORY_ENTRY_EXPORT,
  992. &dwExportSize);
  993. pImports = ImageDirectoryEntryToData(pImageBase,
  994. bMappedAsImage,
  995. IMAGE_DIRECTORY_ENTRY_IMPORT,
  996. &dwImportSize);
  997. pResources = ImageDirectoryEntryToData(pImageBase,
  998. bMappedAsImage,
  999. IMAGE_DIRECTORY_ENTRY_RESOURCE,
  1000. &dwResourceSize);
  1001. if (pResources && dwResourceSize &&
  1002. !pImports && !dwImportSize &&
  1003. !pExports && !dwExportSize) {
  1004. return (TRUE);
  1005. } else {
  1006. return (FALSE);
  1007. }
  1008. }
  1009. BOOL
  1010. MyCopyFile(
  1011. LPCTSTR lpExistingFileName,
  1012. LPCTSTR lpNewFileName
  1013. )
  1014. /*++
  1015. Routine description:
  1016. This handles whether the file is a compressed file or not. First it
  1017. tries to copy in the compressed version of the file. If that works,
  1018. then it will delete the uncompressed file if it exists in the target.
  1019. If the compressed file is not there, then it copies in the
  1020. uncompressed file.
  1021. --*/
  1022. {
  1023. TCHAR lpExistingFileName_C[_MAX_PATH*3]; // Compressed version name
  1024. TCHAR lpNewFileName_C[_MAX_PATH*3]; // Compressed version
  1025. DWORD dw;
  1026. BOOL rc;
  1027. // Put a _ at the end of the compressed names
  1028. _tcscpy( lpExistingFileName_C, lpExistingFileName );
  1029. lpExistingFileName_C[ _tcslen(lpExistingFileName_C) - 1 ] = _T('_');
  1030. _tcscpy( lpNewFileName_C, lpNewFileName );
  1031. lpNewFileName_C[ _tcslen( lpNewFileName_C ) - 1 ] = _T('_');
  1032. // If the compressed file exists, copy it instead of the uncompressed file
  1033. dw = GetFileAttributes( lpExistingFileName_C );
  1034. if ( dw != 0xffffffff) {
  1035. rc = CopyFile( lpExistingFileName_C, lpNewFileName_C, TRUE );
  1036. if ( !rc && GetLastError() != ERROR_FILE_EXISTS ) {
  1037. printf("CopyFile failed to copy %s to %s - GetLastError() = %d\n",
  1038. lpExistingFileName_C, lpNewFileName_C, GetLastError() );
  1039. return (FALSE);
  1040. }
  1041. SetFileAttributes( lpNewFileName_C, FILE_ATTRIBUTE_NORMAL );
  1042. // If the uncompressed file exists, delete it
  1043. dw = GetFileAttributes( lpNewFileName );
  1044. if ( dw != 0xffffffff ) {
  1045. rc = DeleteFile( lpNewFileName );
  1046. if (!rc) {
  1047. printf("Keeping %s, but could not delete %s\n",
  1048. lpNewFileName_C, lpNewFileName );
  1049. }
  1050. }
  1051. } else {
  1052. // Compressed file doesn't exist, try the uncompressed
  1053. dw = GetFileAttributes( lpExistingFileName );
  1054. if ( dw != 0xffffffff ) {
  1055. rc = CopyFile( lpExistingFileName, lpNewFileName, TRUE );
  1056. if ( !rc && GetLastError() != ERROR_FILE_EXISTS ) {
  1057. printf("CopyFile failed to copy %s to %s - GetLastError() = %d\n",
  1058. lpExistingFileName, lpNewFileName, GetLastError() );
  1059. return (FALSE);
  1060. }
  1061. SetFileAttributes( lpNewFileName, FILE_ATTRIBUTE_NORMAL );
  1062. }
  1063. }
  1064. return(TRUE);
  1065. }