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.

3113 lines
99 KiB

  1. #include <windows.h>
  2. #include <lmcons.h>
  3. #include <lmapibuf.h>
  4. #include <lmerr.h>
  5. #include <lmshare.h>
  6. #include <malloc.h>
  7. #include "symutil.h"
  8. #include "symsrv.h"
  9. #include "output.hpp"
  10. #include <SymCommon.h>
  11. #include <strsafe.h>
  12. #define FILE_ID_NOT_FOUND ((DWORD) -1)
  13. typedef struct _FILE_INFO {
  14. DWORD TimeDateStamp;
  15. DWORD CheckSum;
  16. DWORD Signature;
  17. TCHAR szName[_MAX_PATH];
  18. } FILE_INFO, *PFILE_INFO;
  19. // Prototypes
  20. PCOM_ARGS
  21. GetCommandLineArgs(
  22. int argc,
  23. char **argv
  24. );
  25. BOOL
  26. InitializeTrans(
  27. PTRANSACTION *pTrans,
  28. PCOM_ARGS pArgs,
  29. PHANDLE hFile
  30. );
  31. BOOL
  32. DeleteTrans(
  33. PTRANSACTION pTrans,
  34. PCOM_ARGS pArgs
  35. );
  36. VOID
  37. Usage (
  38. VOID
  39. );
  40. StoreDirectory(
  41. LPTSTR szDir,
  42. LPTSTR szFName,
  43. LPTSTR szDestDir,
  44. PFILE_COUNTS pFileCounts,
  45. LPTSTR szPath
  46. );
  47. DWORD
  48. StoreAllDirectories(
  49. LPTSTR szDir,
  50. LPTSTR szFName,
  51. LPTSTR szDestDir,
  52. PFILE_COUNTS pFileCounts,
  53. LPTSTR szPath
  54. );
  55. BOOL
  56. CorrectPath(
  57. LPTSTR szFileName,
  58. LPTSTR szPathName,
  59. LPTSTR szCorrectPath
  60. );
  61. BOOL
  62. AddTransToFile(
  63. PTRANSACTION pTrans,
  64. LPTSTR szFileName,
  65. PHANDLE hFile
  66. );
  67. BOOL
  68. UpdateServerFile(
  69. PTRANSACTION pTrans,
  70. LPTSTR szServerFileName
  71. );
  72. BOOL GetNextId(
  73. LPTSTR szMasterFileName,
  74. LPTSTR *szId,
  75. PHANDLE hFile
  76. );
  77. BOOL
  78. DeleteEntry(
  79. LPTSTR szDir,
  80. LPTSTR szId
  81. );
  82. BOOL
  83. ForceDeleteFile(
  84. LPTSTR szPtrFile
  85. );
  86. BOOL
  87. ForceRemoveDirectory(
  88. LPTSTR szDir
  89. );
  90. BOOL
  91. ForceClosePath(
  92. LPTSTR szDir
  93. );
  94. BOOL
  95. CopyTheFile(
  96. LPTSTR szDir,
  97. LPTSTR szFilePathName
  98. );
  99. BOOL
  100. DeleteTheFile(
  101. LPTSTR szDir,
  102. LPTSTR szFilePathName
  103. );
  104. BOOL
  105. StoreSystemTime(
  106. LPTSTR *szTime,
  107. LPSYSTEMTIME lpSystemTime
  108. );
  109. BOOL
  110. StoreSystemDate(
  111. LPTSTR *szDate,
  112. LPSYSTEMTIME lpSystemTime
  113. );
  114. ULONG GetMaxLineOfHistoryFile(
  115. VOID
  116. );
  117. ULONG GetMaxLineOfTransactionFile(
  118. VOID
  119. );
  120. BOOL GetSrcDirandFileName (
  121. LPTSTR szStr,
  122. LPTSTR szSrcDir,
  123. LPTSTR szFileName,
  124. BOOL LocalFile
  125. );
  126. DWORD AppendTransIDToFile (
  127. FILE *AppendToFile,
  128. LPTSTR szId
  129. );
  130. PCOM_ARGS pArgs;
  131. HANDLE hTransFile;
  132. DWORD StoreFlags;
  133. PTRANSACTION pTrans;
  134. LONG lMaxTrans;
  135. LONG NumSkippedFiles=0;
  136. LPTSTR szPingMe;
  137. BOOL MSArchive=FALSE;
  138. BOOL PubPriPriority=FALSE;
  139. // SymOutput *so;
  140. SymOutput *so;
  141. // display specific text for an error if defined.
  142. void DisplayErrorText(DWORD dwError);
  143. int _cdecl main( int argc, char **argv) {
  144. DWORD NumErrors = 0;
  145. FILE_COUNTS FileCounts;
  146. BOOL rc;
  147. HANDLE hFile;
  148. FILE *hPingMe = NULL;
  149. hFile=0;
  150. so = new SymOutput();
  151. // This also initializes the name of the Log File
  152. pArgs = GetCommandLineArgs(argc, argv);
  153. // Initialize the SymbolServer() function
  154. SymbolServerSetOptions(SSRVOPT_NOCOPY, 1 );
  155. SymbolServerSetOptions(SSRVOPT_PARAMTYPE, SSRVOPT_GUIDPTR);
  156. // Create the pingme.txt
  157. if (pArgs->StoreFlags != ADD_DONT_STORE) {
  158. if ( (hPingMe=_tfopen(szPingMe, "r")) == NULL ) {
  159. hPingMe = _tfopen(szPingMe, "w+");
  160. if ( hPingMe == NULL ) {
  161. so->printf("Cannot create %s.\n", szPingMe);
  162. }
  163. }
  164. if ( hPingMe != NULL ) {
  165. fflush(hPingMe);
  166. fclose(hPingMe);
  167. }
  168. }
  169. // Initialize the transaction record
  170. // Opens the master file (hFile) and leaves it open
  171. // Get exclusive access to this file
  172. // QUERIES don't update the server
  173. if (pArgs->TransState != TRANSACTION_QUERY) {
  174. InitializeTrans(&pTrans, pArgs, &hFile);
  175. }
  176. if ( pArgs->StoreFlags==ADD_STORE_FROM_FILE &&
  177. pArgs->AppendIDToFile ) {
  178. AppendTransIDToFile(pArgs->pStoreFromFile,
  179. pTrans->szId
  180. );
  181. }
  182. if (pArgs->StoreFlags != ADD_DONT_STORE && pArgs->StoreFlags != QUERY) {
  183. AddTransToFile(pTrans, pArgs->szMasterFileName, &hFile);
  184. }
  185. CloseHandle(hFile);
  186. //
  187. // Handle TRANSACTION_DEL and exit
  188. //
  189. if (pArgs->TransState==TRANSACTION_DEL) {
  190. rc = DeleteTrans(pTrans,pArgs);
  191. UpdateServerFile(pTrans, pArgs->szServerFileName);
  192. return(rc);
  193. }
  194. //
  195. // Only TRANSACTION_ADD and TRANSACTION_QUERY get here
  196. //
  197. // QUERY and ADD_DONT_STORE shouldn't update the server file
  198. if ( pArgs->StoreFlags == ADD_STORE ||
  199. pArgs->StoreFlags == ADD_STORE_FROM_FILE ) {
  200. // Update server file
  201. UpdateServerFile(pTrans, pArgs->szServerFileName);
  202. }
  203. // Make sure the directory path exists for the transaction
  204. // file if we are doing ADD_DONT_STORE
  205. if ( pArgs->StoreFlags == ADD_DONT_STORE ) {
  206. if ( !MakeSureDirectoryPathExists(pTrans->szTransFileName) ) {
  207. so->printf("Cannot create the directory %s - GetLastError() = %d\n",
  208. pTrans->szTransFileName, GetLastError() );
  209. exit(1);
  210. }
  211. // Open the file and move the file pointer to the end if we are
  212. // in appending mode.
  213. if (pArgs->AppendStoreFile) {
  214. hTransFile = CreateFile(pTrans->szTransFileName,
  215. GENERIC_WRITE,
  216. FILE_SHARE_READ,
  217. NULL,
  218. OPEN_ALWAYS,
  219. FILE_ATTRIBUTE_NORMAL,
  220. NULL
  221. );
  222. if (hTransFile == INVALID_HANDLE_VALUE ) {
  223. so->printf("Cannot create file %s - GetLastError = %d\n",
  224. pTrans->szTransFileName, GetLastError() );
  225. exit(1);
  226. }
  227. if ( SetFilePointer( hTransFile, 0, NULL, FILE_END )
  228. == INVALID_SET_FILE_POINTER ) {
  229. so->printf("Cannot move to end of file %s - GetLastError = %d\n",
  230. pTrans->szTransFileName, GetLastError() );
  231. exit(1);
  232. }
  233. } else {
  234. hTransFile = CreateFile(pTrans->szTransFileName,
  235. GENERIC_WRITE,
  236. FILE_SHARE_READ,
  237. NULL,
  238. CREATE_ALWAYS,
  239. FILE_ATTRIBUTE_NORMAL,
  240. NULL
  241. );
  242. if (hTransFile == INVALID_HANDLE_VALUE ) {
  243. so->printf("Cannot create file %s - GetLastError = %d\n",
  244. pTrans->szTransFileName, GetLastError() );
  245. exit(1);
  246. }
  247. }
  248. } else {
  249. if (pArgs->TransState!=TRANSACTION_QUERY) {
  250. hTransFile = CreateFile(pTrans->szTransFileName,
  251. GENERIC_WRITE,
  252. FILE_SHARE_READ,
  253. NULL,
  254. CREATE_NEW,
  255. FILE_ATTRIBUTE_NORMAL,
  256. NULL
  257. );
  258. if (hTransFile == INVALID_HANDLE_VALUE ) {
  259. so->printf("Cannot create a new file %s - GetLastError = %d\n",
  260. pTrans->szTransFileName, GetLastError() );
  261. exit(1);
  262. }
  263. }
  264. }
  265. StoreFlags=pArgs->StoreFlags;
  266. if (pArgs->TransState!=TRANSACTION_QUERY) {
  267. if (hTransFile == INVALID_HANDLE_VALUE ) {
  268. so->printf("Cannot create a new file %s - GetLastError = %d\n",
  269. pTrans->szTransFileName, GetLastError() );
  270. exit(1);
  271. }
  272. }
  273. memset( &FileCounts, 0, sizeof(FILE_COUNTS) );
  274. if ( pArgs->StoreFlags==ADD_STORE_FROM_FILE ) {
  275. // This will only store pointers
  276. NumErrors += StoreFromFile(
  277. pArgs->pStoreFromFile,
  278. pArgs->szSymbolsDir,
  279. &FileCounts);
  280. fflush(pArgs->pStoreFromFile);
  281. fclose(pArgs->pStoreFromFile);
  282. } else if ( !pArgs->Recurse ) {
  283. NumErrors += StoreDirectory(
  284. pArgs->szSrcDir,
  285. pArgs->szFileName,
  286. pArgs->szSymbolsDir,
  287. &FileCounts,
  288. pArgs->szSrcPath
  289. );
  290. } else {
  291. NumErrors += StoreAllDirectories(
  292. pArgs->szSrcDir,
  293. pArgs->szFileName,
  294. pArgs->szSymbolsDir,
  295. &FileCounts,
  296. pArgs->szSrcPath
  297. );
  298. }
  299. if ( pArgs->TransState != TRANSACTION_QUERY ) {
  300. if (pArgs->szSrcPath) {
  301. so->printf("SYMSTORE: Number of pointers stored = %d\n",FileCounts.NumPassedFiles);
  302. } else {
  303. so->printf("SYMSTORE: Number of files stored = %d\n",FileCounts.NumPassedFiles);
  304. }
  305. so->printf("SYMSTORE: Number of errors = %d\n",NumErrors);
  306. so->printf("SYMSTORE: Number of ignored files = %d\n", NumSkippedFiles);
  307. SetEndOfFile(hTransFile);
  308. CloseHandle(hTransFile);
  309. }
  310. SymbolServerClose();
  311. delete so;
  312. return (0);
  313. }
  314. DWORD AppendTransIDToFile(FILE *AppendToFile, LPTSTR szId) {
  315. TCHAR szBuffer[35];
  316. long pos;
  317. int i=0;
  318. fflush(AppendToFile);
  319. pos = ftell(AppendToFile);
  320. if ( fseek( AppendToFile, -4, SEEK_END ) != 0) {
  321. so->printf("Cannot move to end of index file - GetLastError = %d\n", GetLastError() );
  322. exit(1);
  323. }
  324. if ( _fgetts(szBuffer, 10, AppendToFile) == NULL) {
  325. so->printf("Cannot read from file - GetLastError = %d\n", GetLastError() );
  326. exit(1);
  327. }
  328. if ( fseek( AppendToFile, -4, SEEK_END ) != 0) {
  329. so->printf("Cannot move to end of index file - GetLastError = %d\n", GetLastError() );
  330. exit(1);
  331. }
  332. fflush(AppendToFile);
  333. while(!iscntrl(szBuffer[i]) && !iswcntrl(szBuffer[i])) {
  334. i++;
  335. }
  336. StringCchPrintf(&szBuffer[i], (sizeof(szBuffer)/sizeof(TCHAR) ) - i, "\r\n;Transaction=%s\r\n", szId);
  337. _fputts(szBuffer, AppendToFile);
  338. fflush(AppendToFile);
  339. if ( fseek( AppendToFile, pos, SEEK_SET ) != 0 ) {
  340. so->printf("Cannot move to offset (%d) of index file - GetLastError = %d\n", pos, GetLastError() );
  341. exit(1);
  342. }
  343. return TRUE;
  344. }
  345. //
  346. // AddTransToFile
  347. //
  348. // Purpose - Add a record to the end of the Master File
  349. //
  350. BOOL
  351. AddTransToFile(
  352. PTRANSACTION pTrans,
  353. LPTSTR szFileName,
  354. PHANDLE hFile
  355. )
  356. {
  357. LPTSTR szBuf=NULL;
  358. LPTSTR szBuf2=NULL;
  359. TCHAR szTransState[4];
  360. TCHAR szFileOrPtr[10];
  361. DWORD dwNumBytesToWrite;
  362. DWORD dwNumBytesWritten;
  363. DWORD FileSizeHigh;
  364. DWORD FileSizeLow;
  365. assert (pTrans);
  366. // Master file should already be opened
  367. assert(*hFile);
  368. // Create the buffer to store one record in
  369. szBuf = (LPTSTR) malloc( sizeof(TCHAR) * (lMaxTrans + 1) );
  370. if (!szBuf) {
  371. CloseHandle(*hFile);
  372. MallocFailed();
  373. }
  374. // Create the buffer to store one record in
  375. szBuf2 = (LPTSTR) malloc( sizeof(TCHAR) * (lMaxTrans + 1) );
  376. if (!szBuf2) {
  377. CloseHandle(*hFile);
  378. MallocFailed();
  379. }
  380. // Move to the end of the file
  381. SetFilePointer( *hFile,
  382. 0,
  383. NULL,
  384. FILE_END );
  385. if (pTrans->TransState == TRANSACTION_ADD)
  386. {
  387. StringCbCopy(szTransState, sizeof(szTransState), _T("add"));
  388. switch (pTrans->FileOrPtr) {
  389. case STORE_FILE: StringCbCopy(szFileOrPtr, sizeof(szFileOrPtr), _T("file"));
  390. break;
  391. default: so->printf("Incorrect value for pTrans->FileOrPtr - assuming ptr\n");
  392. case STORE_PTR: StringCbCopy(szFileOrPtr, sizeof(szFileOrPtr), _T("ptr"));
  393. break;
  394. }
  395. StringCbPrintf(szBuf2,
  396. _msize(szBuf2),
  397. "%s,%s,%s,%s,%s,%s,%s,%s,%s",
  398. pTrans->szId,
  399. szTransState,
  400. szFileOrPtr,
  401. pTrans->szDate,
  402. pTrans->szTime,
  403. pTrans->szProduct,
  404. pTrans->szVersion,
  405. pTrans->szComment,
  406. pTrans->szUnused);
  407. }
  408. else if (pTrans->TransState == TRANSACTION_DEL)
  409. {
  410. StringCbCopy(szTransState, sizeof(szTransState), _T("del"));
  411. StringCbPrintf(szBuf2,
  412. _msize(szBuf2),
  413. "%s,%s,%s",
  414. pTrans->szDelId,
  415. szTransState,
  416. pTrans->szId);
  417. } else {
  418. so->printf("SYMSTORE: The transaction state is unknown\n");
  419. free(szBuf);
  420. free(szBuf2);
  421. return (FALSE);
  422. }
  423. // If this is not the first line in the file, then put a '\n' before the
  424. // line.
  425. FileSizeLow = GetFileSize(*hFile, &FileSizeHigh);
  426. dwNumBytesToWrite = (_tcslen(szBuf2) ) * sizeof(TCHAR);
  427. if ( FileSizeLow == 0 && FileSizeHigh == 0 ) {
  428. StringCbCopy(szBuf, _msize(szBuf), szBuf2);
  429. } else {
  430. StringCbPrintf(szBuf, _msize(szBuf), "\n%s", szBuf2);
  431. dwNumBytesToWrite += 1 * sizeof(TCHAR);
  432. }
  433. // Append this to the master file
  434. WriteFile( *hFile,
  435. (LPCVOID)szBuf,
  436. dwNumBytesToWrite,
  437. &dwNumBytesWritten,
  438. NULL
  439. );
  440. free(szBuf);
  441. free(szBuf2);
  442. if ( dwNumBytesToWrite != dwNumBytesWritten )
  443. {
  444. so->printf( "FAILED to write to %s, with GetLastError = %d\n",
  445. szFileName,
  446. GetLastError());
  447. return (FALSE);
  448. }
  449. return (TRUE);
  450. }
  451. BOOL
  452. CopyTheFile(
  453. LPTSTR szDir,
  454. LPTSTR szFilePathName
  455. )
  456. /*++
  457. IN szDir The directory that the file is copied to
  458. IN szFilePathName The full path and name of the file to be copied
  459. "CopyTheFile" copies szFilePathName to the directory
  460. szDir, if the file does not already exist in szDir
  461. --*/
  462. {
  463. BOOL rc;
  464. USHORT j;
  465. LPTSTR szFileName;
  466. // Figure out index in "szFilePathName" where the file name starts
  467. j = _tcslen(szFilePathName) - 1;
  468. if ( szFilePathName[j] == '\\' ) {
  469. so->printf("SYMSTORE: %s\refs.ptr has a bad file name %s\n",
  470. szDir, szFilePathName);
  471. return(FALSE);
  472. }
  473. while ( szFilePathName[j] != '\\' && j != 0 ) j--;
  474. if ( j == 0 ) {
  475. so->printf("SYMSTORE: %s\refs.ptr has a bad file name for %s\n",
  476. szDir, szFilePathName );
  477. return(FALSE);
  478. }
  479. // Set j == the index of first character after the last '\' in szFilePathName
  480. j++;
  481. // Allocate and store the full path and name of
  482. szFileName = (LPTSTR) malloc ( sizeof(TCHAR) *
  483. (_tcslen(szDir) + _tcslen(szFilePathName+j) + 1) );
  484. if ( szFileName == NULL ) MallocFailed();
  485. StringCbPrintf(szFileName, _msize(szFileName), "%s%s", szDir, szFilePathName+j );
  486. // If this file doesn't exist, then copy it
  487. rc = MyCopyFile( szFilePathName, szFileName );
  488. free(szFileName);
  489. return(rc);
  490. }
  491. BOOL
  492. CorrectPath(
  493. LPTSTR szFileName,
  494. LPTSTR szPathName,
  495. LPTSTR szCorrectPath
  496. )
  497. {
  498. // To return TRUE, szPathName should equal szCorrectPath + \ + szFileName
  499. // The only hitch is that there could be extraneous \'s
  500. TCHAR CorrectPathx[_MAX_PATH + _MAX_FNAME + _MAX_EXT + 2];
  501. TCHAR PathNamex[_MAX_PATH + _MAX_FNAME + _MAX_EXT + 2];
  502. LONG length, index, i;
  503. // Get rid of any extra \'s
  504. length = _tcslen(szPathName);
  505. PathNamex[0] = szPathName[0];
  506. index = 1;
  507. for (i=1; i<=length; i++) {
  508. if ( (szPathName[i-1] != '\\') || (szPathName[i] != '\\') ) {
  509. PathNamex[index] = szPathName[i];
  510. index++;
  511. }
  512. }
  513. length = _tcslen(szCorrectPath);
  514. CorrectPathx[0] = szCorrectPath[0];
  515. index = 1;
  516. for (i=1; i<=length; i++) {
  517. if ( (szCorrectPath[i-1] != '\\') || (szCorrectPath[i] != '\\') ) {
  518. CorrectPathx[index] = szCorrectPath[i];
  519. index++;
  520. }
  521. }
  522. // Make sure that the correct path doesn't end in a '\'
  523. length = _tcslen(CorrectPathx);
  524. if ( CorrectPathx[length-1] == '\\' ) CorrectPathx[length-1] = '\0';
  525. StringCbCat( CorrectPathx, sizeof(CorrectPathx), "\\");
  526. StringCbCat( CorrectPathx, sizeof(CorrectPathx), szFileName);
  527. if ( _tcsicmp(CorrectPathx, szPathName) == 0) return TRUE;
  528. else return FALSE;
  529. }
  530. BOOL
  531. DeleteEntry(
  532. LPTSTR szDir,
  533. LPTSTR szId
  534. )
  535. /*++ This deletes szID from the directory szDir on the symbols server
  536. -- */
  537. {
  538. LPTSTR szRefsFile; // Full path and name of the refs.ptr file
  539. LPTSTR szTempFile; // Full path and name for a temporaty refs.ptr file
  540. LPTSTR szPtrFile; // Full path and name of the pointer file
  541. LPTSTR szParentDir;
  542. FILE *fRefsFile;
  543. FILE *fTempFile;
  544. FILE *fPtrFile;
  545. LPTSTR szBuf; // Used to process entries in the refs file
  546. TCHAR *token;
  547. TCHAR seps[] = _T(",");
  548. fpos_t CurFilePos;
  549. fpos_t IdFilePos;
  550. fpos_t PrevFilePos;
  551. fpos_t Prev2FilePos;
  552. fpos_t PubFilePos;
  553. fpos_t PriFilePos;
  554. BOOL IdIsFile;
  555. BOOL Found;
  556. BOOL rc = FALSE;
  557. ULONG MaxLine; // Maximim length of a record in refs.ptr
  558. ULONG NumLines = 0;
  559. ULONG NumFiles = 0;
  560. ULONG NumPtrs = 0;
  561. ULONG IdLineNum = 0;
  562. ULONG PubLineNum = 0;
  563. ULONG PriLineNum = 0;
  564. ULONG CurLine = 0;
  565. ULONG i;
  566. LONG j;
  567. DWORD len;
  568. ULONG ReplaceIsFile;
  569. ULONG ReplaceLineNum;
  570. szRefsFile = (LPTSTR) malloc ( (_tcslen(szDir) + _tcslen(_T("refs.ptr")) + 1) * sizeof(TCHAR) );
  571. if (!szRefsFile) MallocFailed();
  572. StringCbPrintf(szRefsFile, _msize(szRefsFile), "%srefs.ptr", szDir );
  573. szPtrFile = (LPTSTR) malloc ( (_tcslen(szDir) + _tcslen(_T("file.ptr")) + 1) * sizeof(TCHAR) );
  574. if (!szPtrFile) MallocFailed();
  575. StringCbPrintf(szPtrFile, _msize(szPtrFile), "%sfile.ptr", szDir);
  576. szTempFile = (LPTSTR) malloc ( (_tcslen(szRefsFile) + _tcslen(".tmp") + 1) * sizeof(TCHAR) );
  577. if (!szTempFile) MallocFailed();
  578. StringCbPrintf(szTempFile, _msize(szTempFile), "%s.tmp", szRefsFile );
  579. MaxLine = GetMaxLineOfRefsPtrFile();
  580. szBuf = (LPTSTR) malloc( MaxLine * sizeof(TCHAR) );
  581. if ( !szBuf ) MallocFailed();
  582. ZeroMemory(szBuf,MaxLine*sizeof(TCHAR));
  583. fRefsFile = _tfopen(szRefsFile, _T("r+") );
  584. if ( fRefsFile == NULL ) {
  585. // BARB - Check for corruption -- if the file doesn't exist,
  586. // verify that the parent directory structure doesn't exist either
  587. goto finish_DeleteEntry;
  588. }
  589. //
  590. // Read through the refs.ptr file and gather information
  591. //
  592. NumFiles = 0;
  593. NumPtrs = 0;
  594. Found = FALSE;
  595. NumLines = 0;
  596. fgetpos( fRefsFile, &CurFilePos);
  597. PrevFilePos = CurFilePos; // Position of the current line
  598. Prev2FilePos = CurFilePos; // Position of the line before the current line
  599. while ( _fgetts( szBuf, MaxLine, fRefsFile) != NULL ) {
  600. len=_tcslen(szBuf);
  601. if ( len > 3 ) {
  602. // CurFilePos is set to the next character to be read
  603. // We need to remember the beginning position of this line (PrevFilePos)
  604. // And the beginning position of the line before this line (Prev2FilePos)
  605. Prev2FilePos = PrevFilePos;
  606. PrevFilePos = CurFilePos;
  607. fgetpos( fRefsFile, &CurFilePos);
  608. NumLines++;
  609. token = _tcstok(szBuf, seps); // Look at the ID
  610. if ( _tcscmp(token,szId) == 0 ) {
  611. // We found the ID
  612. Found = TRUE;
  613. IdFilePos = PrevFilePos;
  614. IdLineNum = NumLines;
  615. token = _tcstok(NULL, seps); // Look at the "file" or "ptr" field
  616. if (token && ( _tcscmp(token,_T("file")) == 0)) {
  617. IdIsFile = TRUE;
  618. } else if (token && ( _tcscmp(token,_T("ptr")) == 0 )) {
  619. IdIsFile = FALSE;
  620. } else {
  621. so->printf("SYMSTORE: Error in %s - entry for %s does not contain ""file"" or ""ptr""\n",
  622. szRefsFile, szId);
  623. rc = FALSE;
  624. goto finish_DeleteEntry;
  625. }
  626. } else {
  627. // Record info about the other records
  628. token = _tcstok(NULL, seps); // Look at the "file" or "ptr" field
  629. if (token && ( _tcscmp(token,_T("file")) == 0)) {
  630. NumFiles++;
  631. } else if (token && ( _tcscmp(token,_T("ptr")) == 0 )) {
  632. NumPtrs++;
  633. } else {
  634. so->printf("SYMSTORE: Error in %s - entry for %s does not contain ""file"" or ""ptr""\n",
  635. szRefsFile, szId);
  636. rc = FALSE;
  637. goto finish_DeleteEntry;
  638. }
  639. if ( PubPriPriority > 0 ) {
  640. // Now, see if the next token is pub or pri
  641. token = _tcstok(NULL, seps);
  642. if ( token && PubPriPriority == 1 && (_tcscmp(token,_T("pub")) == 0) ) {
  643. PubFilePos=PrevFilePos;
  644. PubLineNum = NumLines;
  645. } else if ( token && PubPriPriority == 1 && (_tcscmp(token,_T("pri")) == 0) ) {
  646. PriFilePos = PrevFilePos;
  647. PriLineNum = NumLines;
  648. }
  649. }
  650. }
  651. }
  652. ZeroMemory(szBuf, MaxLine*sizeof(TCHAR));
  653. }
  654. fflush(fRefsFile);
  655. fclose(fRefsFile);
  656. // If we didn't find the ID we are deleting, then don't do anything in this directory
  657. if (IdLineNum == 0 ) goto finish_DeleteEntry;
  658. // If there was only one record, then just delete everything
  659. if (NumLines == 1) {
  660. DeleteAllFilesInDirectory(szDir);
  661. // Delete this directory
  662. rc = ForceRemoveDirectory(szDir);
  663. if ( !rc ) {
  664. goto finish_DeleteEntry;
  665. }
  666. // If the first directory was deleted, remove the parent directory
  667. szParentDir=(LPTSTR)malloc(_tcslen(szDir) + 1 );
  668. if ( szParentDir == NULL ) MallocFailed();
  669. // First figure out the parent directory
  670. StringCbCopy(szParentDir, _msize(szParentDir), szDir);
  671. // szDir ended with a '\' -- find the previous one
  672. j = _tcslen(szParentDir)-2;
  673. while ( j >=0 && szParentDir[j] != '\\' ) {
  674. j--;
  675. }
  676. if (j<0) {
  677. so->printf("SYMSTORE: Could not delete the parent directory of %s\n", szDir);
  678. }
  679. else {
  680. szParentDir[j+1] = '\0';
  681. // This call will remove the directory only if its empty
  682. rc = RemoveDirectory(szParentDir);
  683. if ( !rc ) {
  684. goto finish_DeleteEntry;
  685. }
  686. }
  687. free(szParentDir);
  688. goto finish_DeleteEntry;
  689. }
  690. //
  691. // Get the replacement info for this deletion
  692. //
  693. if ( PubPriPriority == 1 && PubLineNum > 0 ) {
  694. ReplaceLineNum = PubLineNum;
  695. } else if ( PubPriPriority == 2 && PriLineNum > 0 ) {
  696. ReplaceLineNum = PriLineNum;
  697. } else if ( IdLineNum == NumLines ) {
  698. ReplaceLineNum = NumLines-1;
  699. } else {
  700. ReplaceLineNum = NumLines;
  701. }
  702. //
  703. // Now, delete the entry from refs.ptr
  704. // Rename "refs.ptr" to "refs.ptr.tmp"
  705. // Then copy refs.ptr.tmp line by line to refs.ptr, skipping the line we are
  706. // supposed to delete
  707. //
  708. rename( szRefsFile, szTempFile);
  709. fTempFile= _tfopen(szTempFile, "r" );
  710. if (fTempFile == NULL) {
  711. goto finish_DeleteEntry;
  712. }
  713. fRefsFile= _tfopen(szRefsFile, "w" );
  714. if (fRefsFile == NULL) {
  715. fflush(fTempFile);
  716. fclose(fTempFile);
  717. goto finish_DeleteEntry;
  718. }
  719. CurLine = 0;
  720. i=0;
  721. while ( _fgetts( szBuf, MaxLine, fTempFile) != NULL ) {
  722. len=_tcslen(szBuf);
  723. if ( len > 3 ) {
  724. i++;
  725. if ( i != IdLineNum ) {
  726. // Make sure that the last line doesn't end with a '\n'
  727. if ( i == NumLines || (IdLineNum == NumLines && i == NumLines-1) ) {
  728. if ( token[_tcslen(token)-1] == '\n' ) {
  729. token[_tcslen(token)-1] = '\0';
  730. }
  731. }
  732. _fputts( szBuf, fRefsFile);
  733. }
  734. // This is the replacement, either get the new file, or update file.ptr
  735. if ( i == ReplaceLineNum ) {
  736. // This is the replacement information,
  737. // Figure out if it is a file or a pointer
  738. token = _tcstok(szBuf, seps); // Skip the ID number
  739. token = _tcstok(NULL, seps); // Get "file" or "ptr" field
  740. if ( _tcscmp(token,_T("file")) == 0) {
  741. ReplaceIsFile = TRUE;
  742. } else if ( _tcscmp(token,_T("ptr")) == 0 ) {
  743. ReplaceIsFile = FALSE;
  744. } else {
  745. so->printf("SYMSTORE: Error in %s - entry for %s does not contain ""file"" or ""ptr""\n",
  746. szRefsFile, szId);
  747. rc = FALSE;
  748. goto finish_DeleteEntry;
  749. }
  750. token = _tcstok(NULL, seps); // Get the replacement path and filename
  751. // Strip off the last character if it is a '\n'
  752. if ( token[_tcslen(token)-1] == '\n' ) {
  753. token[_tcslen(token)-1] = '\0';
  754. }
  755. //
  756. // If the replacement is a file, then copy the file
  757. // If the replacement if a ptr, then update "file.ptr"
  758. //
  759. rc = TRUE;
  760. if (ReplaceIsFile) {
  761. rc = CopyTheFile(szDir, token);
  762. rc = rc && ForceDeleteFile(szPtrFile);
  763. } else {
  764. //
  765. // Put the new pointer into "file.ptr"
  766. //
  767. rc = ForceClosePath(szPtrFile);
  768. fPtrFile = _tfopen(szPtrFile, _T("w") );
  769. if ( !fPtrFile ) {
  770. so->printf("SYMSTORE: Could not open %s for writing\n", szPtrFile);
  771. rc = FALSE;
  772. } else {
  773. _fputts( token, fPtrFile);
  774. fflush(fPtrFile);
  775. fclose(fPtrFile);
  776. }
  777. //
  778. // If the deleted record was a "file", and we are placing it with a
  779. // pointer, and there are no other "file" records in refs.ptr, then
  780. // delete the file from the directory.
  781. //
  782. if ( IdIsFile && (NumFiles == 0 )) {
  783. DeleteTheFile(szDir, token);
  784. }
  785. }
  786. }
  787. }
  788. }
  789. fflush(fTempFile);
  790. fclose(fTempFile);
  791. fflush(fRefsFile);
  792. fclose(fRefsFile);
  793. // Now, delete the temporary file
  794. DeleteFile(szTempFile);
  795. finish_DeleteEntry:
  796. free (szBuf);
  797. free (szRefsFile);
  798. free (szPtrFile);
  799. free (szTempFile);
  800. return (rc);
  801. }
  802. BOOL
  803. DeleteTheFile(
  804. LPTSTR szDir,
  805. LPTSTR szFilePathName
  806. )
  807. /*++
  808. IN szDir The directory that the file is to be deleted from
  809. IN szFilePathName The file name of the file to be deleted. It is
  810. preceded by the wrong path. That's why we need to
  811. strip off the file name and add it to szDir
  812. "DeleteTheFile" figures out the file name at the end of szFilePathName,
  813. and deletes it from szDir if it exists. It will delete the file and/or
  814. the corresponding compressed file name that has the same name with a _
  815. at the end of it.
  816. --*/
  817. {
  818. BOOL rc,returnval=TRUE;
  819. USHORT j;
  820. LPTSTR szFileName;
  821. DWORD dw;
  822. // Figure out index in "szFilePathName" where the file name starts
  823. j = _tcslen(szFilePathName) - 1;
  824. if ( szFilePathName[j] == '\\' ) {
  825. so->printf("SYMSTORE: %s\refs.ptr has a bad file name %s\n",
  826. szDir, szFilePathName);
  827. return(FALSE);
  828. }
  829. while ( szFilePathName[j] != '\\' && j != 0 ) j--;
  830. if ( j == 0 ) {
  831. so->printf("SYMSTORE: %s\refs.ptr has a bad file name for %s\n",
  832. szDir, szFilePathName );
  833. return(FALSE);
  834. }
  835. // Set j == the index of first character after the last '\' in szFilePathName
  836. j++;
  837. // Allocate and store the full path and name of
  838. szFileName = (LPTSTR) malloc ( sizeof(TCHAR) *
  839. (_tcslen(szDir) + _tcslen(szFilePathName+j) + 1) );
  840. if ( szFileName == NULL ) MallocFailed();
  841. StringCbPrintf(szFileName, _msize(szFileName), "%s%s", szDir, szFilePathName+j );
  842. // See if the file exists
  843. dw = GetFileAttributes( szFileName );
  844. if ( dw != 0xffffffff ) {
  845. rc = DeleteFile( szFileName );
  846. if (!rc && GetLastError() != ERROR_NOT_FOUND ) {
  847. rc = ForceDeleteFile( szFileName );
  848. if ( !rc ) {
  849. so->printf("SYMSTORE: Could not delete %s - GetLastError = %d\n",
  850. szFileName, GetLastError() );
  851. returnval=FALSE;
  852. }
  853. }
  854. }
  855. // See if the compressed file exists and delete it.
  856. szFileName[ _tcslen(szFileName) -1 ] = _T('_');
  857. dw = GetFileAttributes( szFileName );
  858. if ( dw != 0xffffffff ) {
  859. rc = DeleteFile( szFileName );
  860. if (!rc && GetLastError() != ERROR_NOT_FOUND ) {
  861. so->printf("SYMSTORE: Could not delete %s - GetLastError = %d\n",
  862. szFileName, GetLastError() );
  863. returnval=FALSE;
  864. }
  865. }
  866. free(szFileName);
  867. return(returnval);
  868. }
  869. BOOL
  870. DeleteTrans(
  871. PTRANSACTION pTrans,
  872. PCOM_ARGS pArgs
  873. )
  874. {
  875. FILE *pFile;
  876. LONG MaxLine;
  877. LPTSTR szBuf;
  878. TCHAR szDir[_MAX_PATH + 2];
  879. TCHAR *token;
  880. TCHAR seps[] = _T(",");
  881. // First, go get the transaction file
  882. // and delete its entries from the symbols server
  883. pFile = _tfopen(pTrans->szTransFileName, _T("r") );
  884. if (!pFile ) {
  885. DWORD Error = GetLastError();
  886. switch(Error) {
  887. case ERROR_FILE_NOT_FOUND:
  888. so->printf("Transaction %s doesn't exist\n", pTrans->szId);
  889. break;
  890. default:
  891. so->printf("Cannot open file %s - GetLastError = %d\n", pTrans->szTransFileName, GetLastError() );
  892. break;
  893. }
  894. exit(1);
  895. }
  896. // Figure out the maximum line length
  897. // Add space for 1 commas and a '\0'
  898. MaxLine = GetMaxLineOfTransactionFile();
  899. szBuf = (LPTSTR)malloc(MaxLine * sizeof(TCHAR) );
  900. if (!szBuf) {
  901. fclose(pFile);
  902. MallocFailed();
  903. }
  904. while ( (!feof(pFile)) && fgets(szBuf, MaxLine, pFile)) {
  905. // Find the first token that ends with ','
  906. token=_tcstok(szBuf, seps);
  907. // Compute the directory we are deleting from
  908. StringCbCopy(szDir, sizeof(szDir), pArgs->szSymbolsDir);
  909. StringCbCat( szDir, sizeof(szDir), token);
  910. MyEnsureTrailingBackslash(szDir);
  911. // Delete entry
  912. DeleteEntry(szDir, pTrans->szId);
  913. }
  914. free(szBuf);
  915. fflush(pFile);
  916. fclose(pFile);
  917. // Don't do this quite yet...
  918. // DeleteFile(pTrans->szTransFileName);
  919. return(TRUE);
  920. }
  921. // display specific text for an error if defined.
  922. void DisplayErrorText(DWORD dwError) {
  923. switch (dwError) {
  924. case ERROR_BAD_FORMAT:
  925. printf("because it is in an unsupported format.");
  926. break;
  927. default:
  928. so->printf("because it is corrupt. (0x%08x)", dwError);
  929. break;
  930. }
  931. }
  932. BOOL
  933. ForceClosePath(
  934. LPTSTR szDir
  935. )
  936. {
  937. LPBYTE BufPtr;
  938. DWORD EntriesRead;
  939. DWORD FileId = FILE_ID_NOT_FOUND;
  940. const DWORD InfoLevel = 2;
  941. NET_API_STATUS Status;
  942. DWORD TotalAvail;
  943. LPFILE_INFO_2 InfoArray;
  944. Status = NetFileEnum(
  945. NULL,
  946. (LPWSTR)szDir,
  947. NULL,
  948. InfoLevel,
  949. &BufPtr,
  950. MAX_PREFERRED_LENGTH,
  951. &EntriesRead,
  952. &TotalAvail,
  953. NULL); // no resume handle
  954. InfoArray = (LPFILE_INFO_2) BufPtr;
  955. if (Status != NERR_Success) {
  956. NetApiBufferFree( (LPVOID) InfoArray );
  957. so->printf( "SYMSTORE: Could not get file ID number for %s. ", szDir);
  958. switch (Status) {
  959. case ERROR_ACCESS_DENIED:
  960. so->printf( "The user does not have access to the requested information.\n");
  961. break;
  962. case ERROR_INVALID_LEVEL:
  963. so->printf( "Requested information level is not supported.\n");
  964. break;
  965. case ERROR_MORE_DATA:
  966. so->printf( "Too many entries were available.\n");
  967. break;
  968. case ERROR_NOT_ENOUGH_MEMORY:
  969. so->printf( "Insufficient memory is available.\n");
  970. break;
  971. case NERR_BufTooSmall:
  972. so->printf("The available memory is insufficient.");
  973. break;
  974. default:
  975. so->printf( "Status=%d, GetLastError=%d.\n", Status, GetLastError() );
  976. }
  977. // Does this really need to be here? Status is locally scoped and we immediately return?
  978. //if (Status == ERROR_NOT_SUPPORTED) {
  979. // Status = FILE_ID_NOT_FOUND; // WFW does not implement this API.
  980. //}
  981. return FALSE;
  982. }
  983. if (EntriesRead > 0) {
  984. FileId = InfoArray->fi2_id;
  985. if ( FileId == FILE_ID_NOT_FOUND ) {
  986. NetApiBufferFree( InfoArray );
  987. return TRUE; // Not an error
  988. }
  989. Status = NetFileClose( NULL, FileId );
  990. if (Status != NERR_Success) {
  991. NetApiBufferFree( InfoArray );
  992. so->printf( "SYMSTORE: Could not close net file %s. GetLastError=%d\n",
  993. szDir, GetLastError() );
  994. return FALSE;
  995. }
  996. }
  997. return TRUE;
  998. }
  999. BOOL ForceDeleteFile(LPTSTR szPtrFile) {
  1000. BOOL rc;
  1001. DWORD dw;
  1002. DWORD lasterror;
  1003. dw = GetFileAttributes( szPtrFile );
  1004. if ( dw != 0xffffffff ) {
  1005. rc = DeleteFile(szPtrFile);
  1006. } else {
  1007. return TRUE;
  1008. }
  1009. if ( !rc ) { // If failed, try to close the path.
  1010. rc = ForceClosePath(szPtrFile);
  1011. if ( rc ) { // If success, try to delete this file.
  1012. rc = DeleteFile(szPtrFile);
  1013. lasterror = GetLastError();
  1014. dw = GetFileAttributes( szPtrFile );
  1015. if (( dw != 0xffffffff ) && (!rc)) {
  1016. so->printf("SYMSTORE: Could not delete %s. GetLastError=%d\n", szPtrFile, lasterror);
  1017. } else {
  1018. return TRUE;
  1019. }
  1020. }
  1021. }
  1022. return rc;
  1023. }
  1024. BOOL
  1025. ForceRemoveDirectory(
  1026. LPTSTR szDir
  1027. )
  1028. /*++
  1029. IN szDir The directory that need force removed
  1030. ForceRemoveDirectory removed the directory that could not be delete
  1031. by RemoveDirectory. It use NetFileClose to stop any user lock this
  1032. file, then call RemoveDirectory to remove it.
  1033. --*/
  1034. {
  1035. BOOL rc;
  1036. DWORD dw;
  1037. DWORD lasterror;
  1038. dw = GetFileAttributes( szDir );
  1039. if ( dw != 0xffffffff ) {
  1040. rc = RemoveDirectory(szDir);
  1041. } else {
  1042. return TRUE;
  1043. }
  1044. if ( !rc ) { // If failed, try to close the path.
  1045. rc = ForceClosePath(szDir);
  1046. if ( rc ) { // If success, try to remove this path again.
  1047. rc = RemoveDirectory(szDir);
  1048. lasterror = GetLastError();
  1049. dw = GetFileAttributes( szDir );
  1050. if (( dw != 0xffffffff ) && (!rc)) {
  1051. so->printf("SYMSTORE: Could not delete %s. GetLastError=%d\n",
  1052. szDir, lasterror );
  1053. } else {
  1054. return TRUE;
  1055. }
  1056. }
  1057. }
  1058. return rc;
  1059. }
  1060. PCOM_ARGS
  1061. GetCommandLineArgs(
  1062. int argc,
  1063. char **argv
  1064. )
  1065. {
  1066. PCOM_ARGS pLocalArgs;
  1067. LONG i,cur,length;
  1068. TCHAR c;
  1069. BOOL NeedSecond = FALSE;
  1070. BOOL AllowLocalNames = FALSE;
  1071. BOOL rc;
  1072. LPTSTR szFileArg = NULL;
  1073. if (argc <= 2) Usage();
  1074. pLocalArgs = (PCOM_ARGS)malloc( sizeof(COM_ARGS) );
  1075. if (!pLocalArgs) MallocFailed();
  1076. memset( pLocalArgs, 0, sizeof(COM_ARGS) );
  1077. pLocalArgs->StorePtrs = FALSE;
  1078. pLocalArgs->Filter = 0;
  1079. if (!_tcsicmp(argv[1], _T("add")) ){
  1080. pLocalArgs->TransState = TRANSACTION_ADD;
  1081. pLocalArgs->StoreFlags=ADD_STORE;
  1082. } else if (!_tcsicmp(argv[1], _T("del")) ) {
  1083. pLocalArgs->TransState = TRANSACTION_DEL;
  1084. pLocalArgs->StoreFlags=DEL;
  1085. } else if (!_tcsicmp(argv[1], _T("query")) ) {
  1086. pLocalArgs->TransState = TRANSACTION_QUERY;
  1087. pLocalArgs->StoreFlags = QUERY;
  1088. } else {
  1089. so->printf("ERROR: First argument needs to be \"add\", \"del\", or \"query\"\n");
  1090. exit(1);
  1091. }
  1092. for (i=2; i<argc; i++) {
  1093. if (!NeedSecond) {
  1094. if ( (argv[i][0] == '/') || (argv[i][0] == '-') ) {
  1095. length = _tcslen(argv[i]);
  1096. cur=1;
  1097. while ( cur < length ) {
  1098. c = argv[i][cur];
  1099. switch (c) {
  1100. case 'a': pLocalArgs->AppendStoreFile = TRUE;
  1101. if (pLocalArgs->TransState==TRANSACTION_QUERY) {
  1102. so->printf("ERROR: /%c is an incorrect parameter with query\n\n", c);
  1103. exit(1);
  1104. }
  1105. break;
  1106. case 'c': NeedSecond = TRUE;
  1107. if (pLocalArgs->TransState==TRANSACTION_QUERY) {
  1108. so->printf("ERROR: /%c is an incorrect parameter with query\n\n", c);
  1109. exit(1);
  1110. }
  1111. break;
  1112. case 'd': NeedSecond = TRUE;
  1113. if (pLocalArgs->TransState==TRANSACTION_QUERY) {
  1114. so->printf("ERROR: /%c is an incorrect parameter with query\n\n", c);
  1115. exit(1);
  1116. }
  1117. break;
  1118. case 'f': NeedSecond = TRUE;
  1119. break;
  1120. case 'g': NeedSecond = TRUE;
  1121. if (pLocalArgs->TransState==TRANSACTION_QUERY) {
  1122. so->printf("ERROR: /%c is an incorrect parameter with query\n\n", c);
  1123. exit(1);
  1124. }
  1125. break;
  1126. case 'h': NeedSecond = TRUE;
  1127. if (pLocalArgs->TransState==TRANSACTION_QUERY) {
  1128. so->printf("ERROR: /%c is an incorrect parameter with query\n\n", c);
  1129. exit(1);
  1130. }
  1131. break;
  1132. case 'i': NeedSecond = TRUE;
  1133. if (pLocalArgs->TransState==TRANSACTION_QUERY) {
  1134. so->printf("ERROR: /%c is an incorrect parameter with query\n\n", c);
  1135. exit(1);
  1136. }
  1137. break;
  1138. case 'k': pLocalArgs->CorruptBinaries = TRUE;
  1139. if (pLocalArgs->TransState==TRANSACTION_QUERY) {
  1140. so->printf("ERROR: /%c is an incorrect parameter with query\n\n", c);
  1141. exit(1);
  1142. }
  1143. break;
  1144. case 'l': AllowLocalNames=TRUE;
  1145. if (pLocalArgs->TransState==TRANSACTION_QUERY) {
  1146. so->printf("ERROR: /%c is an incorrect parameter with query\n\n", c);
  1147. exit(1);
  1148. }
  1149. break;
  1150. case 'm': MSArchive=TRUE;
  1151. if (pLocalArgs->TransState==TRANSACTION_QUERY) {
  1152. so->printf("ERROR: /%c is an incorrect parameter with query\n\n", c);
  1153. exit(1);
  1154. }
  1155. break;
  1156. case 'r': if (pLocalArgs->TransState==TRANSACTION_DEL) {
  1157. so->printf("ERROR: /r is an incorrect parameter with del\n\n");
  1158. exit(1);
  1159. }
  1160. pLocalArgs->Recurse = TRUE;
  1161. break;
  1162. case 'p': pLocalArgs->StorePtrs = TRUE;
  1163. if (pLocalArgs->TransState==TRANSACTION_DEL) {
  1164. so->printf("ERROR: /p is an incorrect parameter with del\n\n");
  1165. exit(1);
  1166. } else if (pLocalArgs->TransState==TRANSACTION_QUERY) {
  1167. so->printf("ERROR: /p is an incorrect parameter with query\n\n");
  1168. exit(1);
  1169. }
  1170. break;
  1171. case 's': NeedSecond = TRUE;
  1172. break;
  1173. case 't': NeedSecond = TRUE;
  1174. if (pLocalArgs->TransState==TRANSACTION_QUERY) {
  1175. so->printf("ERROR: /%c is an incorrect parameter with query\n\n", c);
  1176. exit(1);
  1177. }
  1178. break;
  1179. case 'v': NeedSecond = TRUE;
  1180. if (pLocalArgs->TransState==TRANSACTION_QUERY) {
  1181. so->printf("ERROR: /%c is an incorrect parameter with query\n\n", c);
  1182. exit(1);
  1183. }
  1184. break;
  1185. case 'x': NeedSecond = TRUE;
  1186. if (pLocalArgs->TransState==TRANSACTION_QUERY) {
  1187. so->printf("ERROR: /%c is an incorrect parameter with query\n\n", c);
  1188. exit(1);
  1189. }
  1190. break;
  1191. case 'y': NeedSecond = TRUE;
  1192. if (pLocalArgs->TransState==TRANSACTION_QUERY) {
  1193. so->printf("ERROR: /%c is an incorrect parameter with query\n\n", c);
  1194. exit(1);
  1195. }
  1196. if (cur < length-1) {
  1197. cur++;
  1198. switch(argv[i][cur]) {
  1199. case 'i': pLocalArgs->AppendIDToFile = TRUE;
  1200. break;
  1201. default: so->printf("ERROR: /y%c is an incorrect parameter\n\n",argv[i][cur]);
  1202. exit(1);
  1203. }
  1204. }
  1205. break;
  1206. case 'z': NeedSecond = TRUE;
  1207. if (pLocalArgs->TransState==TRANSACTION_QUERY) {
  1208. so->printf("ERROR: /%c is an incorrect parameter with query\n\n", c);
  1209. exit(1);
  1210. }
  1211. break;
  1212. case 'o': pLocalArgs->VerboseOutput = TRUE;
  1213. break;
  1214. default: Usage();
  1215. }
  1216. cur++;
  1217. }
  1218. }
  1219. else {
  1220. so->printf("ERROR: Expecting a / option before %s\n", argv[i] );
  1221. exit(1);
  1222. }
  1223. }
  1224. else {
  1225. NeedSecond = FALSE;
  1226. switch (c) {
  1227. case 'c': if (pLocalArgs->TransState==TRANSACTION_DEL) {
  1228. so->printf("ERROR: /c is an incorrect parameter with del\n\n");
  1229. exit(1);
  1230. }
  1231. if ( _tcslen(argv[i]) > MAX_COMMENT ) {
  1232. so->printf("ERROR: Comment must be %d characters or less\n", MAX_COMMENT);
  1233. exit(1);
  1234. }
  1235. pLocalArgs->szComment = (LPTSTR)malloc( (_tcslen(argv[i]) + 1) * sizeof(TCHAR) );
  1236. if (!pLocalArgs->szComment) MallocFailed();
  1237. StringCbCopy(pLocalArgs->szComment, _msize(pLocalArgs->szComment), argv[i]);
  1238. break;
  1239. case 'd': so->SetFileName(argv[i]);
  1240. break;
  1241. case 'i': if (pLocalArgs->TransState==TRANSACTION_ADD) {
  1242. so->printf("ERROR: /i is an incorrect parameter with add\n\n");
  1243. exit(1);
  1244. }
  1245. if ( _tcslen(argv[i]) != MAX_ID ) {
  1246. so->printf("ERROR: /i ID is not a valid ID length\n");
  1247. exit(1);
  1248. }
  1249. pLocalArgs->szId = (LPTSTR)malloc( (_tcslen(argv[i]) + 1) * sizeof(TCHAR) );
  1250. if (!pLocalArgs->szId) MallocFailed();
  1251. StringCbCopy(pLocalArgs->szId, _msize(pLocalArgs->szId), argv[i]);
  1252. break;
  1253. case 'f': if (pLocalArgs->TransState==TRANSACTION_DEL) {
  1254. so->printf("ERROR: /f is an incorrect parameter with del\n\n");
  1255. exit(1);
  1256. }
  1257. szFileArg = argv[i];
  1258. break;
  1259. case 'g': if (pLocalArgs->TransState==TRANSACTION_DEL) {
  1260. so->printf("ERROR: /g is an incorrect parameter with del\n\n");
  1261. exit(1);
  1262. }
  1263. pLocalArgs->szShareName=(LPTSTR) malloc( (_tcslen(argv[i]) + 2) * sizeof(TCHAR) );
  1264. if (!pLocalArgs->szShareName) MallocFailed();
  1265. StringCbCopy(pLocalArgs->szShareName, _msize(pLocalArgs->szShareName), argv[i]);
  1266. pLocalArgs->ShareNameLength=_tcslen(pLocalArgs->szShareName);
  1267. break;
  1268. case 'h': if ( _tcscmp( argv[i], _T("pri")) == 0 ) {
  1269. PubPriPriority = 2;
  1270. } else if ( _tcscmp( argv[i], _T("pub")) == 0 ) {
  1271. PubPriPriority = 1;
  1272. } else {
  1273. so->printf("ERROR: /h must be followed by pri or pub\n");
  1274. exit(1);
  1275. }
  1276. break;
  1277. case 's': if ( _tcslen(argv[i]) > (_MAX_PATH-2) ) {
  1278. so->printf("ERROR: Path following /s is too long\n");
  1279. exit(1);
  1280. }
  1281. // Be sure to allocate enough to add a trailing backslash
  1282. pLocalArgs->szRootDir = (LPTSTR) malloc ( (_tcslen(argv[i]) + 2) * sizeof(TCHAR) );
  1283. if (!pLocalArgs->szRootDir) MallocFailed();
  1284. StringCbCopy(pLocalArgs->szRootDir, _msize(pLocalArgs->szRootDir), argv[i]);
  1285. MyEnsureTrailingBackslash(pLocalArgs->szRootDir);
  1286. break;
  1287. case 't': if (pLocalArgs->TransState==TRANSACTION_DEL) {
  1288. so->printf("ERROR: /t is an incorrect parameter with del\n\n");
  1289. exit(1);
  1290. }
  1291. if ( _tcslen(argv[i]) > MAX_PRODUCT ) {
  1292. so->printf("ERROR: Product following /t must be <= %d characters\n",
  1293. MAX_PRODUCT);
  1294. exit(1);
  1295. }
  1296. pLocalArgs->szProduct = (LPTSTR) malloc ( (_tcslen(argv[i]) + 1) * sizeof(TCHAR) );
  1297. if (!pLocalArgs->szProduct) MallocFailed();
  1298. StringCbCopy(pLocalArgs->szProduct, _msize(pLocalArgs->szProduct), argv[i]);
  1299. break;
  1300. case 'v': if (pLocalArgs->TransState==TRANSACTION_DEL) {
  1301. so->printf("ERROR: /v is an incorrect parameter with del\n\n");
  1302. exit(1);
  1303. }
  1304. if ( _tcslen(argv[i]) > MAX_VERSION ) {
  1305. so->printf("ERROR: Version following /v must be <= %d characters\n",
  1306. MAX_VERSION);
  1307. exit(1);
  1308. }
  1309. pLocalArgs->szVersion = (LPTSTR) malloc ( (_tcslen(argv[i]) + 1) * sizeof(TCHAR) );
  1310. if (!pLocalArgs->szVersion) MallocFailed();
  1311. StringCbCopy(pLocalArgs->szVersion, _msize(pLocalArgs->szVersion), argv[i]);
  1312. break;
  1313. case 'x': pLocalArgs->szTransFileName = (LPTSTR) malloc ( (_tcslen(argv[i]) + 1) * sizeof(TCHAR) );
  1314. if (!pLocalArgs->szTransFileName) MallocFailed();
  1315. StringCbCopy(pLocalArgs->szTransFileName, _msize(pLocalArgs->szTransFileName), argv[i]);
  1316. pLocalArgs->StoreFlags = ADD_DONT_STORE;
  1317. // Since we are throwing away the first part of this path, we can allow
  1318. // local paths for the files to be stored on the symbols server
  1319. AllowLocalNames=TRUE;
  1320. break;
  1321. case 'y': if (pLocalArgs->TransState==TRANSACTION_DEL) {
  1322. so->printf("ERROR: /f is an incorrect parameter with del\n\n");
  1323. exit(1);
  1324. }
  1325. pLocalArgs->StoreFlags = ADD_STORE_FROM_FILE;
  1326. szFileArg = argv[i];
  1327. break;
  1328. case 'z': if (_tcsncmp(_tcslwr(argv[i]),"pub", 3)==0) {
  1329. pLocalArgs->Filter=1;
  1330. } else if (_tcsncmp(argv[i],"pri", 3)==0) {
  1331. pLocalArgs->Filter=2;
  1332. } else {
  1333. so->printf("ERROR: only accept pub or pri in -z option");
  1334. exit(1);
  1335. }
  1336. break;
  1337. default: Usage();
  1338. }
  1339. }
  1340. }
  1341. // Check that everything has been entered
  1342. if (NeedSecond) {
  1343. so->printf("ERROR: /%c must be followed by an argument\n\n", c);
  1344. exit(1);
  1345. }
  1346. // RAID 680688 - Using /a option in symstore add that does not involve /x is not prevented.
  1347. if ( pLocalArgs->AppendStoreFile && (pLocalArgs->szTransFileName==NULL) ) {
  1348. so->printf("ERROR: /a requires /x to also be used.\n\n");
  1349. exit(1);
  1350. }
  1351. if (pLocalArgs->CorruptBinaries && pLocalArgs->StorePtrs) {
  1352. so->printf("ERROR: /p cannot be used with /k.\n");
  1353. exit(1);
  1354. }
  1355. if ( pLocalArgs->StoreFlags == ADD_STORE_FROM_FILE ) {
  1356. if (pLocalArgs->szShareName == NULL ) {
  1357. so->printf("/g must be used when /y is used. \n");
  1358. exit(1);
  1359. }
  1360. MyEnsureTrailingBackslash(pLocalArgs->szShareName);
  1361. pLocalArgs->pStoreFromFile = _tfopen(szFileArg, "r+" );
  1362. if (!pLocalArgs->pStoreFromFile ) {
  1363. so->printf("Cannot open file %s - GetLastError = %d\n",
  1364. szFileArg, GetLastError() );
  1365. exit(1);
  1366. }
  1367. }
  1368. if ( pLocalArgs->StoreFlags == ADD_DONT_STORE ) {
  1369. if (pLocalArgs->szShareName == NULL ) {
  1370. so->printf("/g must be used when /x is used. \n");
  1371. exit(1);
  1372. }
  1373. // Verify that szShare is a prefix of szFileArg
  1374. if (szFileArg == NULL ) {
  1375. so->printf("/f <file> is a required parameter\n");
  1376. exit(1);
  1377. }
  1378. if ( _tcslen(szFileArg) < pLocalArgs->ShareNameLength ) {
  1379. so->printf("/g %s must be a prefix of /f %s\n",pLocalArgs->szShareName, szFileArg);
  1380. exit(1);
  1381. }
  1382. if ( _tcsncicmp(pLocalArgs->szShareName, szFileArg, pLocalArgs->ShareNameLength) != 0 ) {
  1383. so->printf("/g %s must be a prefix of /f %s\n", pLocalArgs->szShareName, szFileArg);
  1384. exit(1);
  1385. }
  1386. // Now, make sure that szFileArg has a trailing backslash
  1387. MyEnsureTrailingBackslash(pLocalArgs->szShareName);
  1388. pLocalArgs->ShareNameLength=_tcslen(pLocalArgs->szShareName);
  1389. // Set the symbol directory under the server to ""
  1390. // so that tcscpy's will work correctly in the rest of the
  1391. pLocalArgs->szSymbolsDir = (LPTSTR) malloc ( sizeof(TCHAR) * 2 );
  1392. if ( !pLocalArgs->szSymbolsDir) MallocFailed();
  1393. StringCbCopy(pLocalArgs->szSymbolsDir, _msize(pLocalArgs->szSymbolsDir), _T(""));
  1394. }
  1395. // Get the various symbol server related file names
  1396. if ( pLocalArgs->StoreFlags == ADD_STORE ||
  1397. pLocalArgs->StoreFlags == ADD_STORE_FROM_FILE ||
  1398. pLocalArgs->StoreFlags == DEL ||
  1399. pLocalArgs->StoreFlags == QUERY ) {
  1400. if ( pLocalArgs->szRootDir == NULL ) {
  1401. // Verify that the root of the symbols server was entered
  1402. so->printf("ERROR: /s server is a required parameter\n\n");
  1403. exit(1);
  1404. }
  1405. // Store the name of the symbols dir
  1406. pLocalArgs->szSymbolsDir = (LPTSTR) malloc ( sizeof(TCHAR) *
  1407. (_tcslen(pLocalArgs->szRootDir) + 1) );
  1408. if (!pLocalArgs->szSymbolsDir) MallocFailed();
  1409. StringCbCopy(pLocalArgs->szSymbolsDir, _msize(pLocalArgs->szSymbolsDir), pLocalArgs->szRootDir);
  1410. // Verify that the symbols dir exists
  1411. if ( !MakeSureDirectoryPathExists(pLocalArgs->szSymbolsDir) ) {
  1412. so->printf("Cannot create the directory %s - GetLastError() = %d\n",
  1413. pLocalArgs->szSymbolsDir, GetLastError() );
  1414. exit(1);
  1415. }
  1416. // Store the pingme.txt
  1417. szPingMe = (LPTSTR) malloc( sizeof(TCHAR) *
  1418. (_tcslen(pLocalArgs->szRootDir) + _tcslen(_T("\\pingme.txt")) + 1) );
  1419. if (!szPingMe) MallocFailed();
  1420. StringCbPrintf(szPingMe, _msize(szPingMe), "%s\\pingme.txt", pLocalArgs->szRootDir);
  1421. // Store the name of the admin dir
  1422. pLocalArgs->szAdminDir = (LPTSTR) malloc ( sizeof(TCHAR) *
  1423. (_tcslen(pLocalArgs->szRootDir) + _tcslen(_T("000admin\\")) + 1) );
  1424. if (!pLocalArgs->szAdminDir) MallocFailed();
  1425. StringCbPrintf(pLocalArgs->szAdminDir, _msize(pLocalArgs->szAdminDir), "%s000admin\\", pLocalArgs->szRootDir);
  1426. // Verify that the Admin dir exists
  1427. if ( !MakeSureDirectoryPathExists(pLocalArgs->szAdminDir) ) {
  1428. so->printf("Cannot create the directory %s - GetLastError() = %d\n",
  1429. pLocalArgs->szAdminDir, GetLastError() );
  1430. exit(1);
  1431. }
  1432. // Store the name of the master file
  1433. pLocalArgs->szMasterFileName = (LPTSTR) malloc ( sizeof(TCHAR) *
  1434. (_tcslen(pLocalArgs->szAdminDir) + _tcslen(_T("history.txt")) + 1) );
  1435. if (!pLocalArgs->szMasterFileName ) MallocFailed();
  1436. StringCbPrintf(pLocalArgs->szMasterFileName, _msize(pLocalArgs->szMasterFileName), "%shistory.txt", pLocalArgs->szAdminDir);
  1437. //
  1438. // Store the name of the "server" file - this contains all
  1439. // the transactions that currently make up the server
  1440. //
  1441. pLocalArgs->szServerFileName = (LPTSTR) malloc ( sizeof(TCHAR) *
  1442. (_tcslen(pLocalArgs->szAdminDir) + _tcslen(_T("server.txt")) + 1) );
  1443. if (!pLocalArgs->szServerFileName ) MallocFailed();
  1444. StringCbPrintf(pLocalArgs->szServerFileName, _msize(pLocalArgs->szServerFileName), "%sserver.txt", pLocalArgs->szAdminDir);
  1445. }
  1446. if ( pLocalArgs->StoreFlags==DEL && !pLocalArgs->szId ) {
  1447. so->printf("ERROR: /i id is a required parameter\n\n");
  1448. exit(1);
  1449. }
  1450. // Done if this is a delete transaction
  1451. if ( pLocalArgs->StoreFlags == DEL ) {
  1452. return(pLocalArgs);
  1453. }
  1454. if ( pLocalArgs->StoreFlags == ADD_STORE ||
  1455. pLocalArgs->StoreFlags == ADD_STORE_FROM_FILE ) {
  1456. if ( !pLocalArgs->szProduct ) {
  1457. so->printf("ERROR: /t product is a required parameter\n\n");
  1458. exit(1);
  1459. }
  1460. // Since Version and Comment are optional parameters, initialize them to
  1461. // the empty string if they haven't been assigned
  1462. if ( !pLocalArgs->szVersion ) {
  1463. pLocalArgs->szVersion = (LPTSTR)malloc(sizeof(TCHAR) );
  1464. if (!pLocalArgs->szVersion) MallocFailed();
  1465. StringCbCopy(pLocalArgs->szVersion, _msize(pLocalArgs->szVersion), _T(""));
  1466. }
  1467. if ( !pLocalArgs->szComment ) {
  1468. pLocalArgs->szComment = (LPTSTR)malloc(sizeof(TCHAR) );
  1469. if (!pLocalArgs->szComment) MallocFailed();
  1470. StringCbCopy(pLocalArgs->szComment, _msize(pLocalArgs->szComment), _T(""));
  1471. }
  1472. if ( !pLocalArgs->szUnused ) {
  1473. pLocalArgs->szUnused = (LPTSTR)malloc(sizeof(TCHAR) );
  1474. if (!pLocalArgs->szUnused) MallocFailed();
  1475. StringCbCopy(pLocalArgs->szUnused, _msize(pLocalArgs->szUnused), _T(""));
  1476. }
  1477. }
  1478. if ( pLocalArgs->StoreFlags == ADD_STORE ||
  1479. pLocalArgs->StoreFlags == ADD_DONT_STORE ||
  1480. pLocalArgs->StoreFlags == QUERY)
  1481. {
  1482. pLocalArgs->szSrcDir = (LPTSTR) malloc ( (_MAX_PATH) * sizeof(TCHAR) );
  1483. if (!pLocalArgs->szSrcDir ) MallocFailed();
  1484. pLocalArgs->szFileName = (LPTSTR) malloc ( (_MAX_PATH) * sizeof(TCHAR) );
  1485. if (!pLocalArgs->szFileName ) MallocFailed();
  1486. // Decide what part of szFileArg is a file name and what part of it
  1487. // is a directory
  1488. rc = GetSrcDirandFileName( szFileArg, pLocalArgs->szSrcDir, pLocalArgs->szFileName, AllowLocalNames);
  1489. if (!rc) {
  1490. Usage();
  1491. }
  1492. // Get the pointer path if we are storing pointers
  1493. // Later, if pArgs->szSrcPath == NULL is used as a way of telling if
  1494. // the user wanted pointers or files.
  1495. if ( pLocalArgs->StorePtrs ) {
  1496. if ( !AllowLocalNames ) {
  1497. // Make sure that they are entering a network path.
  1498. // The reason is that this is the path that will be used to
  1499. // add and delete entries from the symbols server. And, when
  1500. // pointers are used, this is the path the debugger will use to
  1501. // get the file.
  1502. if ( _tcslen(szFileArg) >= 2 ) {
  1503. if ( szFileArg[0] != '\\' || szFileArg[1] != '\\' ) {
  1504. so->printf("ERROR: /f must be followed by a network path\n");
  1505. exit(1);
  1506. }
  1507. } else {
  1508. so->printf("ERROR: /f must be followed by a network path\n");
  1509. exit(1);
  1510. }
  1511. }
  1512. pLocalArgs->szSrcPath = (LPTSTR) malloc ( (_tcslen(pLocalArgs->szSrcDir)+1) * sizeof(TCHAR) );
  1513. if (pLocalArgs->szSrcPath == NULL ) MallocFailed();
  1514. StringCbCopy(pLocalArgs->szSrcPath, _msize(pLocalArgs->szSrcPath), pLocalArgs->szSrcDir);
  1515. }
  1516. }
  1517. return (pLocalArgs);
  1518. }
  1519. ULONG GetMaxLineOfHistoryFile(
  1520. VOID
  1521. )
  1522. /*++
  1523. This returns the maximum length of a line in the history file.
  1524. The history file contains one line for every transaction. It exists
  1525. in the admin directory.
  1526. --*/
  1527. {
  1528. ULONG Max;
  1529. Max = MAX_ID + MAX_VERSION + MAX_PRODUCT + MAX_COMMENT +
  1530. TRANS_NUM_COMMAS + TRANS_EOL + TRANS_ADD_DEL + TRANS_FILE_PTR +
  1531. MAX_DATE + MAX_TIME + MAX_UNUSED;
  1532. Max *= sizeof(TCHAR);
  1533. return(Max);
  1534. }
  1535. ULONG GetMaxLineOfRefsPtrFile(
  1536. VOID
  1537. )
  1538. /* ++
  1539. This returns the maximum length of a line in the refs.ptr file.
  1540. This file exists in the individual directories of the symbols server.
  1541. -- */
  1542. {
  1543. ULONG Max;
  1544. Max = _MAX_PATH+2 + MAX_ID + TRANS_FILE_PTR + 3;
  1545. Max *= sizeof(TCHAR);
  1546. return(Max);
  1547. }
  1548. ULONG GetMaxLineOfTransactionFile(
  1549. VOID
  1550. )
  1551. /*++
  1552. This returns the maximum length of a line in a transaction file.
  1553. The transaction file is a unique file for each transaction that
  1554. gets created in the admin directory. Its name is a number
  1555. (i.e., "0000000001")
  1556. --*/
  1557. {
  1558. ULONG Max;
  1559. Max = (_MAX_PATH * 2 + 3) * sizeof(TCHAR);
  1560. return(Max);
  1561. }
  1562. BOOL GetNextId(
  1563. LPTSTR szMasterFileName,
  1564. LPTSTR *szId,
  1565. PHANDLE hFile
  1566. ) {
  1567. WIN32_FIND_DATA FindFileData;
  1568. HANDLE hFoundFile = INVALID_HANDLE_VALUE;
  1569. LONG lFileSize,lId;
  1570. LPTSTR szbuf;
  1571. LONG i,NumLeftZeros;
  1572. BOOL Found;
  1573. LONG lNumBytesToRead;
  1574. DWORD dwNumBytesRead;
  1575. DWORD dwNumBytesToRead;
  1576. DWORD dwrc;
  1577. BOOL rc;
  1578. TCHAR TempId[MAX_ID + 1];
  1579. DWORD First;
  1580. DWORD timeout;
  1581. *szId = (LPTSTR)malloc( (MAX_ID + 1) * sizeof(TCHAR) );
  1582. if (!*szId) MallocFailed();
  1583. memset(*szId,0,MAX_ID + 1);
  1584. szbuf = (LPTSTR) malloc( (lMaxTrans + 1) * sizeof(TCHAR) );
  1585. if (!szbuf) MallocFailed();
  1586. memset(szbuf,0,lMaxTrans+1);
  1587. // If the MasterFile is empty, then use the number "0000000001"
  1588. *hFile = FindFirstFile((LPCTSTR)szMasterFileName, &FindFileData);
  1589. if ( *hFile == INVALID_HANDLE_VALUE) {
  1590. StringCbCopy(*szId, _msize(*szId), _T("0000000001"));
  1591. }
  1592. // Otherwise, get the last number from the master file
  1593. // Open the Master File
  1594. timeout=0;
  1595. First = 1;
  1596. do {
  1597. *hFile = CreateFile(
  1598. szMasterFileName,
  1599. GENERIC_READ | GENERIC_WRITE,
  1600. 0,
  1601. NULL,
  1602. OPEN_EXISTING,
  1603. FILE_ATTRIBUTE_NORMAL,
  1604. NULL );
  1605. if ( *hFile == INVALID_HANDLE_VALUE ) {
  1606. *hFile = CreateFile( szMasterFileName,
  1607. GENERIC_READ | GENERIC_WRITE,
  1608. 0,
  1609. NULL,
  1610. CREATE_ALWAYS,
  1611. FILE_ATTRIBUTE_NORMAL,
  1612. NULL );
  1613. }
  1614. // Only print a message the first time through
  1615. if ( First && *hFile == INVALID_HANDLE_VALUE ) {
  1616. First = 0;
  1617. so->printf("Waiting to open %s ... \n", szMasterFileName);
  1618. }
  1619. if ( *hFile == INVALID_HANDLE_VALUE ) {
  1620. SleepEx(1000,0);
  1621. timeout+=1;
  1622. }
  1623. } while ( *hFile == INVALID_HANDLE_VALUE && timeout <= 50 );
  1624. if (timeout > 50 ) {
  1625. so->printf("Timed out -- could not open %s\n", szMasterFileName);
  1626. return(1);
  1627. }
  1628. if (!_tcscmp(*szId, _T("0000000001") ) ) goto finish_GetNextId;
  1629. // Read the last record in from the end of the file. Allocate one more space to
  1630. // read in the next to last '\n', so we can verify that we are at the beginning of
  1631. // the last record
  1632. lFileSize = GetFileSize(*hFile,NULL);
  1633. if ( lFileSize < (TRANS_NUM_COMMAS + TRANS_EOL + TRANS_ADD_DEL + TRANS_FILE_PTR + MAX_ID) ) {
  1634. //
  1635. // History.txt is corrupt, delete the corrupt file and start a new one
  1636. //
  1637. so->printf("The file %s does not have accurate transaction records in it\n", szMasterFileName);
  1638. CloseHandle(*hFile);
  1639. //
  1640. // This code is a nasty "fix" !
  1641. //
  1642. // kill the existing file
  1643. if ( ! DeleteFile(szMasterFileName) ) {
  1644. so->printf("Couldn't delete corrupt %s. Please send mail to symadmn.\n", szMasterFileName);
  1645. exit(1);
  1646. } else {
  1647. DWORD Temp;
  1648. CHAR drive[_MAX_DRIVE];
  1649. CHAR dir[ _MAX_DIR];
  1650. CHAR file[ _MAX_FNAME];
  1651. CHAR ext[ _MAX_EXT];
  1652. CHAR FileMask[_MAX_PATH];
  1653. CHAR NextId[_MAX_PATH];
  1654. so->printf("Searching for next valid ID");
  1655. // get the path to the transaction files
  1656. _splitpath(szMasterFileName, drive, dir, file, ext);
  1657. // create a filemask for FindFile
  1658. FileMask[0] = '\0';
  1659. StringCbCat(FileMask, sizeof(FileMask), drive);
  1660. StringCbCat(FileMask, sizeof(FileMask), dir);
  1661. StringCbCat(FileMask, sizeof(FileMask), "\\??????????");
  1662. // loop until all are found
  1663. hFoundFile = FindFirstFile(FileMask, &FindFileData);
  1664. while (hFoundFile != INVALID_HANDLE_VALUE) {
  1665. so->printf(".");
  1666. _splitpath(FindFileData.cFileName, drive, dir, file, ext);
  1667. // transaction files don't have an extension
  1668. if ( ext[0] == '\0' ) {
  1669. StringCbCopy(NextId, sizeof(NextId), file);
  1670. }
  1671. if (!FindNextFile(hFoundFile, &FindFileData)) {
  1672. FindClose(hFoundFile);
  1673. hFoundFile = INVALID_HANDLE_VALUE;
  1674. }
  1675. }
  1676. // increment by one
  1677. Temp = atol(NextId);
  1678. Temp++;
  1679. StringCbPrintf(*szId, _msize(*szId), "%010d", Temp);
  1680. so->printf("using %s\n", *szId);
  1681. *hFile = CreateFile( szMasterFileName,
  1682. GENERIC_READ | GENERIC_WRITE,
  1683. 0,
  1684. NULL,
  1685. CREATE_ALWAYS,
  1686. FILE_ATTRIBUTE_NORMAL,
  1687. NULL );
  1688. if ( *hFile == INVALID_HANDLE_VALUE ) {
  1689. so->printf("Re-creation of %s failed. Send mail to symadm.\n", szMasterFileName);
  1690. exit(1);
  1691. }
  1692. goto finish_GetNextId;
  1693. }
  1694. }
  1695. lNumBytesToRead = lFileSize < (lMaxTrans+1) ? lFileSize : (lMaxTrans + 1);
  1696. lNumBytesToRead *= sizeof(TCHAR);
  1697. dwNumBytesToRead = (DWORD)lNumBytesToRead;
  1698. dwrc = SetFilePointer(*hFile,(-1 * dwNumBytesToRead),NULL,FILE_END);
  1699. if ( dwrc == INVALID_SET_FILE_POINTER) {
  1700. so->printf("SYMSTORE: Could not set file pointer\n");
  1701. CloseHandle(*hFile);
  1702. exit(1);
  1703. }
  1704. rc = ReadFile(*hFile,(LPVOID)szbuf,dwNumBytesToRead,&dwNumBytesRead,NULL);
  1705. if ( !rc ) {
  1706. so->printf("SYMSTORE: Read file of %s failed - GetLastError() == %d\n",
  1707. szMasterFileName, GetLastError() );
  1708. CloseHandle(*hFile);
  1709. exit(1);
  1710. }
  1711. if ( dwNumBytesToRead != dwNumBytesRead ) {
  1712. so->printf("SYMSTORE: Read file failure for %s - dwNumBytesToRead = %d, dwNumBytesRead = %d\n",
  1713. szMasterFileName,dwNumBytesToRead, dwNumBytesRead );
  1714. CloseHandle(*hFile);
  1715. exit(1);
  1716. }
  1717. // Now search from the end of the string until you get to the beginning of the string
  1718. // or a '\n'. Count down from the end of the file.
  1719. i = lNumBytesToRead - TRANS_NUM_COMMAS;
  1720. Found = FALSE;
  1721. while ( !Found && (i != 0 ) ) {
  1722. if ( szbuf[i] == '\n' ) {
  1723. Found = TRUE;
  1724. } else {
  1725. i--;
  1726. }
  1727. }
  1728. // Move to the first character of the record
  1729. if (Found) i++;
  1730. // Now, verify that the next ten characters are the ID
  1731. if ( szbuf[i + MAX_ID] != ',' ) {
  1732. so->printf("There is a comma missing after the ID number of the\n");
  1733. so->printf("last record in the file %s\n", szMasterFileName);
  1734. CloseHandle(*hFile);
  1735. exit(1);
  1736. } else {
  1737. szbuf[i + MAX_ID] = '\0';
  1738. }
  1739. // Now increment the number
  1740. lId = atoi(szbuf + i);
  1741. if (lId == 9999999999) {
  1742. so->printf("The last ID number has been used. No more transactions are allowed\n");
  1743. CloseHandle(*hFile);
  1744. exit(1);
  1745. }
  1746. lId++;
  1747. _itoa(lId, TempId, 10);
  1748. // Now pad the left side with zeros
  1749. // *szId was already set to 0
  1750. NumLeftZeros = MAX_ID - _tcslen(TempId);
  1751. StringCbCopy( (*szId) + NumLeftZeros, _msize(*szId) - (sizeof(TCHAR)*NumLeftZeros), TempId);
  1752. for (i=0; i < NumLeftZeros; i++) {
  1753. (*szId)[i] = '0';
  1754. }
  1755. if (_tcslen(*szId) != MAX_ID ) {
  1756. so->printf("Could not obtain a correct Id number\n");
  1757. CloseHandle(*hFile);
  1758. exit(1);
  1759. }
  1760. finish_GetNextId:
  1761. free(szbuf);
  1762. return (TRUE);
  1763. }
  1764. /*
  1765. GetSrcDirandFileName
  1766. This procedure takes a path and separates it into two
  1767. strings. One string for the directory portion of the path
  1768. and one string for the file name portion of the path.
  1769. szStr - INPUT string that contains a path
  1770. szSrcDir - OUTPUT string that contains the directory
  1771. followed by a backslash
  1772. szFileName - OUTPUT string that contains the file name
  1773. */
  1774. BOOL GetSrcDirandFileName(LPTSTR szStr, LPTSTR szSrcDir, LPTSTR szFileName, BOOL LocalFile) {
  1775. // NOTE: szSrcDir and szFileName are assumed to be TCHAR arrays on _MAX_PATH length
  1776. DWORD szStrLength;
  1777. DWORD found, i, j, lastslash;
  1778. HANDLE fHandle;
  1779. WIN32_FIND_DATA FindFileData;
  1780. TCHAR FullPath[_MAX_PATH];
  1781. LPTSTR pFilename = NULL;
  1782. if (szStr==NULL) {
  1783. return(FALSE);
  1784. }
  1785. if (LocalFile) {
  1786. SymCommonGetFullPathName(szStr, sizeof(FullPath)/sizeof(FullPath[0]), FullPath, &pFilename);
  1787. } else {
  1788. StringCbCopy(FullPath, sizeof(FullPath), szStr);
  1789. }
  1790. szStrLength = _tcslen(FullPath);
  1791. if ( szStrLength == 0 ) {
  1792. return (FALSE);
  1793. }
  1794. // See if the user entered "."
  1795. // If so, set the src directory to . followed by a \, and
  1796. // set the file name to *
  1797. if ( szStrLength == 1 && FullPath[0] == _T('.') ) {
  1798. if ( StringCchCopy(szSrcDir, _MAX_PATH, _T(".\\")) != S_OK ) {
  1799. return(FALSE);
  1800. }
  1801. if ( StringCchCopy(szFileName, _MAX_PATH, _T("*")) != S_OK ) {
  1802. return(FALSE);
  1803. }
  1804. return (TRUE);
  1805. }
  1806. // Give an error if the end of the string is a colon
  1807. if ( FullPath[szStrLength-1] == _T(':') ) {
  1808. so->printf("SYMSTORE: ERROR: path %s does not specify a file\n", szStr);
  1809. return (FALSE);
  1810. }
  1811. // See if this is a file name only. See if there are no
  1812. // backslashes in the string.
  1813. found = 0;
  1814. for ( i=0; i<szStrLength; i++ ) {
  1815. if ( FullPath[i] == _T('\\') )
  1816. {
  1817. found = 1;
  1818. }
  1819. }
  1820. if ( !found ) {
  1821. // This is a file name only, so set the directory to
  1822. // the current directory.
  1823. if ( StringCchCopy(szSrcDir, _MAX_PATH, _T(".\\")) != S_OK ) {
  1824. return(FALSE);
  1825. }
  1826. // Set the file name to szStr
  1827. if( StringCchCopy(szFileName, _MAX_PATH, FullPath) != S_OK ) {
  1828. return(FALSE);
  1829. }
  1830. return (TRUE);
  1831. }
  1832. // See if this is a network server and share with no file
  1833. // name after it. If it is, use * for the file name.
  1834. if ( FullPath[0] == FullPath[1] && FullPath[0] == _T('\\') ) {
  1835. // Check the third character to see if its part of
  1836. // a machine name.
  1837. if (szStrLength < 3 ) {
  1838. so->printf("SYMSTORE: ERROR: %s is not a correct UNC path\n", FullPath);
  1839. return (FALSE);
  1840. }
  1841. switch (FullPath[2]) {
  1842. case _T('.'):
  1843. case _T('*'):
  1844. case _T(':'):
  1845. case _T('\\'):
  1846. case _T('?'):
  1847. so->printf("SYMSTORE: ERROR: %s is not a correct UNC path\n",FullPath);
  1848. return (FALSE);
  1849. default: break;
  1850. }
  1851. // Search for the next backslash. This is the backslash between
  1852. // the server and the share (\\server'\'share)
  1853. i=3;
  1854. while ( i<szStrLength && FullPath[i] != _T('\\') ) {
  1855. i++;
  1856. }
  1857. // If the next backslash is at the end of the string, then
  1858. // this is an error because the share part of \\server\share
  1859. // is empty.
  1860. if ( i == szStrLength ) {
  1861. so->printf("SYMSTORE: ERROR: %s is not a correct UNC path\n",FullPath);
  1862. return (FALSE);
  1863. }
  1864. // We've found \\server\ so far.
  1865. // see if there is at least one more character.
  1866. i++;
  1867. if ( i >= szStrLength ) {
  1868. so->printf("SYMSTORE: ERROR: %s is not a correct UNC path\n", FullPath);
  1869. return (FALSE);
  1870. }
  1871. switch (FullPath[i]) {
  1872. case _T('.'):
  1873. case _T('*'):
  1874. case _T(':'):
  1875. case _T('\\'):
  1876. case _T('?'):
  1877. so->printf("SYMSTORE: ERROR: %s is not correct UNC path\n",FullPath);
  1878. return (FALSE);
  1879. default: break;
  1880. }
  1881. // Now, we have \\server\share so far -- if there are no more
  1882. // backslashes, then the filename is * and the directory is
  1883. // szStr
  1884. i++;
  1885. while ( i < szStrLength && FullPath[i] != _T('\\') ) {
  1886. i++;
  1887. }
  1888. if ( i == szStrLength ) {
  1889. // verify that there are no wildcards in this
  1890. found = 0;
  1891. for ( j=0; j<szStrLength; j++ ) {
  1892. if ( FullPath[j] == _T('*') || FullPath[j] == _T('?') ) {
  1893. so->printf("SYMSTORE: ERROR: Wildcards are not allowed in \\\\server\\share\n");
  1894. return (FALSE);
  1895. }
  1896. }
  1897. if ( StringCchCopy(szSrcDir, _MAX_PATH, FullPath) != S_OK ) {
  1898. return(FALSE);
  1899. }
  1900. if ( StringCchCat( szSrcDir, _MAX_PATH, _T("\\")) != S_OK ) {
  1901. return(FALSE);
  1902. }
  1903. if ( StringCchCopy(szFileName, _MAX_PATH, _T("*")) != S_OK ) {
  1904. return(FALSE);
  1905. }
  1906. return (TRUE);
  1907. }
  1908. }
  1909. // See if this has wildcards in it. If it does, then the
  1910. // wildcards are only allowed in the file name part of the
  1911. // string. The last entry is a file name then.
  1912. found = 0;
  1913. for ( i=0; i<szStrLength; i++ ) {
  1914. // Keep track of where the last directory ended
  1915. if ( FullPath[i] == _T('\\') ) {
  1916. lastslash=i;
  1917. }
  1918. if ( FullPath[i] == _T('*') || FullPath[i] == _T('?') ) {
  1919. found = 1;
  1920. }
  1921. if ( found && FullPath[i] == _T('\\') ) {
  1922. so->printf("SYMSTORE: ERROR: Wildcards are only allowed in the filename\n");
  1923. return (FALSE);
  1924. }
  1925. }
  1926. // If there was a wildcard
  1927. // then use the last backslash as the location for splitting between
  1928. // the directory and the file name.
  1929. if ( found ) {
  1930. _tcsncpy( szSrcDir, FullPath, (lastslash+1) * sizeof (TCHAR) );
  1931. *(szSrcDir+lastslash+1)=_T('\0');
  1932. if ( StringCchCopy(szFileName, _MAX_PATH, FullPath+lastslash + 1 ) != S_OK ) {
  1933. return(FALSE);
  1934. }
  1935. return (TRUE);
  1936. }
  1937. // See if this is a directory. If it is then make sure there is
  1938. // a blackslash after the directory and use * for the file name.
  1939. fHandle = FindFirstFile(FullPath, &FindFileData);
  1940. if ( fHandle != INVALID_HANDLE_VALUE &&
  1941. (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
  1942. // If it is a directory then make sure that it ends in a \
  1943. // and use * for the filename
  1944. if ( StringCchCopy(szSrcDir, _MAX_PATH, FullPath) != S_OK ) {
  1945. return(FALSE);
  1946. }
  1947. MyEnsureTrailingBackslash(szSrcDir);
  1948. if ( StringCchCopy(szFileName, _MAX_PATH, _T("*")) != S_OK ) {
  1949. return(FALSE);
  1950. }
  1951. return (TRUE);
  1952. }
  1953. // Otherwise, go backwards from the end of the string and find
  1954. // the last backslash. Divide it up into directory and file name.
  1955. i=szStrLength-1;
  1956. while ( FullPath[i] != _T('\\') ) {
  1957. i--;
  1958. }
  1959. _tcsncpy( szSrcDir, FullPath, i+1 );
  1960. *(szSrcDir+i+1)=_T('\0');
  1961. if ( StringCchCopy(szFileName, _MAX_PATH, FullPath+i+1) != S_OK ) {
  1962. return(FALSE);
  1963. }
  1964. return (TRUE);
  1965. }
  1966. BOOL
  1967. InitializeTrans(
  1968. PTRANSACTION *pTrans,
  1969. PCOM_ARGS pArgs,
  1970. PHANDLE hFile
  1971. )
  1972. {
  1973. BOOL rc;
  1974. SYSTEMTIME SystemTime;
  1975. lMaxTrans = MAX_ID + MAX_VERSION + MAX_PRODUCT + MAX_COMMENT +
  1976. TRANS_NUM_COMMAS + TRANS_EOL + TRANS_ADD_DEL + TRANS_FILE_PTR +
  1977. MAX_DATE + MAX_TIME + MAX_UNUSED;
  1978. *pTrans = NULL;
  1979. *pTrans = (PTRANSACTION) malloc( sizeof(TRANSACTION) );
  1980. if (!*pTrans) {
  1981. so->printf("SYMSTORE: Not enough memory to allocate a TRANSACTION\n");
  1982. exit(1);
  1983. }
  1984. memset(*pTrans,0,sizeof(TRANSACTION) );
  1985. //
  1986. // If this is a delete transaction, then use the ID that was entered from
  1987. // the command line to set the ID of the transaction to be deleted.
  1988. //
  1989. if (pArgs->TransState==TRANSACTION_DEL ) {
  1990. (*pTrans)->TransState = pArgs->TransState;
  1991. (*pTrans)->szId = pArgs->szId;
  1992. rc = GetNextId(pArgs->szMasterFileName,&((*pTrans)->szDelId),hFile);
  1993. } else if ( pArgs->StoreFlags == ADD_DONT_STORE ) {
  1994. rc = TRUE;
  1995. } else{
  1996. rc = GetNextId(pArgs->szMasterFileName,&((*pTrans)->szId),hFile );
  1997. }
  1998. if (!rc) {
  1999. so->printf("SYMSTORE: Cannot create a new transaction ID number\n");
  2000. exit(1);
  2001. }
  2002. // If the things that are needed for both types of adding
  2003. // That is, creating a transaction file only, and adding the
  2004. // files to the symbols server
  2005. if (pArgs->TransState==TRANSACTION_ADD) {
  2006. (*pTrans)->TransState = pArgs->TransState;
  2007. (*pTrans)->FileOrPtr = pArgs->szSrcPath ? STORE_PTR : STORE_FILE;
  2008. }
  2009. // If this is a add, but don't store the files, then the transaction
  2010. // file name is already in pArgs.
  2011. if (pArgs->StoreFlags == ADD_DONT_STORE) {
  2012. (*pTrans)->szTransFileName=(LPTSTR)malloc( sizeof(TCHAR) *(_tcslen(pArgs->szTransFileName) + 1) );
  2013. if (!(*pTrans)->szTransFileName ) {
  2014. so->printf("Malloc cannot allocate memory for (*pTrans)->szTransFileName \n");
  2015. exit(1);
  2016. }
  2017. StringCbCopy((*pTrans)->szTransFileName, _msize((*pTrans)->szTransFileName), pArgs->szTransFileName);
  2018. return TRUE;
  2019. }
  2020. // Now, set the full path name of the transaction file
  2021. (*pTrans)->szTransFileName=(LPTSTR)malloc( sizeof(TCHAR) *
  2022. (_tcslen( pArgs->szAdminDir ) +
  2023. _tcslen( (*pTrans)->szId ) +
  2024. 1 ) );
  2025. if (!(*pTrans)->szTransFileName ) {
  2026. so->printf("Malloc cannot allocate memory for (*pTrans)->szTransFilename \n");
  2027. exit(1);
  2028. }
  2029. StringCbPrintf( (*pTrans)->szTransFileName,
  2030. _msize((*pTrans)->szTransFileName),
  2031. "%s%s",
  2032. pArgs->szAdminDir,
  2033. (*pTrans)->szId );
  2034. (*pTrans)->szProduct = pArgs->szProduct;
  2035. (*pTrans)->szVersion = pArgs->szVersion;
  2036. (*pTrans)->szComment = pArgs->szComment;
  2037. (*pTrans)->szUnused = pArgs->szUnused;
  2038. // Set the time and date
  2039. GetLocalTime(&SystemTime);
  2040. StoreSystemTime( & ((*pTrans)->szTime), &SystemTime );
  2041. StoreSystemDate( & ((*pTrans)->szDate), &SystemTime );
  2042. return (TRUE);
  2043. }
  2044. VOID MallocFailed() {
  2045. so->printf("SYMSTORE: Malloc failed to allocate enough memory\n");
  2046. exit(1);
  2047. }
  2048. DWORD
  2049. StoreAllDirectories(
  2050. LPTSTR szDir,
  2051. LPTSTR szFName,
  2052. LPTSTR szDestDir,
  2053. PFILE_COUNTS pFileCounts,
  2054. LPTSTR szPath
  2055. )
  2056. /* ++
  2057. IN szDir Directory of files to Store
  2058. -- */
  2059. {
  2060. HANDLE hFindFile;
  2061. TCHAR szCurPath[_MAX_PATH];
  2062. TCHAR szFilePtrPath[_MAX_PATH]; // This is the path that will get stored as a
  2063. // pointer to the file.
  2064. LPTSTR szPtrPath = NULL;
  2065. BOOL Found = FALSE;
  2066. DWORD NumBadFiles=0;
  2067. LPWIN32_FIND_DATA lpFindFileData;
  2068. NumBadFiles += StoreDirectory(szDir,
  2069. szFName,
  2070. szDestDir,
  2071. pFileCounts,
  2072. szPath
  2073. );
  2074. lpFindFileData = (LPWIN32_FIND_DATA) malloc (sizeof(WIN32_FIND_DATA) );
  2075. if (!lpFindFileData) {
  2076. so->printf("Symchk: Not enough memory.\n");
  2077. exit(1);
  2078. }
  2079. // Look for all the subdirectories
  2080. StringCbCopy(szCurPath, sizeof(szCurPath), szDir);
  2081. StringCbCat( szCurPath, sizeof(szCurPath), _T("*.*") );
  2082. Found = TRUE;
  2083. hFindFile = FindFirstFile((LPCTSTR)szCurPath, lpFindFileData);
  2084. if ( hFindFile == INVALID_HANDLE_VALUE) {
  2085. Found = FALSE;
  2086. }
  2087. while ( Found ) {
  2088. if ( lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  2089. if ( !_tcscmp(lpFindFileData->cFileName, _T(".")) ||
  2090. !_tcscmp(lpFindFileData->cFileName, _T("..")) ) {
  2091. } else {
  2092. // Get the current path that we are searching in
  2093. StringCbCopy(szCurPath, sizeof(szCurPath), szDir);
  2094. StringCbCat( szCurPath, sizeof(szCurPath), lpFindFileData->cFileName);
  2095. MyEnsureTrailingBackslash(szCurPath);
  2096. // Get the current path to use as the pointer to the
  2097. // file, if we are storing file pointers instead of
  2098. // files in this tree.
  2099. if ( szPath ) {
  2100. StringCbCopy(szFilePtrPath, sizeof(szFilePtrPath), szPath);
  2101. StringCbCat( szFilePtrPath, sizeof(szFilePtrPath), lpFindFileData->cFileName);
  2102. MyEnsureTrailingBackslash(szFilePtrPath);
  2103. szPtrPath = szFilePtrPath;
  2104. }
  2105. NumBadFiles += StoreAllDirectories(
  2106. szCurPath,
  2107. szFName,
  2108. szDestDir,
  2109. pFileCounts,
  2110. szPtrPath
  2111. );
  2112. }
  2113. }
  2114. Found = FindNextFile(hFindFile, lpFindFileData);
  2115. if ( !Found ) {
  2116. DWORD LastError = GetLastError();
  2117. switch (LastError) {
  2118. case ERROR_NO_MORE_FILES: // Completed successfully because there are no
  2119. // more files to process.
  2120. break;
  2121. case ERROR_FILE_NOT_FOUND: {// Possible network error, try again for up to 30 sec
  2122. DWORD SleepCount = 0;
  2123. // Loop until one of the following:
  2124. // 1) A file is found
  2125. // 2) FindNextFile returns an error code other than ERROR_FILE_NOT_FOUND
  2126. // 3) 30 seconds have elapsed
  2127. while ( (Found = FindNextFile(hFindFile, lpFindFileData)) ||
  2128. ( (GetLastError() == ERROR_FILE_NOT_FOUND) &&
  2129. (SleepCount <= 60 ) ) ) {
  2130. SleepCount++;
  2131. Sleep(500); // sleep 1/2 second
  2132. }
  2133. }
  2134. break;
  2135. default:
  2136. so->printf("Symchk: Failed to get next filename. Error code was 0x%08x.\n", LastError);
  2137. break;
  2138. }
  2139. }
  2140. }
  2141. free(lpFindFileData);
  2142. FindClose(hFindFile);
  2143. return(NumBadFiles);
  2144. }
  2145. StoreDirectory(
  2146. LPTSTR szDir,
  2147. LPTSTR szFName,
  2148. LPTSTR szDestDir,
  2149. PFILE_COUNTS pFileCounts,
  2150. LPTSTR szPath
  2151. )
  2152. {
  2153. HANDLE hFindFile;
  2154. TCHAR szFileName[_MAX_PATH];
  2155. TCHAR szCurPath[_MAX_PATH];
  2156. TCHAR szCurFileName[_MAX_PATH];
  2157. TCHAR szCurPtrFileName[_MAX_PATH]; // Ptr to the file to put in "file.ptr"
  2158. // instead of storing the file.
  2159. TCHAR szFullFilename[_MAX_PATH];
  2160. LPTSTR pFilename;
  2161. BOOL Found, length;
  2162. DWORD rc;
  2163. DWORD NumBadFiles=0;
  2164. BOOL skipped = 0;
  2165. USHORT rc_flag;
  2166. BOOL unknowntype = FALSE;
  2167. LPWIN32_FIND_DATA lpFindFileData;
  2168. // Create the file name
  2169. StringCbCopy(szFileName, sizeof(szFileName), szDir);
  2170. StringCbCat( szFileName, sizeof(szFileName), szFName);
  2171. // Get the current path that we are searching in
  2172. StringCbCopy(szCurPath, sizeof(szCurPath), szDir);
  2173. lpFindFileData = (LPWIN32_FIND_DATA) malloc (sizeof(WIN32_FIND_DATA) );
  2174. if (!lpFindFileData) {
  2175. so->printf("Symchk: Not enough memory.\n");
  2176. exit(1);
  2177. }
  2178. Found = TRUE;
  2179. hFindFile = FindFirstFile((LPCTSTR)szFileName, lpFindFileData);
  2180. if ( hFindFile == INVALID_HANDLE_VALUE ) {
  2181. Found = FALSE;
  2182. }
  2183. while ( Found ) {
  2184. // Found a file, not a directory
  2185. if ( !(lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
  2186. rc_flag=0;
  2187. StringCbCopy(szCurFileName, sizeof(szCurFileName), szCurPath);
  2188. StringCbCat( szCurFileName, sizeof(szCurFileName), lpFindFileData->cFileName);
  2189. if ( szPath ) {
  2190. StringCbCopy(szCurPtrFileName, sizeof(szCurPtrFileName), szCurFileName);
  2191. //PrivateGetFullPathName(szCurFileName, sizeof(szCurPtrFileName)/sizeof(szCurPtrFileName[0]), szCurPtrFileName, &pFilename);
  2192. }
  2193. // Figure out if its a dbg or pdb
  2194. length = _tcslen(szCurFileName);
  2195. rc = FALSE;
  2196. skipped = FALSE;
  2197. if (length > 4 ) {
  2198. if ( _tcsicmp(_T(".dbg"), szCurFileName + length - 4) == 0 ) {
  2199. if ( szPath ) {
  2200. rc = StoreDbg( szDestDir, szCurFileName, szCurPtrFileName, &rc_flag );
  2201. }
  2202. else {
  2203. rc = StoreDbg( szDestDir, szCurFileName, NULL, &rc_flag );
  2204. }
  2205. }
  2206. else if ( _tcsicmp(_T(".pdb"), szCurFileName + length - 4) == 0 ) {
  2207. if ( szPath ) {
  2208. rc = StorePdb( szDestDir, szCurFileName, szCurPtrFileName, &rc_flag );
  2209. } else {
  2210. rc = StorePdb( szDestDir, szCurFileName, NULL, &rc_flag );
  2211. }
  2212. }
  2213. else {
  2214. if ( szPath ) {
  2215. rc = StoreNtFile( szDestDir, szCurFileName, szCurPtrFileName, &rc_flag );
  2216. } else {
  2217. rc = StoreNtFile( szDestDir, szCurFileName, NULL, &rc_flag );
  2218. }
  2219. if (rc_flag == FILE_SKIPPED) {
  2220. unknowntype = TRUE;
  2221. }
  2222. }
  2223. }
  2224. if (rc_flag == FILE_SKIPPED) {
  2225. NumSkippedFiles++;
  2226. skipped = TRUE;
  2227. if(pArgs->VerboseOutput) {
  2228. if (unknowntype) {
  2229. so->printf("SYMSTORE: Skipping %s - not a dbg, pdb, or executable\n", szCurFileName);
  2230. unknowntype = FALSE;
  2231. } else {
  2232. so->printf("SYMSTORE: Skipping %s - filter out by -z option\n", szCurFileName);
  2233. unknowntype = FALSE;
  2234. }
  2235. }
  2236. }
  2237. if (!skipped && !rc) {
  2238. pFileCounts->NumFailedFiles++;
  2239. if ( pArgs->TransState != TRANSACTION_QUERY ) {
  2240. NumBadFiles++;
  2241. so->printf("SYMSTORE: ERROR: Cannot store %s ", szCurFileName);
  2242. DisplayErrorText(rc_flag);
  2243. so->printf("\n");
  2244. } else {
  2245. NumSkippedFiles++; // don't fail invalid files when doing query
  2246. if(pArgs->VerboseOutput) {
  2247. so->printf("SYMSTORE: Skipping: %s - not a valid file for symbol server.\n", szCurFileName);
  2248. }
  2249. }
  2250. } else if (!skipped) {
  2251. pFileCounts->NumPassedFiles++;
  2252. if ( pArgs->TransState != TRANSACTION_QUERY ) {
  2253. if (pFileCounts->NumPassedFiles % 50 == 0) {
  2254. so->stdprintf(".");
  2255. }
  2256. }
  2257. }
  2258. }
  2259. Found = FindNextFile(hFindFile, lpFindFileData);
  2260. }
  2261. free(lpFindFileData);
  2262. FindClose(hFindFile);
  2263. return(NumBadFiles);
  2264. }
  2265. BOOL
  2266. StoreSystemDate(
  2267. LPTSTR *szBuf,
  2268. LPSYSTEMTIME lpSystemTime
  2269. )
  2270. {
  2271. TCHAR Day[20];
  2272. TCHAR Month[20];
  2273. TCHAR Year[20];
  2274. (*szBuf) = (LPTSTR) malloc (20 * sizeof(TCHAR) );
  2275. if ( (*szBuf) == NULL ) MallocFailed();
  2276. _itoa(lpSystemTime->wMonth, Month, 10);
  2277. _itoa(lpSystemTime->wDay, Day, 10);
  2278. _itoa(lpSystemTime->wYear, Year, 10);
  2279. StringCbPrintf(*szBuf, _msize(*szBuf), "%2s/%2s/%2s", Month, Day, Year+2 );
  2280. if ( (*szBuf)[0] == ' ' ) (*szBuf)[0] = '0';
  2281. if ( (*szBuf)[3] == ' ' ) (*szBuf)[3] = '0';
  2282. return(TRUE);
  2283. }
  2284. BOOL
  2285. StoreSystemTime(
  2286. LPTSTR *szBuf,
  2287. LPSYSTEMTIME lpSystemTime
  2288. )
  2289. {
  2290. TCHAR Hour[20];
  2291. TCHAR Minute[20];
  2292. TCHAR Second[20];
  2293. (*szBuf) = (LPTSTR) malloc (20 * sizeof(TCHAR) );
  2294. if ( (*szBuf) == NULL ) MallocFailed();
  2295. _itoa(lpSystemTime->wHour, Hour, 10);
  2296. _itoa(lpSystemTime->wMinute, Minute, 10);
  2297. _itoa(lpSystemTime->wSecond, Second, 10);
  2298. StringCbPrintf(*szBuf, _msize(*szBuf), "%2s:%2s:%2s", Hour, Minute, Second );
  2299. if ( (*szBuf)[0] == ' ' ) (*szBuf)[0] = '0';
  2300. if ( (*szBuf)[3] == ' ' ) (*szBuf)[3] = '0';
  2301. if ( (*szBuf)[6] == ' ' ) (*szBuf)[6] = '0';
  2302. return(TRUE);
  2303. }
  2304. BOOL
  2305. UpdateServerFile(
  2306. PTRANSACTION pTrans,
  2307. LPTSTR szServerFileName
  2308. )
  2309. /* ++
  2310. IN pTrans // Transaction Info
  2311. IN szServerFile // Full path and name of the server transaction file
  2312. // This file tells what is currently on the server
  2313. Purpose: UpdateServerFile adds the transaction to the server text file if this is an
  2314. "add. If this is a "del", it deletes it from the server file. The "server.txt" file
  2315. is in the admin directory.
  2316. -- */
  2317. {
  2318. ULONG i;
  2319. ULONG NumLines;
  2320. ULONG IdLineNum;
  2321. LPTSTR szBuf;
  2322. LPTSTR szTempFileName;
  2323. FILE *fTempFile;
  2324. FILE *fServerFile;
  2325. ULONG MaxLine;
  2326. TCHAR *token;
  2327. TCHAR seps[]=",";
  2328. BOOL rc;
  2329. HANDLE hFile;
  2330. DWORD First;
  2331. DWORD timeout;
  2332. if (pTrans->TransState == TRANSACTION_ADD ) {
  2333. // Open the File -- wait until we can get access to it
  2334. First = 1;
  2335. timeout=0;
  2336. do {
  2337. hFile = CreateFile(
  2338. szServerFileName,
  2339. GENERIC_READ | GENERIC_WRITE,
  2340. 0,
  2341. NULL,
  2342. OPEN_EXISTING,
  2343. FILE_ATTRIBUTE_NORMAL,
  2344. NULL );
  2345. if ( hFile == INVALID_HANDLE_VALUE ) {
  2346. hFile = CreateFile(
  2347. szServerFileName,
  2348. GENERIC_READ | GENERIC_WRITE,
  2349. 0,
  2350. NULL,
  2351. CREATE_ALWAYS,
  2352. FILE_ATTRIBUTE_NORMAL,
  2353. NULL );
  2354. }
  2355. if ( First && hFile == INVALID_HANDLE_VALUE ) {
  2356. First = 0;
  2357. so->printf("Waiting to open %s ... \n", szServerFileName);
  2358. }
  2359. if ( hFile == INVALID_HANDLE_VALUE ) {
  2360. SleepEx(1000,0);
  2361. timeout++;
  2362. }
  2363. } while ( hFile == INVALID_HANDLE_VALUE && timeout <= 50 );
  2364. if ( timeout > 50 ) {
  2365. so->printf("Timed out -- could not open %s\n", szServerFileName);
  2366. CloseHandle(hFile);
  2367. return (1);
  2368. }
  2369. rc = AddTransToFile(pTrans, szServerFileName,&hFile);
  2370. CloseHandle(hFile);
  2371. return(rc);
  2372. }
  2373. if (pTrans->TransState != TRANSACTION_DEL) {
  2374. return(FALSE);
  2375. }
  2376. //
  2377. // Now, delete this transaction ID from the file
  2378. // Get the name of the temporary file
  2379. // and open it for writing
  2380. //
  2381. szTempFileName = (LPTSTR)malloc(sizeof(TCHAR) *
  2382. _tcslen(szServerFileName) + _tcslen(".tmp") + 1 );
  2383. if (szTempFileName == NULL) MallocFailed();
  2384. StringCbPrintf(szTempFileName, _msize(szTempFileName), "%s.tmp", szServerFileName);
  2385. fTempFile = _tfopen(szTempFileName, _T("w") );
  2386. if ( fTempFile == NULL ) {
  2387. so->printf("SYMSTORE: Cannot create a temporary file %s\n", szTempFileName);
  2388. exit(1);
  2389. }
  2390. //
  2391. // Open the Server file for reading
  2392. //
  2393. fServerFile = _tfopen(szServerFileName, _T("r") );
  2394. if ( fServerFile == NULL ) {
  2395. so->printf("SYMSTORE: Cannot create a temporary file %s\n", szServerFileName);
  2396. exit(1);
  2397. }
  2398. //
  2399. // Allocate enough space to hold a line of the master file
  2400. //
  2401. MaxLine = GetMaxLineOfHistoryFile();
  2402. szBuf = (LPTSTR)malloc(sizeof(TCHAR) * MaxLine);
  2403. if (szBuf == NULL) MallocFailed();
  2404. //
  2405. // Copy the master file to the temporary file.
  2406. //
  2407. // Do some stuff so that we don't put an extra '\n' at the end of the file
  2408. // Figure out how many lines there are and which line the ID is on.
  2409. // If we are removing the last line of the file, then the next to the last
  2410. // line needs to have a '\n' stripped from it.
  2411. //
  2412. NumLines = 0;
  2413. IdLineNum = 0;
  2414. while ( _fgetts( szBuf, MaxLine, fServerFile) != NULL ) {
  2415. NumLines++;
  2416. token = _tcstok(szBuf,seps);
  2417. if (_tcscmp(token, pTrans->szId) == 0 ) {
  2418. IdLineNum = NumLines;
  2419. }
  2420. }
  2421. fflush(fServerFile);
  2422. fclose(fServerFile);
  2423. // Now, reopen it and copy it, deleting the line with ID in it
  2424. fServerFile = _tfopen(szServerFileName, _T("r") );
  2425. if ( fServerFile == NULL ) {
  2426. so->printf("SYMSTORE: Cannot create a temporary file %s\n", szServerFileName);
  2427. exit(1);
  2428. }
  2429. for (i=1; i<=NumLines; i++ ) {
  2430. if ( _fgetts( szBuf, MaxLine, fServerFile) == NULL )
  2431. {
  2432. so->printf( "SYMSTORE: Cannot read from %s - GetLastError = %d\n",
  2433. szServerFileName, GetLastError()
  2434. );
  2435. exit(1);
  2436. }
  2437. if ( i != IdLineNum ) {
  2438. // Make sure that the last line doesn't end with a '\n'
  2439. if ( i == NumLines || (IdLineNum == NumLines && i == NumLines-1) ) {
  2440. if ( szBuf[_tcslen(szBuf)-1] == '\n' ) {
  2441. szBuf[_tcslen(szBuf)-1] = '\0';
  2442. }
  2443. }
  2444. _fputts( szBuf, fTempFile);
  2445. }
  2446. }
  2447. fflush(fServerFile);
  2448. fclose(fServerFile);
  2449. fflush(fTempFile);
  2450. fclose(fTempFile);
  2451. // Now, delete the original Server file and
  2452. // replace it with the temporary file
  2453. rc = DeleteFile(szServerFileName);
  2454. if (!rc) {
  2455. so->printf("SYMSTORE: Could not delete %s to update it with %s\n",
  2456. szServerFileName, szTempFileName);
  2457. exit(1);
  2458. }
  2459. rc = _trename(szTempFileName, szServerFileName);
  2460. if ( rc != 0 ) {
  2461. so->printf("SYMSTORE: Could not rename %s to %s\n",
  2462. szTempFileName, szServerFileName);
  2463. exit(1);
  2464. }
  2465. free(szBuf);
  2466. free(szTempFileName);
  2467. return(TRUE);
  2468. }
  2469. VOID
  2470. Usage (
  2471. VOID
  2472. )
  2473. {
  2474. so->printf("\n"
  2475. "Usage:\n"
  2476. "symstore add [/r] [/p] [/l] /f File /s Store /t Product [/v Version]\n"
  2477. " [/c Comment] [/d LogFile]\n\n"
  2478. "symstore add [/r] [/p] [/l] /g Share /f File /x IndexFile [/a] [/d LogFile]\n\n"
  2479. "symstore add /y IndexFile /g Share /s Store [/p] /t Product [/v Version]\n"
  2480. " [/c Comment] [/d LogFile]\n\n"
  2481. "symstore del /i ID /s Store [/d LogFile]\n\n"
  2482. "symstore query [/r] [/o] /f File /s Store\n\n"
  2483. " add Add files to server or create an index file.\n\n"
  2484. " del Delete a transaction from the server.\n\n"
  2485. " query Check if file(s) are indexed on the server.\n\n"
  2486. " /f File Network path of files or directories to add.\n\n"
  2487. " /g Share This is the server and share where the symbol files were\n"
  2488. " originally stored. When used with /f, Share should be\n"
  2489. " identical to the beginning of the File specifier. When\n"
  2490. " used with the /y, Share should be the location of the\n"
  2491. " original symbol files, not the index file. This allows\n"
  2492. " you to later change this portion of the file path in case\n"
  2493. " you move the symbol files to a different server and share.\n\n"
  2494. " /i ID Transaction ID string.\n\n"
  2495. " /l Allows the file to be in a local directory rather than a\n"
  2496. " network path.(This option is only used with the /p option.)\n\n"
  2497. " /p Causes SymStore to store a pointer to the file, rather than\n"
  2498. " the file itself.\n\n"
  2499. " /r Add files or directories recursively.\n\n"
  2500. " /s Store Root directory for the symbol store.\n\n"
  2501. " /t Product Name of the product.\n\n"
  2502. " /v Version Version of the product.\n\n"
  2503. " /c Comment Comment for the transaction.\n\n"
  2504. " /d LogFile Send output to LogFile instead of standard output.\n\n"
  2505. " /x IndexFile Causes SymStore not to store the actual symbol files in the\n"
  2506. " symbol store. Instead, information is stored which will\n"
  2507. " allow the files to be added later.\n\n"
  2508. " /y IndexFile This reads the data from a file created with /x.\n\n"
  2509. " /yi IndexFile Append a comment with the transaction ID to the end of the\n"
  2510. " index file.\n\n"
  2511. /*
  2512. " /z pub | pri Put option will only index symbols that have had the full\n"
  2513. " source information stripped. Pri will only index symbols\n"
  2514. " that contain the full source information. Both options\n"
  2515. " will index binaries.\n\n"
  2516. " /m MSarchive\n\n"
  2517. " /h pub | pri Give priority to pub or pri."
  2518. */
  2519. " /a Causes SymStore to append new indexing information\n"
  2520. " to an existing index file. (This option is only used with\n"
  2521. " /x option.)\n\n"
  2522. " /o Give verbose output.\n\n"
  2523. "\n" );
  2524. exit(1);
  2525. }