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.

1747 lines
54 KiB

  1. /*
  2. * Utility program to munge a set of files, translating names from
  3. * one form to another. Usage:
  4. *
  5. * munge scriptFile files...
  6. *
  7. * where the first parameter is the name of a file that consists of
  8. * one or more lines of the following format:
  9. *
  10. * oldName newName
  11. *
  12. * and the remaining parameters are the names of the files to munge.
  13. * Each file is _read into memory, scanned once, where each occurence
  14. * of an oldName string is replaced by its corresponding newName.
  15. * If any changes are made to a file, the old version is RMed and
  16. * the new version written out under the same name.
  17. *
  18. */
  19. #include "munge.h"
  20. BOOL SymbolsInserted;
  21. BOOL InitTokenMappingTable( void );
  22. BOOL SaveTokenMapping( char *, char * );
  23. char *FindTokenMapping( char * );
  24. #define MAXFILESIZE 0x1000000L
  25. char *InputFileBuf;
  26. char *OutputFileBuf;
  27. int fClean;
  28. int fQuery;
  29. int fFileOnly;
  30. int fRecurse;
  31. int fUseAttrib;
  32. int fUseSLM;
  33. int fForceSLM;
  34. int fTrustMe;
  35. int fVerbose;
  36. int fSummary;
  37. int fRemoveDuplicateCR;
  38. int fRemoveImbeddedNulls;
  39. int fTruncateWithCtrlZ;
  40. int fInsideQuotes;
  41. int fInsideComments;
  42. int fNeuter;
  43. int fCaseSensitive;
  44. int fEntireLine;
  45. #define MAX_LITERAL_STRINGS 64
  46. void
  47. DoFiles(
  48. char *p,
  49. struct findType *b,
  50. void *Args
  51. );
  52. unsigned long NumberOfLiteralStrings;
  53. char *LiteralStrings[ MAX_LITERAL_STRINGS ];
  54. unsigned long LiteralStringsLength[ MAX_LITERAL_STRINGS ];
  55. char *NewLiteralStrings[ MAX_LITERAL_STRINGS ];
  56. char LeadingLiteralChars[ MAX_LITERAL_STRINGS+1 ];
  57. unsigned long NumberOfFileExtensions = 0;
  58. char *FileExtensions[ 64 ];
  59. unsigned long NumberOfFileNames = 0;
  60. char *FileNames[ 64 ];
  61. unsigned long NumberOfFileNameAndExts = 0;
  62. char *FileNameAndExts[ 64 ];
  63. char *UndoScriptFileName;
  64. FILE *UndoScriptFile;
  65. int UndoCurDirCount;
  66. void
  67. DisplayFilePatterns( void );
  68. char *
  69. PushCurrentDirectory(
  70. char *NewCurrentDirectory
  71. );
  72. void
  73. PopCurrentDirectory(
  74. char *OldCurrentDirectory
  75. );
  76. NTSTATUS
  77. CreateSymbolTable(
  78. IN ULONG NumberOfBuckets,
  79. IN ULONG MaxSymbolTableSize,
  80. OUT PVOID *SymbolTableHandle
  81. );
  82. NTSTATUS
  83. AddSymbolToSymbolTable(
  84. IN PVOID SymbolTableHandle,
  85. IN PUNICODE_STRING SymbolName,
  86. IN ULONG_PTR *SymbolValue OPTIONAL
  87. );
  88. NTSTATUS
  89. LookupSymbolInSymbolTable(
  90. IN PVOID SymbolTableHandle,
  91. IN PUNICODE_STRING SymbolName,
  92. OUT ULONG_PTR *SymbolValue OPTIONAL
  93. );
  94. BOOL
  95. myread( int fh, unsigned long cb )
  96. {
  97. HANDLE InputFileMapping;
  98. InputFileMapping = CreateFileMapping( (HANDLE)_get_osfhandle( fh ),
  99. NULL,
  100. PAGE_READONLY,
  101. 0,
  102. cb,
  103. NULL
  104. );
  105. if (InputFileMapping == NULL) {
  106. if (cb != 0) {
  107. fprintf( stderr, "Unable to map file (%d) - ", GetLastError() );
  108. }
  109. return FALSE;
  110. }
  111. InputFileBuf = MapViewOfFile( InputFileMapping,
  112. FILE_MAP_READ,
  113. 0,
  114. 0,
  115. cb
  116. );
  117. CloseHandle( InputFileMapping );
  118. if (InputFileBuf == NULL) {
  119. if (cb != 0) {
  120. fprintf( stderr, "Unable to map view (%d) - ", GetLastError() );
  121. }
  122. CloseHandle( InputFileMapping );
  123. return FALSE;
  124. } else {
  125. return TRUE;
  126. }
  127. }
  128. unsigned long mywrite( int fh, char *s, unsigned long cb )
  129. {
  130. unsigned long cbWritten;
  131. if (!WriteFile( (HANDLE)_get_osfhandle( fh ), s, cb, &cbWritten, NULL )) {
  132. printf( "(%d)", GetLastError() );
  133. return 0L;
  134. } else {
  135. return cbWritten;
  136. }
  137. }
  138. static char lineBuf[ 1024 ];
  139. ReadScriptFile( s )
  140. char *s;
  141. {
  142. FILE *fh;
  143. int lineNum, result;
  144. char *pOldName, *pNewName, *pEnd;
  145. unsigned n;
  146. char LeadingChar, QuoteChar, SaveChar;
  147. NumberOfLiteralStrings = 0;
  148. n = 0;
  149. fprintf( stderr, "Reading script file - %s", s );
  150. if ( !( fh = fopen( s, "r" ) ) ) {
  151. fprintf( stderr, " *** unable to open\n" );
  152. return FALSE;
  153. }
  154. result = TRUE;
  155. lineNum = -1;
  156. while ( pOldName = fgets( lineBuf, sizeof( lineBuf ), fh ) ) {
  157. lineNum++;
  158. while ( *pOldName == ' ' )
  159. pOldName++;
  160. if (*pOldName == '-' && (pOldName[1] == 'f' || pOldName[1] == 'F')) {
  161. pOldName += 2;
  162. while (*pOldName) {
  163. while (*pOldName == ' ') {
  164. pOldName++;
  165. }
  166. pEnd = pOldName;
  167. while (*pEnd > ' ') {
  168. pEnd++;
  169. }
  170. SaveChar = *pEnd;
  171. *pEnd = '\0';
  172. if (*pOldName == '.') {
  173. pNewName = MakeStr( ++pOldName );
  174. if (pNewName)
  175. _strlwr(pNewName);
  176. FileExtensions[ NumberOfFileExtensions++ ] = pNewName;
  177. } else
  178. if (pEnd > pOldName && pEnd[ -1 ] == '.') {
  179. pEnd[ - 1 ] = '\0';
  180. pNewName = MakeStr(pOldName);
  181. if (pNewName)
  182. _strlwr(pNewName);
  183. FileNames[ NumberOfFileNames++ ] = pNewName;
  184. } else {
  185. pNewName = MakeStr(pOldName);
  186. if (pNewName)
  187. _strlwr(pNewName);
  188. FileNameAndExts[ NumberOfFileNameAndExts++ ] = pNewName;
  189. }
  190. *pEnd = SaveChar;
  191. pOldName = pEnd;
  192. }
  193. } else
  194. if (*pOldName == '"' || *pOldName == '\'') {
  195. if (NumberOfLiteralStrings >= MAX_LITERAL_STRINGS) {
  196. fprintf( stderr, " *** too many literal strings\n" );
  197. fprintf( stderr, "%s(%d) - %s\n", s, lineNum, &lineBuf[ 0 ] );
  198. result = FALSE;
  199. break;
  200. }
  201. QuoteChar = *pOldName;
  202. LeadingChar = *++pOldName;
  203. pNewName = pOldName;
  204. while (*pNewName >= ' ' && *pNewName != QuoteChar) {
  205. pNewName++;
  206. }
  207. if (*pNewName != QuoteChar) {
  208. fprintf( stderr, " *** invalid literal string\n" );
  209. fprintf( stderr, "%s(%d) - %s\n", s, lineNum, &lineBuf[ 0 ] );
  210. result = FALSE;
  211. continue;
  212. }
  213. *pNewName++ = '\0';
  214. while ( *pNewName == ' ' )
  215. pNewName++;
  216. if (*pNewName != QuoteChar) {
  217. if (!fQuery) {
  218. fprintf( stderr, " *** invalid literal string\n" );
  219. fprintf( stderr, "%s(%d) - %s\n", s, lineNum, &lineBuf[ 0 ] );
  220. result = FALSE;
  221. continue;
  222. }
  223. } else {
  224. PUCHAR pDest, pSrc;
  225. BOOL fEscaped = FALSE;
  226. pEnd = ++pNewName;
  227. pDest = pSrc = pEnd;
  228. while ((*pSrc >= ' ') && ((*pSrc != QuoteChar) || fEscaped)) {
  229. if (fEscaped) {
  230. switch(pSrc[0]) {
  231. case 'n':
  232. *pDest++ = '\r';
  233. *pDest++ = '\n';
  234. break;
  235. default:
  236. *pDest++ = *pSrc;
  237. break;
  238. }
  239. fEscaped = FALSE;
  240. } else {
  241. if (pSrc[0] == '\\') {
  242. fEscaped = TRUE;
  243. } else {
  244. *pDest++ = *pSrc;
  245. }
  246. }
  247. pSrc++;
  248. }
  249. pEnd = pSrc;
  250. if (*pEnd != QuoteChar) {
  251. fprintf( stderr, " *** invalid literal string\n" );
  252. fprintf( stderr, "%s(%d) - %s\n", s, lineNum, &lineBuf[ 0 ] );
  253. result = FALSE;
  254. continue;
  255. }
  256. *pDest = '\0';
  257. }
  258. LiteralStrings[ NumberOfLiteralStrings ] = MakeStr( ++pOldName );
  259. LiteralStringsLength[ NumberOfLiteralStrings ] = strlen( pOldName );
  260. NewLiteralStrings[ NumberOfLiteralStrings ] = MakeStr( pNewName );
  261. LeadingLiteralChars[ NumberOfLiteralStrings ] = LeadingChar;
  262. NumberOfLiteralStrings += 1;
  263. } else {
  264. pNewName = pOldName;
  265. while ( *pNewName != '\0' && *pNewName != ' ' ) {
  266. pNewName += 1;
  267. }
  268. if (*pNewName == '\0') {
  269. if (!fQuery) {
  270. if (result)
  271. fprintf( stderr, " *** invalid script file\n" );
  272. fprintf( stderr, "%s(%d) - %s\n", s, lineNum, &lineBuf[ 0 ] );
  273. result = FALSE;
  274. continue;
  275. }
  276. while (pNewName > pOldName && pNewName[ -1 ] < ' ') {
  277. *--pNewName = '\0';
  278. }
  279. pNewName = MakeStr( pOldName );
  280. } else {
  281. *pNewName++ = 0;
  282. while ( *pNewName == ' ' )
  283. pNewName++;
  284. pEnd = pNewName;
  285. while ( *pEnd > ' ' )
  286. pEnd++;
  287. *pEnd = 0;
  288. pNewName = MakeStr( pNewName );
  289. }
  290. if (!pNewName || !SaveTokenMapping( pOldName, pNewName )) {
  291. if (result)
  292. fprintf( stderr, " *** out of memory\n" );
  293. if (pNewName) {
  294. free(pNewName);
  295. }
  296. fprintf( stderr, "%s(%d) - can't add symbol '%s'\n", s, lineNum, pOldName );
  297. result = FALSE;
  298. } else {
  299. SymbolsInserted = TRUE;
  300. n++;
  301. }
  302. }
  303. }
  304. fclose( fh );
  305. if (result) {
  306. fprintf( stderr, " %d tokens", n );
  307. if (NumberOfLiteralStrings) {
  308. fprintf( stderr, " and %d literal strings\n", NumberOfLiteralStrings );
  309. } else {
  310. fprintf( stderr, "\n" );
  311. }
  312. if (!NumberOfFileExtensions && !NumberOfFileNames && !NumberOfFileNameAndExts) {
  313. FileExtensions[ NumberOfFileExtensions++ ] = "asm";
  314. FileExtensions[ NumberOfFileExtensions++ ] = "bat";
  315. FileExtensions[ NumberOfFileExtensions++ ] = "c";
  316. FileExtensions[ NumberOfFileExtensions++ ] = "cli";
  317. FileExtensions[ NumberOfFileExtensions++ ] = "cpp";
  318. FileExtensions[ NumberOfFileExtensions++ ] = "cxx";
  319. FileExtensions[ NumberOfFileExtensions++ ] = "def";
  320. FileExtensions[ NumberOfFileExtensions++ ] = "dlg";
  321. FileExtensions[ NumberOfFileExtensions++ ] = "h";
  322. FileExtensions[ NumberOfFileExtensions++ ] = "htm";
  323. FileExtensions[ NumberOfFileExtensions++ ] = "hpj";
  324. FileExtensions[ NumberOfFileExtensions++ ] = "hxx";
  325. FileExtensions[ NumberOfFileExtensions++ ] = "idl";
  326. FileExtensions[ NumberOfFileExtensions++ ] = "inc";
  327. FileExtensions[ NumberOfFileExtensions++ ] = "inf";
  328. FileExtensions[ NumberOfFileExtensions++ ] = "lic";
  329. FileExtensions[ NumberOfFileExtensions++ ] = "mak";
  330. FileExtensions[ NumberOfFileExtensions++ ] = "mc";
  331. FileExtensions[ NumberOfFileExtensions++ ] = "odl";
  332. FileExtensions[ NumberOfFileExtensions++ ] = "rc";
  333. FileExtensions[ NumberOfFileExtensions++ ] = "rcv";
  334. FileExtensions[ NumberOfFileExtensions++ ] = "reg";
  335. FileExtensions[ NumberOfFileExtensions++ ] = "s";
  336. FileExtensions[ NumberOfFileExtensions++ ] = "src";
  337. FileExtensions[ NumberOfFileExtensions++ ] = "srv";
  338. FileExtensions[ NumberOfFileExtensions++ ] = "tk";
  339. FileExtensions[ NumberOfFileExtensions++ ] = "w";
  340. FileExtensions[ NumberOfFileExtensions++ ] = "x";
  341. FileNameAndExts[ NumberOfFileNameAndExts++ ] = "makefil0";
  342. FileNameAndExts[ NumberOfFileNameAndExts++ ] = "makefile";
  343. FileNameAndExts[ NumberOfFileNameAndExts++ ] = "sources";
  344. }
  345. }
  346. return result;
  347. }
  348. int
  349. MungeFile(
  350. int fRepeatMunge,
  351. char *FileName,
  352. char *OldBuf,
  353. unsigned long OldSize,
  354. char *NewBuf,
  355. unsigned long MaxNewSize,
  356. unsigned long *FinalNewSize
  357. )
  358. {
  359. unsigned long NewSize = MaxNewSize;
  360. unsigned Changes = 0;
  361. unsigned LineNumber;
  362. char c, *Identifier, *BegLine, *EndLine, *OrigOldBuf;
  363. char IdentifierBuffer[ 256 ];
  364. char *p, *p1;
  365. int i, j, k;
  366. BOOL TruncatedByCtrlZ;
  367. BOOL ImbeddedNullsStripped;
  368. BOOL DuplicateCRStripped;
  369. BOOL InSingleQuotes;
  370. BOOL InDoubleQuotes;
  371. BOOL Escape = FALSE;
  372. BOOL Star = FALSE;
  373. BOOL Backslash = FALSE;
  374. BOOL Pound = FALSE;
  375. BOOL Semi = FALSE;
  376. BOOL LastEscape;
  377. BOOL LastStar;
  378. BOOL LastBackslash;
  379. BOOL LastPound;
  380. BOOL LastSemi;
  381. BOOL SkipChar;
  382. BOOL InLineComment;
  383. BOOL InComment;
  384. *FinalNewSize = 0;
  385. LineNumber = 1;
  386. TruncatedByCtrlZ = FALSE;
  387. ImbeddedNullsStripped = FALSE;
  388. DuplicateCRStripped = FALSE;
  389. InSingleQuotes = FALSE;
  390. InDoubleQuotes = FALSE;
  391. InLineComment = FALSE;
  392. InComment = FALSE;
  393. LastEscape = FALSE;
  394. LastStar = FALSE;
  395. LastBackslash = FALSE;
  396. OrigOldBuf = OldBuf;
  397. while (OldSize) {
  398. OldSize--;
  399. c = *OldBuf++;
  400. if (c == '\r') {
  401. while (OldSize && *OldBuf == '\r') {
  402. DuplicateCRStripped = TRUE;
  403. OldSize--;
  404. c = *OldBuf++;
  405. }
  406. }
  407. if (c == 0x1A) {
  408. TruncatedByCtrlZ = TRUE;
  409. break;
  410. }
  411. SkipChar = FALSE;
  412. if ( !fInsideQuotes || !fInsideComments ) {
  413. LastEscape = Escape;
  414. LastStar = Star;
  415. LastBackslash = Backslash;
  416. LastPound = Pound;
  417. LastSemi = Semi;
  418. Escape = (c == '\\');
  419. Star = (c == '*' );
  420. Backslash = (c == '/' );
  421. Pound = (c == '#' );
  422. Semi = (c == ';' );
  423. if ( Escape && LastEscape ) { // two in a row don't mean escape
  424. Escape = FALSE;
  425. }
  426. if ( c == '\r' || c == '\n' ) {
  427. InLineComment = FALSE;
  428. }
  429. // Don't process Include or Pragma directives
  430. if ( LastPound && OldSize > 6 ) {
  431. if ( !strncmp(OldBuf-1,"include",7)
  432. || !strncmp(OldBuf-1,"pragma",6) ) {
  433. InLineComment = TRUE;
  434. }
  435. }
  436. if (c == '"' && !InSingleQuotes && !LastEscape
  437. && !InLineComment && !InComment ) {
  438. InDoubleQuotes = !InDoubleQuotes;
  439. if ( fNeuter ) {
  440. if ( InDoubleQuotes ) {
  441. if ( NewSize < 5 ) {
  442. return( -1 );
  443. }
  444. strcpy(NewBuf,"TEXT(");
  445. NewBuf+=5;
  446. NewSize -= 5;
  447. } else {
  448. if ( NewSize < 1 ) {
  449. return( -1 );
  450. }
  451. *NewBuf++ = '"';
  452. NewSize--;
  453. c = ')';
  454. }
  455. }
  456. }
  457. if (c == '\'' && !InDoubleQuotes && !LastEscape
  458. && !InLineComment && !InComment ) {
  459. InSingleQuotes = !InSingleQuotes;
  460. if ( fNeuter ) {
  461. if ( InSingleQuotes ) {
  462. if ( NewSize < 5 ) {
  463. return( -1 );
  464. }
  465. strcpy(NewBuf,"TEXT(");
  466. NewBuf+=5;
  467. NewSize -= 5;
  468. } else {
  469. if ( NewSize < 1 ) {
  470. return( -1 );
  471. }
  472. *NewBuf++ = '\'';
  473. NewSize--;
  474. c = ')';
  475. }
  476. }
  477. }
  478. if ( !InDoubleQuotes && !InSingleQuotes
  479. && !InLineComment && !InComment ) {
  480. if ( LastBackslash ) {
  481. switch (c) {
  482. case '*': InComment = TRUE; break;
  483. case '/': InLineComment = TRUE; break;
  484. }
  485. }
  486. }
  487. if ( InComment && LastStar && Backslash ) {
  488. InComment = FALSE;
  489. }
  490. if ( !fInsideQuotes && ( InSingleQuotes || InDoubleQuotes ) ) {
  491. SkipChar = TRUE;
  492. } else
  493. if ( !fInsideComments && ( InLineComment || InComment ) ) {
  494. SkipChar = TRUE;
  495. }
  496. }
  497. if (c != 0 && NumberOfLiteralStrings != 0 && !SkipChar ) {
  498. p = LeadingLiteralChars;
  499. while (p = strchr( p, c )) {
  500. i = (int)(p - LeadingLiteralChars);
  501. p++;
  502. if (OldSize >= LiteralStringsLength[ i ]) {
  503. p1 = IdentifierBuffer;
  504. Identifier = OldBuf;
  505. j = LiteralStringsLength[ i ];
  506. while (j--) {
  507. *p1++ = *Identifier++;
  508. }
  509. *p1 = '\0';
  510. if (!strcmp( LiteralStrings[ i ], IdentifierBuffer )) {
  511. BegLine = OldBuf - 1;
  512. OldSize -= LiteralStringsLength[ i ];
  513. OldBuf = Identifier;
  514. p1 = NewLiteralStrings[ i ];
  515. if (!fRepeatMunge && !fSummary) {
  516. if (fFileOnly) {
  517. if (Changes == 0) { // Display just file name on first match
  518. printf( "%s\n", FileName );
  519. }
  520. } else {
  521. printf( "%s(%d) : ",
  522. FileName,
  523. LineNumber
  524. );
  525. if (fQuery) {
  526. EndLine = BegLine;
  527. while (*EndLine != '\0' && *EndLine != '\n') {
  528. EndLine += 1;
  529. }
  530. if (fEntireLine) {
  531. while (BegLine > OrigOldBuf && *BegLine != '\n') {
  532. BegLine -= 1;
  533. }
  534. if (*BegLine == '\n') {
  535. BegLine += 1;
  536. }
  537. }
  538. printf( "%.*s\n", EndLine - BegLine, BegLine );
  539. } else {
  540. printf( "Matched \"%c%s\", replace with \"%s\"\n",
  541. c,
  542. LiteralStrings[ i ],
  543. p1
  544. );
  545. }
  546. }
  547. fflush( stdout );
  548. }
  549. Changes++;
  550. while (*p1) {
  551. if (NewSize--) {
  552. *NewBuf++ = *p1++;
  553. } else {
  554. return( -1 );
  555. }
  556. }
  557. c = '\0';
  558. break;
  559. }
  560. }
  561. }
  562. } else {
  563. p = NULL;
  564. }
  565. if (SymbolsInserted && (p == NULL) && iscsymf( c )) {
  566. BegLine = OldBuf - 1;
  567. Identifier = IdentifierBuffer;
  568. k = sizeof( IdentifierBuffer ) - 1;
  569. while (iscsym( c )) {
  570. if (k) {
  571. *Identifier++ = c;
  572. k--;
  573. } else {
  574. break;
  575. }
  576. if (OldSize--) {
  577. c = *OldBuf++;
  578. } else {
  579. // OldSize will get updated below...
  580. c = '\0';
  581. }
  582. }
  583. c = '\0'; // No character to add to output stream
  584. --OldBuf; // Went a little too far
  585. OldSize++;
  586. *Identifier++ = 0;
  587. if (k == 0 || (Identifier = FindTokenMapping( IdentifierBuffer )) == NULL || SkipChar ) {
  588. Identifier = IdentifierBuffer;
  589. } else {
  590. if (!fRepeatMunge && !fSummary) {
  591. if (fFileOnly) {
  592. if (Changes == 0) { // Display just file name on first match
  593. printf( "%s\n", FileName );
  594. }
  595. } else {
  596. printf( "%s(%d) : ", FileName, LineNumber );
  597. if (fQuery) {
  598. EndLine = BegLine;
  599. while (*EndLine != '\0' && *EndLine != '\r' && *EndLine != '\n') {
  600. EndLine += 1;
  601. }
  602. if (*EndLine == '\0') {
  603. EndLine -= 1;
  604. }
  605. if (*EndLine == '\n') {
  606. EndLine -= 1;
  607. }
  608. if (*EndLine == '\r') {
  609. EndLine -= 1;
  610. }
  611. if (fEntireLine) {
  612. while (BegLine > OrigOldBuf && *BegLine != '\n') {
  613. BegLine -= 1;
  614. }
  615. if (*BegLine == '\n') {
  616. BegLine += 1;
  617. }
  618. }
  619. printf( "%.*s", EndLine - BegLine + 1, BegLine );
  620. } else {
  621. printf( "Matched %s replace with %s", IdentifierBuffer, Identifier );
  622. }
  623. printf( "\n" );
  624. }
  625. fflush( stdout );
  626. }
  627. Changes++;
  628. }
  629. while (*Identifier) {
  630. if (NewSize--) {
  631. *NewBuf++ = *Identifier++;
  632. } else {
  633. return( -1 );
  634. }
  635. }
  636. }
  637. if (c == '\n') {
  638. LineNumber++;
  639. }
  640. if (c != '\0') {
  641. if (NewSize--) {
  642. *NewBuf++ = c;
  643. } else {
  644. return( -1 );
  645. }
  646. } else {
  647. ImbeddedNullsStripped = TRUE;
  648. }
  649. }
  650. if (!Changes && fClean) {
  651. if (fTruncateWithCtrlZ && TruncatedByCtrlZ) {
  652. if (!fRepeatMunge && !fSummary) {
  653. printf( "%s(%d) : File truncated by Ctrl-Z\n",
  654. FileName,
  655. LineNumber
  656. );
  657. fflush( stdout );
  658. }
  659. Changes++;
  660. }
  661. if (fRemoveImbeddedNulls && ImbeddedNullsStripped) {
  662. if (!fRepeatMunge && !fSummary) {
  663. printf( "%s(%d) : Imbedded null characters removed.\n",
  664. FileName,
  665. LineNumber
  666. );
  667. fflush( stdout );
  668. }
  669. Changes++;
  670. }
  671. if (fRemoveDuplicateCR && DuplicateCRStripped) {
  672. if (!fRepeatMunge && !fSummary) {
  673. printf( "%s(%d) : Duplicate Carriage returns removed.\n",
  674. FileName,
  675. LineNumber
  676. );
  677. fflush( stdout );
  678. }
  679. Changes++;
  680. }
  681. }
  682. *FinalNewSize = MaxNewSize - NewSize;
  683. return( Changes );
  684. }
  685. typedef struct _MUNGED_LIST_ELEMENT {
  686. struct _MUNGED_LIST_ELEMENT *Next;
  687. char *FileName;
  688. int NumberOfChanges;
  689. } MUNGED_LIST_ELEMENT, *PMUNGED_LIST_ELEMENT;
  690. PMUNGED_LIST_ELEMENT MungedListHead;
  691. BOOL
  692. RememberMunge(
  693. char *FileName,
  694. int NumberOfChanges
  695. );
  696. BOOL
  697. CheckIfMungedAlready(
  698. char *FileName
  699. );
  700. void
  701. DumpMungedList( void );
  702. BOOL
  703. RememberMunge(
  704. char *FileName,
  705. int NumberOfChanges
  706. )
  707. {
  708. PMUNGED_LIST_ELEMENT p;
  709. p = (PMUNGED_LIST_ELEMENT)malloc( sizeof( *p ) + strlen( FileName ) + 4 );
  710. if (p == NULL) {
  711. return FALSE;
  712. }
  713. p->FileName = (char *)(p + 1);
  714. strcpy( p->FileName, FileName );
  715. p->NumberOfChanges = NumberOfChanges;
  716. p->Next = MungedListHead;
  717. MungedListHead = p;
  718. return TRUE;
  719. }
  720. BOOL
  721. CheckIfMungedAlready(
  722. char *FileName
  723. )
  724. {
  725. PMUNGED_LIST_ELEMENT p;
  726. p = MungedListHead;
  727. while (p) {
  728. if (!strcmp( FileName, p->FileName )) {
  729. return TRUE;
  730. }
  731. p = p->Next;
  732. }
  733. return FALSE;
  734. }
  735. void
  736. DumpMungedList( void )
  737. {
  738. PMUNGED_LIST_ELEMENT p, p1;
  739. if (!fSummary) {
  740. return;
  741. }
  742. p = MungedListHead;
  743. while (p) {
  744. p1 = p;
  745. printf( "%u changes made to the file %s(1).\n", p->NumberOfChanges, p->FileName );
  746. p = p->Next;
  747. free( (char *)p1 );
  748. }
  749. }
  750. void
  751. DoFile( p )
  752. char *p;
  753. {
  754. int fh, n;
  755. unsigned long oldSize;
  756. unsigned long newSize;
  757. int count, rc;
  758. char newName[ 128 ];
  759. char bakName[ 128 ];
  760. char CommandLine[ 192 ];
  761. char *s, *CurrentDirectory;
  762. DWORD dwFileAttributes;
  763. int fRepeatMunge;
  764. if (CheckIfMungedAlready( p )) {
  765. return;
  766. }
  767. if (fVerbose)
  768. fprintf( stderr, "Scanning %s\n", p );
  769. strcpy( &newName[ 0 ], p );
  770. strcpy( &bakName[ 0 ], p );
  771. for (n = strlen( &newName[ 0 ] )-1; n > 0; n--) {
  772. if (newName[ n ] == '.') {
  773. break;
  774. } else
  775. if (newName[ n ] == '\\') {
  776. n = 0;
  777. break;
  778. }
  779. }
  780. if (n == 0) {
  781. n = strlen( &newName[ 0 ] );
  782. }
  783. strcpy( &newName[ n ], ".mge" );
  784. strcpy( &bakName[ n ], ".bak" );
  785. fRepeatMunge = FALSE;
  786. RepeatMunge:
  787. if ( (fh = _open( p, O_BINARY )) == -1) {
  788. fprintf( stderr, "%s - unable to open\n", p );
  789. return;
  790. }
  791. oldSize = _lseek( fh, 0L, 2 );
  792. if (_lseek( fh, 0L, 0 ) == -1) {
  793. fprintf(stderr, "%s - unable to seek to start of file\n", p);
  794. _close(fh);
  795. return;
  796. }
  797. count = 0;
  798. if (oldSize > MAXFILESIZE)
  799. fprintf( stderr, "%s - file too large (%ld)\n", p, oldSize );
  800. else
  801. if (!myread( fh, oldSize )) {
  802. if (oldSize != 0) {
  803. fprintf( stderr, "%s - error while reading\n", p );
  804. }
  805. } else {
  806. count = MungeFile( fRepeatMunge,
  807. p,
  808. InputFileBuf,
  809. oldSize,
  810. OutputFileBuf,
  811. MAXFILESIZE,
  812. (unsigned long *)&newSize
  813. );
  814. if (count == -1)
  815. fprintf( stderr, "%s - output buffer overflow", p );
  816. UnmapViewOfFile( InputFileBuf );
  817. }
  818. _close( fh );
  819. if (count > 0) {
  820. if (fRepeatMunge) {
  821. fprintf( stderr, " - munge again" );
  822. } else {
  823. dwFileAttributes = GetFileAttributes( p );
  824. fprintf( stderr, "%s", p );
  825. }
  826. if (!fQuery && _access( p, 2 ) == -1) {
  827. if (!(fUseSLM || fUseAttrib)) {
  828. fprintf( stderr, "%s - write protected, unable to apply changes\n", p );
  829. return;
  830. }
  831. if (fRepeatMunge) {
  832. fprintf( stderr, " - %s failed, %s still write-protected\n",
  833. fUseSLM ? "OUT" : "ATTRIB", p );
  834. printf( "%s(1) : UNABLE TO RUN %s command.\n", p, fUseSLM ? "OUT" : "ATTRIB" );
  835. fflush( stdout );
  836. return;
  837. }
  838. s = p + strlen( p );
  839. while (s > p) {
  840. if (*--s == '\\') {
  841. *s++ = '\0';
  842. break;
  843. }
  844. }
  845. if (s != p) {
  846. CurrentDirectory = PushCurrentDirectory( p );
  847. } else {
  848. CurrentDirectory = NULL;
  849. }
  850. if (fUseAttrib) {
  851. fprintf( stderr, " - ATTRIB -r" );
  852. if (SetFileAttributes( s,
  853. dwFileAttributes & ~(FILE_ATTRIBUTE_READONLY |
  854. FILE_ATTRIBUTE_HIDDEN |
  855. FILE_ATTRIBUTE_SYSTEM
  856. )
  857. )
  858. ) {
  859. } else {
  860. if (CurrentDirectory) {
  861. s[-1] = '\\';
  862. }
  863. fprintf( stderr, " - failed (rc == %d), %s still write-protected\n",
  864. GetLastError(), p );
  865. printf( "%s(1) : UNABLE TO MAKE WRITABLE\n", p );
  866. fflush( stdout );
  867. return;
  868. }
  869. } else {
  870. sprintf( CommandLine, "out %s%s", fForceSLM ? "-z " : "", s );
  871. fprintf( stderr, " - check out" );
  872. fflush( stdout );
  873. fflush( stderr );
  874. rc = system( CommandLine );
  875. if (rc == -1) {
  876. if (CurrentDirectory) {
  877. s[-1] = '\\';
  878. }
  879. fprintf( stderr, " - OUT failed (rc == %d), %s still write-protected\n", errno, p );
  880. printf( "%s(1) : UNABLE TO CHECK OUT\n", p );
  881. fflush( stdout );
  882. return;
  883. }
  884. }
  885. GetCurrentDirectory( sizeof( CommandLine ), CommandLine );
  886. if (CurrentDirectory) {
  887. PopCurrentDirectory( CurrentDirectory );
  888. s[-1] = '\\';
  889. }
  890. if (fUseSLM && UndoScriptFile != NULL) {
  891. if (!(UndoCurDirCount++ % 8)) {
  892. if (UndoCurDirCount == 1) {
  893. fprintf( UndoScriptFile, "\ncd %s", CommandLine );
  894. }
  895. fprintf( UndoScriptFile, "\nin -vi" );
  896. }
  897. fprintf( UndoScriptFile, " %s", s );
  898. fflush( UndoScriptFile );
  899. }
  900. fRepeatMunge = TRUE;
  901. goto RepeatMunge;
  902. } else
  903. if (!fQuery && _access( p, 2 ) != -1 && fUseSLM && !fRepeatMunge) {
  904. if (!fSummary) {
  905. printf( "%s(1) : FILE ALREADY CHECKED OUT\n", p );
  906. fflush( stdout );
  907. }
  908. }
  909. RememberMunge( p, count );
  910. if (fQuery) {
  911. fprintf( stderr, " [%d potential changes]\n", count );
  912. } else {
  913. if ( (fh = _creat( newName, S_IWRITE | S_IREAD )) == -1 )
  914. fprintf( stderr, " - unable to create new version (%s)\n",
  915. newName );
  916. else
  917. if (mywrite( fh, OutputFileBuf, newSize ) != newSize) {
  918. fprintf( stderr, " - error while writing\n" );
  919. _close( fh );
  920. _unlink( newName );
  921. } else {
  922. _close( fh );
  923. if (fTrustMe) {
  924. _unlink( p );
  925. } else {
  926. if (_access( bakName, 0 ) == 0) {
  927. _unlink( bakName );
  928. }
  929. if (rename( p, bakName )) {
  930. fprintf( stderr, "MUNGE: rename %s to %s failed\n",
  931. p, bakName );
  932. return;
  933. }
  934. }
  935. if (rename( newName, p )) {
  936. fprintf( stderr, "MUNGE: rename %s to %s failed\n",
  937. newName, p );
  938. } else {
  939. if (fRepeatMunge && fUseAttrib) {
  940. SetFileAttributes( p, dwFileAttributes );
  941. } else {
  942. fprintf( stderr, "\n" );
  943. }
  944. RememberMunge( p, count );
  945. }
  946. }
  947. }
  948. }
  949. }
  950. void
  951. DoFiles(
  952. char *p,
  953. struct findType *b,
  954. void *Args
  955. )
  956. {
  957. int SaveCurDirCount;
  958. char *s;
  959. unsigned long i;
  960. int FileProcessed;
  961. if (strcmp ((const char *)b->fbuf.cFileName, ".") &&
  962. strcmp ((const char *)b->fbuf.cFileName, "..") &&
  963. strcmp ((const char *)b->fbuf.cFileName, "slm.dif")
  964. ) {
  965. if (HASATTR(b->fbuf.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY)) {
  966. switch (p[strlen(p)-1]) {
  967. case '/':
  968. case '\\': strcat (p, "*.*"); break;
  969. default: strcat (p, "\\*.*");
  970. }
  971. if (fRecurse) {
  972. fprintf( stderr, "Scanning %s\n", p );
  973. SaveCurDirCount = UndoCurDirCount;
  974. UndoCurDirCount = 0;
  975. forfile( p,
  976. FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN ,
  977. DoFiles,
  978. NULL
  979. );
  980. if (UndoScriptFile != NULL) {
  981. if (UndoCurDirCount != 0) {
  982. fprintf( UndoScriptFile, "\n" );
  983. fflush( UndoScriptFile );
  984. UndoCurDirCount = 0;
  985. } else {
  986. UndoCurDirCount = SaveCurDirCount;
  987. }
  988. }
  989. }
  990. } else {
  991. s = _strlwr( (char *)b->fbuf.cFileName );
  992. while (*s != '.') {
  993. if (*s == '\0') {
  994. break;
  995. } else {
  996. s++;
  997. }
  998. }
  999. FileProcessed = FALSE;
  1000. if (*s) {
  1001. if (!strcmp( s, "mge" ) || !strcmp( s, "bak" )) {
  1002. FileProcessed = TRUE;
  1003. } else {
  1004. for (i=0; i<NumberOfFileExtensions; i++) {
  1005. if (!strcmp( FileExtensions[ i ], s+1 )) {
  1006. FileProcessed = TRUE;
  1007. DoFile( p );
  1008. break;
  1009. }
  1010. }
  1011. }
  1012. if (!FileProcessed) {
  1013. *s = '\0';
  1014. for (i=0; i<NumberOfFileNames; i++) {
  1015. if (!strcmp( FileNames[ i ], (const char *)b->fbuf.cFileName )) {
  1016. FileProcessed = TRUE;
  1017. DoFile( p );
  1018. break;
  1019. }
  1020. }
  1021. *s = '.';
  1022. }
  1023. } else {
  1024. for (i=0; i<NumberOfFileNames; i++) {
  1025. if (!strcmp( FileNames[ i ], (const char *)b->fbuf.cFileName )) {
  1026. FileProcessed = TRUE;
  1027. DoFile( p );
  1028. break;
  1029. }
  1030. }
  1031. }
  1032. if (!FileProcessed) {
  1033. for (i=0; i<NumberOfFileNameAndExts; i++) {
  1034. if (!strcmp( FileNameAndExts[ i ], (const char *)b->fbuf.cFileName )) {
  1035. FileProcessed = TRUE;
  1036. DoFile( p );
  1037. break;
  1038. }
  1039. }
  1040. }
  1041. }
  1042. }
  1043. Args;
  1044. }
  1045. void
  1046. Usage( char *MsgFmt, int MsgArg )
  1047. {
  1048. fputs("usage: munge scriptFile [-q [-e] [-o]] [-v] [-i] [-k] [-r] [-c [-m] [-z] [-@]]\n"
  1049. " [-n] [-l | -L] [-a | -s [-f]] [-u undoFileName]\n"
  1050. " filesToMunge...\n"
  1051. "Where...\n"
  1052. " -q\tQuery only - don't actually make changes.\n"
  1053. " -e\tQuery only - display entire line for each match\n"
  1054. " -o\tQuery only - just display filename once on first match\n"
  1055. " -v\tVerbose - show files being scanned\n"
  1056. " -i\tJust output summary of files changed at end\n"
  1057. " -k\tCase - Case sensitive scriptFile\n"
  1058. " -r\tRecurse.\n"
  1059. " -c\tIf no munge of file, then check for cleanlyness\n"
  1060. " -m\tCollapse multiple carriage returns into one\n"
  1061. " -z\tCtrl-Z will truncate file\n"
  1062. " -@\tRemove null characters\n"
  1063. " -n\tNeuter - Surround all strings with TEXT()\n"
  1064. " -l\tLiterals - process any quoted text (includes comments too)\n"
  1065. " -L\tLiterals - process any quoted text (excludes comments)\n"
  1066. " -s\tUse OUT command command for files that are readonly\n"
  1067. " -a\tUse ATTRIB -r command for files that are readonly\n"
  1068. " -f\tUse -z flag for SLM OUT command\n"
  1069. " -t\tTrust me and dont create .bak files\n"
  1070. " -u\tGenerate an undo script file for any SLM OUT commands invoked.\n"
  1071. " -?\tGets you this message\n\n"
  1072. "and scriptFile lines take any of the following forms:\n\n"
  1073. " oldName newName\n"
  1074. " \"oldString\" \"newString\"\n"
  1075. " -F .Ext Name. Name.Ext\n\n"
  1076. "Where...\n"
  1077. " oldName and newName following C Identifier rules\n"
  1078. " oldString and newString are arbitrary text strings\n"
  1079. " -F limits the munge to files that match:\n"
  1080. " a particular extension (.Ext)\n"
  1081. " a particular name (Name.)\n"
  1082. " a particular name and extension (Name.Ext)\n"
  1083. " If no -F line is seen in the scriptFile, then\n"
  1084. " the following is the default:\n"
  1085. " -F .asm .bat .c .cli .cpp .cxx .def .dlg .h .htm .hpj .hxx .idl .inc\n"
  1086. " -F .inf .lic .mak .mc .odl .rc .rcv .reg .s .src .srv .tk .w .x\n"
  1087. " -F makefil0 makefile sources\n",
  1088. stderr);
  1089. if (MsgFmt != NULL) {
  1090. fprintf( stderr, "\n" );
  1091. fprintf( stderr, MsgFmt, MsgArg );
  1092. fprintf( stderr, "\n" );
  1093. }
  1094. exit( 1 );
  1095. }
  1096. int
  1097. __cdecl
  1098. main(
  1099. int argc,
  1100. char *argv[]
  1101. )
  1102. {
  1103. int i;
  1104. char *s, pathBuf[ 64 ];
  1105. int FileArgsSeen = 0;
  1106. ConvertAppToOem( argc, argv );
  1107. if (argc < 3) {
  1108. Usage( NULL, 0 );
  1109. }
  1110. if ( !InitTokenMappingTable()) {
  1111. fprintf( stderr, "MUNGE: Unable to create symbol table\n" );
  1112. exit( 1 );
  1113. }
  1114. OutputFileBuf = (char *)VirtualAlloc( NULL,
  1115. MAXFILESIZE,
  1116. MEM_COMMIT,
  1117. PAGE_READWRITE
  1118. );
  1119. if ( OutputFileBuf == NULL) {
  1120. fprintf( stderr, "not enough memory\n" );
  1121. exit( 1 );
  1122. }
  1123. fClean = FALSE;
  1124. fRemoveDuplicateCR = FALSE;
  1125. fRemoveImbeddedNulls = FALSE;
  1126. fTruncateWithCtrlZ = FALSE;
  1127. fQuery = FALSE;
  1128. fFileOnly = FALSE;
  1129. fRecurse = FALSE;
  1130. fUseAttrib = FALSE;
  1131. fUseSLM = FALSE;
  1132. fForceSLM = FALSE;
  1133. fTrustMe = FALSE;
  1134. fVerbose = FALSE;
  1135. UndoScriptFileName = NULL;
  1136. UndoScriptFile = NULL;
  1137. fSummary = FALSE;
  1138. fInsideQuotes = FALSE;
  1139. fInsideComments = FALSE;
  1140. fNeuter = FALSE;
  1141. fEntireLine = FALSE;
  1142. for (i=2; i<argc; i++) {
  1143. s = argv[ i ];
  1144. if (*s == '-' || *s == '/') {
  1145. while (*++s) {
  1146. switch ( tolower( *s ) ) {
  1147. case 'm': fRemoveDuplicateCR = TRUE; break;
  1148. case '@': fRemoveImbeddedNulls = TRUE; break;
  1149. case 'z': fTruncateWithCtrlZ = TRUE; break;
  1150. case 'c': fClean = TRUE; break;
  1151. case 'q': fQuery = TRUE; break;
  1152. case 'o': fFileOnly = TRUE; break;
  1153. case 'r': fRecurse = TRUE; break;
  1154. case 'a': fUseAttrib = TRUE; break;
  1155. case 's': fUseSLM = TRUE; break;
  1156. case 'f': fForceSLM = TRUE; break;
  1157. case 't': fTrustMe = TRUE; break;
  1158. case 'v': fVerbose = TRUE; break;
  1159. case 'i': fSummary = TRUE; break;
  1160. case 'l': if (*s != 'L') fInsideComments = TRUE;
  1161. fInsideQuotes = TRUE; break;
  1162. case 'n': fNeuter = TRUE; fInsideQuotes = FALSE; break;
  1163. case 'k': fCaseSensitive = TRUE; break;
  1164. case 'e': fEntireLine = TRUE; break;
  1165. case 'u': UndoScriptFileName = argv[ ++i ];
  1166. break;
  1167. default: Usage( "invalid switch - '%c'", *s );
  1168. }
  1169. }
  1170. } else {
  1171. if ((fFileOnly | fEntireLine) && !fQuery) {
  1172. Usage( "-e or -o invalid without -q", 0 );
  1173. }
  1174. if (fQuery && (fClean ||
  1175. fRemoveDuplicateCR ||
  1176. fRemoveImbeddedNulls ||
  1177. fTruncateWithCtrlZ ||
  1178. fUseSLM ||
  1179. fForceSLM ||
  1180. fTrustMe ||
  1181. UndoScriptFile ||
  1182. fNeuter
  1183. )
  1184. ) {
  1185. Usage( "-q valid only with -e or -o", 0 );
  1186. }
  1187. if (fClean &&
  1188. !fRemoveDuplicateCR &&
  1189. !fRemoveImbeddedNulls &&
  1190. !fTruncateWithCtrlZ
  1191. ) {
  1192. Usage( "-c requires at least one of -m, -z or -@", 0 );
  1193. }
  1194. if (UndoScriptFileName != NULL) {
  1195. if (!fUseSLM) {
  1196. Usage ("-u invalid with -s", 0 );
  1197. } else {
  1198. UndoScriptFile = fopen( UndoScriptFileName, "w" );
  1199. if (UndoScriptFile == NULL) {
  1200. fprintf( stderr, "Unable to open %s\n", UndoScriptFileName );
  1201. exit( 1 );
  1202. }
  1203. }
  1204. }
  1205. if (!FileArgsSeen++) {
  1206. if (!ReadScriptFile( argv[ 1 ] )) {
  1207. fprintf( stderr, "Invalid script file - %s\n", argv[ 1 ] );
  1208. exit( 1 );
  1209. }
  1210. if (fVerbose) {
  1211. DisplayFilePatterns();
  1212. }
  1213. }
  1214. if (GetFileAttributes( s ) & FILE_ATTRIBUTE_DIRECTORY) {
  1215. s = strcpy( pathBuf, s );
  1216. switch (s[strlen(s)-1]) {
  1217. case '/':
  1218. case '\\': strcat (s, "*.*"); break;
  1219. default: strcat (s, "\\*.*");
  1220. }
  1221. fprintf( stderr, "Scanning %s\n", s );
  1222. UndoCurDirCount = 0;
  1223. forfile( s,
  1224. FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN ,
  1225. DoFiles,
  1226. NULL
  1227. );
  1228. } else {
  1229. UndoCurDirCount = 0;
  1230. DoFile( s );
  1231. }
  1232. }
  1233. }
  1234. if (FileArgsSeen == 0) {
  1235. if (!ReadScriptFile( argv[ 1 ] )) {
  1236. fprintf( stderr, "Invalid script file - %s\n", argv[ 1 ] );
  1237. exit( 1 );
  1238. }
  1239. if (fVerbose) {
  1240. DisplayFilePatterns();
  1241. }
  1242. s = "*.*";
  1243. fprintf( stderr, "Scanning %s\n", s );
  1244. UndoCurDirCount = 0;
  1245. forfile( s,
  1246. FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN ,
  1247. DoFiles,
  1248. NULL
  1249. );
  1250. }
  1251. if (UndoScriptFile != NULL) {
  1252. if (UndoCurDirCount != 0) {
  1253. fprintf( UndoScriptFile, "\n" );
  1254. }
  1255. fclose( UndoScriptFile );
  1256. }
  1257. DumpMungedList();
  1258. return( 0 );
  1259. }
  1260. void
  1261. DisplayFilePatterns( void )
  1262. {
  1263. unsigned long i;
  1264. if (NumberOfFileExtensions) {
  1265. fprintf( stderr, "Munge will look at files with the following extensions:\n " );
  1266. for (i=0; i<NumberOfFileExtensions; i++) {
  1267. fprintf( stderr, " %s", FileExtensions[ i ] );
  1268. }
  1269. fprintf( stderr, "\n" );
  1270. }
  1271. if (NumberOfFileNames) {
  1272. fprintf( stderr, "Munge will look at files with the following names:\n " );
  1273. for (i=0; i<NumberOfFileNames; i++) {
  1274. fprintf( stderr, " %s", FileNames[ i ] );
  1275. }
  1276. fprintf( stderr, "\n" );
  1277. }
  1278. if (NumberOfFileNameAndExts) {
  1279. fprintf( stderr, "Munge will look at files with the following name and extensions:\n " );
  1280. for (i=0; i<NumberOfFileNameAndExts; i++) {
  1281. fprintf( stderr, " %s", FileNameAndExts[ i ] );
  1282. }
  1283. fprintf( stderr, "\n" );
  1284. }
  1285. }
  1286. char *
  1287. PushCurrentDirectory(
  1288. char *NewCurrentDirectory
  1289. )
  1290. {
  1291. char *OldCurrentDirectory;
  1292. if (OldCurrentDirectory = malloc( MAX_PATH )) {
  1293. GetCurrentDirectory( MAX_PATH, OldCurrentDirectory );
  1294. SetCurrentDirectory( NewCurrentDirectory );
  1295. } else {
  1296. fprintf( stderr,
  1297. "MUNGE: (Fatal Error) PushCurrentDirectory out of memory\n"
  1298. );
  1299. exit( 16 );
  1300. }
  1301. return( OldCurrentDirectory );
  1302. }
  1303. void
  1304. PopCurrentDirectory(
  1305. char *OldCurrentDirectory
  1306. )
  1307. {
  1308. if (OldCurrentDirectory) {
  1309. SetCurrentDirectory( OldCurrentDirectory );
  1310. free( OldCurrentDirectory );
  1311. }
  1312. }
  1313. PVOID SymbolTableHandle;
  1314. BOOL
  1315. InitTokenMappingTable( void )
  1316. {
  1317. NTSTATUS Status;
  1318. Status = CreateSymbolTable( 257, 0x20000, &SymbolTableHandle );
  1319. if (NT_SUCCESS( Status )) {
  1320. return TRUE;
  1321. } else {
  1322. return FALSE;
  1323. }
  1324. }
  1325. BOOL
  1326. SaveTokenMapping(
  1327. char *String,
  1328. char *Value
  1329. )
  1330. {
  1331. NTSTATUS Status;
  1332. ANSI_STRING AnsiString;
  1333. UNICODE_STRING SymbolName;
  1334. ULONG_PTR SymbolValue;
  1335. RtlInitString( &AnsiString, String );
  1336. Status = RtlAnsiStringToUnicodeString( &SymbolName, &AnsiString, TRUE );
  1337. if (!NT_SUCCESS( Status )) {
  1338. return FALSE;
  1339. }
  1340. SymbolValue = (ULONG_PTR)Value;
  1341. Status = AddSymbolToSymbolTable( SymbolTableHandle,
  1342. &SymbolName,
  1343. &SymbolValue
  1344. );
  1345. RtlFreeUnicodeString( &SymbolName );
  1346. if (NT_SUCCESS( Status )) {
  1347. return TRUE;
  1348. } else {
  1349. return FALSE;
  1350. }
  1351. }
  1352. char *
  1353. FindTokenMapping(
  1354. char *String
  1355. )
  1356. {
  1357. NTSTATUS Status;
  1358. ANSI_STRING AnsiString;
  1359. UNICODE_STRING SymbolName;
  1360. ULONG_PTR SymbolValue;
  1361. RtlInitString( &AnsiString, String );
  1362. Status = RtlAnsiStringToUnicodeString( &SymbolName, &AnsiString, TRUE );
  1363. if (!NT_SUCCESS( Status )) {
  1364. return NULL;
  1365. }
  1366. Status = LookupSymbolInSymbolTable( SymbolTableHandle,
  1367. &SymbolName,
  1368. &SymbolValue
  1369. );
  1370. RtlFreeUnicodeString( &SymbolName );
  1371. if (NT_SUCCESS( Status )) {
  1372. return (char *)SymbolValue;
  1373. } else {
  1374. return NULL;
  1375. }
  1376. }
  1377. typedef struct _SYMBOL_TABLE_ENTRY {
  1378. struct _SYMBOL_TABLE_ENTRY *HashLink;
  1379. ULONG_PTR Value;
  1380. UNICODE_STRING Name;
  1381. } SYMBOL_TABLE_ENTRY, *PSYMBOL_TABLE_ENTRY;
  1382. typedef struct _SYMBOL_TABLE {
  1383. ULONG NumberOfBuckets;
  1384. PSYMBOL_TABLE_ENTRY Buckets[1];
  1385. } SYMBOL_TABLE, *PSYMBOL_TABLE;
  1386. NTSTATUS
  1387. CreateSymbolTable(
  1388. IN ULONG NumberOfBuckets,
  1389. IN ULONG MaxSymbolTableSize,
  1390. OUT PVOID *SymbolTableHandle
  1391. )
  1392. {
  1393. NTSTATUS Status = STATUS_SUCCESS;
  1394. PSYMBOL_TABLE p;
  1395. ULONG Size;
  1396. RtlLockHeap( GetProcessHeap() );
  1397. if (*SymbolTableHandle == NULL) {
  1398. Size = sizeof( SYMBOL_TABLE ) +
  1399. (sizeof( SYMBOL_TABLE_ENTRY ) * (NumberOfBuckets-1));
  1400. p = (PSYMBOL_TABLE)RtlAllocateHeap( GetProcessHeap(), 0, Size );
  1401. if (p == NULL) {
  1402. Status = STATUS_NO_MEMORY;
  1403. } else {
  1404. RtlZeroMemory( p, Size );
  1405. p->NumberOfBuckets = NumberOfBuckets;
  1406. *SymbolTableHandle = p;
  1407. }
  1408. }
  1409. RtlUnlockHeap( GetProcessHeap() );
  1410. return( Status );
  1411. }
  1412. PSYMBOL_TABLE_ENTRY
  1413. BasepHashStringToSymbol(
  1414. IN PSYMBOL_TABLE p,
  1415. IN PUNICODE_STRING Name,
  1416. OUT PSYMBOL_TABLE_ENTRY **PreviousSymbol
  1417. )
  1418. {
  1419. ULONG n, Hash;
  1420. WCHAR c;
  1421. PWCH s;
  1422. PSYMBOL_TABLE_ENTRY *pps, ps;
  1423. n = Name->Length / sizeof( c );
  1424. s = Name->Buffer;
  1425. if ( fCaseSensitive ) {
  1426. Hash = 0;
  1427. while (n--) {
  1428. c = *s++;
  1429. Hash = Hash + (c << 1) + (c >> 1) + c;
  1430. }
  1431. } else {
  1432. Hash = 0;
  1433. while (n--) {
  1434. c = RtlUpcaseUnicodeChar( *s++ );
  1435. Hash = Hash + (c << 1) + (c >> 1) + c;
  1436. }
  1437. }
  1438. pps = &p->Buckets[ Hash % p->NumberOfBuckets ];
  1439. while (ps = *pps) {
  1440. if (RtlEqualUnicodeString( &ps->Name, Name, (BOOLEAN)!fCaseSensitive )) {
  1441. break;
  1442. } else {
  1443. pps = &ps->HashLink;
  1444. }
  1445. }
  1446. *PreviousSymbol = pps;
  1447. return( ps );
  1448. }
  1449. NTSTATUS
  1450. AddSymbolToSymbolTable(
  1451. IN PVOID SymbolTableHandle,
  1452. IN PUNICODE_STRING SymbolName,
  1453. IN ULONG_PTR * SymbolValue OPTIONAL
  1454. )
  1455. {
  1456. NTSTATUS Status;
  1457. PSYMBOL_TABLE p = (PSYMBOL_TABLE)SymbolTableHandle;
  1458. PSYMBOL_TABLE_ENTRY ps, *pps;
  1459. ULONG_PTR Value;
  1460. if (ARGUMENT_PRESENT( SymbolValue )) {
  1461. Value = *SymbolValue;
  1462. } else {
  1463. Value = 0;
  1464. }
  1465. Status = STATUS_SUCCESS;
  1466. RtlLockHeap( GetProcessHeap() );
  1467. try {
  1468. ps = BasepHashStringToSymbol( p, SymbolName, &pps );
  1469. if (ps == NULL) {
  1470. ps = RtlAllocateHeap( GetProcessHeap(), 0, (sizeof( *ps ) + SymbolName->Length) );
  1471. if (ps != NULL) {
  1472. ps->HashLink = NULL;
  1473. ps->Value = Value;
  1474. ps->Name.Buffer = (PWSTR)(ps + 1);
  1475. ps->Name.Length = SymbolName->Length;
  1476. ps->Name.MaximumLength = (USHORT)(SymbolName->Length + sizeof( UNICODE_NULL ));
  1477. RtlMoveMemory( ps->Name.Buffer, SymbolName->Buffer, SymbolName->Length );
  1478. *pps = ps;
  1479. } else {
  1480. Status = STATUS_NO_MEMORY;
  1481. }
  1482. }
  1483. else {
  1484. Status = STATUS_OBJECT_NAME_EXISTS;
  1485. }
  1486. }
  1487. except (EXCEPTION_EXECUTE_HANDLER) {
  1488. Status = GetExceptionCode();
  1489. }
  1490. RtlUnlockHeap( GetProcessHeap() );
  1491. return( Status );
  1492. }
  1493. NTSTATUS
  1494. LookupSymbolInSymbolTable(
  1495. IN PVOID SymbolTableHandle,
  1496. IN PUNICODE_STRING SymbolName,
  1497. OUT ULONG_PTR *SymbolValue OPTIONAL
  1498. )
  1499. {
  1500. NTSTATUS Status;
  1501. PSYMBOL_TABLE p = (PSYMBOL_TABLE)SymbolTableHandle;
  1502. PSYMBOL_TABLE_ENTRY ps, *pps;
  1503. ULONG_PTR Value;
  1504. RtlLockHeap( GetProcessHeap() );
  1505. try {
  1506. ps = BasepHashStringToSymbol( p, SymbolName, &pps );
  1507. if (ps == NULL) {
  1508. Status = STATUS_OBJECT_NAME_NOT_FOUND;
  1509. Value = 0;
  1510. } else {
  1511. Status = STATUS_SUCCESS;
  1512. Value = ps->Value;
  1513. }
  1514. }
  1515. except (EXCEPTION_EXECUTE_HANDLER) {
  1516. Status = GetExceptionCode();
  1517. }
  1518. RtlUnlockHeap( GetProcessHeap() );
  1519. if (NT_SUCCESS( Status )) {
  1520. if (ARGUMENT_PRESENT( SymbolValue )) {
  1521. *SymbolValue = Value;
  1522. }
  1523. }
  1524. return( Status );
  1525. }