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