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.

880 lines
24 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. gensrv.c
  5. Abstract:
  6. This module implements a program which generates the system service
  7. dispatch table that is used by the trap handler and the system service
  8. stub procedures which are used to call the services. These files are
  9. both generated as text files that must be run through the assembler
  10. to produce the actual files.
  11. This program can also be used to generate the user mode system service
  12. stub procedures.
  13. If the -P switch is provided, it will also generate Profile
  14. in the user mode system service stub procedures.
  15. Author:
  16. David N. Cutler (davec) 29-Apr-1989
  17. Environment:
  18. User mode.
  19. Revision History:
  20. Russ Blake (russbl) 23-Apr-1991 - add Profile switch
  21. --*/
  22. #include <windows.h>
  23. #include <stdlib.h>
  24. #include <stdio.h>
  25. #include <string.h>
  26. CHAR InputFileNameBuffer[ 128 ];
  27. CHAR StubFileNameBuffer[ 128 ];
  28. CHAR TableFileNameBuffer[ 128 ];
  29. CHAR StubHeaderNameBuffer[ 128 ];
  30. CHAR TableHeaderNameBuffer[ 128 ];
  31. CHAR ProfFileNameBuffer[ 128 ];
  32. CHAR ProfHeaderNameBuffer[ 128 ];
  33. CHAR ProfDotHFileNameBuffer[ 128 ];
  34. CHAR ProfIncFileNameBuffer[ 128 ];
  35. CHAR ProfTblFileNameBuffer[ 128 ];
  36. CHAR InputRecord[132];
  37. CHAR OutputRecord[132];
  38. #define GENSRV_MAXSERVICES 1000
  39. CHAR MemoryArgs[GENSRV_MAXSERVICES];
  40. CHAR ErrorReturns[GENSRV_MAXSERVICES];
  41. // Increment this everytime a change to this file is made
  42. #define GENSRV_VERSION "1.3"
  43. #define GENSRV_MACRONAME "STUBS_ENTRY%d"
  44. #define GENSRV_MACROARGS " %d, %s, %d"
  45. PCHAR UsrStbsFmtMacroName = "USR" GENSRV_MACRONAME;
  46. #define USRSTUBS_MAXARGS 8
  47. PCHAR SysStbsFmtMacroName = "SYS" GENSRV_MACRONAME;
  48. PCHAR StbFmtMacroArgs = GENSRV_MACROARGS;
  49. PCHAR TableEntryFmtNB = "TABLE_ENTRY %s, %d, %d \n";
  50. PCHAR TableEntryFmtB = "TABLE_ENTRY( %s, %d, %d )\n";
  51. PCHAR TableEntryFmt;
  52. PCHAR ProfTblFmt = "\t\t\"%s\",\n";
  53. PCHAR ProfDotHFmt = "#define NAP_API_COUNT %d \n";
  54. PCHAR ProfIncFmt = "NapCounterServiceNumber\tEQU\t%d\n";
  55. PCHAR ProfTblPrefixFmt = "#include <nt.h>\n\n"
  56. "PCHAR NapNames[] = {\n\t\t\"NapCalibrationData\",\n";
  57. PCHAR ProfTblSuffixFmt = "\t\t\"NapTerminalEntry\" };\n";
  58. VOID
  59. ClearArchiveBit(
  60. PCHAR FileName
  61. );
  62. SHORT ParseAndSkipShort(
  63. CHAR **ppBuffer
  64. );
  65. VOID
  66. PrintStubLine (
  67. FILE * pf,
  68. SHORT Index1,
  69. PCHAR pszMacro,
  70. SHORT ServiceNumber,
  71. SHORT ArgIndex,
  72. SHORT *Arguments,
  73. SHORT Braces);
  74. VOID
  75. GenerateTable(
  76. FILE * pf,
  77. PCHAR pszMacro,
  78. SHORT ServiceNumber,
  79. SHORT Args,
  80. SHORT Braces
  81. );
  82. int __cdecl
  83. main (argc, argv)
  84. int argc;
  85. char *argv[];
  86. {
  87. LONG InRegisterArgCount;
  88. SHORT Index1;
  89. SHORT Index2;
  90. SHORT Limit;
  91. FILE *InputFile;
  92. CHAR *Ipr;
  93. CHAR *Opr;
  94. SHORT ServiceNumber = 0;
  95. SHORT TotalArgs = 0;
  96. SHORT NapCounterServiceNumber;
  97. FILE *StubFile;
  98. FILE *TableFile;
  99. FILE *DebugFile;
  100. FILE *StubHeaderFile;
  101. FILE *TableHeaderFile;
  102. FILE *DefFile;
  103. FILE *ProfFile;
  104. FILE *ProfHeaderFile;
  105. FILE *ProfDotHFile;
  106. FILE *ProfIncFile;
  107. FILE *ProfTblFile;
  108. CHAR Terminal;
  109. CHAR *GenDirectory;
  110. CHAR *AltOutputDirectory;
  111. CHAR *StubDirectory;
  112. CHAR *InputFileName;
  113. CHAR *StubFileName = NULL;
  114. CHAR *TableFileName;
  115. CHAR *StubHeaderName = NULL;
  116. CHAR *TableHeaderName = NULL;
  117. CHAR *TargetDirectory;
  118. CHAR *TargetExtension;
  119. CHAR *DefFileData;
  120. CHAR *ProfFileName;
  121. CHAR *ProfHeaderName;
  122. CHAR *ProfDotHFileName;
  123. CHAR *ProfIncFileName;
  124. CHAR *ProfTblFileName;
  125. SHORT Braces;
  126. SHORT DispatchCount;
  127. SHORT Profile;
  128. SHORT LineStart;
  129. SHORT LineEnd;
  130. SHORT Arguments[ USRSTUBS_MAXARGS ];
  131. SHORT ArgIndex;
  132. SHORT ErrorReturnTable;
  133. if (argc == 2 && (!strcmp(argv[1],"-?") || !strcmp(argv[1],"/?"))) {
  134. PrintUsage:
  135. printf("GENSRV: System Service Dispatch Table Generator. Version " GENSRV_VERSION "\n");
  136. printf("Usage: gensrv [-d targetdir] [-e targetext] [-f defdata] [-B] [-P] [-C] [-R] [-a altoutputdir] [-s stubdir] [services.tab directory]\n");
  137. printf("-B Use braces\n");
  138. printf("-P Generate profile stubs data\n");
  139. printf("-C Spew dispatch count\n");
  140. printf("-R Generate ConvertToGui error return table\n");
  141. exit(1);
  142. }
  143. //
  144. // Determine name of target directory for output files. Requires that
  145. // the -d switch be specified and that the argument after the switch is
  146. // the target directory name. If no -d switch then defaults to "."
  147. //
  148. if (argc >= 3 && !strcmp(argv[1],"-d")) {
  149. TargetDirectory = argv[2];
  150. argc -= 2;
  151. argv += 2;
  152. } else {
  153. TargetDirectory = ".";
  154. }
  155. //
  156. // Determine name of target extension for output files. Requires that
  157. // the -e switch be specified and that the argument after the switch is
  158. // the target extension string. If no -e switch then defaults to "s"
  159. //
  160. if (argc >= 3 && !strcmp(argv[1],"-e")) {
  161. TargetExtension = argv[2];
  162. argc -= 2;
  163. argv += 2;
  164. } else {
  165. TargetExtension = "s";
  166. }
  167. //
  168. // Determine if def file data is to be generated
  169. //
  170. if (argc >= 3 && !strcmp(argv[1],"-f")) {
  171. DefFileData = argv[2];
  172. argc -= 2;
  173. argv += 2;
  174. } else {
  175. DefFileData = NULL;
  176. }
  177. //
  178. // Change default directory used for generated files.
  179. //
  180. if (argc >= 3 && !strcmp(argv[1],"-g")) {
  181. GenDirectory = argv[2];
  182. argc -= 2;
  183. argv += 2;
  184. } else {
  185. GenDirectory = ".";
  186. }
  187. //
  188. // Change name of usrstubs.s
  189. //
  190. if (argc >= 3 && !strcmp(argv[1],"-stubs")) {
  191. StubFileName = argv[2];
  192. argc -= 2;
  193. argv += 2;
  194. }
  195. //
  196. // Change name of services.stb
  197. //
  198. if (argc >= 3 && !strcmp(argv[1],"-sstb")) {
  199. StubHeaderName = argv[2];
  200. argc -= 2;
  201. argv += 2;
  202. }
  203. if (argc >= 3 && !strcmp(argv[1],"-stable")) {
  204. TableHeaderName = argv[2];
  205. argc -= 2;
  206. argv += 2;
  207. }
  208. //
  209. // Determine if braces are to be generated
  210. //
  211. if (argc >= 2 && !strcmp(argv[1],"-B")) {
  212. Braces = 1;
  213. argc -= 1;
  214. argv += 1;
  215. } else {
  216. Braces = 0;
  217. }
  218. //
  219. // Determine if services Profile stubs data is to be generated
  220. //
  221. if (argc >= 2 && !strcmp(argv[1],"-P")) {
  222. Profile = 1;
  223. argc -= 1;
  224. argv += 1;
  225. } else {
  226. Profile = 0;
  227. }
  228. //
  229. // Determine if dispatch count should be spewed
  230. //
  231. if (argc >= 2 && !strcmp(argv[1],"-C")) {
  232. DispatchCount = 1;
  233. argc -= 1;
  234. argv += 1;
  235. } else {
  236. DispatchCount = 0;
  237. }
  238. //
  239. // Determine if error return table should be generated
  240. //
  241. if (argc >= 2 && !strcmp(argv[1],"-R")) {
  242. ErrorReturnTable = 1;
  243. argc -= 1;
  244. argv += 1;
  245. } else {
  246. ErrorReturnTable = 0;
  247. }
  248. //
  249. // ALT_PROJECT output directory.
  250. //
  251. if (argc >= 3 && !strcmp(argv[1],"-a")) {
  252. AltOutputDirectory = argv[2];
  253. argc -= 2;
  254. argv += 2;
  255. } else {
  256. AltOutputDirectory = GenDirectory;
  257. }
  258. //
  259. // table.stb and services.stb directory.
  260. //
  261. if (argc >= 3 && !strcmp(argv[1],"-s")) {
  262. StubDirectory = argv[2];
  263. argc -= 2;
  264. argv += 2;
  265. } else {
  266. StubDirectory = GenDirectory;
  267. }
  268. //
  269. // Determine name of input and output files, based on the argument
  270. // to the program. If no argument other than program name, then
  271. // generate the kernel mode system service files (stubs and dispatch
  272. // table). Otherwise, expect a single argument that is the path name
  273. // of the services.tab file and produce output file(s), which
  274. // contain the user mode system service stubs (and profiled stubs if
  275. // selected.)
  276. //
  277. if (argc == 1) {
  278. if (DefFileData) {
  279. goto PrintUsage;
  280. }
  281. sprintf(InputFileName = InputFileNameBuffer,
  282. "%s\\services.tab",GenDirectory);
  283. sprintf(StubFileName = StubFileNameBuffer,
  284. "%s\\sysstubs.%s",AltOutputDirectory,TargetExtension);
  285. sprintf(TableFileName = TableFileNameBuffer,
  286. "%s\\systable.%s",AltOutputDirectory,TargetExtension);
  287. if (TableHeaderName == NULL) {
  288. sprintf(TableHeaderName = TableHeaderNameBuffer,
  289. "%s\\table.stb",StubDirectory);
  290. }
  291. if (StubHeaderName == NULL) {
  292. sprintf(StubHeaderName = StubHeaderNameBuffer,
  293. "%s\\services.stb",StubDirectory);
  294. }
  295. } else {
  296. if (argc == 2) {
  297. if (StubDirectory == GenDirectory) {
  298. StubDirectory = argv[1];
  299. }
  300. sprintf(InputFileName = InputFileNameBuffer,
  301. "%s\\services.tab",argv[1]);
  302. if (DefFileData == NULL) {
  303. if (StubFileName == NULL) {
  304. sprintf(StubFileName = StubFileNameBuffer,
  305. "%s\\usrstubs.%s",TargetDirectory,TargetExtension);
  306. }
  307. if (StubHeaderName == NULL) {
  308. sprintf(StubHeaderName = StubHeaderNameBuffer,
  309. "%s\\services.stb",StubDirectory);
  310. }
  311. if (Profile) {
  312. sprintf(ProfFileName = ProfFileNameBuffer,
  313. "%s\\napstubs.%s",TargetDirectory,TargetExtension);
  314. sprintf(ProfHeaderName = ProfHeaderNameBuffer,
  315. "%s\\%s\\services.nap",argv[1],TargetDirectory);
  316. sprintf(ProfDotHFileName = ProfDotHFileNameBuffer,
  317. ".\\ntnapdef.h");
  318. sprintf(ProfIncFileName = ProfIncFileNameBuffer,
  319. "%s\\ntnap.inc",TargetDirectory);
  320. sprintf(ProfTblFileName = ProfTblFileNameBuffer,
  321. ".\\ntnaptbl.c");
  322. }
  323. }
  324. TableFileName = NULL;
  325. } else {
  326. goto PrintUsage;
  327. }
  328. }
  329. //
  330. // Open input and output files.
  331. //
  332. InputFile = fopen(InputFileName, "r");
  333. if (!InputFile) {
  334. printf("\nfatal error Unable to open system services file %s\n", InputFileName);
  335. goto PrintUsage;
  336. }
  337. if (DefFileData == NULL) {
  338. StubFile = fopen(StubFileName, "w");
  339. if (!StubFile) {
  340. printf("\nfatal error Unable to open system services file %s\n", StubFileName);
  341. fclose(InputFile);
  342. exit(1);
  343. }
  344. StubHeaderFile = fopen(StubHeaderName, "r");
  345. if (!StubHeaderFile) {
  346. printf("\nfatal error Unable to open system services stub file %s\n", StubHeaderName);
  347. fclose(StubFile);
  348. fclose(InputFile);
  349. exit(1);
  350. }
  351. if (Profile) {
  352. ProfHeaderFile = fopen(ProfHeaderName, "r");
  353. if (!ProfHeaderFile) {
  354. printf("\nfatal error Unable to open system services profiling stub file %s\n", ProfHeaderName);
  355. fclose(StubHeaderFile);
  356. fclose(StubFile);
  357. fclose(InputFile);
  358. exit(1);
  359. }
  360. ProfFile = fopen(ProfFileName, "w");
  361. if (!ProfFile) {
  362. printf("\nfatal error Unable to open system services file %s\n", ProfFileName);
  363. fclose(ProfHeaderFile);
  364. fclose(StubHeaderFile);
  365. fclose(StubFile);
  366. fclose(InputFile);
  367. exit(1);
  368. }
  369. ProfDotHFile = fopen(ProfDotHFileName, "w");
  370. if (!ProfDotHFile) {
  371. printf("\nfatal error Unable to open system services file %s\n", ProfFileName);
  372. fclose(ProfFile);
  373. fclose(ProfHeaderFile);
  374. fclose(StubHeaderFile);
  375. fclose(StubFile);
  376. fclose(InputFile);
  377. exit(1);
  378. }
  379. ProfIncFile = fopen(ProfIncFileName, "w");
  380. if (!ProfIncFile) {
  381. printf("\nfatal error Unable to open system services file %s\n", ProfFileName);
  382. fclose(ProfFile);
  383. fclose(ProfHeaderFile);
  384. fclose(StubHeaderFile);
  385. fclose(StubFile);
  386. fclose(InputFile);
  387. exit(1);
  388. }
  389. ProfTblFile = fopen(ProfTblFileName, "w");
  390. if (!ProfTblFile) {
  391. printf("\nfatal error Unable to open system services file %s\n", ProfFileName);
  392. fclose(ProfIncFile);
  393. fclose(ProfDotHFile);
  394. fclose(ProfFile);
  395. fclose(ProfHeaderFile);
  396. fclose(StubHeaderFile);
  397. fclose(StubFile);
  398. fclose(InputFile);
  399. exit(1);
  400. }
  401. }
  402. }
  403. if (TableFileName != NULL) {
  404. TableFile = fopen(TableFileName, "w");
  405. if (!TableFile) {
  406. printf("\nfatal error Unable to open system services file %s\n",
  407. TableFileName);
  408. fclose(StubHeaderFile);
  409. fclose(StubFile);
  410. fclose(InputFile);
  411. exit(1);
  412. }
  413. TableHeaderFile = fopen(TableHeaderName, "r");
  414. if (!TableHeaderFile) {
  415. printf("\nfatal error Unable to open system services stub file %s\n",
  416. TableHeaderName);
  417. fclose(TableFile);
  418. fclose(StubHeaderFile);
  419. fclose(StubFile);
  420. fclose(InputFile);
  421. exit(1);
  422. }
  423. } else {
  424. TableFile = NULL;
  425. TableHeaderFile = NULL;
  426. }
  427. if ( DefFileData ) {
  428. DefFile = fopen(DefFileData, "w");
  429. if (!DefFile) {
  430. printf("\nfatal error Unable to open def file data file %s\n", DefFileData);
  431. if ( TableFile ) {
  432. fclose(TableHeaderFile);
  433. fclose(TableFile);
  434. }
  435. fclose(StubHeaderFile);
  436. fclose(StubFile);
  437. fclose(InputFile);
  438. exit(1);
  439. }
  440. } else {
  441. DefFile = NULL;
  442. }
  443. //
  444. // Output header information to the stubs file and table file. This
  445. // information is obtained from the Services stub file and from the
  446. // table stub file.
  447. //
  448. if (DefFile == NULL) {
  449. while( fgets(InputRecord, 132, StubHeaderFile) ) {
  450. fputs(InputRecord, StubFile);
  451. }
  452. if (Profile) {
  453. while( fgets(InputRecord, 132, ProfHeaderFile) ) {
  454. fputs(InputRecord, ProfFile);
  455. }
  456. fputs(ProfTblPrefixFmt, ProfTblFile);
  457. }
  458. }
  459. if (TableFile != NULL) {
  460. if (!fgets(InputRecord, 132, TableHeaderFile) ) {
  461. printf("\nfatal error Format Error in table stub file %s\n", TableHeaderName);
  462. fclose(TableHeaderFile);
  463. fclose(TableFile);
  464. fclose(StubHeaderFile);
  465. fclose(StubFile);
  466. fclose(InputFile);
  467. exit(1);
  468. }
  469. InRegisterArgCount = atol(InputRecord);
  470. while( fgets(InputRecord, 132, TableHeaderFile) ) {
  471. fputs(InputRecord, TableFile);
  472. }
  473. } else {
  474. InRegisterArgCount = 0;
  475. }
  476. if (Braces) {
  477. TableEntryFmt = TableEntryFmtB;
  478. } else {
  479. TableEntryFmt = TableEntryFmtNB;
  480. }
  481. //
  482. // Read service name table and generate file data.
  483. //
  484. while ( fgets(InputRecord, 132, InputFile) ){
  485. //
  486. // Generate stub file entry.
  487. //
  488. Ipr = &InputRecord[0];
  489. Opr = &OutputRecord[0];
  490. //
  491. // If services.tab was generated by C_PREPROCESSOR, there might
  492. // be empty lines in this file. Using the preprocessor allows
  493. // people to use #ifdef, #includes, etc in the original services.tab
  494. //
  495. switch (*Ipr) {
  496. case '\n':
  497. case ' ':
  498. continue;
  499. }
  500. while ((*Ipr != '\n') && (*Ipr != ',')) {
  501. *Opr++ = *Ipr++;
  502. }
  503. *Opr = '\0';
  504. //
  505. // If the input record ended in ',', then the service has inmemory
  506. // arguments and the number of in memory arguments follows the comma.
  507. //
  508. MemoryArgs[ServiceNumber] = 0;
  509. Terminal = *Ipr;
  510. *Ipr++ = 0;
  511. if (Terminal == ',') {
  512. MemoryArgs[ServiceNumber] = (char) atoi(Ipr);
  513. }
  514. // Move to the end of the line or past the next comma
  515. while (*Ipr != '\n') {
  516. if (*Ipr++ == ',') {
  517. break ;
  518. }
  519. }
  520. //
  521. // If an error return value table is to be generated, then the following value
  522. // might follow:
  523. // 0 = return 0
  524. // -1 = return -1
  525. // 1 = return status code. (This is the default if no value is specified)
  526. //
  527. // This table is used by the dispatcher when convertion to GUI fails.
  528. //
  529. if (ErrorReturnTable) {
  530. if (*Ipr != '\n') {
  531. ErrorReturns[ServiceNumber] = (char)ParseAndSkipShort(&Ipr);
  532. } else {
  533. ErrorReturns[ServiceNumber] = 1;
  534. }
  535. }
  536. //
  537. //
  538. // If there are more arguments, then this stub doesn't use the default code (lines 1 to 8)
  539. // The following format is expected:
  540. // LineStart,LineEnd,Argument1[,Argument2[,Argument3]....]
  541. //
  542. ArgIndex = 0;
  543. if (*Ipr != '\n') {
  544. LineStart = ParseAndSkipShort(&Ipr);
  545. LineEnd = ParseAndSkipShort(&Ipr);
  546. while ((ArgIndex < USRSTUBS_MAXARGS) && (*Ipr != '\n')) {
  547. Arguments[ ArgIndex++ ] = ParseAndSkipShort(&Ipr);
  548. }
  549. } else {
  550. LineStart = 1;
  551. LineEnd = 8;
  552. }
  553. TotalArgs += MemoryArgs[ServiceNumber];
  554. if ( MemoryArgs[ServiceNumber] > InRegisterArgCount ) {
  555. MemoryArgs[ServiceNumber] -= (CHAR)InRegisterArgCount;
  556. } else {
  557. MemoryArgs[ServiceNumber] = 0;
  558. }
  559. if ( DefFile ) {
  560. fprintf(DefFile," Zw%s\n",OutputRecord);
  561. fprintf(DefFile," Nt%s\n",OutputRecord);
  562. } else {
  563. for (Index1=LineStart; Index1<=LineEnd; Index1++) {
  564. if (!TableFile) {
  565. PrintStubLine(StubFile, Index1, UsrStbsFmtMacroName,
  566. ServiceNumber, ArgIndex, Arguments, Braces);
  567. if (Profile) {
  568. PrintStubLine(ProfFile, Index1, UsrStbsFmtMacroName,
  569. ServiceNumber, ArgIndex, Arguments, Braces);
  570. if (Index1 == LineStart) {
  571. fprintf(ProfTblFile,ProfTblFmt,
  572. OutputRecord,
  573. MemoryArgs[ServiceNumber]);
  574. if (!strcmp(OutputRecord,
  575. "QueryPerformanceCounter")) {
  576. NapCounterServiceNumber = ServiceNumber;
  577. }
  578. }
  579. }
  580. } else {
  581. PrintStubLine(StubFile, Index1, SysStbsFmtMacroName,
  582. ServiceNumber, ArgIndex, Arguments, Braces);
  583. }
  584. }
  585. }
  586. //
  587. // Generate table file entry and update service number.
  588. //
  589. if (TableFile != NULL) {
  590. fprintf(TableFile,
  591. TableEntryFmt,
  592. InputRecord,
  593. (MemoryArgs[ServiceNumber] ? 1 : 0 ),
  594. MemoryArgs[ServiceNumber]);
  595. }
  596. ServiceNumber = ServiceNumber + 1;
  597. }
  598. if (TableFile == NULL) {
  599. DebugFile = StubFile;
  600. } else {
  601. DebugFile = TableFile;
  602. }
  603. //
  604. // Generate Error Return table if required.
  605. // This table must be concatenated at the end of the system call service table.
  606. //
  607. if (ErrorReturnTable && (TableFile != NULL)) {
  608. GenerateTable(TableFile, "ERRTBL", ServiceNumber, FALSE, Braces);
  609. }
  610. if (DispatchCount ) {
  611. if ( Braces ) {
  612. fprintf(DebugFile, "\n\nDECLARE_DISPATCH_COUNT( %d, %d )\n", ServiceNumber, TotalArgs);
  613. } else {
  614. fprintf(DebugFile, "\n\nDECLARE_DISPATCH_COUNT 0%xh, 0%xh\n", ServiceNumber, TotalArgs);
  615. }
  616. }
  617. if (TableFile != NULL) {
  618. //
  619. // Generate highest service number.
  620. //
  621. if ( Braces )
  622. fprintf(TableFile, "\nTABLE_END( %d )\n", ServiceNumber - 1);
  623. else
  624. fprintf(TableFile, "\nTABLE_END %d \n", ServiceNumber - 1);
  625. //
  626. // Generate number of arguments in memory table.
  627. //
  628. GenerateTable(TableFile, "ARGTBL", ServiceNumber, TRUE, Braces);
  629. fclose(TableHeaderFile);
  630. fclose(TableFile);
  631. }
  632. if (!DefFile) {
  633. fprintf(StubFile, "\nSTUBS_END\n");
  634. fclose(StubHeaderFile);
  635. fclose(StubFile);
  636. if (Profile) {
  637. fprintf(ProfFile, "\nSTUBS_END\n");
  638. fprintf(ProfTblFile, ProfTblSuffixFmt);
  639. fprintf(ProfDotHFile, ProfDotHFmt, ServiceNumber);
  640. fprintf(ProfIncFile, ProfIncFmt, NapCounterServiceNumber);
  641. fclose(ProfHeaderFile);
  642. fclose(ProfFile);
  643. fclose(ProfDotHFile);
  644. fclose(ProfTblFile);
  645. }
  646. }
  647. fclose(InputFile);
  648. //
  649. // Clear the Archive bit for all the files created, since they are
  650. // generated, there is no reason to back them up.
  651. //
  652. ClearArchiveBit(TableFileName);
  653. ClearArchiveBit(StubFileName);
  654. if (DefFile) {
  655. ClearArchiveBit(DefFileData);
  656. }
  657. if (Profile) {
  658. ClearArchiveBit(ProfFileName);
  659. ClearArchiveBit(ProfDotHFileName);
  660. ClearArchiveBit(ProfIncFileName);
  661. ClearArchiveBit(ProfTblFileName);
  662. }
  663. return (0);
  664. }
  665. VOID
  666. PrintStubLine (
  667. FILE * pf,
  668. SHORT Index1,
  669. PCHAR pszMacro,
  670. SHORT ServiceNumber,
  671. SHORT ArgIndex,
  672. SHORT *Arguments,
  673. SHORT Braces
  674. )
  675. {
  676. SHORT Index2;
  677. fprintf(pf, pszMacro, Index1);
  678. fprintf(pf, Braces ? "(" : " ");
  679. fprintf(pf, StbFmtMacroArgs, ServiceNumber,
  680. OutputRecord, MemoryArgs[ServiceNumber]);
  681. for (Index2=0; Index2<ArgIndex; Index2++) {
  682. fprintf(pf, ", %d", Arguments[Index2]);
  683. }
  684. fprintf(pf, Braces ? " )\n" : " \n");
  685. }
  686. SHORT
  687. ParseAndSkipShort(
  688. CHAR **ppBuffer
  689. )
  690. {
  691. SHORT s = (SHORT)atoi(*ppBuffer);
  692. while (**ppBuffer != '\n') {
  693. if (*(*ppBuffer)++ == ',') {
  694. break;
  695. }
  696. }
  697. return s;
  698. }
  699. VOID
  700. ClearArchiveBit(
  701. PCHAR FileName
  702. )
  703. {
  704. DWORD Attributes;
  705. Attributes = GetFileAttributes(FileName);
  706. if (Attributes != -1 && (Attributes & FILE_ATTRIBUTE_ARCHIVE)) {
  707. SetFileAttributes(FileName, Attributes & ~FILE_ATTRIBUTE_ARCHIVE);
  708. }
  709. return;
  710. }
  711. VOID
  712. GenerateTable(
  713. FILE * pf,
  714. PCHAR pszMacro,
  715. SHORT ServiceNumber,
  716. SHORT Args,
  717. SHORT Braces
  718. )
  719. {
  720. SHORT Index1, Index2, Limit, Value;
  721. PCHAR pValues = (Args ? MemoryArgs : ErrorReturns);
  722. fprintf(pf, "\n%s_BEGIN\n", pszMacro);
  723. for (Index1 = 0; Index1 <= ServiceNumber - 1; Index1 += 8) {
  724. fprintf(pf, "%s_ENTRY%s", pszMacro, Braces ? "(" : " ");
  725. Limit = ServiceNumber - Index1 - 1;
  726. if (Limit >= 7) {
  727. Limit = 7;
  728. }
  729. for (Index2 = 0; Index2 <= Limit; Index2 += 1) {
  730. Value = *(pValues + Index1 + Index2);
  731. if (Args) {
  732. Value *= 4;
  733. }
  734. fprintf(pf, Index2 == Limit ? "%d" : "%d,", Value);
  735. }
  736. if (Limit < 7) {
  737. while(Index2 <= 7) {
  738. fprintf(pf, ",0");
  739. Index2++;
  740. }
  741. }
  742. fprintf(pf, Braces ? ")\n" : " \n");
  743. }
  744. fprintf(pf, "\n%s_END\n", pszMacro);
  745. }