Added little prog. that builds the WIN32K.SYS service table
[reactos.git] / reactos / iface / addsys / mktab.cc
1 /* $Id: mktab.cc,v 1.1 2000/02/20 22:52:47 ea Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT : ReactOS
5 * FILE : iface/addsys/mktab.c
6 * PURPOSE : Generating any files required for a kernel module
7 * to register an additional system calls table in
8 * NTOSKRNL.
9 * REVISIONS:
10 * 2000-02-13 (ea)
11 * Derived from genntdll.c mainly to build
12 * win32k.sys functions table.
13 */
14
15 /* INCLUDE ******************************************************************/
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20
21 #define VERBOSE
22
23 #define INPUT_BUFFER_SIZE 255
24
25 #define DB_RECORD_NAME_SIZE 64
26
27 #define STACK_ENTRY_SIZE (sizeof(void*))
28
29 #define FALSE 0
30 #define TRUE 1
31
32 typedef unsigned int DWORD;
33 typedef int INT;
34 typedef char * LPSTR, CHAR, * PCHAR;
35 typedef int BOOL;
36 typedef void VOID, * PVOID;
37
38 typedef
39 struct _DB_RECORD
40 {
41 CHAR Name [DB_RECORD_NAME_SIZE];
42 INT ArgumentCount;
43 INT StackSize;
44
45 } DB_RECORD, * PDB_RECORD;
46
47 typedef
48 enum
49 {
50 SELECT_OK,
51 SELECT_EOF,
52 SELECT_ERROR
53
54 } SELECT_TYPE;
55
56
57 /* FUNCTIONS ****************************************************************/
58
59
60 void usage (char * argv0)
61 {
62 printf (
63 "\nUsage: %s api.db mask table.c apistubs.c\n\n"
64 " api.db additional system functions database (NAME, ARG_COUNT)\n"
65 " mask service table mask (in hex; e.g. 0x1000000)\n"
66 " table.c service table file to be linked in the kernel module\n"
67 " apistubs.c stubs for user mode clients to call the API\n\n"
68 "NOTE: NAME must be an ASCII string and ARG_COUNT a decimal number;\n"
69 "between NAME and ARG_COUNT there must be at least one space or tab.\n",
70 argv0
71 );
72 }
73
74
75 void
76 CloseAllFiles (FILE * f0, FILE * f1, FILE * f2)
77 {
78 if (f0) fclose (f0);
79 if (f1) fclose (f1);
80 if (f2) fclose (f2);
81 }
82
83
84 SELECT_TYPE
85 GetNextRecord (
86 FILE * InputFile,
87 PDB_RECORD Dbr
88 )
89 {
90 CHAR InputBuffer [INPUT_BUFFER_SIZE];
91 PCHAR s;
92 static INT LineNumber = 0;
93 BOOL BadData = TRUE;
94
95 if ( (NULL == InputFile)
96 || (NULL == Dbr)
97 )
98 {
99 fprintf (stderr, "GetNextRecord: bad argument!\n");
100 return SELECT_ERROR;
101 }
102 while (TRUE == BadData)
103 {
104 if ( feof (InputFile)
105 || (NULL == fgets (
106 InputBuffer,
107 sizeof InputBuffer,
108 InputFile
109 )
110 )
111 )
112 {
113 #ifdef VERBOSE
114 fprintf (
115 stderr,
116 "GetNextRecord: EOF at line %d\n",
117 LineNumber
118 );
119 #endif
120 return SELECT_EOF;
121 }
122 ++ LineNumber;
123 /*
124 * Remove, if present, the trailing CR.
125 * (os specific?)
126 */
127 if (NULL != (s = (char *) strchr (InputBuffer,'\r')))
128 {
129 *s = '\0';
130 }
131 /*
132 * Skip comments (#) and empty lines.
133 */
134 s = & InputBuffer [0];
135 if ( ('#' != (*s))
136 && ('\0' != (*s))
137 )
138 {
139 BadData = FALSE;
140 }
141 }
142 if (2 != sscanf (
143 InputBuffer,
144 "%s%d",
145 Dbr->Name,
146 & Dbr->ArgumentCount
147 )
148 )
149 {
150 fprintf (
151 stderr,
152 "GetNextRecord: line %d: syntax error!\n",
153 LineNumber
154 );
155 return SELECT_ERROR;
156 }
157 Dbr->StackSize = (Dbr->ArgumentCount * sizeof (void*));
158 return SELECT_OK;
159 }
160
161
162 /* User mode service stubs file generation */
163
164
165 void
166 OutputStubPrologue (FILE * of)
167 {
168 fprintf (
169 of,
170 "/* Machine generated. Don't edit! */\n\n"
171 "__asm (\n"
172 );
173 }
174
175
176 BOOL
177 OutputStub (FILE * of, PDB_RECORD Dbr, INT Id, DWORD Mask)
178 {
179 DWORD CallId = (Mask | (DWORD) Id);
180 CHAR DecoratedName [DB_RECORD_NAME_SIZE];
181
182 sprintf (
183 DecoratedName,
184 "_%s@%d",
185 Dbr->Name,
186 Dbr->StackSize
187 );
188 fprintf (
189 of,
190 "\t\".global %s\\n\\t\"\n"
191 "\"%s:\\n\\t\"\n"
192 "\t\"mov\t$0x%08x,%%eax\\n\\t\"\n"
193 "\t\"lea\t4(%%esp),%%edx\\n\\t\"\n"
194 "\t\"int\t$0x2E\\n\\t\"\n"
195 "\t\"ret\t$%d\\n\\t\"\n",
196 DecoratedName,
197 DecoratedName,
198 CallId,
199 Dbr->StackSize
200 );
201 return TRUE;
202 }
203
204
205 void
206 OutputStubEpilog (FILE * of)
207 {
208 fprintf (
209 of,
210 ");\n\n/* EOF */\n"
211 );
212 }
213
214
215 /* Service table file generation (used by the kernel module) */
216
217
218 void
219 OutputTablePrologue (FILE * of)
220 {
221 fprintf (
222 of,
223 "/* Machine generated. Don't edit! */\n\n"
224 "SERVICE_TABLE W32kServiceTable [] =\n{\n"
225 );
226 }
227
228
229 BOOL
230 OutputTable (FILE * of, PDB_RECORD Dbr)
231 {
232 static BOOL First = TRUE;
233
234 if (TRUE == First)
235 {
236 fprintf (
237 of,
238 "{%d,(ULONG)%s}",
239 Dbr->StackSize,
240 Dbr->Name
241 );
242 First = FALSE;
243 }
244 else
245 {
246 fprintf (
247 of,
248 ",\n{%d,(ULONG)%s}",
249 Dbr->StackSize,
250 Dbr->Name
251 );
252 }
253 return TRUE;
254 }
255
256
257 void
258 OutputTableEpilog (FILE * of)
259 {
260 fprintf (
261 of,
262 "\n};\n/* EOF */"
263 );
264 }
265
266
267 /* MAIN */
268
269 int
270 main (int argc, char * argv [])
271 {
272 FILE * ApiDb = NULL;
273 FILE * Table = NULL;
274 FILE * Stubs = NULL;
275
276 DWORD Mask = 0;
277 DB_RECORD Dbr;
278 INT Id = 0;
279
280 SELECT_TYPE ReturnValue;
281
282 /* --- Check arguments --- */
283
284 if (argc != 5)
285 {
286 usage (argv[0]);
287 return (1);
288 }
289
290 /* --- Create files --- */
291
292 ApiDb = fopen (argv[1], "rb");
293 if (NULL == ApiDb)
294 {
295 fprintf (
296 stderr,
297 "%s: fatal: could not open the file \"%s\".\n",
298 argv [0],
299 argv [1]
300 );
301 return (1);
302 }
303 printf ("< %s\n", argv[1]);
304
305 Stubs = fopen (argv[3], "wb");
306 if (NULL == Stubs)
307 {
308 fprintf (
309 stderr,
310 "%s: fatal: could not open the file \"%s\".\n",
311 argv [0],
312 argv [3]
313 );
314 CloseAllFiles (ApiDb, Table, Stubs);
315 return (1);
316 }
317 printf ("> %s\n", argv[3]);
318
319 Table = fopen (argv[4], "wb");
320 if (NULL == Table)
321 {
322 fprintf (
323 stderr,
324 "%s: fatal: could not open the file \"%s\".\n",
325 argv [0],
326 argv [4]
327 );
328 CloseAllFiles (ApiDb, Table, Stubs);
329 return (1);
330 }
331 printf ("> %s\n", argv[4]);
332
333 /* --- Convert the mask value --- */
334
335 if (1 != sscanf (argv[2], "%x", & Mask))
336 {
337 fprintf (
338 stderr,
339 "%s: fatal: could not convert the mask \"%s\".\n",
340 argv [0],
341 argv [2]
342 );
343 CloseAllFiles (ApiDb, Table, Stubs);
344 return (1);
345 }
346 printf ("& 0x%08x\n", Mask);
347
348 /* --- Process data --- */
349
350 printf ("Processing data...\n");
351 OutputStubPrologue (Stubs);
352 OutputTablePrologue (Table);
353 while (SELECT_OK == (ReturnValue = GetNextRecord (ApiDb, & Dbr)))
354 {
355 if (TRUE == OutputTable (Table, & Dbr))
356 {
357 if (FALSE == OutputStub (Stubs, & Dbr, Id, Mask))
358 {
359 fprintf (
360 stderr,
361 "%s: WARNING: %s has no user mode stub\n",
362 argv [0],
363 Dbr.Name
364 );
365 }
366 }
367 else
368 {
369 fprintf (
370 stderr,
371 "%s: WARNING: %s skipped on I/O error\n",
372 argv [0],
373 Dbr.Name
374 );
375 }
376 ++ Id;
377 #ifdef VERBOSE
378 printf (
379 "%3d: _%s@%d\n",
380 Id,
381 Dbr.Name,
382 Dbr.StackSize
383 );
384 #endif
385 }
386 if (SELECT_EOF == ReturnValue)
387 {
388 OutputStubEpilog (Stubs);
389 OutputTableEpilog (Table);
390 }
391 else
392 {
393 fprintf (
394 stderr,
395 "%s: generated files may be incomplete!\n",
396 argv [0]
397 );
398 }
399
400 /* --- Close files --- */
401
402 CloseAllFiles (ApiDb, Table, Stubs);
403
404 printf ("Done\n");
405
406 return (0);
407 }
408
409
410 /* EOF */