Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1904 lines
54 KiB

  1. #include <assert.h>
  2. #include <SymCommon.h>
  3. #include "symutil.h"
  4. #include "symutil_c.h"
  5. #include "share.h"
  6. #include "winbase.h"
  7. #include "symsrv.h"
  8. #include "output.hpp"
  9. #include "PEWhack.h"
  10. #include <string.h>
  11. #include "strsafe.h"
  12. // SymOutput *so;
  13. extern pSymOutput so;
  14. extern BOOL MSArchive;
  15. TCHAR szPriPubBin[4] = "";
  16. BOOL PrivateStripped=FALSE;
  17. // Stuff for Checking symbols
  18. // Typedefs
  19. typedef struct _FILE_INFO {
  20. DWORD TimeDateStamp;
  21. DWORD CheckSum;
  22. TCHAR szName[MAX_PATH];
  23. } FILE_INFO, *PFILE_INFO;
  24. BOOL
  25. AddToReferenceCount(
  26. LPTSTR szDir, // Directory where refs.ptr belongs
  27. LPTSTR szFileName, // Full path and name of the file that is referenced.
  28. LPTSTR szPtrOrFile, // Was a file or a pointer written
  29. BOOL DeleteRefsPtr // Flag to delete current refs.ptr and start over
  30. );
  31. BOOL
  32. DecidePriority(
  33. LPTSTR szCurrentFilePtr,
  34. LPTSTR szCandidateFilePtr,
  35. LPTSTR szRefsDir,
  36. PUINT choice
  37. );
  38. BOOL
  39. CheckPriPub(
  40. LPTSTR szDir,
  41. LPTSTR szFilePtr, // Current string that is in file.ptr
  42. LPTSTR szPubPriType // Return value - whether file.ptr is
  43. ); // a pri, pub, bin, or unknown
  44. PCHAR
  45. GetFileNameStart(
  46. LPTSTR FileName
  47. );
  48. PIMAGE_NT_HEADERS
  49. GetNtHeader (
  50. PIMAGE_DOS_HEADER pDosHeader,
  51. HANDLE hDosFile
  52. );
  53. BOOL
  54. GetSymbolServerDirs(
  55. LPTSTR szFileName,
  56. GUID *guid,
  57. DWORD dwNum1,
  58. DWORD dwNum2,
  59. LPTSTR szDirName
  60. );
  61. BOOL
  62. ReadFilePtr(
  63. LPTSTR szContents,
  64. HANDLE hFile
  65. );
  66. BOOL
  67. StoreFile(
  68. LPTSTR szDestDir,
  69. LPTSTR szFileName,
  70. LPTSTR szString2,
  71. LPTSTR szPtrFileName
  72. );
  73. BOOL
  74. StoreFilePtr(
  75. LPTSTR szDestDir,
  76. LPTSTR szString2,
  77. LPTSTR szPtrFileName
  78. );
  79. _TCHAR* _tcsistr(_TCHAR *s1, _TCHAR *s2) {
  80. /* Do case insensitve search for string 2 in string 1.
  81. */
  82. LONG i,j,k;
  83. k = _tcslen(s2);
  84. j = _tcslen(s1) - k + 1;
  85. // it is not fast way, but works
  86. for (i=0; i<j; i++)
  87. {
  88. if (_tcsnicmp( &s1[i], s2, k) == NULL)
  89. {
  90. return &s1[i];
  91. }
  92. }
  93. return NULL;
  94. }
  95. BOOL
  96. AddToReferenceCount(
  97. LPTSTR szDir, // Directory where refs.ptr belongs
  98. LPTSTR szFileName, // Full path and name of the file that is referenced.
  99. LPTSTR szPtrOrFile, // Was a file or a pointer written
  100. BOOL DeleteRefsPtr // Should we delete the current refs.ptr?
  101. )
  102. {
  103. HANDLE hFile;
  104. TCHAR szRefsEntry[_MAX_PATH * 3];
  105. TCHAR szRefsFileName[_MAX_PATH + 1];
  106. DWORD dwPtr=0;
  107. DWORD dwError=0;
  108. DWORD dwNumBytesToWrite=0;
  109. DWORD dwNumBytesWritten=0;
  110. BOOL FirstEntry = FALSE;
  111. DWORD First;
  112. StringCbPrintf( szRefsFileName, sizeof(szRefsFileName), "%s\\%s", szDir, _T("refs.ptr") );
  113. // Find out if this is the first entry in the file or not
  114. // First, try opening an existing file. If that doesn't work
  115. // then create a new one.
  116. First=1;
  117. do {
  118. FirstEntry = FALSE;
  119. hFile = CreateFile( szRefsFileName,
  120. GENERIC_READ | GENERIC_WRITE,
  121. 0,
  122. NULL,
  123. OPEN_EXISTING,
  124. FILE_ATTRIBUTE_NORMAL,
  125. NULL );
  126. if ( hFile == INVALID_HANDLE_VALUE ) {
  127. FirstEntry = TRUE;
  128. hFile = CreateFile( szRefsFileName,
  129. GENERIC_READ | GENERIC_WRITE,
  130. 0,
  131. NULL,
  132. CREATE_ALWAYS,
  133. FILE_ATTRIBUTE_NORMAL,
  134. NULL );
  135. }
  136. // Only print a message the first time through
  137. if ( First && hFile == INVALID_HANDLE_VALUE ) {
  138. First = 0;
  139. so->printf( "Trying to get write access to %s ...\n", szRefsFileName);
  140. }
  141. } while ( hFile == INVALID_HANDLE_VALUE);
  142. if (DeleteRefsPtr) {
  143. FirstEntry = TRUE;
  144. dwPtr = SetFilePointer ( hFile,
  145. 0,
  146. NULL,
  147. FILE_BEGIN );
  148. } else {
  149. dwPtr = SetFilePointer( hFile,
  150. 0,
  151. NULL,
  152. FILE_END );
  153. }
  154. if (dwPtr == INVALID_SET_FILE_POINTER) {
  155. // Obtain the error code.
  156. dwError = GetLastError() ;
  157. so->printf("Failed to set end of the file %s with GetLastError = %d\n",
  158. szRefsFileName, dwError);
  159. SetEndOfFile(hFile);
  160. CloseHandle(hFile);
  161. return(FALSE);
  162. }
  163. //
  164. // Put in a '\n' if this isn't the first entry
  165. //
  166. if ( FirstEntry ) {
  167. StringCbPrintf( szRefsEntry,
  168. sizeof(szRefsEntry),
  169. "%s,%s,%s,%s,,,,",
  170. pTrans->szId,
  171. szPtrOrFile,
  172. szFileName,
  173. szPriPubBin
  174. );
  175. } else {
  176. StringCbPrintf( szRefsEntry, sizeof(szRefsEntry), "\n%s,%s,%s,%s,,,,",
  177. pTrans->szId, szPtrOrFile, szFileName, szPriPubBin
  178. );
  179. }
  180. dwNumBytesToWrite = (_tcslen(szRefsEntry) ) * sizeof(TCHAR);
  181. WriteFile( hFile,
  182. (LPCVOID) szRefsEntry,
  183. dwNumBytesToWrite,
  184. &dwNumBytesWritten,
  185. NULL
  186. );
  187. if ( dwNumBytesToWrite != dwNumBytesWritten ) {
  188. so->printf( "FAILED to write %s, with GetLastError = %d\n",
  189. szRefsEntry,
  190. GetLastError()
  191. );
  192. SetEndOfFile(hFile);
  193. CloseHandle(hFile);
  194. return (FALSE);
  195. }
  196. SetEndOfFile(hFile);
  197. CloseHandle(hFile);
  198. return (TRUE);
  199. }
  200. BOOL
  201. CheckPriPub(
  202. LPTSTR szDir,
  203. LPTSTR szFilePtr, // Current string that is in file.ptr
  204. LPTSTR szPubPriType // Return value - whether file.ptr is
  205. // a pri, pub, bin, or unknown
  206. )
  207. /*++ Figure out if the current entry is a public or private symbol
  208. IN szDir Directory where refs.ptr should be
  209. In szFilePtr Contents of current file.ptr
  210. OUT szPubPriType Result equal to "pub", "pri", or "bin", according
  211. to the pub/pri/bin field for this entry in refs.ptr.
  212. If the entry isn't found or the entry does not have
  213. the type of file filled in, this is the empty string.
  214. Return value: This returns TRUE, if the file.ptr contents were found
  215. in refs.ptr. It returns FALSE otherwise.
  216. -- */
  217. {
  218. TCHAR szRefsFile[_MAX_PATH]; // Full path and name of the refs.ptr file
  219. FILE *fRefsFile;
  220. LPTSTR szBuf; // Used to process entries in the refs file
  221. TCHAR *token;
  222. TCHAR seps[] = _T(",");
  223. BOOL rc = FALSE;
  224. ULONG MaxLine; // Maximim length of a record in refs.ptr
  225. DWORD len;
  226. StringCbCopy( szPubPriType, sizeof(szPubPriType), _T("") );
  227. StringCbPrintf(szRefsFile, sizeof(szRefsFile), "%srefs.ptr", szDir );
  228. MaxLine = GetMaxLineOfRefsPtrFile();
  229. szBuf = (LPTSTR) malloc( MaxLine * sizeof(TCHAR) );
  230. if ( !szBuf ) MallocFailed();
  231. ZeroMemory(szBuf,MaxLine*sizeof(TCHAR));
  232. fRefsFile = _tfopen(szRefsFile, _T("r+") );
  233. if ( fRefsFile == NULL ) {
  234. // BARB - Check for corruption -- if the file doesn't exist,
  235. // verify that the parent directory structure doesn't exist either
  236. goto finish_CheckPriPub;
  237. }
  238. //
  239. // Read through the refs.ptr file and gather information
  240. //
  241. while ( _fgetts( szBuf, MaxLine, fRefsFile) != NULL ) {
  242. len=_tcslen(szBuf);
  243. if ( len > 3 ) {
  244. // See if this has a match with the current value in file.ptr
  245. if ( _tcsistr( szBuf, szFilePtr ) != NULL ) {
  246. rc = TRUE;
  247. token = _tcstok(szBuf, seps); // Look at the ID
  248. if (token) {
  249. token = _tcstok(NULL, seps); // "file" or "ptr"
  250. }
  251. if (token) {
  252. token = _tcstok(NULL, seps); // value of file.ptr
  253. }
  254. if (token) {
  255. token = _tcstok(NULL, seps); // bin, pri, pub
  256. }
  257. if (token) {
  258. if ( _tcsicmp( token, _T("pri"))== 0 ||
  259. _tcsicmp( token, _T("pub"))== 0 ||
  260. _tcsicmp( token, _T("bin"))== 0 ) {
  261. StringCbCopy( szPubPriType, sizeof(szPubPriType), token);
  262. goto finish_CheckPriPub;
  263. }
  264. }
  265. }
  266. }
  267. ZeroMemory(szBuf, MaxLine*sizeof(TCHAR));
  268. }
  269. finish_CheckPriPub:
  270. if ( fRefsFile != NULL)
  271. {
  272. fclose(fRefsFile);
  273. }
  274. free (szBuf);
  275. return (rc);
  276. }
  277. /* Decides if the current string has priority over the
  278. new string. This is used for deciding whether or not to add
  279. the new string to file.ptr and refs.ptr.
  280. There are 3 choices:
  281. 1. Add it to file.ptr and refs.ptr
  282. 2. Add it to refs.ptr, but not file.ptr
  283. 3. Don't add it at all.
  284. IN LPTSTR current -- The current string in file.ptr
  285. IN LPTSTR new -- The new replacement candidate for file.ptr
  286. IN LPTSTR szRefsDir The directory where refs.ptr is
  287. OUT choice -- SKIP_ENTIRE_ENTRY, ADD_ENTIRE_ENTRY, or ADD_ONLY_REFSPTR
  288. */
  289. BOOL
  290. DecidePriority(
  291. LPTSTR szCurrentFilePtr,
  292. LPTSTR szCandidateFilePtr,
  293. LPTSTR szRefsDir,
  294. PUINT choice
  295. )
  296. {
  297. BOOL CurrentIsArch=FALSE;
  298. BOOL NewIsArch=FALSE;
  299. BOOL UpdateFilePtr=TRUE;
  300. BOOL CurrentIsEnglish=FALSE;
  301. BOOL NewIsEnglish=FALSE;
  302. TCHAR szPubPriType[4] = "";
  303. *choice = 0;
  304. CurrentIsArch=(_tcsnicmp( szCurrentFilePtr, "\\\\arch\\", 7) == 0 );
  305. NewIsArch=(_tcsnicmp( szCandidateFilePtr, "\\\\arch\\", 7) == 0 );
  306. if ( CurrentIsArch && !NewIsArch)
  307. {
  308. // Don't store it
  309. *choice = SKIP_ENTIRE_ENTRY;
  310. return(TRUE);
  311. }
  312. if ( NewIsArch && !CurrentIsArch)
  313. {
  314. *choice = ADD_ENTIRE_ENTRY | DELETE_REFSPTR; // Overwrite file.ptr no matter what
  315. return(TRUE);
  316. }
  317. // Look at private versus public priority
  318. if ( PubPriPriority > 0 && // We're checking private and
  319. // public priority
  320. CheckPriPub( szRefsDir, szCurrentFilePtr, szPubPriType ) && // There is something in current
  321. _tcsicmp( szPubPriType, szPriPubBin ) != 0 ) // Current and candidate are not
  322. // the same. Note: they can be
  323. // "pub", "pri", "bin", or "null"
  324. // because earlier index files didn't
  325. // have a type in pub, pri, bin.
  326. {
  327. if ( _tcsicmp( szPubPriType, _T("")) == 0 ) // Current doesn't have types defined
  328. {
  329. *choice = ADD_ENTIRE_ENTRY;
  330. return(TRUE);
  331. }
  332. if ( _tcsicmp( szPriPubBin, _T("")) == 0 ) // Candidate doesn't have types defined
  333. {
  334. *choice = ADD_ONLY_REFSPTR;
  335. return(TRUE);
  336. }
  337. if ( ( PubPriPriority == 1 && // Give priority to public files
  338. _tcsicmp( szPubPriType, _T("pub")) == 0 ) || // and current is a public, or
  339. ( PubPriPriority == 2 && // Give priority to private files
  340. _tcsicmp( szPubPriType, _T("pri")) == 0 ) ) // and current is a private
  341. {
  342. *choice = ADD_ONLY_REFSPTR;
  343. return(TRUE);
  344. }
  345. if ( ( PubPriPriority == 1 && // Give priority to public files
  346. _tcsicmp( szPubPriType, _T("pri")) == 0 ) || // and current is a private
  347. ( PubPriPriority == 2 && // Give priority to private files
  348. _tcsicmp( szPubPriType, _T("pub")) == 0 ) ) // and current is a public
  349. {
  350. *choice = ADD_ENTIRE_ENTRY;
  351. return(TRUE);
  352. }
  353. }
  354. // At this point both are on the archive or both are not on the archive.
  355. // Next, give priority to English vs. non-English. If this is non-English,
  356. // then put it in refs.ptr, but don't update file.ptr.
  357. if ( _tcsistr(szCurrentFilePtr,_T("\\enu\\")) != NULL ||
  358. _tcsistr(szCurrentFilePtr,_T("\\en\\")) != NULL ||
  359. _tcsistr(szCurrentFilePtr,_T("\\usa\\")) != NULL )
  360. {
  361. CurrentIsEnglish=TRUE;
  362. }
  363. if ( _tcsistr(szCandidateFilePtr,_T("\\enu\\")) != NULL ||
  364. _tcsistr(szCandidateFilePtr,_T("\\en\\")) != NULL ||
  365. _tcsistr(szCandidateFilePtr,_T("\\usa\\")) != NULL )
  366. {
  367. NewIsEnglish=TRUE;
  368. }
  369. if ( CurrentIsEnglish == TRUE && NewIsEnglish == FALSE )
  370. {
  371. *choice = ADD_ONLY_REFSPTR;
  372. return(TRUE);
  373. }
  374. *choice = ADD_ENTIRE_ENTRY;
  375. return(TRUE);
  376. }
  377. BOOL
  378. DeleteAllFilesInDirectory(
  379. LPTSTR szDir
  380. )
  381. {
  382. HANDLE hFindFile;
  383. BOOL Found = FALSE;
  384. BOOL rc = TRUE;
  385. TCHAR szBuf[_MAX_PATH];
  386. TCHAR szDir2[_MAX_PATH];
  387. WIN32_FIND_DATA FindFileData;
  388. StringCbCopy( szDir2, sizeof(szDir2), szDir);
  389. StringCbCat( szDir2, sizeof(szDir2), _T("*.*") );
  390. Found = TRUE;
  391. hFindFile = FindFirstFile((LPCTSTR)szDir2, &FindFileData);
  392. if ( hFindFile == INVALID_HANDLE_VALUE)
  393. {
  394. Found = FALSE;
  395. }
  396. while ( Found )
  397. {
  398. if ( !(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
  399. StringCbPrintf(szBuf, sizeof(szBuf), "%s%s", szDir, FindFileData.cFileName);
  400. if (!DeleteFile(szBuf))
  401. {
  402. rc = FALSE;
  403. }
  404. }
  405. Found = FindNextFile(hFindFile, &FindFileData);
  406. }
  407. FindClose(hFindFile);
  408. return(rc);
  409. }
  410. //
  411. // Filename is expected to point to the complete path+filename (relative or absolute)
  412. // returns TRUE if Filename matches the regexp /.*~\d+\..{0,3}/
  413. //
  414. BOOL DoesThisLookLikeAShortFilenameHack(char *Filename) {
  415. BOOL bReturnValue = FALSE;
  416. CHAR FilenameOnly[_MAX_FNAME+1];
  417. CHAR FileExtOnly[ _MAX_EXT+1];
  418. CHAR* Temp;
  419. CHAR* chTilde = NULL;
  420. if (Filename != NULL) {
  421. _splitpath(Filename, NULL, NULL, FilenameOnly, FileExtOnly);
  422. if ( strlen(FileExtOnly) > 4 || strlen(FilenameOnly) > 8) {
  423. // a short filename will never be generated that is bigger than 8.3
  424. // but FileExtOnly will also contain the '.', so account for it
  425. bReturnValue = FALSE;
  426. } else {
  427. if ( (chTilde = strrchr(FilenameOnly, '~')) == NULL ) {
  428. // generated short filenames always contain a '~'
  429. bReturnValue = FALSE;
  430. } else {
  431. // point to the end of the filename
  432. Temp = (CHAR*)FilenameOnly + strlen(FilenameOnly);
  433. bReturnValue = TRUE; // start with true
  434. while (++chTilde < Temp) {
  435. // only stay true if all characters past the '~' are digits
  436. bReturnValue = bReturnValue && isdigit(*chTilde);
  437. }
  438. }
  439. }
  440. } else { // if (Filename != NULL) {
  441. bReturnValue = FALSE;
  442. }
  443. return(bReturnValue);
  444. }
  445. BOOL FileExists(IN LPCSTR FileName,
  446. OUT PWIN32_FIND_DATA FindData) {
  447. UINT OldMode;
  448. BOOL Found;
  449. HANDLE FindHandle;
  450. OldMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  451. FindHandle = FindFirstFile(FileName,FindData);
  452. if (FindHandle == INVALID_HANDLE_VALUE) {
  453. Found = FALSE;
  454. } else {
  455. FindClose(FindHandle);
  456. Found = TRUE;
  457. }
  458. SetErrorMode(OldMode);
  459. return(Found);
  460. }
  461. /* GetFileNameStart This returns the address of the first character of the file name */
  462. PCHAR GetFileNameStart(LPTSTR FileName) {
  463. LPTSTR c_ptr;
  464. c_ptr = FileName + _tcslen(FileName) - 1;
  465. while ( c_ptr > FileName ) {
  466. if ( *c_ptr == _T('\\') ) {
  467. return (++c_ptr);
  468. } else {
  469. c_ptr--;
  470. }
  471. }
  472. return(FileName);
  473. }
  474. P_LIST GetList(LPTSTR szFileName) {
  475. /* GetList gets the list and keeps the original file name which could
  476. * have included the path to the file
  477. * Note, it can be merged with GetExcludeList. I first created it for
  478. * use in creating the symbols CD, and didn't want to risk entering a
  479. * bug into symchk
  480. */
  481. P_LIST pList;
  482. FILE *fFile;
  483. TCHAR szCurFile[_MAX_FNAME+1], *c;
  484. TCHAR fname[_MAX_FNAME+1], ext[_MAX_EXT+1];
  485. DWORD i, rc;
  486. LPTSTR szEndName;
  487. ULONG RetVal = FALSE;
  488. pList = (P_LIST)malloc(sizeof(LIST));
  489. if (pList)
  490. {
  491. pList->dNumFiles = 0;
  492. if ( (fFile = _tfopen(szFileName,_T("r") )) == NULL )
  493. {
  494. // printf( "Cannot open the exclude file %s\n",szFileName );
  495. }
  496. else
  497. {
  498. while ( _fgetts(szCurFile,_MAX_FNAME,fFile) ) {
  499. if ( szCurFile[0] == ';' ) continue;
  500. (pList->dNumFiles)++;
  501. }
  502. // Go back to the beginning of the file
  503. rc = fseek(fFile,0,0);
  504. if ( rc != 0 )
  505. {
  506. free(pList);
  507. fclose(fFile);
  508. return(NULL);
  509. }
  510. pList->List = (LIST_ELEM*)malloc( sizeof(LIST_ELEM) *
  511. (pList->dNumFiles));
  512. if (pList->List)
  513. {
  514. i = 0;
  515. while ( i < pList->dNumFiles )
  516. {
  517. memset(szCurFile,'\0',sizeof(TCHAR) * (_MAX_FNAME+1) );
  518. if ( _fgetts(szCurFile,_MAX_FNAME,fFile) == NULL )
  519. {
  520. fclose(fFile);
  521. return(NULL);
  522. }
  523. // Replace the \n with \0
  524. c = NULL;
  525. c = _tcschr(szCurFile, '\n');
  526. if ( c != NULL) *c='\0';
  527. if ( szCurFile[0] == ';' ) continue;
  528. if ( _tcslen(szCurFile) > _MAX_FNAME ) {
  529. so->printf("File %s has a string that is too large\n",szFileName);
  530. break;
  531. }
  532. // Allow for spaces and a ; after the file name
  533. // Move the '\0' back until it has erased the ';' and any
  534. // tabs and spaces that might come before it
  535. szEndName = _tcschr(szCurFile, ';');
  536. if (szEndName != NULL ) {
  537. while ( *szEndName == ';' || *szEndName == ' '
  538. || *szEndName == '\t' ){
  539. *szEndName = '\0';
  540. if ( szEndName > szCurFile ) szEndName--;
  541. }
  542. }
  543. StringCbCopy(pList->List[i].Path, sizeof(pList->List[i].Path), szCurFile);
  544. _tsplitpath(szCurFile,NULL,NULL,fname,ext);
  545. StringCbCopy(pList->List[i].FName,sizeof(pList->List[i].FName), fname);
  546. StringCbCat( pList->List[i].FName,sizeof(pList->List[i].FName), ext);
  547. i++;
  548. }
  549. if (i == pList->dNumFiles)
  550. {
  551. RetVal = TRUE;
  552. }
  553. else
  554. {
  555. free(pList->List);
  556. }
  557. }
  558. fclose(fFile);
  559. }
  560. if (!RetVal)
  561. {
  562. free(pList);
  563. pList = NULL;
  564. }
  565. }
  566. // Sort the List
  567. // qsort( (void*)pList->List, (size_t)pList->dNumFiles,
  568. // (size_t)sizeof(LIST_ELEM), SymComp2 );
  569. return (pList);
  570. }
  571. PIMAGE_NT_HEADERS
  572. GetNtHeader ( PIMAGE_DOS_HEADER pDosHeader,
  573. HANDLE hDosFile
  574. )
  575. {
  576. /*
  577. Returns the pointer the address of the NT Header. If there isn't
  578. an NT header, it returns NULL
  579. */
  580. PIMAGE_NT_HEADERS pNtHeader = NULL;
  581. BY_HANDLE_FILE_INFORMATION FileInfo;
  582. //
  583. // If the image header is not aligned on a long boundary.
  584. // Report this as an invalid protect mode image.
  585. //
  586. if ( ((ULONG)(pDosHeader->e_lfanew) & 3) == 0)
  587. {
  588. if (GetFileInformationByHandle( hDosFile, &FileInfo) &&
  589. ((ULONG)(pDosHeader->e_lfanew) <= FileInfo.nFileSizeLow))
  590. {
  591. pNtHeader = (PIMAGE_NT_HEADERS)((PCHAR)pDosHeader +
  592. (ULONG)pDosHeader->e_lfanew);
  593. if (pNtHeader->Signature != IMAGE_NT_SIGNATURE)
  594. {
  595. pNtHeader = NULL;
  596. }
  597. }
  598. }
  599. return pNtHeader;
  600. }
  601. /***********************************************************************************
  602. Function: GetSymbolServerDirs
  603. Purpose:
  604. To get the directory structure on the symbol server for the file passed in.
  605. Parameters:
  606. IN szFileName File name that is being stored on the symbol server.
  607. If it has path information, that will get stripped off.
  608. IN guid This is a Guid for the PDB that is being stored.
  609. IN dwNum1 This is a timedatestamp for exe's or dbg's that are being stored.
  610. Note: Either guid must be null or dwNum1 must be 0.
  611. IN dwNum2 SizeOfImage for exe's and dbg's. Age for PDb's.
  612. OUT szString String with the two directories on the symbol server that this
  613. file is stored under.
  614. Return value:
  615. Returns TRUE is the function succeeds. Returns FALSE if it fails.
  616. ************************************************************************************/
  617. BOOL GetSymbolServerDirs(
  618. LPTSTR szFileName,
  619. GUID *guid,
  620. DWORD dwNum1,
  621. DWORD dwNum2,
  622. LPTSTR szString
  623. )
  624. {
  625. BOOL rc;
  626. GUID MyGuid;
  627. PCHAR FileNameStart;
  628. CHAR Buf[_MAX_PATH] = _T("");
  629. FileNameStart = GetFileNameStart(szFileName);
  630. if (guid != NULL)
  631. {
  632. rc = SymbolServer( _T("X"), FileNameStart, guid, dwNum2, 0, Buf );
  633. } else {
  634. // Turn this into a GUID so that we don't have to reset the SymbolServerOptions
  635. // SymbolServerSetOptions was set in main.
  636. memset( &MyGuid, 0, sizeof(MyGuid) );
  637. MyGuid.Data1 = dwNum1;
  638. rc = SymbolServer( _T("X"), FileNameStart, &MyGuid, dwNum2, 0, Buf );
  639. }
  640. // Remove the X\ that comes back at the beginning of Buf
  641. StringCchCopy(szString, _MAX_PATH, Buf+2 );
  642. // Remove the "\filename" that is at the end of Buf
  643. FileNameStart = GetFileNameStart( szString );
  644. *(FileNameStart-1) = _T('\0');
  645. return (TRUE);
  646. }
  647. BOOL
  648. MyCopyFile(
  649. LPCTSTR lpExistingFileName,
  650. LPCTSTR lpNewFileName
  651. )
  652. /*++
  653. Routine description:
  654. This handles whether the file is a compressed file or not. First it
  655. tries to copy in the compressed version of the file. If that works,
  656. then it will delete the uncompressed file if it exists in the target.
  657. If the compressed file is not there, then it copies in the
  658. uncompressed file.
  659. --*/
  660. {
  661. TCHAR ExistingFileName_C[_MAX_PATH]; // Compressed version name
  662. TCHAR NewFileName_C[_MAX_PATH]; // Compressed version
  663. DWORD dw;
  664. BOOL rc;
  665. // Put a _ at the end of the compressed names
  666. StringCbCopy( ExistingFileName_C, sizeof(ExistingFileName_C), lpExistingFileName );
  667. ExistingFileName_C[ _tcslen(ExistingFileName_C) - 1 ] = _T('_');
  668. StringCbCopy( NewFileName_C, sizeof(NewFileName_C), lpNewFileName );
  669. NewFileName_C[ _tcslen( NewFileName_C ) - 1 ] = _T('_');
  670. // If the compressed file exists, copy it instead of the uncompressed file
  671. dw = GetFileAttributes( ExistingFileName_C );
  672. if ( dw != 0xffffffff) {
  673. rc = CopyFile( ExistingFileName_C, NewFileName_C, TRUE );
  674. if ( !rc && GetLastError() != ERROR_FILE_EXISTS ) {
  675. so->printf("CopyFile failed to copy %s to %s - GetLastError() = %d\n",
  676. ExistingFileName_C, NewFileName_C, GetLastError() );
  677. return (FALSE);
  678. }
  679. SetFileAttributes( NewFileName_C, FILE_ATTRIBUTE_NORMAL );
  680. // If the uncompressed file exists, delete it
  681. dw = GetFileAttributes( lpNewFileName );
  682. if ( dw != 0xffffffff ) {
  683. rc = DeleteFile( lpNewFileName );
  684. if (!rc) {
  685. so->printf("Keeping %s, but could not delete %s\n",
  686. NewFileName_C, lpNewFileName );
  687. }
  688. }
  689. } else {
  690. // Compressed file doesn't exist, try the uncompressed
  691. dw = GetFileAttributes( lpExistingFileName );
  692. if ( dw != 0xffffffff ) {
  693. rc = CopyFile( lpExistingFileName, lpNewFileName, TRUE );
  694. if ( !rc && GetLastError() != ERROR_FILE_EXISTS ) {
  695. so->printf("CopyFile failed to copy %s to %s - GetLastError() = %d\n",
  696. lpExistingFileName, lpNewFileName, GetLastError() );
  697. return (FALSE);
  698. }
  699. SetFileAttributes( lpNewFileName, FILE_ATTRIBUTE_NORMAL );
  700. }
  701. }
  702. return(TRUE);
  703. }
  704. void MyEnsureTrailingBackslash(char *sz) {
  705. return MyEnsureTrailingChar(sz, '\\');
  706. }
  707. void MyEnsureTrailingChar(char *sz, char c) {
  708. int i;
  709. assert(sz);
  710. i = strlen(sz);
  711. if (!i)
  712. return;
  713. if (sz[i - 1] == c)
  714. return;
  715. sz[i] = c;
  716. sz[i + 1] = '\0';
  717. }
  718. void MyEnsureTrailingCR(char *sz) {
  719. return MyEnsureTrailingChar(sz, '\n');
  720. }
  721. void MyEnsureTrailingSlash(char *sz) {
  722. return MyEnsureTrailingChar(sz, '/');
  723. }
  724. BOOL
  725. ReadFilePtr(
  726. LPTSTR szContents,
  727. HANDLE hFile
  728. )
  729. {
  730. BOOL rc;
  731. DWORD size;
  732. DWORD cb;
  733. LPTSTR p;
  734. DWORD high;
  735. size = GetFileSize(hFile, NULL);
  736. if (!size || size > _MAX_PATH) {
  737. return FALSE;
  738. }
  739. // read it
  740. if (!ReadFile(hFile, szContents, size, &cb, 0)) {
  741. rc=FALSE;
  742. goto cleanup;
  743. }
  744. if (cb != size) {
  745. rc=FALSE;
  746. goto cleanup;
  747. }
  748. rc = true;
  749. // trim string down to the CR
  750. for (p = szContents; *p; p++) {
  751. if (*p == 10 || *p == 13)
  752. {
  753. *p = 0;
  754. break;
  755. }
  756. }
  757. cleanup:
  758. // done
  759. SetFilePointer( hFile, 0, NULL, FILE_BEGIN);
  760. return rc;
  761. }
  762. BOOL
  763. StoreDbg(
  764. LPTSTR szDestDir,
  765. LPTSTR szFileName,
  766. LPTSTR szPtrFileName,
  767. USHORT *rc_flag
  768. )
  769. /* ++
  770. Routine Description:
  771. Stores this file as "szDestDir\szFileName\Checksum"
  772. Return Value:
  773. TRUE - file was stored successfully
  774. FALSE - file was not stored successfully
  775. -- */
  776. {
  777. PIMAGE_SEPARATE_DEBUG_HEADER pDbgHeader;
  778. HANDLE hFile;
  779. BOOL rc;
  780. TCHAR szString[_MAX_PATH];
  781. UINT i;
  782. IMAGE_DEBUG_DIRECTORY UNALIGNED *DebugDirectory, *pDbgDir;
  783. ULONG NumberOfDebugDirectories;
  784. ZeroMemory(szString, _MAX_PATH * sizeof(TCHAR) );
  785. pDbgHeader = SymCommonMapDbgHeader ( szFileName, &hFile );
  786. if (pDbgHeader == NULL) {
  787. so->printf("ERROR: StoreDbg(), %s was not opened successfully\n",szFileName);
  788. SymCommonUnmapFile((LPCVOID)pDbgHeader, hFile);
  789. return FALSE;
  790. }
  791. DebugDirectory = NULL;
  792. DebugDirectory = GetDebugDirectoryInDbg(
  793. pDbgHeader,
  794. &NumberOfDebugDirectories
  795. );
  796. PrivateStripped = TRUE;
  797. if (DebugDirectory != NULL) {
  798. for ( i=0; i< NumberOfDebugDirectories; i++ ) {
  799. pDbgDir = DebugDirectory + i;
  800. __try
  801. {
  802. switch (pDbgDir->Type) {
  803. case IMAGE_DEBUG_TYPE_MISC:
  804. break;
  805. case IMAGE_DEBUG_TYPE_CODEVIEW:
  806. if ( !DBGPrivateStripped(
  807. DebugDirectory->PointerToRawData + (PCHAR)pDbgHeader,
  808. DebugDirectory->SizeOfData
  809. ) ) {
  810. PrivateStripped = FALSE;
  811. }
  812. if (PrivateStripped) {
  813. StringCbCopy(szPriPubBin, sizeof(szPriPubBin), _T("pub") );
  814. }
  815. break;
  816. default:
  817. // Nothing except the CV entry should point to raw data
  818. if ( pDbgDir->SizeOfData != 0 ) {
  819. PrivateStripped = FALSE;
  820. }
  821. break;
  822. }
  823. }
  824. __except( EXCEPTION_EXECUTE_HANDLER )
  825. {
  826. SymCommonUnmapFile((LPCVOID)pDbgHeader, hFile);
  827. return FALSE;
  828. }
  829. }
  830. }
  831. // Something is wrong with how we are figuring out what has private info stripped.
  832. // Go back to saying that every DBG is public until we get it figured out.
  833. PrivateStripped = TRUE;
  834. if (PrivateStripped) {
  835. StringCbCopy(szPriPubBin, sizeof(szPriPubBin), _T("pub") );
  836. } else {
  837. StringCbCopy(szPriPubBin, sizeof(szPriPubBin), _T("pri") );
  838. }
  839. if ( ( (pArgs->Filter == 2) && PrivateStripped ) ||
  840. ( (pArgs->Filter == 1) && !PrivateStripped ) ) {
  841. SymCommonUnmapFile((LPCVOID)pDbgHeader, hFile);
  842. *rc_flag = FILE_SKIPPED;
  843. return TRUE;
  844. }
  845. GetSymbolServerDirs( szFileName,
  846. NULL,
  847. (DWORD) pDbgHeader->TimeDateStamp,
  848. (DWORD) pDbgHeader->SizeOfImage,
  849. szString
  850. );
  851. rc = StoreFile( szDestDir,
  852. szFileName,
  853. szString,
  854. szPtrFileName );
  855. SymCommonUnmapFile((LPCVOID)pDbgHeader, hFile);
  856. return rc;
  857. }
  858. BOOL
  859. StoreFile(
  860. LPTSTR szDestDir,
  861. LPTSTR szFileName,
  862. LPTSTR szString2,
  863. LPTSTR szPtrFileName
  864. )
  865. {
  866. TCHAR szPathName[_MAX_PATH + _MAX_FNAME + 2];
  867. TCHAR szFileNameOnly[_MAX_FNAME + _MAX_EXT];
  868. TCHAR szExt[_MAX_EXT];
  869. TCHAR szBuf[_MAX_PATH * 3];
  870. TCHAR szRefsDir[_MAX_PATH * 3];
  871. DWORD dwNumBytesToWrite;
  872. DWORD dwNumBytesWritten;
  873. BOOL rc;
  874. DWORD dwSizeDestDir;
  875. DWORD dwFileSizeLow;
  876. DWORD dwFileSizeHigh;
  877. if (DoesThisLookLikeAShortFilenameHack(szFileName)) {
  878. fprintf(stderr, "SYMSTORE: Skipping bad filename: %s\n", szFileName);
  879. return(FILE_SKIPPED);
  880. }
  881. // If ADD_DONT_STORE, then write the function parameters
  882. // to a file so we can call this function exactly when
  883. // running ADD_STORE_FROM_FILE
  884. if ( StoreFlags == ADD_DONT_STORE ) {
  885. // Don't need to store szDestDir because it will
  886. // be given when adding from file
  887. dwFileSizeLow = GetFileSize(hTransFile, &dwFileSizeHigh);
  888. StringCbPrintf( szBuf,
  889. sizeof(szBuf),
  890. "%s,%s,",
  891. szFileName+pArgs->ShareNameLength,
  892. szString2
  893. );
  894. if ( szPtrFileName != NULL ) {
  895. StringCbCat(szBuf, sizeof(szBuf), szPtrFileName+pArgs->ShareNameLength);
  896. }
  897. StringCbCat(szBuf, sizeof(szBuf), _T(",") );
  898. StringCbCat(szBuf, sizeof(szBuf), szPriPubBin);
  899. StringCbCat(szBuf, sizeof(szBuf), _T(",,,,\r\n") );
  900. dwNumBytesToWrite = _tcslen(szBuf) * sizeof(TCHAR);
  901. WriteFile( hTransFile,
  902. (LPCVOID)szBuf,
  903. dwNumBytesToWrite,
  904. &dwNumBytesWritten,
  905. NULL
  906. );
  907. if ( dwNumBytesToWrite != dwNumBytesWritten ) {
  908. so->printf( "FAILED to write to %s, with GetLastError = %d\n",
  909. szPathName,
  910. GetLastError()
  911. );
  912. return (FALSE);
  913. } else {
  914. return (TRUE);
  915. }
  916. }
  917. if ( szPtrFileName != NULL ) {
  918. rc = StoreFilePtr ( szDestDir,
  919. szString2,
  920. szPtrFileName
  921. );
  922. return (rc);
  923. }
  924. _tsplitpath(szFileName, NULL, NULL, szFileNameOnly, szExt);
  925. StringCbCat(szFileNameOnly, sizeof(szFileNameOnly), szExt);
  926. StringCbPrintf( szPathName,
  927. sizeof(szPathName),
  928. "%s%s",
  929. szDestDir,
  930. szString2
  931. );
  932. // Save a copy for writing refs.ptr
  933. StringCbCopy(szRefsDir, sizeof(szRefsDir), szPathName);
  934. // Create the directory to store the file if its not already there
  935. MyEnsureTrailingBackslash(szPathName);
  936. if ( pArgs->TransState != TRANSACTION_QUERY ) {
  937. if ( !MakeSureDirectoryPathExists( szPathName ) ) {
  938. so->printf("Could not create %s\n", szPathName);
  939. return (FALSE);
  940. }
  941. }
  942. StringCbCat( szPathName, sizeof(szPathName), szFileNameOnly );
  943. // Enter this into the log, skipping the Destination directory
  944. // at the beginning of szPathName
  945. //
  946. dwSizeDestDir = _tcslen(szDestDir);
  947. dwFileSizeLow = GetFileSize(hTransFile, &dwFileSizeHigh);
  948. if ( dwFileSizeLow == 0 && dwFileSizeHigh == 0 ) {
  949. StringCbPrintf( szBuf, sizeof(szBuf), "%s,%s", szRefsDir+dwSizeDestDir, szFileName );
  950. } else {
  951. StringCbPrintf( szBuf, sizeof(szBuf), "\n%s,%s", szRefsDir+dwSizeDestDir, szFileName );
  952. }
  953. if ( pArgs->TransState == TRANSACTION_QUERY ) {
  954. WIN32_FIND_DATA FindData;
  955. if ( FileExists(szPathName, &FindData) ) {
  956. if ( !(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
  957. printf("SYMSTORE: \"%s\"\t\"%s\"\n", szFileName, szPathName);
  958. } else {
  959. // handle the case of it being a directory
  960. printf("SYMSTORE: ERROR: %s is a directory!\n", szPathName);
  961. }
  962. } else {
  963. // handle the case of file.ptr
  964. CHAR drive[_MAX_DRIVE];
  965. CHAR dir[ _MAX_DIR];
  966. CHAR file[ _MAX_FNAME];
  967. CHAR ext[ _MAX_EXT];
  968. CHAR NewFilename[MAX_PATH];
  969. _splitpath(szPathName, drive, dir, file, ext);
  970. //
  971. // 'Magic' to handle the fact that splitpath() doesn't do the
  972. // Right Thing(tm) with UNC paths.
  973. //
  974. if ( drive[0] != '\0') {
  975. StringCbCopy(NewFilename, sizeof(NewFilename), drive);
  976. StringCbCat( NewFilename, sizeof(NewFilename), "\\");
  977. } else {
  978. NewFilename[0] = '\0';
  979. }
  980. StringCbCat( NewFilename, sizeof(NewFilename), dir);
  981. StringCbCat( NewFilename, sizeof(NewFilename), "file.ptr");
  982. if ( FileExists(NewFilename, &FindData) ) {
  983. if ( !(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
  984. HANDLE hFile = CreateFile( NewFilename,
  985. GENERIC_READ,
  986. 0,
  987. NULL,
  988. OPEN_ALWAYS,
  989. FILE_ATTRIBUTE_NORMAL,
  990. NULL );
  991. if (hFile != INVALID_HANDLE_VALUE) {
  992. if ( ReadFilePtr(szBuf, hFile) ) {
  993. if ( FileExists(szBuf, &FindData) ) {
  994. printf("SYMSTORE: \"%s\"\t\"%s\"\n", szFileName, szBuf);
  995. } else {
  996. if(pArgs->VerboseOutput) {
  997. printf("SYMSTORE: Skipped \"%s\" - doesn't exist!\n", szBuf);
  998. }
  999. }
  1000. }
  1001. } else {
  1002. printf("SYMSTORE: ERROR: Couldn't read %s!\n", NewFilename);
  1003. }
  1004. } else {
  1005. printf("SYMSTORE: ERROR: %s is a directory!\n", NewFilename);
  1006. }
  1007. } else {
  1008. if(pArgs->VerboseOutput) {
  1009. printf("SYMSTORE: Skipped \"%s\" - doesn't exist!\n", szPathName);
  1010. }
  1011. }
  1012. }
  1013. return(1); // so we don't get a failed store message
  1014. }
  1015. if ( pArgs->TransState != TRANSACTION_QUERY ) {
  1016. dwNumBytesToWrite = _tcslen(szBuf) * sizeof(TCHAR);
  1017. WriteFile( hTransFile,
  1018. (LPCVOID)szBuf,
  1019. dwNumBytesToWrite,
  1020. &dwNumBytesWritten,
  1021. NULL
  1022. );
  1023. if ( dwNumBytesToWrite != dwNumBytesWritten ) {
  1024. so->printf( "FAILED to write to %s, with GetLastError = %d\n",
  1025. szPathName,
  1026. GetLastError()
  1027. );
  1028. return (FALSE);
  1029. }
  1030. rc = MyCopyFile(szFileName, szPathName);
  1031. if (!rc) return (FALSE);
  1032. MyEnsureTrailingBackslash(szRefsDir);
  1033. rc = AddToReferenceCount(szRefsDir, szFileName, _T("file"), FALSE );
  1034. }
  1035. return (rc);
  1036. }
  1037. BOOL
  1038. StoreFilePtr(
  1039. LPTSTR szDestDir,
  1040. LPTSTR szString2,
  1041. LPTSTR szPtrFileName
  1042. )
  1043. {
  1044. /*
  1045. szPathName The full path with "file.ptr" appended to it.
  1046. This is the path for storing file.ptr
  1047. */
  1048. TCHAR szPathName[_MAX_PATH];
  1049. TCHAR szRefsDir[_MAX_PATH];
  1050. TCHAR szPubPriType[4]="";
  1051. HANDLE hFile;
  1052. DWORD dwNumBytesToWrite;
  1053. DWORD dwNumBytesWritten;
  1054. DWORD rc=1;
  1055. DWORD dwSizeDestDir;
  1056. DWORD dwFileSizeLow;
  1057. DWORD dwFileSizeHigh;
  1058. DWORD timeout;
  1059. TCHAR szCurrentFilePtr[_MAX_PATH]= "";
  1060. DWORD size=0;
  1061. DWORD highsize=0;
  1062. DWORD dwError;
  1063. BOOL UpdateRefsPtr=TRUE;
  1064. BOOL UpdateFilePtr=TRUE;
  1065. BOOL DeleteRefsPtr=FALSE;
  1066. UINT DecisionFlags;
  1067. StringCbPrintf( szPathName, sizeof(szPathName), "%s%s",
  1068. szDestDir,
  1069. szString2 );
  1070. MyEnsureTrailingBackslash( szPathName );
  1071. // Save this for passing in the refs.ptr directory
  1072. StringCbCopy(szRefsDir, sizeof(szRefsDir), szPathName);
  1073. StringCbPrintf( szPathName,
  1074. sizeof(szPathName),
  1075. "%s%s",
  1076. szPathName,
  1077. _T("file.ptr")
  1078. );
  1079. if ( !MakeSureDirectoryPathExists( szPathName ) ) {
  1080. so->printf("Could not create %s\n", szPathName);
  1081. return (FALSE);
  1082. }
  1083. // Put this file into file.ptr. If file.ptr is already there, then
  1084. // replace the contents with this pointer
  1085. // Wait for the file to become available
  1086. timeout=0;
  1087. do {
  1088. hFile = CreateFile( szPathName,
  1089. GENERIC_WRITE | GENERIC_READ,
  1090. 0,
  1091. NULL,
  1092. OPEN_ALWAYS,
  1093. FILE_ATTRIBUTE_NORMAL,
  1094. NULL );
  1095. // Make sure that delete didn't come through and remove the directory
  1096. if ( !MakeSureDirectoryPathExists( szPathName ) ) {
  1097. so->printf("Could not create %s\n", szPathName);
  1098. return (FALSE);
  1099. }
  1100. if ( hFile == INVALID_HANDLE_VALUE ) {
  1101. SleepEx(1000,0);
  1102. timeout++;
  1103. }
  1104. } while ( hFile == INVALID_HANDLE_VALUE && timeout <= 50 ) ;
  1105. if ( (hFile == INVALID_HANDLE_VALUE) || (timeout > 50) ) {
  1106. so->printf( "Failed to open %s for writing, with GetLastError = %d\n", szPathName, GetLastError() );
  1107. return(FALSE);
  1108. }
  1109. // If the pointer we are adding points to \\arch\, then add it.
  1110. // If the pointer we are adding doesn't point to \\arch\, then
  1111. // don't overwrite a file.ptr that does point to \\arch\.
  1112. UpdateFilePtr = TRUE;
  1113. UpdateRefsPtr = TRUE;
  1114. DeleteRefsPtr = FALSE;
  1115. if ( MSArchive && ReadFilePtr( szCurrentFilePtr, hFile ) )
  1116. {
  1117. DecidePriority( szCurrentFilePtr,
  1118. szPtrFileName,
  1119. szRefsDir,
  1120. &DecisionFlags
  1121. );
  1122. if ( DecisionFlags & SKIP_ENTIRE_ENTRY )
  1123. {
  1124. UpdateFilePtr = FALSE;
  1125. UpdateRefsPtr = FALSE;
  1126. }
  1127. if ( DecisionFlags & ADD_ONLY_REFSPTR )
  1128. {
  1129. UpdateFilePtr = FALSE;
  1130. }
  1131. if ( DecisionFlags & DELETE_REFSPTR )
  1132. {
  1133. DeleteRefsPtr = TRUE;
  1134. }
  1135. }
  1136. if ( UpdateFilePtr ) {
  1137. dwNumBytesToWrite = _tcslen(szPtrFileName) * sizeof(TCHAR);
  1138. WriteFile( hFile,
  1139. (LPCVOID)szPtrFileName,
  1140. dwNumBytesToWrite,
  1141. &dwNumBytesWritten,
  1142. NULL
  1143. );
  1144. if ( dwNumBytesToWrite != dwNumBytesWritten ) {
  1145. so->printf( "FAILED to write %s, with GetLastError = %d\n",
  1146. szPathName,
  1147. GetLastError()
  1148. );
  1149. CloseHandle(hFile);
  1150. return (FALSE);
  1151. }
  1152. SetEndOfFile(hFile);
  1153. }
  1154. if ( UpdateRefsPtr ) {
  1155. // Enter this into the log, skipping the first part that is the root
  1156. // of the symbols server
  1157. dwSizeDestDir = _tcslen(szDestDir);
  1158. dwFileSizeLow = GetFileSize(hTransFile, &dwFileSizeHigh);
  1159. if ( dwFileSizeLow == 0 && dwFileSizeHigh == 0 ) {
  1160. StringCbPrintf( szPathName, sizeof(szPathName), "%s,%s", szRefsDir + dwSizeDestDir, szPtrFileName);
  1161. } else {
  1162. StringCbPrintf( szPathName, sizeof(szPathName), "\n%s,%s", szRefsDir + dwSizeDestDir, szPtrFileName);
  1163. }
  1164. dwNumBytesToWrite = _tcslen(szPathName) * sizeof(TCHAR);
  1165. WriteFile( hTransFile,
  1166. (LPCVOID)(szPathName),
  1167. dwNumBytesToWrite,
  1168. &dwNumBytesWritten,
  1169. NULL
  1170. );
  1171. if ( dwNumBytesToWrite != dwNumBytesWritten ) {
  1172. so->printf( "FAILED to write to %s, with GetLastError = %d\n",
  1173. szPathName,
  1174. GetLastError()
  1175. );
  1176. return (FALSE);
  1177. }
  1178. // File.ptr was created successfully, now, add the contents of
  1179. // szPathName to refs.ptr
  1180. MyEnsureTrailingBackslash(szRefsDir);
  1181. rc = AddToReferenceCount( szRefsDir, szPtrFileName, "ptr", DeleteRefsPtr );
  1182. if (!rc) {
  1183. so->printf("AddToReferenceCount failed for %s,ptr,%s",
  1184. szDestDir, szPtrFileName);
  1185. }
  1186. }
  1187. // If you close this handle sooner, there will be problems if add and
  1188. // delete are running at the same time. The delete process can come in
  1189. // and delete the directory before AddToReferenceCount gets called.
  1190. // Then the CreateFile in there fails.
  1191. CloseHandle(hFile);
  1192. return (rc);
  1193. }
  1194. DWORD
  1195. StoreFromFile(
  1196. FILE *pStoreFromFile,
  1197. LPTSTR szDestDir,
  1198. PFILE_COUNTS pFileCounts) {
  1199. LPTSTR szFileName;
  1200. DWORD dw1,dw2;
  1201. LPTSTR szPtrFileName;
  1202. LPTSTR szBufCut;
  1203. TCHAR szFullFileName[_MAX_PATH];
  1204. TCHAR szFullPtrFileName[_MAX_PATH];
  1205. TCHAR szBuf[_MAX_PATH*4];
  1206. TCHAR szString[_MAX_PATH];
  1207. LPTSTR token2,token3,token4,token5,token6,token7;
  1208. ULONG i,comma_count,token_start;
  1209. BOOL rc;
  1210. ZeroMemory( szString, sizeof(szString) );
  1211. // Read in each line of the file
  1212. while ( !feof( pStoreFromFile) ) {
  1213. szFileName = NULL;
  1214. szPtrFileName = NULL;
  1215. StringCbCopy(szBuf, sizeof(szBuf), _T("") );
  1216. if (!fgets( szBuf, _MAX_PATH*4, pStoreFromFile)) {
  1217. break;
  1218. }
  1219. // Cut the comment
  1220. if ( (szBufCut = _tcschr( szBuf, ';' ) ) != NULL ) {
  1221. szBufCut[0] = '\0';
  1222. }
  1223. // skip no fields line
  1224. if (_tcschr( szBuf, ',' ) == NULL)
  1225. {
  1226. continue;
  1227. }
  1228. StringCbCopy( szFullFileName, sizeof(szFullFileName), pArgs->szShareName );
  1229. StringCbCopy( szFullPtrFileName, sizeof(szFullPtrFileName), pArgs->szShareName );
  1230. // Step through szBuf and count how many commas there are
  1231. // If there are 3 commas, this is a new style file. If there
  1232. // are 4 commas, this is an old style file.
  1233. // If there are 7 commas, this is the newest style file.
  1234. token2=NULL;
  1235. token3=NULL;
  1236. token4=NULL;
  1237. token5=NULL;
  1238. token6=NULL;
  1239. token7=NULL;
  1240. comma_count=0;
  1241. i=0;
  1242. token_start=i;
  1243. while ( szBuf[i] != _T('\0') && comma_count < 7 ) {
  1244. if ( szBuf[i] == _T(',') ) {
  1245. switch (comma_count) {
  1246. case 0: szFileName=szBuf;
  1247. break;
  1248. case 1: token2=szBuf+token_start;
  1249. break;
  1250. case 2: token3=szBuf+token_start;
  1251. break;
  1252. case 3: token4=szBuf+token_start;
  1253. break;
  1254. case 4: token5=szBuf+token_start;
  1255. break;
  1256. case 5: token6=szBuf+token_start;
  1257. break;
  1258. case 6: token7=szBuf+token_start;
  1259. break;
  1260. default: break;
  1261. }
  1262. token_start=i+1;
  1263. szBuf[i]=_T('\0');
  1264. comma_count++;
  1265. }
  1266. i++;
  1267. }
  1268. if ( szFileName != NULL ) {
  1269. StringCbCat( szFullFileName, sizeof(szFullFileName), szFileName);
  1270. if ( comma_count == 3 || comma_count == 7 ) {
  1271. //This is the new style
  1272. StringCbCopy( szString, sizeof(szString), token2);
  1273. if ( (token3 != NULL ) && (*token3 != _T('\0')) ) {
  1274. szPtrFileName=token3;
  1275. }
  1276. } else {
  1277. dw1=atoi(token2);
  1278. dw2=atoi(token3);
  1279. if ( *token4 != _T('\0') ) {
  1280. szPtrFileName=token4;
  1281. }
  1282. GetSymbolServerDirs( szFileName, NULL, dw1, dw2, szString );
  1283. }
  1284. if ( comma_count == 7 ) {
  1285. StringCbCopy( szPriPubBin, sizeof(szPriPubBin), token4 );
  1286. }
  1287. if (pArgs->StorePtrs == TRUE) {
  1288. szPtrFileName=szFileName;
  1289. }
  1290. if ( szPtrFileName != NULL ) {
  1291. StringCbCat( szFullPtrFileName, sizeof(szFullPtrFileName), szPtrFileName);
  1292. }
  1293. if ( szPtrFileName == NULL ) {
  1294. rc = StoreFile(szDestDir,szFullFileName,szString,NULL);
  1295. } else {
  1296. rc = StoreFile(szDestDir,szFullFileName,szString,szFullPtrFileName);
  1297. }
  1298. if (rc) {
  1299. pFileCounts->NumPassedFiles++;
  1300. } else {
  1301. pFileCounts->NumFailedFiles++;
  1302. }
  1303. }
  1304. }
  1305. free(szBuf);
  1306. return(pFileCounts->NumFailedFiles);
  1307. }
  1308. BOOL
  1309. StoreNtFile(
  1310. LPTSTR szDestDir,
  1311. LPTSTR szFileName,
  1312. LPTSTR szPtrFileName,
  1313. USHORT *rc
  1314. )
  1315. /*++
  1316. Routine Description:
  1317. Stores this file as "szDestDir\szFileName\Checksum"
  1318. Return Value:
  1319. TRUE - file was stored successfully
  1320. FALSE - file was not stored successfully
  1321. --*/
  1322. {
  1323. BOOL temp_rc;
  1324. HANDLE DosFile = 0;
  1325. DWORD dwErrorCode = 0;
  1326. PIMAGE_DOS_HEADER pDosHeader = NULL;
  1327. PIMAGE_NT_HEADERS pNtHeader = NULL;
  1328. ULONG TimeDateStamp;
  1329. ULONG SizeOfImage;
  1330. TCHAR szString[_MAX_PATH];
  1331. ZeroMemory(szString, _MAX_PATH*sizeof(TCHAR) );
  1332. pDosHeader = SymCommonMapFileHeader( szFileName, &DosFile, &dwErrorCode );
  1333. if ( pDosHeader == NULL ) {
  1334. *rc = FILE_SKIPPED;
  1335. return FALSE;
  1336. };
  1337. pNtHeader = GetNtHeader( pDosHeader, DosFile);
  1338. if ( pNtHeader == NULL ) {
  1339. SymCommonUnmapFile((LPCVOID)pDosHeader,DosFile);
  1340. *rc = FILE_SKIPPED;
  1341. return FALSE;
  1342. }
  1343. __try {
  1344. // Resource Dll's shouldn't have symbols
  1345. if ( SymCommonResourceOnlyDll((PVOID)pDosHeader) ) {
  1346. *rc = FILE_SKIPPED;
  1347. __leave;
  1348. }
  1349. TimeDateStamp = pNtHeader->FileHeader.TimeDateStamp;
  1350. if (pNtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  1351. SizeOfImage = ((PIMAGE_NT_HEADERS32)pNtHeader)->OptionalHeader.SizeOfImage;
  1352. } else {
  1353. if (pNtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
  1354. SizeOfImage = ((PIMAGE_NT_HEADERS64)pNtHeader)->OptionalHeader.SizeOfImage;
  1355. } else {
  1356. SizeOfImage = 0;
  1357. }
  1358. }
  1359. } __finally {
  1360. SymCommonUnmapFile((LPCVOID)pDosHeader,DosFile);
  1361. }
  1362. if (*rc == FILE_SKIPPED)
  1363. {
  1364. return(FALSE);
  1365. }
  1366. StringCbCopy( szPriPubBin, sizeof(szPriPubBin), _T("bin") );
  1367. GetSymbolServerDirs( szFileName,
  1368. NULL,
  1369. (DWORD) TimeDateStamp,
  1370. (DWORD) SizeOfImage,
  1371. szString );
  1372. temp_rc = StoreFile( szDestDir,
  1373. szFileName,
  1374. szString,
  1375. szPtrFileName );
  1376. *rc = (USHORT)temp_rc;
  1377. if (temp_rc) {
  1378. if (pArgs->CorruptBinaries) {
  1379. TCHAR BinToCorrupt[_MAX_PATH];
  1380. TCHAR Temp[_MAX_PATH];
  1381. LPTSTR pFilename;
  1382. DWORD dwRet = 0xFFFFFFFF;
  1383. SymCommonGetFullPathName(szDestDir, sizeof(BinToCorrupt)/sizeof(BinToCorrupt[0]), BinToCorrupt, &pFilename);
  1384. SymCommonGetFullPathName(szFileName, sizeof(Temp)/sizeof(Temp[0]), Temp, &pFilename);
  1385. StringCbCat(BinToCorrupt, sizeof(BinToCorrupt), szString );
  1386. StringCbCat(BinToCorrupt, sizeof(BinToCorrupt), TEXT("\\") );
  1387. StringCbCat(BinToCorrupt, sizeof(BinToCorrupt), pFilename );
  1388. if (! (dwRet=CorruptFile(BinToCorrupt))==PEWHACK_SUCCESS ) {
  1389. fprintf(stderr, "Unable to corrupt %s (0x%08x).\n", BinToCorrupt, dwRet);
  1390. }
  1391. }
  1392. return (TRUE);
  1393. }
  1394. else {
  1395. return (FALSE);
  1396. }
  1397. }
  1398. BOOL
  1399. StorePdb(
  1400. LPTSTR szDestDir,
  1401. LPTSTR szFileName,
  1402. LPTSTR szPtrFileName,
  1403. USHORT *rc_flag
  1404. )
  1405. /*++
  1406. Routine Description:
  1407. Validates the PDB
  1408. Return Value:
  1409. TRUE PDB validates
  1410. FALSE PDB doesn't validate
  1411. --*/
  1412. {
  1413. BOOL rc;
  1414. BOOL valid;
  1415. PDB *pdb;
  1416. EC ec;
  1417. char szError[cbErrMax] = _T("");
  1418. SIG sig;
  1419. AGE age=0;
  1420. SIG70 sig70;
  1421. TCHAR szString[_MAX_PATH];
  1422. DBI *pdbi;
  1423. GSI *pgsi;
  1424. ZeroMemory( szString, _MAX_PATH * sizeof(TCHAR) );
  1425. ZeroMemory( &sig70, sizeof(SIG70) );
  1426. pdb=NULL;
  1427. __try
  1428. {
  1429. valid = PDBOpen( szFileName,
  1430. _T("r"),
  1431. 0,
  1432. &ec,
  1433. szError,
  1434. &pdb
  1435. );
  1436. }
  1437. __except( EXCEPTION_EXECUTE_HANDLER )
  1438. {
  1439. valid=FALSE;
  1440. }
  1441. if ( !valid ) {
  1442. SetLastError(ec);
  1443. *rc_flag = (USHORT)ec;
  1444. return FALSE;
  1445. }
  1446. // The DBI age is created when the exe is created.
  1447. // This age will not change if an operation is performed
  1448. // on the PDB that increments its PDB age.
  1449. __try
  1450. {
  1451. valid = PDBOpenDBI(pdb, pdbRead, NULL, &pdbi);
  1452. }
  1453. __except( EXCEPTION_EXECUTE_HANDLER )
  1454. {
  1455. valid=FALSE;
  1456. }
  1457. if ( !valid ) {
  1458. SetLastError(ec);
  1459. *rc_flag = (USHORT)ec;
  1460. PDBClose(pdb);
  1461. return FALSE;
  1462. }
  1463. // Do we need to determine if this is a public or private pdb?
  1464. // If we do, then proceed through the next section.
  1465. //
  1466. // Windows stuffs type info into the kernels so this section tries
  1467. // a way around checking for type info to determine if this is a
  1468. // private pdb or not.
  1469. valid = TRUE;
  1470. __try
  1471. {
  1472. PrivateStripped=PDBPrivateStripped(pdb, pdbi);
  1473. }
  1474. __except( EXCEPTION_EXECUTE_HANDLER )
  1475. {
  1476. valid = FALSE;
  1477. }
  1478. if ( !valid) {
  1479. DBIClose(pdbi);
  1480. PDBClose(pdb);
  1481. return FALSE;
  1482. }
  1483. if (PrivateStripped) {
  1484. StringCbCopy( szPriPubBin, sizeof(szPriPubBin), _T("pub") );
  1485. } else {
  1486. StringCbCopy( szPriPubBin, sizeof(szPriPubBin), _T("pri") );
  1487. }
  1488. // Determine if we are supposed to skip this file or index it.
  1489. if ( ( PrivateStripped && (pArgs->Filter == 2)) || // public pdb and index private pdbs
  1490. (!PrivateStripped && (pArgs->Filter == 1)) ) { // private pdb and index public pdbs
  1491. *rc_flag = FILE_SKIPPED;
  1492. DBIClose(pdbi);
  1493. PDBClose(pdb);
  1494. return TRUE;
  1495. }
  1496. if (PrivateStripped) {
  1497. StringCbCopy( szPriPubBin, sizeof(szPriPubBin), _T("pub") );
  1498. } else {
  1499. StringCbCopy( szPriPubBin, sizeof(szPriPubBin), _T("pri") );
  1500. }
  1501. age = pdbi->QueryAge();
  1502. // If the DBI age is zero, then use the pdb age
  1503. if ( age == 0 )
  1504. {
  1505. age = pdb->QueryAge();
  1506. }
  1507. sig = PDBQuerySignature(pdb);
  1508. rc = PDBQuerySignature2(pdb, &sig70);
  1509. DBIClose(pdbi);
  1510. PDBClose(pdb);
  1511. if (rc) {
  1512. GetSymbolServerDirs( szFileName,
  1513. &sig70,
  1514. (DWORD) sig,
  1515. (DWORD) age,
  1516. szString );
  1517. } else {
  1518. GetSymbolServerDirs( szFileName,
  1519. NULL,
  1520. (DWORD) sig,
  1521. (DWORD) age,
  1522. szString );
  1523. }
  1524. rc = StoreFile( szDestDir,
  1525. szFileName,
  1526. szString,
  1527. szPtrFileName
  1528. );
  1529. return (rc);
  1530. }