Initial revision
[reactos.git] / msvc6 / iface / native / genntdll.c
1 /* $Id: genntdll.c,v 1.1 2004/02/06 08:21:56 fireball Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS version of ntdll
5 * FILE: iface/native/genntdll.c
6 * PURPOSE: Generates the system call stubs in ntdll
7 * CHANGE HISTORY: Added a '@xx' to deal with stdcall [ Ariadne ]
8 * 19990616 (ea)
9 * Four arguments now required; 4th is the file
10 * for ntoskrnl ZwXXX functions (which are merely calls
11 * to twin NtXXX calls, via int 0x2e (x86).
12 * 19990617 (ea)
13 * Fixed a bug in function numbers in kernel ZwXXX stubs.
14 *
15 */
16
17 /* INCLUDE ******************************************************************/
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #define PARAMETERIZED_LIBS
24
25 /* #define VERBOSE */
26
27 #define INPUT_BUFFER_SIZE 255
28
29 /* FUNCTIONS ****************************************************************/
30
31 void write_syscall_stub(FILE* out, FILE* out3, char* name, char* name2,
32 char* nr_args, unsigned int sys_call_idx)
33 {
34 int i;
35 int nArgBytes = atoi(nr_args);
36 #ifdef PARAMETERIZED_LIBS
37 fprintf(out,"__asm__(\"\\n\\t.global _%s@%s\\n\\t\"\n",name,nr_args);
38 fprintf(out,"\".global _%s@%s\\n\\t\"\n",name2,nr_args);
39 fprintf(out,"\"_%s@%s:\\n\\t\"\n",name,nr_args);
40 fprintf(out,"\"_%s@%s:\\n\\t\"\n",name2,nr_args);
41 #else
42 fprintf(out,"__asm__(\"\\n\\t.global _%s\\n\\t\"\n",name);
43 fprintf(out,"\".global _%s\\n\\t\"\n",name2);
44 fprintf(out,"\"_%s:\\n\\t\"\n",name);
45 fprintf(out,"\"_%s:\\n\\t\"\n",name2);
46 #endif
47 fprintf(out,"\t\"pushl\t%%ebp\\n\\t\"\n");
48 fprintf(out,"\t\"movl\t%%esp, %%ebp\\n\\t\"\n");
49 fprintf(out,"\t\"mov\t$%d,%%eax\\n\\t\"\n",sys_call_idx);
50 fprintf(out,"\t\"lea\t8(%%ebp),%%edx\\n\\t\"\n");
51 fprintf(out,"\t\"int\t$0x2E\\n\\t\"\n");
52 fprintf(out,"\t\"popl\t%%ebp\\n\\t\"\n");
53 fprintf(out,"\t\"ret\t$%s\\n\\t\");\n\n",nr_args);
54
55 /*
56 * Now write the NTOSKRNL stub for the
57 * current system call. ZwXXX does NOT
58 * alias the corresponding NtXXX call.
59 */
60 #if 0
61 fprintf(out3,"__asm__(\n");
62 fprintf(out3,"\".global _%s@%s\\n\\t\"\n",name2,nr_args);
63 fprintf(out3,"\"_%s@%s:\\n\\t\"\n",name2,nr_args);
64 fprintf(out3,"\t\"pushl\t%%ebp\\n\\t\"\n");
65 fprintf(out3,"\t\"movl\t%%esp, %%ebp\\n\\t\"\n");
66 fprintf(out3,"\t\"mov\t$%d,%%eax\\n\\t\"\n",sys_call_idx);
67 fprintf(out3,"\t\"lea\t8(%%ebp),%%edx\\n\\t\"\n");
68 fprintf(out3,"\t\"int\t$0x2E\\n\\t\"\n");
69 fprintf(out3,"\t\"popl\t%%ebp\\n\\t\"\n");
70 fprintf(out3,"\t\"ret\t$%s\\n\\t\");\n\n",nr_args);
71 #else
72 fprintf(out3,"__declspec(naked) __stdcall\n");
73 fprintf(out3,"%s(", name2); // make it emit callconv, reval and full signature too
74 for (i=0; i*4 < nArgBytes; ++i) {
75 fprintf(out3,"int dummy%d", i);
76 if (((i+1)*4) < nArgBytes) fprintf(out3,",");
77 }
78 fprintf(out3,")\n{\n");
79 fprintf(out3,"\t__asm {\n");
80 fprintf(out3,"\t\tpush\tebp\n");
81 fprintf(out3,"\t\tmov\tebp, esp\n");
82 fprintf(out3,"\t\tmov\teax,%d\n",sys_call_idx);
83 fprintf(out3,"\t\tlea\tedx, 8[ebp]\n");
84 fprintf(out3,"\t\tint\t0x2E\n");
85 fprintf(out3,"\t\tpop\tebp\n");
86 fprintf(out3,"\t\tret\t%s\n",nr_args);
87 fprintf(out3,"\t}\n");
88 fprintf(out3,"}\n\n");
89 #endif
90 }
91
92 int makeSystemServiceTable(FILE *in, FILE *out)
93 {
94 char line [INPUT_BUFFER_SIZE];
95 char *s;
96 char *name;
97 char *name2;
98 int sys_call_idx;
99 char *nr_args;
100 char *stmp;
101
102 /*
103 * Main SSDT Header
104 */
105 fprintf(out,"// Machine generated, don't edit\n");
106 fprintf(out,"\n\n");
107
108 /*
109 * First we build the Main SSDT
110 */
111 fprintf(out,"\n\n\n");
112 fprintf(out,"SSDT MainSSDT[] = {\n");
113
114 for ( /* First system call has index zero */
115 sys_call_idx = 0;
116 /* Go on until EOF or read zero bytes */
117 ( (!feof(in))
118 && (fgets(line, sizeof line, in) != NULL)
119 );
120 /* Next system call index */
121 sys_call_idx++
122 )
123 {
124 if ((s = (char *) strchr(line,'\r')) != NULL)
125 {
126 *s = '\0';
127 }
128 /*
129 * Skip comments (#) and empty lines.
130 */
131 s = & line[0];
132 if ((*s) != '#' && (*s) != '\0')
133 {
134 /* Extract the NtXXX name */
135 name = (char *)strtok(s," \t");
136 /* Extract the ZwXXX name */
137 name2 = (char *)strtok(NULL," \t");
138 //value = strtok(NULL," \t");
139 /* Extract the stack size */
140 nr_args = (char *)strtok(NULL," \t");
141 /*
142 * Remove, if present, the trailing LF.
143 */
144 if ((stmp = strchr(nr_args, '\n')) != NULL)
145 {
146 *stmp = '\0';
147 }
148 #ifdef VERBOSE
149 printf("%3d \"%s\"\n",sys_call_idx,name);
150 #endif
151
152 if (sys_call_idx > 0)
153 {
154 fprintf(out,",\n");
155 }
156 /*
157 * Now write the current system call's name
158 * in the service table.
159 */
160 fprintf(out,"\t\t{ (ULONG)%s }",name);
161 }
162 }
163 /* Close the service table (C syntax) */
164 fprintf(out,"\n};\n");
165
166 /*
167 * Now we build the Main SSPT
168 */
169 rewind(in);
170 fprintf(out,"\n\n\n");
171 fprintf(out,"SSPT MainSSPT[] = {\n");
172
173 for ( /* First system call has index zero */
174 sys_call_idx = 0;
175 /* Go on until EOF or read zero bytes */
176 ( (!feof(in))
177 && (fgets(line, sizeof line, in) != NULL)
178 );
179 /* Next system call index */
180 sys_call_idx++
181 )
182 {
183 if ((s = (char *) strchr(line,'\r')) != NULL)
184 {
185 *s = '\0';
186 }
187 /*
188 * Skip comments (#) and empty lines.
189 */
190 s = & line[0];
191 if ((*s) != '#' && (*s) != '\0')
192 {
193 /* Extract the NtXXX name */
194 name = (char *)strtok(s," \t");
195 /* Extract the ZwXXX name */
196 name2 = (char *)strtok(NULL," \t");
197 //value = strtok(NULL," \t");
198 /* Extract the stack size */
199 nr_args = (char *)strtok(NULL," \t");
200 /*
201 * Remove, if present, the trailing LF.
202 */
203 if ((stmp = strchr(nr_args, '\n')) != NULL)
204 {
205 *stmp = '\0';
206 }
207 #ifdef VERBOSE
208 printf("%3d \"%s\"\n",sys_call_idx,name);
209 #endif
210
211 if (sys_call_idx > 0)
212 {
213 fprintf(out,",\n");
214 }
215 /*
216 * Now write the current system call's ID
217 * in the service table along with its Parameters Size.
218 */
219 fprintf(out,"\t\t{ %s }",nr_args);
220 }
221 }
222 /*
223 * Close the service table (C syntax)
224 */
225 fprintf(out,"\n};\n");
226
227 /*
228 * We write some useful defines
229 */
230 fprintf(out, "\n\n#define MIN_SYSCALL_NUMBER 0\n");
231 fprintf(out, "#define MAX_SYSCALL_NUMBER %d\n", sys_call_idx-1);
232 fprintf(out, "#define NUMBER_OF_SYSCALLS %d\n", sys_call_idx);
233
234 return(0);
235 }
236
237
238 int
239 process(
240 FILE * in,
241 FILE * out,
242 FILE * out2,
243 FILE * out3
244 )
245 {
246 char line [INPUT_BUFFER_SIZE];
247 char * s;
248 char * name; /* NtXXX name */
249 char * name2; /* ZwXXX name */
250 int sys_call_idx; /* NtXXX index number in the service table */
251 char * nr_args; /* stack_size / machine_word_size */
252 char * stmp;
253
254 /*
255 * NTDLL stubs file header
256 */
257 fprintf(out,"// Machine generated, don't edit\n");
258 fprintf(out,"\n\n");
259
260 /*
261 * NTOSKRNL Zw functions stubs header
262 */
263 fprintf(out3,"// Machine generated by genntdll, don't edit\n");
264 fprintf(out3,"\n\n");
265 /*
266 * Scan the database. DB is a text file; each line
267 * is a record, which contains data for one system
268 * function. Each record has three columns:
269 *
270 * NT_NAME (e.g. NtCreateProcess)
271 * ZW_NAME (e.g. ZwCreateProcess)
272 * STACK_SIZE (in machine words: for x[3456]86
273 * processors a machine word is 4 bytes)
274 */
275 for ( /* First system call has index zero */
276 sys_call_idx = 0;
277 /* Go on until EOF or read zero bytes */
278 ( (!feof(in))
279 && (fgets(line, sizeof line, in) != NULL)
280 );
281 /* Next system call index */
282 sys_call_idx++
283 )
284 {
285 /*
286 * Remove, if present, the trailing CR.
287 * (os specific?)
288 */
289 if ((s = (char *) strchr(line,'\r')) != NULL)
290 {
291 *s = '\0';
292 }
293 /*
294 * Skip comments (#) and empty lines.
295 */
296 s = & line[0];
297 if ((*s) != '#' && (*s) != '\0')
298 {
299 /* Extract the NtXXX name */
300 name = (char *)strtok(s," \t");
301 /* Extract the ZwXXX name */
302 name2 = (char *)strtok(NULL," \t");
303 //value = strtok(NULL," \t");
304 /* Extract the stack size */
305 nr_args = (char *)strtok(NULL," \t");
306 /*
307 * Remove, if present, the trailing LF.
308 */
309 if ((stmp = strchr(nr_args, '\n')) != NULL)
310 {
311 *stmp = '\0';
312 }
313 #ifdef VERBOSE
314 printf("%3d \"%s\"\n",sys_call_idx,name);
315 #endif
316 /*
317 * Write the NTDLL stub for the current
318 * system call: NtXXX and ZwXXX symbols
319 * are aliases.
320 */
321 write_syscall_stub(out, out3, name, name2,
322 nr_args, sys_call_idx);
323 }
324 }
325
326 return(0);
327 }
328
329 void usage(char * argv0)
330 {
331 printf("Usage: %s sysfuncs.lst napi.c napi.h zw.c\n"
332 " sysfuncs.lst system functions database\n"
333 " napi.c NTDLL stubs\n"
334 " napi.h NTOSKRNL service table\n"
335 " zw.c NTOSKRNL Zw stubs\n",
336 argv0
337 );
338 }
339
340 int main(int argc, char* argv[])
341 {
342 FILE * in; /* System calls database */
343 FILE * out1; /* NTDLL stubs */
344 FILE * out2; /* SERVICE_TABLE */
345 FILE * out3; /* NTOSKRNL Zw stubs */
346 int ret;
347
348 if (argc != 5)
349 {
350 usage(argv[0]);
351 return(1);
352 }
353
354 in = fopen(argv[1],"rb");
355 if (in == NULL)
356 {
357 perror("Failed to open input file (system calls database)");
358 return(1);
359 }
360
361 out1 = fopen(argv[2],"wb");
362 if (out1 == NULL)
363 {
364 perror("Failed to open output file (NTDLL stubs)");
365 return(1);
366 }
367
368 out2 = fopen(argv[3],"wb");
369 if (out2 == NULL)
370 {
371 perror("Failed to open output file (NTOSKRNL service table)");
372 return(1);
373 }
374
375 out3 = fopen(argv[4],"wb");
376 if (out3 == NULL)
377 {
378 perror("Failed to open output file (NTOSKRNL Zw stubs)");
379 return(1);
380 }
381
382 ret = process(in,out1,out2,out3);
383 rewind(in);
384 ret = makeSystemServiceTable(in, out2);
385
386 fclose(in);
387 fclose(out1);
388 fclose(out2);
389 fclose(out3);
390
391 return(ret);
392 }