Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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