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.

2551 lines
72 KiB

  1. #include <assert.h>
  2. #include "symutil.h"
  3. #include "private.h"
  4. #include "dbgimage.h"
  5. #include "cvinfo.h"
  6. #include "exe_vxd.h"
  7. #include "share.h"
  8. #include "winbase.h"
  9. // Stuff for Checking symbols
  10. #define DBGSYM 2
  11. #define PDBSYM 3
  12. #define lengthof(a) (sizeof(a) / sizeof(a[0]))
  13. BOOL CheckPrivate=FALSE;
  14. BOOL CheckCodeView=TRUE;
  15. PEXCLUDE_LIST pErrorFilterList=NULL;
  16. P_LIST pCDIncludeList=NULL;
  17. BOOL Recurse = FALSE;
  18. BOOL LogCheckSumErrors = TRUE;
  19. // private version of qsort used to avoid compat problems on NT4 and win2k.
  20. // code is published from base\crts
  21. extern
  22. void __cdecl dbg_qsort(void *, size_t, size_t,
  23. int (__cdecl *) (const void *, const void *));
  24. #if defined(use_SymutilX)
  25. static BOOL RSDSLibLoaded=FALSE;
  26. // Typedefs
  27. typedef BOOL ( __cdecl *PPDBOPENVALIDATE4 ) (
  28. const wchar_t *wszPDB,
  29. const char *szMode,
  30. PCSIG70 pcsig70,
  31. SIG sig,
  32. AGE age,
  33. OUT EC *pec,
  34. OUT wchar_t *wszError,
  35. size_t cchErrMax,
  36. OUT PDB **pppdb
  37. );
  38. typedef BOOL ( __cdecl *PPDBCLOSE ) (
  39. PDB* ppdb
  40. );
  41. typedef BOOL ( __cdecl *PDBIQUERYNEXTMOD ) (
  42. DBI* pdbi, Mod* pmod, Mod** ppmodNext
  43. );
  44. typedef BOOL ( __cdecl *PMODCLOSE ) (
  45. Mod* pmod
  46. );
  47. typedef BOOL ( __cdecl *PMODQUERYLINES ) (
  48. Mod* pmod, BYTE* pbLines, long* pcb
  49. );
  50. typedef BOOL ( __cdecl *PMODQUERYSYMBOLS ) (
  51. Mod* pmod, BYTE* pbSym, long* pcb
  52. );
  53. typedef BOOL ( __cdecl *PDBIQUERYTYPESERVER ) (
  54. DBI* pdbi, ITSM itsm, OUT TPI** pptpi
  55. );
  56. typedef BOOL ( __cdecl *PPDBOPENTPI ) (
  57. PDB* ppdb, const char* szMode, OUT TPI** pptpi
  58. );
  59. typedef BOOL ( __cdecl *PTYPESQUERYTIMINEX ) (
  60. TPI* ptpi
  61. );
  62. typedef BOOL ( __cdecl *PTYPESQUERYTIMACEX ) (
  63. TPI* ptpi
  64. );
  65. typedef BOOL ( __cdecl *PTYPESCLOSE ) (
  66. TPI* ptpi
  67. );
  68. typedef BOOL ( __cdecl *PPDBOPENDBI ) (
  69. PDB* ppdb, const char* szMode, const char* szTarget, OUT DBI** ppdbi
  70. );
  71. typedef BOOL ( __cdecl *PDBICLOSE ) (
  72. DBI* pdbi
  73. );
  74. static PPDBOPENVALIDATE4 pPDBOpenValidate4 = NULL;
  75. static PPDBCLOSE pPDBClose = NULL;
  76. static PDBIQUERYNEXTMOD pDBIQueryNextMod = NULL;
  77. static PMODCLOSE pModClose = NULL;
  78. static PMODQUERYLINES pModQueryLines = NULL;
  79. static PMODQUERYSYMBOLS pModQuerySymbols = NULL;
  80. static PDBIQUERYTYPESERVER pDBIQueryTypeServer = NULL;
  81. static PPDBOPENTPI pPDBOpenTpi = NULL;
  82. static PTYPESQUERYTIMINEX pTypesQueryTiMinEx = NULL;
  83. static PTYPESQUERYTIMACEX pTypesQueryTiMacEx = NULL;
  84. static PTYPESCLOSE pTypesClose = NULL;
  85. static PPDBOPENDBI pPDBOpenDBI = NULL;
  86. static PDBICLOSE pDBIClose = NULL;
  87. #endif
  88. BOOL
  89. ansi2wcs(
  90. PSTR psz,
  91. PWSTR pwsz,
  92. DWORD pwszlen
  93. );
  94. typedef struct _FILE_INFO {
  95. DWORD TimeDateStamp;
  96. DWORD SizeOfImage;
  97. DWORD CheckSum;
  98. TCHAR szName[MAX_PATH];
  99. } FILE_INFO, *PFILE_INFO;
  100. PIMAGE_DOS_HEADER
  101. MapFileHeader (
  102. LPTSTR szFileName,
  103. PHANDLE phFile,
  104. PSYM_ERR pSymErr
  105. );
  106. PIMAGE_NT_HEADERS
  107. GetNtHeader (
  108. PIMAGE_DOS_HEADER pDosHeader,
  109. HANDLE hDosFile,
  110. LPTSTR szFileName,
  111. PSYM_ERR pSymErr,
  112. LPBY_HANDLE_FILE_INFORMATION lpFileInfo
  113. );
  114. BOOL
  115. ResourceOnlyDll(
  116. PVOID pImageBase,
  117. BOOLEAN bMappedAsImage
  118. );
  119. PIMAGE_SEPARATE_DEBUG_HEADER
  120. MapDbgHeader (
  121. LPTSTR szFileName,
  122. PHANDLE phFile,
  123. PSYM_ERR pSymErr
  124. );
  125. BOOL
  126. UnmapFile(
  127. LPCVOID phFileMap,
  128. HANDLE hFile
  129. );
  130. IMAGE_DEBUG_DIRECTORY UNALIGNED *
  131. GetDebugDirectoryInExe(
  132. PIMAGE_DOS_HEADER pDosHeader,
  133. ULONG *NumberOfDebugDirectories
  134. );
  135. IMAGE_DEBUG_DIRECTORY UNALIGNED *
  136. GetDebugDirectoryInDbg(
  137. PIMAGE_SEPARATE_DEBUG_HEADER pDbgHeader,
  138. ULONG *NumberOfDebugDirectories
  139. );
  140. PIMAGE_SEPARATE_DEBUG_HEADER
  141. MapMatchingDbgFile(
  142. LPTSTR szSearchPath,
  143. PFILE_INFO pFileInfo,
  144. LPTSTR szFoundPath
  145. );
  146. BOOL
  147. VerifyCV(
  148. LPTSTR szFileName,
  149. PCHAR pImageBase,
  150. IMAGE_DEBUG_DIRECTORY UNALIGNED *pDbgDir,
  151. LPTSTR szExtPath,
  152. LPTSTR szSearchPath,
  153. PSYM_ERR pSymErr,
  154. LPTSTR szRSDSDllToLoad
  155. );
  156. LPSTR
  157. GetMiscFile(
  158. PCHAR pImageBase,
  159. IMAGE_DEBUG_DIRECTORY UNALIGNED *pDbgDir
  160. );
  161. BOOL
  162. SearchForSymbolFile (
  163. LPTSTR szSearchPath,
  164. LPTSTR szSymName,
  165. LPTSTR szPathExt,
  166. PSYM_ERR pSymErr,
  167. DWORD SymType,
  168. PVOID pelem1,
  169. LPTSTR szResult,
  170. DWORD dwResultLength,
  171. LPTSTR szRSDSDllToLoad
  172. );
  173. USHORT
  174. __cdecl
  175. CompDbg(
  176. PVOID pelem1,
  177. LPTSTR szSymName,
  178. PSYM_ERR pSymErr
  179. );
  180. USHORT
  181. __cdecl
  182. CompPdb(
  183. PVOID pelem1,
  184. LPTSTR szSymName,
  185. PSYM_ERR pSymErr,
  186. LPTSTR szRSDSDllToLoad
  187. );
  188. BOOL
  189. AddToSymbolsCDLog(
  190. FILE *hSymCDLog,
  191. PSYM_ERR pSymErr,
  192. LPTSTR szSymbolPath,
  193. LPTSTR szFileExt
  194. );
  195. BOOL PDBPrivateStripped(
  196. PDB *ppdb,
  197. DBI *pdbi
  198. );
  199. #if defined(use_SymutilX)
  200. BOOL PDBPrivateStrippedX(
  201. PDB *ppdb,
  202. DBI *pdbi
  203. );
  204. #endif
  205. BOOL
  206. RemoveDuplicateSlashes(
  207. LPTSTR Str
  208. );
  209. int __cdecl
  210. SymComp(
  211. const void *e1,
  212. const void *e2
  213. );
  214. PEXCLUDE_LIST
  215. GetExcludeList(
  216. LPTSTR szFileName
  217. )
  218. {
  219. PEXCLUDE_LIST pExcList;
  220. FILE *fFile;
  221. TCHAR szCurFile[_MAX_FNAME+1], *c;
  222. TCHAR fname[_MAX_FNAME+1], ext[_MAX_EXT+1];
  223. DWORD i;
  224. LPTSTR szEndName;
  225. if ( (fFile = _tfopen(szFileName,_T("r") )) == NULL ) {
  226. // printf( "Cannot open the exclude file %s\n",szFileName );
  227. return FALSE;
  228. }
  229. pExcList = (PEXCLUDE_LIST)malloc(sizeof(EXCLUDE_LIST));
  230. if (pExcList)
  231. {
  232. pExcList->dNumFiles = 0;
  233. while ( _fgetts(szCurFile,_MAX_FNAME,fFile) ) {
  234. if ( szCurFile[0] == ';' ) continue;
  235. (pExcList->dNumFiles)++;
  236. }
  237. // Go back to the beginning of the file
  238. fseek(fFile,0,0);
  239. pExcList->szExcList = (LPTSTR*)malloc( sizeof(LPTSTR) *
  240. (pExcList->dNumFiles));
  241. if (pExcList->szExcList == NULL)
  242. {
  243. free(pExcList);
  244. pExcList = NULL;
  245. }
  246. else
  247. {
  248. i = 0;
  249. while ( i < pExcList->dNumFiles )
  250. {
  251. pExcList->szExcList[i] = NULL;
  252. memset(szCurFile,'\0',sizeof(TCHAR) * (_MAX_FNAME+1) );
  253. _fgetts(szCurFile,_MAX_FNAME,fFile);
  254. // Replace the \n with \0
  255. c = NULL;
  256. c = _tcschr(szCurFile, '\n');
  257. if ( c != NULL)
  258. {
  259. *c='\0';
  260. }
  261. if ( szCurFile[0] == ';' )
  262. {
  263. continue;
  264. }
  265. if ( _tcslen(szCurFile) > _MAX_FNAME )
  266. {
  267. printf("File %s has a string that is too large\n",szFileName);
  268. continue;
  269. }
  270. // Allow for spaces and a ; after the file name
  271. // Move the '\0' back until it has erased the ';' and any
  272. // tabs and spaces that might come before it
  273. // Set the pointer to the ; if there is a comment
  274. szEndName = _tcschr(szCurFile, ';');
  275. // Set the pointer to the last character in the string if
  276. // there wasn't a comment
  277. if (szEndName == NULL ) {
  278. if (_tcslen(szCurFile) > 0 ) {
  279. szEndName = szCurFile + _tcslen(szCurFile) - 1;
  280. }
  281. }
  282. if (szEndName != NULL ) {
  283. while ( *szEndName == ';' || *szEndName == ' '
  284. || *szEndName == '\t' ) {
  285. *szEndName = '\0';
  286. if ( szEndName > szCurFile ) szEndName--;
  287. }
  288. }
  289. pExcList->szExcList[i]=(LPTSTR)
  290. malloc( sizeof(TCHAR) * (_tcslen(szCurFile)+1) );
  291. if (pExcList->szExcList[i] == NULL )
  292. {
  293. printf("Malloc failed for %s\n",szCurFile);
  294. }
  295. else
  296. {
  297. _tsplitpath(szCurFile,NULL,NULL,fname,ext);
  298. _tcscpy(pExcList->szExcList[i],fname);
  299. _tcscat(pExcList->szExcList[i],ext);
  300. }
  301. i++;
  302. }
  303. // Sort the List
  304. dbg_qsort( (void*)pExcList->szExcList, (size_t)pExcList->dNumFiles,
  305. (size_t)sizeof(LPTSTR), SymComp );
  306. }
  307. }
  308. fclose(fFile);
  309. return (pExcList);
  310. }
  311. BOOL
  312. InExcludeList(
  313. LPTSTR szFileName,
  314. PEXCLUDE_LIST pExcludeList
  315. )
  316. {
  317. DWORD i;
  318. int High;
  319. int Low;
  320. int Middle;
  321. int Result;
  322. // Lookup the name using a binary search
  323. if ( pExcludeList == NULL ) return FALSE;
  324. if ( pExcludeList->dNumFiles == 0 ) return FALSE;
  325. Low = 0;
  326. High = pExcludeList->dNumFiles - 1;
  327. while ( High >= Low ) {
  328. Middle = (Low + High) >> 1;
  329. Result = _tcsicmp( szFileName, pExcludeList->szExcList[Middle] );
  330. if ( Result < 0 ) {
  331. High = Middle - 1;
  332. } else if ( Result > 0 ) {
  333. Low = Middle + 1;
  334. } else {
  335. break;
  336. }
  337. }
  338. if ( High < Low ) return FALSE;
  339. return TRUE;
  340. }
  341. BOOL
  342. InList(
  343. LPTSTR szFileName,
  344. P_LIST pExcludeList
  345. )
  346. {
  347. DWORD i;
  348. int High;
  349. int Low;
  350. int Middle;
  351. int Result;
  352. // Lookup the name using a binary search
  353. if ( pExcludeList == NULL ) return FALSE;
  354. if ( pExcludeList->dNumFiles == 0 ) return FALSE;
  355. Low = 0;
  356. High = pExcludeList->dNumFiles - 1;
  357. while ( High >= Low ) {
  358. Middle = (Low + High) >> 1;
  359. Result = _tcsicmp( szFileName, pExcludeList->List[Middle].Path );
  360. if ( Result < 0 ) {
  361. High = Middle - 1;
  362. } else if ( Result > 0 ) {
  363. Low = Middle + 1;
  364. } else {
  365. break;
  366. }
  367. }
  368. if ( High < Low ) return FALSE;
  369. return TRUE;
  370. }
  371. int __cdecl
  372. SymComp(
  373. const void *e1,
  374. const void *e2
  375. )
  376. {
  377. LPTSTR* p1;
  378. LPTSTR* p2;
  379. p1 = (LPTSTR*)e1;
  380. p2 = (LPTSTR*)e2;
  381. return ( _tcsicmp(*p1,*p2) );
  382. }
  383. BOOL
  384. CheckSymbols (
  385. LPTSTR ErrMsg,
  386. LPTSTR szSearchPath,
  387. LPTSTR szFileName,
  388. FILE *hSymCDLog,
  389. ULONG SymchkFlag,
  390. BOOL Verbose,
  391. LPTSTR szRSDSDllToLoad
  392. )
  393. /*++
  394. Routine Description:
  395. This function accepts a file name and a symbol search path
  396. (delimited by ;) and determines if its symbols match.
  397. Arguments:
  398. szSearchPath Search path delimited by ;
  399. szFileName Full path and name of the file to verify symbols for
  400. szCopyDest If this is not a NULL value, then generate actually copy the
  401. symbols to this destination
  402. SymchkFlag Specifies action to take according to whether symbols are
  403. split or not split.
  404. Possible values:
  405. ERROR_IF_SPLIT Print an error if the image is split already
  406. ERROR_IF_NOT_SPLIT Error if image is not split
  407. IGNORE_IF_SPLIT Don't check symbols for split images
  408. Verbose If true, print an output line for every file
  409. If false, print output only for files that fail
  410. Return Value:
  411. TRUE if symbols are correct, or symbol checking was ignored
  412. FALSE if symbols are not correct
  413. --*/
  414. {
  415. PIMAGE_NT_HEADERS pNtHeader = NULL;
  416. PIMAGE_DOS_HEADER pDosHeader = NULL;
  417. PIMAGE_SEPARATE_DEBUG_HEADER pDbgHeader= NULL;
  418. IMAGE_DEBUG_DIRECTORY UNALIGNED *DebugDirectory;
  419. IMAGE_DEBUG_DIRECTORY UNALIGNED *pDbgDir=NULL;
  420. PIMAGE_DEBUG_MISC pDebugMisc;
  421. PTCHAR pImageBase;
  422. ULONG NumberOfDebugDirectories;
  423. FILE_INFO FileInfo;
  424. LPSTR szMiscFileName;
  425. UINT i;
  426. PNB10I pDebugCV;
  427. TCHAR path_buffer[_MAX_PATH];
  428. TCHAR drive[_MAX_DRIVE];
  429. TCHAR dir[_MAX_DIR];
  430. TCHAR fname[_MAX_FNAME];
  431. TCHAR ext[_MAX_EXT];
  432. TCHAR szDbgFileName[_MAX_PATH*sizeof(TCHAR)];
  433. DWORD dwDbgFileNameLength = _MAX_PATH;
  434. HANDLE DbgFile = 0;
  435. HANDLE DosFile = 0;
  436. BOOL SymbolsOK = TRUE;
  437. BOOL CVFound = FALSE;
  438. BOOL MiscFound = FALSE;
  439. BOOL RawDataFound = FALSE;
  440. BOOL rc= FALSE;
  441. BY_HANDLE_FILE_INFORMATION HandleFileInfo;
  442. SYM_ERR SymErr;
  443. // Get the file name and the extension
  444. _tsplitpath( szFileName,drive,dir,fname,ext);
  445. // Initialize SymErr
  446. memset( &SymErr,0,sizeof(SYM_ERR) );
  447. SymErr.Verbose = Verbose;
  448. _tcscpy( SymErr.szFileName, szFileName );
  449. _tcscpy( SymErr.szSymbolSearchPath, szSearchPath );
  450. _tcscpy( SymErr.szSymbolFileName, _T("") );
  451. _tcscpy( SymErr.szPdbErr, _T("") );
  452. _tcscpy( SymErr.szPdbFileName, _T("") );
  453. pDosHeader = MapFileHeader( szFileName, &DosFile, &SymErr );
  454. if ( SymErr.ErrNo > 0 ) {
  455. LogError( ErrMsg, &SymErr, 0);
  456. return TRUE;
  457. }
  458. pNtHeader = GetNtHeader( pDosHeader, DosFile, szFileName, &SymErr, &HandleFileInfo );
  459. if ( SymErr.ErrNo > 0 ) {
  460. UnmapFile((LPCVOID)pDosHeader,DosFile);
  461. LogError( ErrMsg, &SymErr,0 );
  462. return TRUE;
  463. }
  464. __try {
  465. // Resource Dll's shouldn't have symbols
  466. if ( ResourceOnlyDll((PVOID)pDosHeader, FALSE) ) {
  467. LogError( ErrMsg, &SymErr,RESOURCE_ONLY_DLL);
  468. SymbolsOK = TRUE;
  469. __leave;
  470. }
  471. // Get info out of file header for comparison later
  472. if (pNtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  473. FileInfo.CheckSum = ((PIMAGE_NT_HEADERS32)pNtHeader)->OptionalHeader.CheckSum;
  474. FileInfo.SizeOfImage = ((PIMAGE_NT_HEADERS32)pNtHeader)->OptionalHeader.SizeOfImage;
  475. } else {
  476. if (pNtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
  477. FileInfo.CheckSum = ((PIMAGE_NT_HEADERS64)pNtHeader)->OptionalHeader.CheckSum;
  478. FileInfo.SizeOfImage = ((PIMAGE_NT_HEADERS64)pNtHeader)->OptionalHeader.SizeOfImage;
  479. } else {
  480. FileInfo.CheckSum = -1;
  481. }
  482. }
  483. FileInfo.TimeDateStamp = pNtHeader->FileHeader.TimeDateStamp;
  484. _tcscpy(FileInfo.szName,szFileName);
  485. // Locate the Debug Directory in this file
  486. DebugDirectory = NULL;
  487. DebugDirectory = GetDebugDirectoryInExe(
  488. pDosHeader,
  489. &NumberOfDebugDirectories
  490. );
  491. if (!DebugDirectory) {
  492. LogError( ErrMsg, &SymErr,NO_DEBUG_DIRECTORIES);
  493. SymbolsOK = FALSE;
  494. __leave;
  495. }
  496. pImageBase = (PCHAR) pDosHeader;
  497. // Do some checks on the Debug Directories
  498. // Debug Information is stripped, we need the misc directory to find
  499. // out the DBG file name
  500. if ( (pNtHeader->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) ) {
  501. if (SymchkFlag & ERROR_IF_SPLIT) {
  502. // Image is split, log error and continue;
  503. LogError( ErrMsg, &SymErr,ERROR_IF_SPLIT);
  504. SymbolsOK = FALSE;
  505. __leave;
  506. } else if (SymchkFlag & IGNORE_IF_SPLIT ) {
  507. // Image is split, don't check the symbols
  508. LogError( ErrMsg, &SymErr,IGNORE_IF_SPLIT);
  509. SymbolsOK = TRUE;
  510. __leave;
  511. }
  512. // Get the MISC entry
  513. i=0;
  514. while ( (i<NumberOfDebugDirectories) &&
  515. ((DebugDirectory+i)->Type != IMAGE_DEBUG_TYPE_MISC) ) i++;
  516. if (i >= NumberOfDebugDirectories) {
  517. LogError( ErrMsg, &SymErr,NO_MISC_ENTRY);
  518. SymbolsOK = FALSE;
  519. __leave;
  520. }
  521. szMiscFileName = NULL;
  522. szMiscFileName = GetMiscFile(pImageBase,DebugDirectory + i);
  523. if (!szMiscFileName) {
  524. LogError( ErrMsg, &SymErr,NO_FILE_IN_MISC);
  525. SymbolsOK = FALSE;
  526. __leave;
  527. }
  528. // Debug info is stripped.
  529. // First, locate the correct DBG file
  530. rc = SearchForSymbolFile (
  531. szSearchPath,
  532. szMiscFileName,
  533. ext+1, // Extension of the image
  534. &SymErr,
  535. DBGSYM,
  536. (PVOID)&FileInfo,
  537. szDbgFileName,
  538. dwDbgFileNameLength,
  539. szRSDSDllToLoad );
  540. if (!rc) {
  541. LogDbgError(ErrMsg, &SymErr);
  542. SymbolsOK = FALSE;
  543. __leave;
  544. } else if ( hSymCDLog != NULL) {
  545. AddToSymbolsCDLog( hSymCDLog, &SymErr, SymErr.szSymbolFileName, ext+1);
  546. }
  547. pDbgHeader = NULL;
  548. pDbgHeader = MapDbgHeader(szDbgFileName,&DbgFile, &SymErr);
  549. if (!pDbgHeader) {
  550. SymbolsOK = FALSE;
  551. // 0 means info is inside of SymErr
  552. LogError(ErrMsg, &SymErr,0);
  553. __leave;
  554. }
  555. DebugDirectory = NULL;
  556. DebugDirectory = GetDebugDirectoryInDbg(
  557. pDbgHeader,
  558. &NumberOfDebugDirectories
  559. );
  560. if (!DebugDirectory) {
  561. LogError( ErrMsg, &SymErr,NO_DEBUG_DIRECTORIES_IN_DBG_HEADER);
  562. SymbolsOK = FALSE;
  563. __leave;
  564. }
  565. pImageBase = (PCHAR)pDbgHeader;
  566. }
  567. // Image is not split
  568. else {
  569. // VC 6 compiler always produces non-split images.
  570. // Check the debug directories to determine if this is a VC 6 image.
  571. RawDataFound = FALSE;
  572. CVFound = FALSE;
  573. MiscFound = FALSE;
  574. for ( i=0; i< NumberOfDebugDirectories; i++ ) {
  575. pDbgDir = DebugDirectory + i;
  576. switch (pDbgDir->Type) {
  577. case IMAGE_DEBUG_TYPE_MISC:
  578. MiscFound = TRUE;
  579. break;
  580. case IMAGE_DEBUG_TYPE_CODEVIEW:
  581. CVFound = TRUE;
  582. break;
  583. default:
  584. // Nothing except the CV entry should point to raw data
  585. if ( pDbgDir->SizeOfData != 0 ) {
  586. RawDataFound = TRUE;
  587. }
  588. break;
  589. }
  590. }
  591. if ( !MiscFound && CVFound ) {
  592. // This is using the 6.0 linker. It does not
  593. // need to be split into iamge + dbg, so don't
  594. // give an error for it, unless there is another
  595. // debug directory with a non-null pointer to raw data.
  596. if ( RawDataFound ) {
  597. LogError( ErrMsg, &SymErr, EXTRA_RAW_DATA_IN_6);
  598. return ( FALSE);
  599. } else {
  600. // Continue - image should not be split
  601. }
  602. } else {
  603. DWORD CertificateSize;
  604. PVOID pCertificates = ImageDirectoryEntryToData(
  605. (PVOID)pDosHeader,
  606. FALSE,
  607. IMAGE_DIRECTORY_ENTRY_SECURITY,
  608. &CertificateSize
  609. );
  610. if ( pCertificates ) {
  611. // Image is signed and non-split
  612. // It should be split before it is signed
  613. LogError( ErrMsg, &SymErr, SIGNED_AND_NON_SPLIT);
  614. SymbolsOK = FALSE;
  615. __leave;
  616. } else if (SymchkFlag & ERROR_IF_NOT_SPLIT) {
  617. // Image isn't split, log error and continue;
  618. LogError( ErrMsg, &SymErr,ERROR_IF_NOT_SPLIT);
  619. SymbolsOK = FALSE;
  620. __leave;
  621. }
  622. }
  623. // File with the DBG info is the original image file name
  624. // This line may not be necessary.
  625. _tcscpy( SymErr.szSymbolFileName, szFileName );
  626. }
  627. CVFound = FALSE;
  628. // Process the Debug Directories
  629. for ( i=0; i<NumberOfDebugDirectories; i++) {
  630. pDbgDir = DebugDirectory + i;
  631. switch (pDbgDir->Type) {
  632. // Don't need to process entry since directory table has
  633. // already been located.
  634. case IMAGE_DEBUG_TYPE_MISC: break;
  635. case IMAGE_DEBUG_TYPE_CODEVIEW:
  636. CVFound = TRUE;
  637. if ( !VerifyCV(
  638. szFileName,
  639. pImageBase,
  640. pDbgDir,
  641. ext+1,
  642. szSearchPath,
  643. &SymErr,
  644. szRSDSDllToLoad
  645. )
  646. ) {
  647. LogPdbError(ErrMsg, &SymErr);
  648. SymbolsOK = FALSE;
  649. } else if (hSymCDLog != NULL && _tcscmp(SymErr.szPdbFileName, "") ) {
  650. // Copy SymErr.szPdbFileName to Symbol Dest\ext
  651. AddToSymbolsCDLog( hSymCDLog, &SymErr, SymErr.szPdbFileName, ext+1 );
  652. }
  653. break;
  654. default: break;
  655. }
  656. }
  657. if (!CVFound && CheckCodeView ) {
  658. SymErr.ErrNo = NO_CODE_VIEW;
  659. LogPdbError(ErrMsg, &SymErr);
  660. SymbolsOK=FALSE;
  661. }
  662. } __finally {
  663. UnmapFile((LPCVOID)pDbgHeader,DbgFile);
  664. UnmapFile((LPCVOID)pDosHeader,DosFile);
  665. }
  666. if (SymbolsOK) {
  667. LogError( ErrMsg, &SymErr, IMAGE_PASSED );
  668. }
  669. return SymbolsOK;
  670. }
  671. PIMAGE_DOS_HEADER
  672. MapFileHeader (
  673. LPTSTR szFileName,
  674. PHANDLE phFile,
  675. PSYM_ERR pSymErr
  676. )
  677. {
  678. /*
  679. Creates a file mapping and returns Handle for the DOS_HEADER
  680. If the file does not have a DOS_HEADER, then it returns NULL.
  681. */
  682. HANDLE hFileMap;
  683. PIMAGE_DOS_HEADER pDosHeader;
  684. DWORD dFileType;
  685. BOOL rc;
  686. // phFile map needs to be returned, so it can be closed later
  687. (*phFile) = CreateFile( (LPCTSTR) szFileName,
  688. GENERIC_READ,
  689. FILE_SHARE_READ,
  690. NULL,
  691. OPEN_EXISTING,
  692. FILE_ATTRIBUTE_NORMAL,
  693. NULL
  694. );
  695. if (*phFile == INVALID_HANDLE_VALUE) {
  696. pSymErr->ErrNo = CREATE_FILE_FAILED;
  697. pSymErr->ErrNo2 = GetLastError();
  698. _tcscpy( pSymErr->szFileName, szFileName);
  699. return(NULL);
  700. }
  701. hFileMap = CreateFileMapping( *phFile,
  702. NULL,
  703. PAGE_READONLY,
  704. 0,
  705. 0,
  706. NULL
  707. );
  708. if ( hFileMap == INVALID_HANDLE_VALUE) {
  709. pSymErr->ErrNo = CREATE_FILE_MAPPING_FAILED;
  710. pSymErr->ErrNo2 = GetLastError();
  711. _tcscpy( pSymErr->szFileName, szFileName);
  712. CloseHandle(*phFile);
  713. return(NULL);
  714. }
  715. pDosHeader = (PIMAGE_DOS_HEADER) MapViewOfFile( hFileMap,
  716. FILE_MAP_READ,
  717. 0, // high
  718. 0, // low
  719. 0 // whole file
  720. );
  721. rc = CloseHandle(hFileMap);
  722. if ( !pDosHeader ) {
  723. pSymErr->ErrNo = MAPVIEWOFFILE_FAILED;
  724. pSymErr->ErrNo2 = GetLastError();
  725. _tcscpy( pSymErr->szFileName, szFileName);
  726. CloseHandle(*phFile);
  727. return(NULL);
  728. }
  729. //
  730. // Check to determine if this is an NT image (PE format)
  731. if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
  732. pSymErr->ErrNo = NO_DOS_HEADER;
  733. UnmapViewOfFile(pDosHeader);
  734. CloseHandle(*phFile);
  735. return(NULL);
  736. }
  737. return (pDosHeader);
  738. }
  739. PIMAGE_NT_HEADERS
  740. GetNtHeader ( PIMAGE_DOS_HEADER pDosHeader,
  741. HANDLE hDosFile,
  742. LPTSTR szFileName,
  743. PSYM_ERR pSymErr,
  744. LPBY_HANDLE_FILE_INFORMATION lpFileInfo
  745. )
  746. {
  747. /*
  748. Returns the pointer the address of the NT Header. If there isn't
  749. an NT header, it returns NULL
  750. */
  751. PIMAGE_NT_HEADERS pNtHeader;
  752. if (!GetFileInformationByHandle( hDosFile, lpFileInfo)) {
  753. pSymErr->ErrNo = GET_FILE_INFO_FAILED;
  754. pSymErr->ErrNo2 = GetLastError();
  755. return(NULL);
  756. }
  757. if ( ((ULONG)(pDosHeader->e_lfanew) & 3) != 0) {
  758. //
  759. // The image header is not aligned on a long boundary.
  760. // Report this as an invalid protect mode image.
  761. //
  762. pSymErr->ErrNo = HEADER_NOT_ON_LONG_BOUNDARY;
  763. return (NULL);
  764. }
  765. if ((ULONG)(pDosHeader->e_lfanew) > lpFileInfo->nFileSizeLow) {
  766. pSymErr->ErrNo = IMAGE_BIGGER_THAN_FILE;
  767. return (NULL);
  768. }
  769. pNtHeader = (PIMAGE_NT_HEADERS)((PCHAR)pDosHeader +
  770. (ULONG)pDosHeader->e_lfanew);
  771. if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
  772. pSymErr->ErrNo = NOT_NT_IMAGE;
  773. return(NULL);
  774. }
  775. return (pNtHeader);
  776. }
  777. PIMAGE_SEPARATE_DEBUG_HEADER
  778. MapDbgHeader (
  779. LPTSTR szFileName,
  780. PHANDLE phFile,
  781. PSYM_ERR pSymErr
  782. )
  783. {
  784. HANDLE hFileMap;
  785. PIMAGE_SEPARATE_DEBUG_HEADER pDbgHeader;
  786. DWORD dFileType;
  787. (*phFile) = CreateFile( (LPCTSTR) szFileName,
  788. GENERIC_READ,
  789. FILE_SHARE_READ,
  790. NULL,
  791. OPEN_EXISTING,
  792. FILE_ATTRIBUTE_NORMAL,
  793. NULL
  794. );
  795. if (*phFile == INVALID_HANDLE_VALUE) {
  796. pSymErr->ErrNo = CREATE_FILE_FAILED;
  797. pSymErr->ErrNo2 = GetLastError();
  798. _tcscpy( pSymErr->szFileName, szFileName);
  799. CloseHandle(*phFile);
  800. return(NULL);
  801. }
  802. hFileMap = CreateFileMapping( *phFile,
  803. NULL,
  804. PAGE_READONLY,
  805. 0,
  806. 0,
  807. NULL
  808. );
  809. if ( hFileMap == INVALID_HANDLE_VALUE) {
  810. pSymErr->ErrNo = CREATE_FILE_MAPPING_FAILED;
  811. pSymErr->ErrNo2 = GetLastError();
  812. _tcscpy( pSymErr->szFileName, szFileName);
  813. CloseHandle(*phFile);
  814. return(NULL);
  815. }
  816. pDbgHeader = (PIMAGE_SEPARATE_DEBUG_HEADER) MapViewOfFile( hFileMap,
  817. FILE_MAP_READ,
  818. 0, // high
  819. 0, // low
  820. 0 // whole file
  821. );
  822. CloseHandle(hFileMap);
  823. if ( !pDbgHeader ) {
  824. pSymErr->ErrNo = MAPVIEWOFFILE_FAILED;
  825. pSymErr->ErrNo2 = GetLastError();
  826. _tcscpy( pSymErr->szFileName, szFileName);
  827. UnmapFile((LPCVOID)pDbgHeader, *phFile);
  828. return(NULL);
  829. }
  830. return (pDbgHeader);
  831. }
  832. BOOL
  833. UnmapFile( LPCVOID phFileMap, HANDLE hFile )
  834. {
  835. BOOL rc;
  836. if ((PHANDLE)phFileMap != NULL) {
  837. FlushViewOfFile(phFileMap,0);
  838. rc = UnmapViewOfFile( phFileMap );
  839. if (rc == 0) {
  840. printf("UnmapView of File failed with GetLastError=%d\n",GetLastError() );
  841. }
  842. }
  843. if (hFile) {
  844. rc = CloseHandle(hFile);
  845. }
  846. return TRUE;
  847. }
  848. IMAGE_DEBUG_DIRECTORY UNALIGNED *
  849. GetDebugDirectoryInExe(
  850. PIMAGE_DOS_HEADER pDosHeader,
  851. ULONG *NumberOfDebugDirectories
  852. )
  853. {
  854. /* Exe is already mapped and a pointer to the base is
  855. passed in. Find a pointer to the Debug Directories
  856. */
  857. ULONG size;
  858. IMAGE_DEBUG_DIRECTORY UNALIGNED *pDebugDirectory = NULL;
  859. ULONG DebugDirectorySize;
  860. PIMAGE_SECTION_HEADER pSectionHeader;
  861. size = sizeof(IMAGE_DEBUG_DIRECTORY);
  862. pDebugDirectory = (PIMAGE_DEBUG_DIRECTORY)
  863. ImageDirectoryEntryToDataEx (
  864. (PVOID)pDosHeader,
  865. FALSE,
  866. IMAGE_DIRECTORY_ENTRY_DEBUG,
  867. &DebugDirectorySize,
  868. &pSectionHeader );
  869. if (pDebugDirectory) {
  870. (*NumberOfDebugDirectories) =
  871. DebugDirectorySize / sizeof(IMAGE_DEBUG_DIRECTORY);
  872. return (pDebugDirectory);
  873. } else return(NULL);
  874. }
  875. IMAGE_DEBUG_DIRECTORY UNALIGNED *
  876. GetDebugDirectoryInDbg(
  877. PIMAGE_SEPARATE_DEBUG_HEADER pDbgHeader,
  878. ULONG *NumberOfDebugDirectories
  879. )
  880. /* Dbg is already mapped and a pointer to the base is
  881. passed in. Returns a pointer to the Debug directories
  882. */
  883. {
  884. IMAGE_DEBUG_DIRECTORY UNALIGNED *pDebugDirectory = NULL;
  885. pDebugDirectory = (PIMAGE_DEBUG_DIRECTORY) ((PCHAR)pDbgHeader +
  886. sizeof(IMAGE_SEPARATE_DEBUG_HEADER) +
  887. pDbgHeader->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) +
  888. pDbgHeader->ExportedNamesSize);
  889. if (!pDebugDirectory) {
  890. return(NULL);
  891. }
  892. (*NumberOfDebugDirectories) = pDbgHeader->DebugDirectorySize /
  893. sizeof(IMAGE_DEBUG_DIRECTORY);
  894. return (pDebugDirectory);
  895. }
  896. BOOL
  897. VerifyCV(
  898. LPTSTR szFileName,
  899. PCHAR pImageBase,
  900. IMAGE_DEBUG_DIRECTORY UNALIGNED *pDbgDir,
  901. LPTSTR szExtPath,
  902. LPTSTR szSearchPath,
  903. PSYM_ERR pSymErr,
  904. LPTSTR szRSDSDllToLoad
  905. )
  906. {
  907. TCHAR szFName[_MAX_FNAME];
  908. TCHAR szExt[_MAX_EXT];
  909. TCHAR szPdbFileName[_MAX_PATH*sizeof(TCHAR)];
  910. DWORD dwPdbFileNameLength = _MAX_PATH;
  911. BOOL rc;
  912. PCVDD pDebugCV = (PCVDD) (pImageBase +
  913. pDbgDir->PointerToRawData );
  914. // Initialize pSymErr
  915. pSymErr->PdbFileFound = FALSE;
  916. pSymErr->PdbValid = FALSE;
  917. _tcscpy(pSymErr->szPdbErr,_T("") );
  918. _tcscpy(pSymErr->szPdbFileName,_T("") );
  919. switch (pDebugCV->dwSig)
  920. {
  921. case '05BN':
  922. // CVpack failed
  923. // Symbols are not OK
  924. _tcscpy(pSymErr->szPdbErr,_T("Codeview type is NB05") );
  925. return (FALSE);
  926. break;
  927. case '90BN':
  928. // For NB09 and NB11, the codeview info is in the image file
  929. // Thus, no need to locate symbols. They are probably OK.
  930. return(TRUE);
  931. break;
  932. case '11BN':
  933. return(TRUE);
  934. break;
  935. case '01BN':
  936. // Symbols are type NB10
  937. // Locate the PDB information
  938. rc = SearchForSymbolFile (
  939. szSearchPath,
  940. pDebugCV->nb10i.szPdb, // File Name
  941. szExtPath,
  942. pSymErr,
  943. PDBSYM,
  944. (PVOID)pDebugCV,
  945. szPdbFileName,
  946. dwPdbFileNameLength,
  947. szRSDSDllToLoad
  948. );
  949. if (rc ) {
  950. // SearchForSymbolFile already gave pSymErr->szPdbFilename its value
  951. return TRUE;
  952. } else {
  953. _tsplitpath(pDebugCV->nb10i.szPdb,NULL,NULL,szFName,szExt);
  954. _tcscpy(pSymErr->szPdbFileName,szFName);
  955. _tcscat(pSymErr->szPdbFileName,szExt);
  956. return FALSE;
  957. }
  958. break;
  959. case 'SDSR':
  960. rc = SearchForSymbolFile (
  961. szSearchPath,
  962. pDebugCV->rsdsi.szPdb, // File Name
  963. szExtPath,
  964. pSymErr,
  965. PDBSYM,
  966. (PVOID)pDebugCV,
  967. szPdbFileName,
  968. dwPdbFileNameLength,
  969. szRSDSDllToLoad
  970. );
  971. if (rc ) {
  972. // SearchForSymbolFile already gave pSymErr->szPdbFilename its value
  973. return TRUE;
  974. } else {
  975. _tsplitpath(pDebugCV->rsdsi.szPdb,NULL,NULL,szFName,szExt);
  976. _tcscpy(pSymErr->szPdbFileName,szFName);
  977. _tcscat(pSymErr->szPdbFileName,szExt);
  978. return FALSE;
  979. }
  980. break;
  981. default:
  982. _tcscpy(pSymErr->szPdbErr,
  983. _T("Codeview info is not NB09, NB10, or NB11\n") );
  984. return(FALSE);
  985. break;
  986. }
  987. }
  988. LPSTR
  989. GetMiscFile(
  990. PCHAR pImageBase,
  991. IMAGE_DEBUG_DIRECTORY UNALIGNED *pDbgDir
  992. )
  993. {
  994. PIMAGE_DEBUG_MISC pDebugMisc;
  995. LPSTR szData;
  996. // Nothing to verify, but here is how to get to the DBG entry
  997. // Get the debug directory
  998. pDebugMisc = (PIMAGE_DEBUG_MISC)(pImageBase +
  999. pDbgDir->PointerToRawData );
  1000. szData = (LPSTR) &pDebugMisc->Data[0];
  1001. return(szData);
  1002. }
  1003. BOOL SearchForSymbolFile ( LPTSTR szSearchPath, // ; separated search path
  1004. LPTSTR szSymName, // Symbol File to search for
  1005. LPTSTR szPathExt, // Extension directory
  1006. PSYM_ERR pSymErr,
  1007. DWORD dSymType,
  1008. PVOID pelem1,
  1009. LPTSTR szResult,
  1010. DWORD dwResultLength,
  1011. LPTSTR szRSDSDllToLoad
  1012. )
  1013. {
  1014. /*++
  1015. Routine Description:
  1016. For each symbol path in szSearchPath, this function looks in the path
  1017. and in the path concatenated with the szPathExt subdirectory.
  1018. Arguments:
  1019. szSearchPath ; separated symbol path
  1020. szSymName Symbol file to search for
  1021. szPathExt Extension for the image that the symbol file matches
  1022. pSymErr Error structure
  1023. dSymType Type of symbol. Possible values: DBGSYM, PDBSYM
  1024. pelem1 Pointer to structure needed for comparing the symbols
  1025. szResult OUT Filename returned
  1026. dwResultLength IN Length of szResult
  1027. Return Value:
  1028. If the symbol file is found and verifies, it returns the full path and
  1029. name of the symbol file. Otherwise, it returns NULL.
  1030. --*/
  1031. TCHAR szTmpSearchPath[_MAX_PATH];
  1032. TCHAR szExtPath[_MAX_PATH];
  1033. TCHAR szFName[_MAX_FNAME];
  1034. TCHAR szExt[_MAX_EXT];
  1035. LPTSTR szResultFileName;
  1036. LPTSTR seps = _T(";");
  1037. LPTSTR szCurPath;
  1038. DWORD FoundLength;
  1039. DWORD CurLen, ExtLen;
  1040. _tcscpy( szResult,_T("") );
  1041. // Make a copy of szSearchPath because tcstok alters it
  1042. _tcscpy(szTmpSearchPath,(LPCTSTR)szSearchPath);
  1043. // Strip FileName from its path
  1044. _tsplitpath(szSymName, NULL, NULL, szFName, szExt);
  1045. _tcscat(szFName, szExt);
  1046. // Try each search path
  1047. szCurPath = _tcstok(szTmpSearchPath,seps);
  1048. while ( szCurPath != NULL ) {
  1049. FoundLength = SearchPath( szCurPath,
  1050. szFName,
  1051. NULL,
  1052. dwResultLength,
  1053. szResult,
  1054. &szResultFileName
  1055. );
  1056. if (FoundLength > 0 && FoundLength < dwResultLength) {
  1057. switch ( dSymType ) {
  1058. case DBGSYM:
  1059. // Status info, a match was found
  1060. pSymErr->SymbolFileFound = TRUE;
  1061. _tcscpy(pSymErr->szSymbolFileName, szResult);
  1062. // Validate the DBG file
  1063. if ( CompDbg(pelem1, szResult, pSymErr) ) {
  1064. return (TRUE);
  1065. }
  1066. break;
  1067. case PDBSYM:
  1068. // Status info, a match was found
  1069. pSymErr->PdbFileFound = TRUE;
  1070. _tcscpy(pSymErr->szPdbFileName, szResult);
  1071. // Validate the PDB file
  1072. if ( CompPdb(pelem1, szResult, pSymErr, szRSDSDllToLoad) ) {
  1073. return (TRUE);
  1074. }
  1075. break;
  1076. default: break;
  1077. }
  1078. }
  1079. // Now try the path with szPathExt at the end of it
  1080. // Don't try it if current path already has the extension
  1081. // at the end of it
  1082. CurLen = _tcslen(szCurPath);
  1083. ExtLen = _tcslen(szPathExt);
  1084. if ( _tcscmp ( (szCurPath + CurLen - ExtLen), szPathExt ) ) {
  1085. _tcscpy(szExtPath, szCurPath);
  1086. _tcscat(szExtPath, _T("\\") );
  1087. _tcscat(szExtPath, szPathExt);
  1088. FoundLength = SearchPath( szExtPath,
  1089. szFName,
  1090. NULL,
  1091. dwResultLength,
  1092. szResult,
  1093. &szResultFileName
  1094. );
  1095. if (FoundLength > 0 && FoundLength < dwResultLength) {
  1096. switch ( dSymType ) {
  1097. case DBGSYM:
  1098. // Status info, a match was found
  1099. pSymErr->SymbolFileFound = TRUE;
  1100. _tcscpy(pSymErr->szSymbolFileName, szResult);
  1101. // Validate the DBG file
  1102. if ( CompDbg(pelem1, szResult, pSymErr) ) {
  1103. return (TRUE);
  1104. }
  1105. break;
  1106. case PDBSYM:
  1107. // Status info, a match was found
  1108. pSymErr->PdbFileFound = TRUE;
  1109. _tcscpy(pSymErr->szPdbFileName, szResult);
  1110. // Validate the PDB file
  1111. if ( CompPdb(pelem1, szResult, pSymErr, szRSDSDllToLoad) ) {
  1112. return (TRUE);
  1113. }
  1114. break;
  1115. default: break;
  1116. }
  1117. }
  1118. }
  1119. szCurPath = _tcstok(NULL,seps);
  1120. }
  1121. // Symbol wasn't found. Put name of file into SymErr for error message
  1122. switch ( dSymType ) {
  1123. case DBGSYM:
  1124. _tcscpy(pSymErr->szSymbolFileName,szFName);
  1125. break;
  1126. case PDBSYM:
  1127. _tcscpy(pSymErr->szPdbFileName, szFName);
  1128. break;
  1129. default: break;
  1130. }
  1131. return (FALSE);
  1132. }
  1133. USHORT
  1134. __cdecl
  1135. CompDbg(
  1136. PVOID pelem1,
  1137. LPTSTR szSymName,
  1138. PSYM_ERR pSymErr
  1139. )
  1140. /*++
  1141. Routine Description:
  1142. Validates the DBG against the original image
  1143. Return Value:
  1144. TRUE - DBG matches
  1145. FALSE - DBG doesn't match timedatestamp and checksum
  1146. --*/
  1147. {
  1148. PFILE_INFO pFileInfo;
  1149. PIMAGE_SEPARATE_DEBUG_HEADER pDbgHeader;
  1150. HANDLE hFile;
  1151. pFileInfo = (PFILE_INFO)(pelem1);
  1152. pDbgHeader = MapDbgHeader ( szSymName, &hFile, pSymErr );
  1153. if (pDbgHeader == NULL) {
  1154. printf("ERROR: CompDbg(), %s was not opened successfully\n",szSymName);
  1155. UnmapFile((LPCVOID)pDbgHeader, hFile);
  1156. return FALSE;
  1157. }
  1158. if (pDbgHeader->Signature != IMAGE_SEPARATE_DEBUG_SIGNATURE) {
  1159. printf("ERROR: CompDbg(), %s doesn't have Debug signature in header\n", szSymName);
  1160. UnmapFile((LPCVOID)pDbgHeader, hFile);
  1161. return FALSE;
  1162. }
  1163. // Record specifics of whether timedatestamp and checksum matched
  1164. if ( pDbgHeader->SizeOfImage == pFileInfo->SizeOfImage ) {
  1165. pSymErr->SizeOfImageMatch = TRUE;
  1166. } else pSymErr->SizeOfImageMatch = FALSE;
  1167. if ( pDbgHeader->TimeDateStamp == pFileInfo->TimeDateStamp ) {
  1168. pSymErr->TimeDateStampsMatch = TRUE;
  1169. } else pSymErr->TimeDateStampsMatch = FALSE;
  1170. if ( pDbgHeader->CheckSum == pFileInfo->CheckSum ) {
  1171. pSymErr->CheckSumsMatch = TRUE;
  1172. } else pSymErr->CheckSumsMatch = FALSE;
  1173. // Just check the timedatestamp for determining if the DBG matches
  1174. // VC and KD don't pay attention to the checksum anymore.
  1175. if ( pSymErr->TimeDateStampsMatch &&
  1176. pSymErr->SizeOfImageMatch &&
  1177. ( !LogCheckSumErrors || pSymErr->CheckSumsMatch ) ) {
  1178. UnmapFile((LPCVOID)pDbgHeader, hFile);
  1179. return TRUE;
  1180. } else {
  1181. UnmapFile((LPCVOID)pDbgHeader, hFile);
  1182. return FALSE;
  1183. }
  1184. }
  1185. USHORT
  1186. __cdecl
  1187. CompPdb(
  1188. PVOID pelem1,
  1189. LPTSTR szSymName,
  1190. PSYM_ERR pSymErr,
  1191. LPTSTR szRSDSDllToLoad
  1192. )
  1193. /*++
  1194. Routine Description:
  1195. Validates the PDB
  1196. Return Value:
  1197. TRUE PDB validates
  1198. FALSE PDB doesn't validate
  1199. --*/
  1200. {
  1201. PCVDD pPdbInfo;
  1202. WCHAR wszSymName[_MAX_PATH + 1];
  1203. BOOL valid=FALSE;
  1204. PDB *pdb;
  1205. EC ec;
  1206. char szError[cbErrMax] = _T("");
  1207. wchar_t wszError[cbErrMax] = L"";
  1208. DBI *pdbi;
  1209. HMODULE hDll;
  1210. pdb=NULL;
  1211. pPdbInfo = (PCVDD)(pelem1);
  1212. switch (pPdbInfo->dwSig)
  1213. {
  1214. case '01BN':
  1215. __try
  1216. {
  1217. valid = PDBOpenValidate(szSymName,
  1218. NULL,
  1219. _T("r"),
  1220. pPdbInfo->nb10i.sig,
  1221. pPdbInfo->nb10i.age,
  1222. &ec,
  1223. szError,
  1224. &pdb
  1225. );
  1226. if ( !valid ) {
  1227. pSymErr->PdbValid = FALSE;
  1228. __leave;
  1229. } else pSymErr->PdbValid = TRUE;
  1230. if (!CheckPrivate) {
  1231. PDBClose(pdb);
  1232. __leave;
  1233. }
  1234. // Verify that private information is stripped
  1235. // Verify that line information is removed
  1236. if ( !PDBOpenDBI(pdb, pdbRead, NULL, &pdbi) ) {
  1237. // OpenDBI failed
  1238. pSymErr->PdbValid = FALSE;
  1239. pSymErr->ErrNo = PDB_MAY_BE_CORRUPT;
  1240. DBIClose(pdbi);
  1241. __leave;
  1242. }
  1243. if ( !PDBPrivateStripped(pdb, pdbi) ) {
  1244. //Error - Source line info is not stripped
  1245. pSymErr->PdbValid = FALSE;
  1246. pSymErr->ErrNo = PRIVATE_INFO_NOT_REMOVED;
  1247. }
  1248. DBIClose(pdbi);
  1249. PDBClose(pdb);
  1250. }
  1251. __except( EXCEPTION_EXECUTE_HANDLER )
  1252. {
  1253. pSymErr->PdbValid = FALSE;
  1254. valid=FALSE;
  1255. }
  1256. return (USHORT)pSymErr->PdbValid;
  1257. break;
  1258. case 'SDSR':
  1259. #if defined(use_SymutilX)
  1260. if ( !RSDSLibLoaded ) {
  1261. hDll = LoadLibrary( szRSDSDllToLoad );
  1262. if (hDll != NULL) {
  1263. RSDSLibLoaded = TRUE;
  1264. pPDBOpenValidate4 = ( PPDBOPENVALIDATE4 ) GetProcAddress( hDll, "PDBOpenValidate4" );
  1265. if (pPDBOpenValidate4 == NULL ) {
  1266. _tcscpy(pSymErr->szPdbErr,"Cannot load PDBOpenValidate4");
  1267. return (FALSE);
  1268. }
  1269. pPDBClose = ( PPDBCLOSE ) GetProcAddress( hDll, "PDBClose" );
  1270. if (pPDBClose == NULL ) {
  1271. _tcscpy(pSymErr->szPdbErr,"Cannot load PDBClose");
  1272. return (FALSE);
  1273. }
  1274. } else {
  1275. if (_tcslen(szRSDSDllToLoad) + _tcslen("Cannot load ") + 1 < MAX_PDB_ERR ) {
  1276. _tcscpy(pSymErr->szPdbErr,"Cannot load ");
  1277. _tcscat(pSymErr->szPdbErr, szRSDSDllToLoad);
  1278. } else {
  1279. pSymErr->ErrNo = CANNOT_LOAD_RSDS;
  1280. }
  1281. pSymErr->PdbValid = FALSE;
  1282. return (FALSE);
  1283. }
  1284. }
  1285. #endif
  1286. ansi2wcs(szSymName, wszSymName, lengthof(wszSymName));
  1287. __try
  1288. {
  1289. #if defined(use_SymutilX)
  1290. valid = pPDBOpenValidate4(wszSymName,
  1291. #else
  1292. valid = PDBOpenValidate4(wszSymName,
  1293. #endif
  1294. _T("r"),
  1295. (PCSIG70) &(pPdbInfo->rsdsi.guidSig),
  1296. 0,
  1297. (AGE) pPdbInfo->rsdsi.age,
  1298. &ec,
  1299. wszError,
  1300. cbErrMax,
  1301. &pdb
  1302. );
  1303. }
  1304. __except( EXCEPTION_EXECUTE_HANDLER )
  1305. {
  1306. valid = FALSE;
  1307. }
  1308. if ( !valid ) {
  1309. pSymErr->PdbValid = FALSE;
  1310. return FALSE;
  1311. } else pSymErr->PdbValid = TRUE;
  1312. if (!CheckPrivate) {
  1313. #if defined(use_SymutilX)
  1314. pPDBClose(pdb);
  1315. #else
  1316. PDBClose(pdb);
  1317. #endif
  1318. return (USHORT)pSymErr->PdbValid;
  1319. }
  1320. // Verify that private information is stripped
  1321. // Verify that line information is removed
  1322. #if defined(use_SymutilX)
  1323. if ( pDBIQueryNextMod == NULL ) {
  1324. pDBIQueryNextMod = ( PDBIQUERYNEXTMOD ) GetProcAddress( hDll, "DBIQueryNextMod" );
  1325. if (pPDBOpenValidate4 == NULL ) {
  1326. _tcscpy(pSymErr->szPdbErr,"Cannot load PDBClose, GetProcAddress failed.");
  1327. return (FALSE);
  1328. }
  1329. }
  1330. if ( pModClose == NULL ) {
  1331. pModClose = ( PMODCLOSE ) GetProcAddress( hDll, "ModClose" );
  1332. if (pModClose == NULL ) {
  1333. _tcscpy(pSymErr->szPdbErr,"Cannot load PDBClose, GetProcAddress failed.");
  1334. return (FALSE);
  1335. }
  1336. }
  1337. if ( pModQueryLines == NULL ) {
  1338. pModQueryLines = ( PMODQUERYLINES ) GetProcAddress( hDll, "ModQueryLines" );
  1339. if (pModQueryLines == NULL ) {
  1340. _tcscpy(pSymErr->szPdbErr,"Cannot load ModQueryLines, GetProcAddress failed.");
  1341. return (FALSE);
  1342. }
  1343. }
  1344. if ( pModQuerySymbols == NULL ) {
  1345. pModQuerySymbols = ( PMODQUERYSYMBOLS ) GetProcAddress( hDll, "ModQuerySymbols" );
  1346. if (pModQuerySymbols == NULL ) {
  1347. _tcscpy(pSymErr->szPdbErr,"Cannot load ModQuerySymbols, GetProcAddress failed.");
  1348. return (FALSE);
  1349. }
  1350. }
  1351. if ( pDBIQueryTypeServer == NULL ) {
  1352. pDBIQueryTypeServer = ( PDBIQUERYTYPESERVER ) GetProcAddress( hDll, "DBIQueryTypeServer" );
  1353. if (pDBIQueryTypeServer == NULL ) {
  1354. _tcscpy(pSymErr->szPdbErr,"Cannot load DBIQueryTypeServer, GetProcAddress failed.");
  1355. return (FALSE);
  1356. }
  1357. }
  1358. if ( pPDBOpenTpi == NULL ) {
  1359. pPDBOpenTpi = ( PPDBOPENTPI ) GetProcAddress( hDll, "PDBOpenTpi" );
  1360. if (pPDBOpenTpi == NULL ) {
  1361. _tcscpy(pSymErr->szPdbErr,"Cannot load PDBOpenTpi, GetProcAddress failed.");
  1362. return (FALSE);
  1363. }
  1364. }
  1365. if ( pTypesQueryTiMinEx == NULL ) {
  1366. pTypesQueryTiMinEx = ( PTYPESQUERYTIMINEX ) GetProcAddress( hDll, "TypesQueryTiMinEx" );
  1367. if (pTypesQueryTiMinEx == NULL ) {
  1368. _tcscpy(pSymErr->szPdbErr,"Cannot load TypesQueryTiMinEx, GetProcAddress failed.");
  1369. return (FALSE);
  1370. }
  1371. }
  1372. if ( pTypesQueryTiMacEx == NULL ) {
  1373. pTypesQueryTiMacEx = ( PTYPESQUERYTIMACEX ) GetProcAddress( hDll, "TypesQueryTiMacEx" );
  1374. if (pTypesQueryTiMacEx == NULL ) {
  1375. _tcscpy(pSymErr->szPdbErr,"Cannot load TypesQueryTiMacEx, GetProcAddress failed.");
  1376. return (FALSE);
  1377. }
  1378. }
  1379. if ( pTypesClose == NULL ) {
  1380. pTypesClose = ( PTYPESCLOSE ) GetProcAddress( hDll, "TypesClose" );
  1381. if (pTypesClose == NULL ) {
  1382. _tcscpy(pSymErr->szPdbErr,"Cannot load TypesClose, GetProcAddress failed.");
  1383. return (FALSE);
  1384. }
  1385. }
  1386. if ( pPDBOpenDBI == NULL ) {
  1387. pPDBOpenDBI = ( PPDBOPENDBI ) GetProcAddress( hDll, "PDBOpenDBI" );
  1388. if (pPDBOpenDBI == NULL ) {
  1389. _tcscpy(pSymErr->szPdbErr,"Cannot load PDBOpenDBI, GetProcAddress failed.");
  1390. return (FALSE);
  1391. }
  1392. }
  1393. if ( pDBIClose == NULL ) {
  1394. pDBIClose = ( PDBICLOSE ) GetProcAddress( hDll, "DBIClose" );
  1395. if (pDBIClose == NULL ) {
  1396. _tcscpy(pSymErr->szPdbErr,"Cannot load DBIClose, GetProcAddress failed.");
  1397. return (FALSE);
  1398. }
  1399. }
  1400. if ( !pPDBOpenDBI(pdb, pdbRead, NULL, &pdbi) ) {
  1401. // OpenDBI failed
  1402. pSymErr->ErrNo = PDB_MAY_BE_CORRUPT;
  1403. pDBIClose(pdbi);
  1404. return FALSE;
  1405. }
  1406. if ( !PDBPrivateStrippedX(pdb, pdbi) ) {
  1407. //Error - Source line info is not stripped
  1408. pSymErr->PdbValid = FALSE;
  1409. pSymErr->ErrNo = PRIVATE_INFO_NOT_REMOVED;
  1410. }
  1411. pDBIClose(pdbi);
  1412. pPDBClose(pdb);
  1413. return (USHORT)pSymErr->PdbValid;
  1414. break;
  1415. #else
  1416. if ( !PDBOpenDBI(pdb, pdbRead, NULL, &pdbi) ) {
  1417. // OpenDBI failed
  1418. pSymErr->ErrNo = PDB_MAY_BE_CORRUPT;
  1419. DBIClose(pdbi);
  1420. return FALSE;
  1421. }
  1422. if ( !PDBPrivateStripped(pdb, pdbi) ) {
  1423. //Error - Source line info is not stripped
  1424. pSymErr->PdbValid = FALSE;
  1425. pSymErr->ErrNo = PRIVATE_INFO_NOT_REMOVED;
  1426. }
  1427. DBIClose(pdbi);
  1428. PDBClose(pdb);
  1429. return (USHORT)pSymErr->PdbValid;
  1430. break;
  1431. #endif
  1432. default: break;
  1433. }
  1434. return (FALSE);
  1435. }
  1436. BOOL
  1437. ResourceOnlyDll(
  1438. PVOID pImageBase,
  1439. BOOLEAN bMappedAsImage
  1440. )
  1441. /*++
  1442. Routine Description:
  1443. Returns true if the image is a resource only dll.
  1444. --*/
  1445. {
  1446. PVOID pExports, pImports, pResources;
  1447. DWORD dwExportSize, dwImportSize, dwResourceSize;
  1448. BOOL fResourceOnlyDll;
  1449. pExports = ImageDirectoryEntryToData(pImageBase,
  1450. bMappedAsImage,
  1451. IMAGE_DIRECTORY_ENTRY_EXPORT,
  1452. &dwExportSize);
  1453. pImports = ImageDirectoryEntryToData(pImageBase,
  1454. bMappedAsImage,
  1455. IMAGE_DIRECTORY_ENTRY_IMPORT,
  1456. &dwImportSize);
  1457. pResources = ImageDirectoryEntryToData(pImageBase,
  1458. bMappedAsImage,
  1459. IMAGE_DIRECTORY_ENTRY_RESOURCE,
  1460. &dwResourceSize);
  1461. if (pResources && dwResourceSize &&
  1462. !pImports && !dwImportSize &&
  1463. !pExports && !dwExportSize) {
  1464. return (TRUE);
  1465. } else {
  1466. return (FALSE);
  1467. }
  1468. }
  1469. BOOL
  1470. LogError(
  1471. LPTSTR ErrMsg,
  1472. PSYM_ERR pSymErr,
  1473. UINT ErrNo )
  1474. {
  1475. TCHAR szFName[_MAX_FNAME];
  1476. TCHAR szExt[_MAX_EXT];
  1477. TCHAR szCurName[_MAX_FNAME];
  1478. if (pSymErr->ErrNo != 0) ErrNo = pSymErr->ErrNo;
  1479. // Get the file name without any path info:
  1480. _tsplitpath(pSymErr->szFileName,NULL,NULL,szFName,szExt);
  1481. _tcscpy(szCurName,szFName);
  1482. _tcscat(szCurName,szExt);
  1483. _tcscpy(ErrMsg,_T(""));
  1484. // See if this is a file that we aren't supposed to report errors
  1485. // for. If it is, just return without writing an error.
  1486. if ( pErrorFilterList != NULL ) {
  1487. if ( InExcludeList( szCurName, pErrorFilterList ) ) {
  1488. return(TRUE);
  1489. }
  1490. }
  1491. switch (ErrNo) {
  1492. case NO_DEBUG_DIRECTORIES:
  1493. _stprintf(ErrMsg, "%-20s FAILED - Built with no debugging information\n",
  1494. szCurName);
  1495. return(TRUE);
  1496. case NO_DEBUG_DIRECTORIES_IN_DBG_HEADER:
  1497. _stprintf(ErrMsg, "%-20s FAILED - Image header has no debugging information\n",
  1498. szCurName);
  1499. return(TRUE);
  1500. case NO_MISC_ENTRY:
  1501. _stprintf(ErrMsg, "%-20s FAILED - No MISC entry in debug directories\n",
  1502. szCurName);
  1503. return(TRUE);
  1504. case NO_FILE_IN_MISC:
  1505. _stprintf(ErrMsg, "%-20s FAILED - MISC entry contains no .dbg file information\n",
  1506. szCurName);
  1507. return(TRUE);
  1508. case ERROR_IF_SPLIT:
  1509. _stprintf(ErrMsg, "%-20s FAILED - Image points to a .DBG symbol file - fix with dbgtopdb.exe\n",
  1510. szCurName);
  1511. return(TRUE);
  1512. case ERROR_IF_NOT_SPLIT:
  1513. _stprintf(ErrMsg, "%-20s FAILED - Image contains .DBG file data - fix with dbgtopdb.exe\n",
  1514. szCurName);
  1515. return(TRUE);
  1516. case EXTRA_RAW_DATA_IN_6:
  1517. _stprintf(ErrMsg, "%-20s FAILED - No misc entry, but debug directories point to non-Codeview data\n",
  1518. szCurName );
  1519. return (TRUE);
  1520. case IGNORE_IF_SPLIT:
  1521. if ( pSymErr->Verbose) {
  1522. _stprintf(ErrMsg, "%-20s IGNORED - Image is already split\n",szCurName);
  1523. }
  1524. return(TRUE);
  1525. case NO_CODE_VIEW:
  1526. _stprintf(ErrMsg, "%-20s FAILED - %s does not have a pointer to CodeView information\n",
  1527. szCurName, pSymErr->szSymbolFileName);
  1528. return(TRUE);
  1529. case FILE_NOT_FOUND:
  1530. _stprintf(ErrMsg, "%-20s FAILED - File does not exist\n",szCurName);
  1531. return(TRUE);
  1532. case CREATE_FILE_FAILED :
  1533. if ( pSymErr->Verbose) {
  1534. _stprintf(ErrMsg, "%-20s IGNORED - Image is not a valid NT image.\n", szCurName);
  1535. }
  1536. return(TRUE);
  1537. case CREATE_FILE_MAPPING_FAILED :
  1538. if ( pSymErr->Verbose) {
  1539. _stprintf(ErrMsg, "%-20s IGNORED - Image is not a valid NT image.\n", szCurName);
  1540. }
  1541. return(TRUE);
  1542. case MAPVIEWOFFILE_FAILED :
  1543. if ( pSymErr->Verbose) {
  1544. _stprintf(ErrMsg, "%-20s IGNORED - Image is not a valid NT image.\n", szCurName);
  1545. }
  1546. return(TRUE);
  1547. case GET_FILE_INFO_FAILED :
  1548. if ( pSymErr->Verbose) {
  1549. _stprintf(ErrMsg, "%-20s IGNORED - Image is not a valid NT image.\n", szCurName);
  1550. }
  1551. return(TRUE);
  1552. case HEADER_NOT_ON_LONG_BOUNDARY:
  1553. // Not an NT image - ignore the error
  1554. if (pSymErr->Verbose) {
  1555. _stprintf(ErrMsg, "%-20s IGNORED - This is either corrupt or a DOS image\n", szCurName);
  1556. }
  1557. return(TRUE);
  1558. case IMAGE_BIGGER_THAN_FILE:
  1559. if (pSymErr->Verbose) {
  1560. _stprintf(ErrMsg, "%-20s IGNORED - This is either corrupt or a DOS image\n", szCurName);
  1561. }
  1562. return(TRUE);
  1563. case INVALID_ADDRESSOFRAWDATA_ZERO_DEBUG:
  1564. _stprintf(ErrMsg, "%-20s FAILED - Invalid AddressOfRawData for zero sized debug info\n",
  1565. szCurName);
  1566. return(TRUE);
  1567. case INVALID_POINTERTORAWDATA_NON_ZERO:
  1568. _stprintf(ErrMsg, "%-20s FAILED - Invalid PointerToRawData for non-zero sized debug info\n",
  1569. szCurName);
  1570. return(TRUE);
  1571. case INVALID_POINTERTORAWDATA_ZERO_DEBUG:
  1572. _stprintf(ErrMsg, "%-20s FAILED - Invalid PointerToRawData for zero sized debug info\n",
  1573. szCurName);
  1574. return(TRUE);
  1575. case NO_DOS_HEADER:
  1576. if ( pSymErr->Verbose) {
  1577. _stprintf(ErrMsg, "%-20s IGNORED - Image does not have a DOS header\n",
  1578. szCurName);
  1579. }
  1580. return(TRUE);
  1581. case NOT_NT_IMAGE:
  1582. if ( pSymErr->Verbose) {
  1583. _stprintf(ErrMsg, "%-20s IGNORED - Image does not have an NT header\n",
  1584. szCurName);
  1585. }
  1586. return(TRUE);
  1587. case IMAGE_PASSED :
  1588. if ( pSymErr->Verbose) {
  1589. _stprintf(ErrMsg, "%-20s PASSED \n",szCurName);
  1590. }
  1591. return(TRUE);
  1592. case RESOURCE_ONLY_DLL:
  1593. if ( pSymErr->Verbose) {
  1594. _stprintf(ErrMsg, "%-20s IGNORED - Resource only DLL\n",szCurName);
  1595. }
  1596. return(TRUE);
  1597. case SIGNED_AND_NON_SPLIT:
  1598. _stprintf(ErrMsg, "%-20s FAILED - It is signed and debug info can't be stripped without invalidating the signature\n",
  1599. szCurName);
  1600. return(TRUE);
  1601. default:
  1602. return(TRUE);
  1603. }
  1604. return (FALSE);
  1605. }
  1606. BOOL
  1607. LogDbgError(
  1608. LPTSTR ErrMsg,
  1609. PSYM_ERR pSymErr
  1610. )
  1611. {
  1612. TCHAR szFName[_MAX_FNAME];
  1613. TCHAR szExt[_MAX_EXT];
  1614. TCHAR szCurName[_MAX_FNAME];
  1615. TCHAR szSymName[_MAX_FNAME];
  1616. // Get the file name without any path info:
  1617. _tsplitpath(pSymErr->szFileName,NULL,NULL,szFName,szExt);
  1618. _tcscpy(szCurName,szFName);
  1619. _tcscat(szCurName,szExt);
  1620. _tcscpy(ErrMsg,_T("") );
  1621. // See if this is a file that we aren't supposed to report errors
  1622. // for. If it is, just return without writing an error.
  1623. if ( pErrorFilterList != NULL ) {
  1624. if ( InExcludeList( szCurName, pErrorFilterList ) ) {
  1625. return(TRUE);
  1626. }
  1627. }
  1628. // Get the file name without any path info:
  1629. _tsplitpath(pSymErr->szSymbolFileName,NULL,NULL,szFName,szExt);
  1630. _tcscpy(szSymName,szFName);
  1631. _tcscat(szSymName,szExt);
  1632. if ( !pSymErr->SymbolFileFound ) {
  1633. _stprintf(ErrMsg, "%-20s FAILED - Image is split correctly, but %s is missing\n",
  1634. szCurName, szSymName);
  1635. return(TRUE);
  1636. }
  1637. if ( LogCheckSumErrors && !pSymErr->CheckSumsMatch) {
  1638. _stprintf(ErrMsg, "%-20s FAILED - Checksum doesn't match with %s\n",
  1639. szCurName, szSymName);
  1640. return(TRUE);
  1641. }
  1642. if ( !pSymErr->SizeOfImageMatch) {
  1643. _stprintf(ErrMsg, "%-20s FAILED - Size of image doesn't match with %s\n",
  1644. szCurName, szSymName);
  1645. return(TRUE);
  1646. }
  1647. if ( !pSymErr->TimeDateStampsMatch) {
  1648. _stprintf(ErrMsg, "%-20s FAILED - Timedate stamp doesn't match with %s\n",
  1649. szCurName, szSymName);
  1650. return(TRUE);
  1651. }
  1652. return(TRUE);
  1653. }
  1654. BOOL
  1655. LogPdbError(
  1656. LPTSTR ErrMsg,
  1657. PSYM_ERR pSymErr
  1658. )
  1659. {
  1660. TCHAR szFName[_MAX_FNAME];
  1661. TCHAR szExt[_MAX_EXT];
  1662. TCHAR szCurName[_MAX_FNAME];
  1663. TCHAR szSymName[_MAX_FNAME];
  1664. TCHAR szPdbName[_MAX_FNAME];
  1665. // Get the file name without any path info:
  1666. _tsplitpath(pSymErr->szFileName,NULL,NULL,szFName,szExt);
  1667. _tcscpy(szCurName,szFName);
  1668. _tcscat(szCurName,szExt);
  1669. _tcscpy(ErrMsg,_T("") );
  1670. // See if this is a file that we aren't supposed to report errors
  1671. // for. If it is, just return without writing an error.
  1672. if ( pErrorFilterList != NULL ) {
  1673. if ( InExcludeList( szCurName, pErrorFilterList ) ) {
  1674. return(TRUE);
  1675. }
  1676. }
  1677. // Get the file name without any path info:
  1678. _tsplitpath(pSymErr->szSymbolFileName,NULL,NULL,szFName,szExt);
  1679. _tcscpy(szSymName,szFName);
  1680. _tcscat(szSymName,szExt);
  1681. // Get the file name without any path info:
  1682. _tsplitpath(pSymErr->szPdbFileName,NULL,NULL,szFName,szExt);
  1683. _tcscpy(szPdbName,szFName);
  1684. _tcscat(szPdbName,szExt);
  1685. if (pSymErr->ErrNo == NO_CODE_VIEW) {
  1686. _stprintf(ErrMsg, "%-20s FAILED - %s does not point to CodeView information\n",
  1687. szCurName, szSymName);
  1688. return(TRUE);
  1689. }
  1690. if (pSymErr->ErrNo == PRIVATE_INFO_NOT_REMOVED) {
  1691. _stprintf(ErrMsg, "%-20s FAILED - %s contains private information\n",
  1692. szCurName, szPdbName);
  1693. return(TRUE);
  1694. }
  1695. if (pSymErr->ErrNo == PDB_MAY_BE_CORRUPT) {
  1696. _stprintf(ErrMsg, "%-20s FAILED - %s may be corrupt\n",
  1697. szCurName, szPdbName);
  1698. return(TRUE);
  1699. }
  1700. if (pSymErr->ErrNo == CANNOT_LOAD_RSDS) {
  1701. _stprintf(ErrMsg, "%-20s FAILED - Cannot load the RSDS dll \n",
  1702. szCurName);
  1703. return(TRUE);
  1704. }
  1705. if ( _tcscmp(pSymErr->szPdbErr,_T("") ) ) {
  1706. _stprintf(ErrMsg, "%-20s FAILED - %s\n",szCurName, pSymErr->szPdbErr );
  1707. return(TRUE);
  1708. }
  1709. if ( pSymErr->SymbolFileFound && !pSymErr->PdbFileFound ) {
  1710. _stprintf(ErrMsg, "%-20s FAILED - %s is correct, but %s is missing\n",
  1711. szCurName, szSymName, szPdbName);
  1712. return(TRUE);
  1713. }
  1714. if ( !pSymErr->PdbFileFound ) {
  1715. _stprintf(ErrMsg, "%-20s FAILED - %s is missing \n",szCurName,szPdbName );
  1716. return(TRUE);
  1717. }
  1718. // There was a DBG file, but PDB file didn't validate
  1719. if ( pSymErr->SymbolFileFound && !pSymErr->PdbValid ) {
  1720. _stprintf(ErrMsg, "%-20s FAILED - %s and %s signatures do not match\n",
  1721. szCurName, szSymName, szPdbName);
  1722. return(TRUE);
  1723. }
  1724. // There isn't supposed to be a DBG file. PDB doesn't validate against
  1725. // image.
  1726. if ( !pSymErr->PdbValid ) {
  1727. _stprintf(ErrMsg, "%-20s FAILED - signature does not match %s\n",
  1728. szCurName, szPdbName );
  1729. return(TRUE);
  1730. }
  1731. return(FALSE);
  1732. }
  1733. BOOL AddToSymbolsCDLog(
  1734. FILE *hSymCDLog,
  1735. PSYM_ERR pSymErr,
  1736. LPTSTR szSymbolPath,
  1737. LPTSTR szFileExt
  1738. )
  1739. /*
  1740. szSymbolPath is the full path and name to the symbol file
  1741. szFileExt is the extension of the image without the '.' at
  1742. the front
  1743. */
  1744. {
  1745. LPTSTR szSrc;
  1746. LPTSTR szDest;
  1747. LPTSTR szTmp;
  1748. TCHAR szFName[_MAX_FNAME+1];
  1749. TCHAR szExt[_MAX_EXT+1];
  1750. TCHAR szCurName[_MAX_FNAME + _MAX_EXT + 1];
  1751. TCHAR szDestDir[_MAX_PATH];
  1752. TCHAR szSymName[_MAX_FNAME + 1];
  1753. TCHAR szSymExt[_MAX_EXT + 1];
  1754. // If there is a list of the files that belong on the
  1755. // CD, then only write this file to the log for the
  1756. // symbol CD if the file is in the list
  1757. //
  1758. // Originally, this was used for the international
  1759. // incremental builds.
  1760. //
  1761. if ( pCDIncludeList != NULL ) {
  1762. if ( !InList( szSymbolPath, pCDIncludeList ) ) {
  1763. return (TRUE);
  1764. }
  1765. }
  1766. // Get the file name without any path info:
  1767. _tsplitpath(pSymErr->szFileName,NULL,NULL,szFName,szExt);
  1768. _tcscpy(szCurName,szFName);
  1769. // Put the path below "binaries" as the source
  1770. szSrc = _tcsstr(szSymbolPath, _T("symbols\\") );
  1771. if (szSrc == NULL) {
  1772. printf("%s: Cannot find \"symbols\\\" in the symbol file's path\n",
  1773. szCurName);
  1774. exit(1);
  1775. }
  1776. if ( _tcscmp( szSrc, _T("symbols\\") ) == 0 ) {
  1777. printf("Symbol file name cannot end with \"symbols\\\"\n");
  1778. exit(1);
  1779. }
  1780. // Move the Destination up to the directory after symbols. If this is
  1781. // the retail directory, don't include retail in the path.
  1782. szDest = szSrc + _tcslen(_T("symbols\\"));
  1783. if ( _tcsncmp( szDest, _T("retail\\"), _tcslen(_T("retail\\")) ) == 0 ) {
  1784. szDest = szDest + _tcslen(_T("retail\\"));
  1785. }
  1786. _tsplitpath(szDest,NULL,szDestDir,NULL,NULL);
  1787. // Remove the '\' from the end of the string;
  1788. szTmp = szDestDir + _tcslen(szDestDir) - 1;
  1789. while ( _tcscmp( szTmp, _T("\\")) == 0 ) {
  1790. _tcscpy( szTmp, _T("") );
  1791. szTmp--;
  1792. }
  1793. // get the symbol file name
  1794. _tsplitpath(szSymbolPath,NULL,NULL,szSymName,szSymExt);
  1795. RemoveDuplicateSlashes(pSymErr->szFileName);
  1796. fprintf(hSymCDLog, "%s,%s%s,%s,%s\n", pSymErr->szFileName,
  1797. szSymName,szSymExt,szSrc,szDestDir);
  1798. return (TRUE);
  1799. }
  1800. P_LIST
  1801. GetList(
  1802. LPTSTR szFileName
  1803. )
  1804. {
  1805. /* GetList gets the list and keeps the original file name which could
  1806. * have included the path to the file
  1807. * Note, it can be merged with GetExcludeList. I first created it for
  1808. * use in creating the symbols CD, and didn't want to risk entering a
  1809. * bug into symchk
  1810. */
  1811. P_LIST pList;
  1812. FILE *fFile;
  1813. TCHAR szCurFile[_MAX_FNAME+1], *c;
  1814. TCHAR fname[_MAX_FNAME+1], ext[_MAX_EXT+1];
  1815. DWORD i;
  1816. LPTSTR szEndName;
  1817. if ( (fFile = _tfopen(szFileName,_T("r") )) == NULL )
  1818. {
  1819. // printf( "Cannot open the exclude file %s\n",szFileName );
  1820. return NULL;
  1821. }
  1822. pList = (P_LIST)malloc(sizeof(LIST));
  1823. if (pList)
  1824. {
  1825. pList->dNumFiles = 0;
  1826. while ( _fgetts(szCurFile,_MAX_FNAME,fFile) )
  1827. {
  1828. if ( szCurFile[0] == ';' ) continue;
  1829. (pList->dNumFiles)++;
  1830. }
  1831. // Go back to the beginning of the file
  1832. fseek(fFile,0,0);
  1833. pList->List = (LIST_ELEM*)malloc( sizeof(LIST_ELEM) *
  1834. (pList->dNumFiles));
  1835. if (pList->List == NULL)
  1836. {
  1837. free(pList);
  1838. pList = NULL;
  1839. }
  1840. else
  1841. {
  1842. i = 0;
  1843. while ( i < pList->dNumFiles )
  1844. {
  1845. memset(szCurFile,'\0',sizeof(TCHAR) * (_MAX_FNAME+1) );
  1846. _fgetts(szCurFile,_MAX_FNAME,fFile);
  1847. // Replace the \n with \0
  1848. c = NULL;
  1849. c = _tcschr(szCurFile, '\n');
  1850. if ( c != NULL) *c='\0';
  1851. if ( szCurFile[0] == ';' ) continue;
  1852. if ( _tcslen(szCurFile) > _MAX_FNAME ) {
  1853. printf("File %s has a string that is too large\n",szFileName);
  1854. free(pList->List);
  1855. free(pList);
  1856. fclose(fFile);
  1857. return(NULL);
  1858. }
  1859. // Allow for spaces and a ; after the file name
  1860. // Move the '\0' back until it has erased the ';' and any
  1861. // tabs and spaces that might come before it
  1862. szEndName = _tcschr(szCurFile, ';');
  1863. // Set the pointer to the last character in the string if
  1864. // there wasn't a comment
  1865. if (szEndName == NULL ) {
  1866. if (_tcslen(szCurFile) > 0 ) {
  1867. szEndName = szCurFile + _tcslen(szCurFile) - 1;
  1868. }
  1869. }
  1870. if (szEndName != NULL ) {
  1871. while ( *szEndName == ';' || *szEndName == ' '
  1872. || *szEndName == '\t' ) {
  1873. *szEndName = '\0';
  1874. if ( szEndName > szCurFile ) szEndName--;
  1875. }
  1876. }
  1877. _tcscpy(pList->List[i].Path,szCurFile);
  1878. _tsplitpath(szCurFile,NULL,NULL,fname,ext);
  1879. _tcscpy(pList->List[i].FName,fname);
  1880. _tcscat(pList->List[i].FName,ext);
  1881. i++;
  1882. }
  1883. // Sort the List
  1884. dbg_qsort( (void*)pList->List, (size_t)pList->dNumFiles,
  1885. (size_t)sizeof(LIST_ELEM), SymComp2 );
  1886. }
  1887. }
  1888. fclose(fFile);
  1889. return (pList);
  1890. }
  1891. int __cdecl
  1892. SymComp2(
  1893. const void *e1,
  1894. const void *e2
  1895. )
  1896. {
  1897. LPTSTR p1,n1;
  1898. LPTSTR p2,n2;
  1899. int rc;
  1900. p1 = ((LIST_ELEM*)e1)->FName;
  1901. p2 = ((LIST_ELEM*)e2)->FName;
  1902. n1 = ((LIST_ELEM*)e1)->Path;
  1903. n2 = ((LIST_ELEM*)e2)->Path;
  1904. rc = _tcsicmp(p1,p2);
  1905. if (rc == 0) return ( _tcsicmp(n1,n2) );
  1906. else return (rc);
  1907. }
  1908. BOOL PDBPrivateStripped(
  1909. PDB *ppdb,
  1910. DBI *pdbi
  1911. )
  1912. {
  1913. // Return values:
  1914. // FALSE - Private Information has NOT been stripped
  1915. // TRUE - Private Information has been stripped
  1916. Mod *pmod;
  1917. Mod *prevmod;
  1918. long cb;
  1919. unsigned itsm;
  1920. TPI *ptpi;
  1921. TI tiMin;
  1922. TI tiMac;
  1923. pmod = NULL;
  1924. prevmod=NULL;
  1925. while (DBIQueryNextMod(pdbi, pmod, &pmod) && pmod) {
  1926. if (prevmod != NULL) ModClose(prevmod);
  1927. // Check that Source line info is removed
  1928. ModQueryLines(pmod, NULL, &cb);
  1929. if (cb != 0) {
  1930. ModClose(pmod);
  1931. return FALSE;
  1932. }
  1933. // Check that local symbols are removed
  1934. ModQuerySymbols(pmod, NULL, &cb);
  1935. if (cb != 0) {
  1936. ModClose(pmod);
  1937. return FALSE;
  1938. }
  1939. prevmod=pmod;
  1940. }
  1941. if (pmod != NULL) ModClose(pmod);
  1942. if (prevmod != NULL) ModClose(prevmod);
  1943. // Check that types are removed
  1944. for ( itsm = 0; itsm < 256; itsm++) {
  1945. ptpi = 0;
  1946. if (DBIQueryTypeServer(pdbi, (ITSM) itsm, &ptpi)) {
  1947. continue;
  1948. }
  1949. if (!ptpi) {
  1950. PDBOpenTpi(ppdb, pdbRead, &ptpi);
  1951. tiMin = TypesQueryTiMinEx(ptpi);
  1952. tiMac = TypesQueryTiMacEx(ptpi);
  1953. if (tiMin < tiMac) {
  1954. TypesClose(ptpi);
  1955. return FALSE;
  1956. }
  1957. }
  1958. }
  1959. TypesClose(ptpi);
  1960. return (TRUE);
  1961. }
  1962. #if defined(use_SymutilX)
  1963. BOOL PDBPrivateStrippedX(
  1964. PDB *ppdb,
  1965. DBI *pdbi
  1966. )
  1967. {
  1968. // Return values:
  1969. // FALSE - Private Information has NOT been stripped
  1970. // TRUE - Private Information has been stripped
  1971. Mod *pmod;
  1972. Mod *prevmod;
  1973. long cb;
  1974. unsigned itsm;
  1975. TPI *ptpi;
  1976. TI tiMin;
  1977. TI tiMac;
  1978. pmod = NULL;
  1979. prevmod=NULL;
  1980. while (pDBIQueryNextMod(pdbi, pmod, &pmod) && pmod) {
  1981. if (prevmod != NULL) pModClose(prevmod);
  1982. // Check that Source line info is removed
  1983. pModQueryLines(pmod, NULL, &cb);
  1984. if (cb != 0) {
  1985. pModClose(pmod);
  1986. return FALSE;
  1987. }
  1988. // Check that local symbols are removed
  1989. pModQuerySymbols(pmod, NULL, &cb);
  1990. if (cb != 0) {
  1991. pModClose(pmod);
  1992. return FALSE;
  1993. }
  1994. prevmod=pmod;
  1995. }
  1996. if (pmod != NULL) pModClose(pmod);
  1997. if (prevmod != NULL) pModClose(prevmod);
  1998. // Check that types are removed
  1999. for ( itsm = 0; itsm < 256; itsm++) {
  2000. ptpi = 0;
  2001. if (pDBIQueryTypeServer(pdbi, (ITSM) itsm, &ptpi)) {
  2002. continue;
  2003. }
  2004. if (!ptpi) {
  2005. pPDBOpenTpi(ppdb, pdbRead, &ptpi);
  2006. tiMin = pTypesQueryTiMinEx(ptpi);
  2007. tiMac = pTypesQueryTiMacEx(ptpi);
  2008. if (tiMin < tiMac) {
  2009. pTypesClose(ptpi);
  2010. return FALSE;
  2011. }
  2012. }
  2013. }
  2014. pTypesClose(ptpi);
  2015. return (TRUE);
  2016. }
  2017. #endif
  2018. BOOL
  2019. RemoveDuplicateSlashes(
  2020. LPTSTR Str
  2021. ) {
  2022. ULONG i,j;
  2023. BOOL prev;
  2024. LPTSTR cur;
  2025. prev = FALSE; // False means the previous character was not a '\'
  2026. // True means the previous character was a '\'
  2027. j = _tcslen(Str);
  2028. if (j == 0 ) return TRUE;
  2029. cur = Str;
  2030. for (i=0; i< j; i++ ) {
  2031. if ( *(Str+i) == _T('\\') ) {
  2032. if ( prev == FALSE ) {
  2033. prev=TRUE;
  2034. *cur=*(Str+i);
  2035. cur++;
  2036. } else {
  2037. // do nothing
  2038. }
  2039. } else {
  2040. prev=FALSE;
  2041. *cur=*(Str+i);
  2042. cur++;
  2043. }
  2044. }
  2045. *cur=_T('\0');
  2046. return(TRUE);
  2047. }
  2048. BOOL
  2049. ansi2wcs(
  2050. PSTR psz,
  2051. PWSTR pwsz,
  2052. DWORD pwszlen
  2053. )
  2054. {
  2055. BOOL rc;
  2056. int len;
  2057. assert(psz && pwsz);
  2058. len = strlen(psz);
  2059. if (!len)
  2060. return FALSE;
  2061. rc = MultiByteToWideChar(CP_ACP,
  2062. MB_COMPOSITE,
  2063. psz,
  2064. len,
  2065. pwsz,
  2066. pwszlen);
  2067. if (!rc)
  2068. return FALSE;
  2069. pwsz[len] = 0;
  2070. return TRUE;
  2071. }