4753567a972154eaa698555d7bf4e4b799f5183b
2 * FILE: tools/nci/ncitool.c
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: Native Call Interface Support Tool
5 * PURPOSE: Generates NCI Tables and Stubs.
6 * PROGRAMMER; Alex Ionescu (alex@relsoft.net)
7 * CHANGE HISTORY: 14/01/05 - Created. Based on original code by
8 * KJK::Hyperion and Emanuelle Aliberti.
12 /* INCLUDE ******************************************************************/
21 /* DEFINES ****************************************************************/
23 #define INPUT_BUFFER_SIZE 255
26 /******* Table Indexes ************/
27 #define MAIN_INDEX 0x0
28 #define WIN32K_INDEX 0x1000
30 /******* Argument List ************/
31 /* First, define the Databases */
32 #define NativeSystemDb 0
35 /* Now the Service Tables */
36 #define NtosServiceTable 2
37 #define Win32kServiceTable 3
39 /* And finally, the stub files. */
40 #define NtosUserStubs 4
41 #define NtosKernelStubs 5
42 #define Win32kGdiStubs 6
43 #define Win32kUserStubs 7
45 /********** Stub Code ************/
48 * This stubs calls into KUSER_SHARED_DATA where either a
49 * sysenter or interrupt is performed, depending on CPU support.
52 #define UserModeStub_x86 " movl $0x%x, %%eax\n" \
53 " movl $KUSER_SHARED_SYSCALL, %%ecx\n" \
56 #elif defined(_MSC_VER)
57 #define UserModeStub_x86 " asm { \n" \
59 " mov ecx, KUSER_SHARED_SYSCALL\n" \
64 #error Unknown compiler for inline assembler
68 * This stub calls KiSystemService directly with a fake INT2E stack.
69 * Because EIP is pushed during the call, the handler will return here.
72 #define KernelModeStub_x86 " movl $0x%x, %%eax\n" \
73 " leal 4(%%esp), %%edx\n" \
75 " pushl $KERNEL_CS\n" \
76 " call _KiSystemService\n" \
78 #elif defined(_MSC_VER)
79 #define KernelModeStub_x86 " asm { \n" \
81 " lea edx, [esp+4]\n" \
84 " call _KiSystemService\n" \
88 #error Unknown compiler for inline assembler
91 /***** Arch Dependent Stuff ******/
93 #define ARGS_TO_BYTES(x) x*4
94 #define UserModeStub UserModeStub_x86
95 #define KernelModeStub KernelModeStub_x86
98 //#error Unsupported Architecture
101 /* FUNCTIONS ****************************************************************/
106 * Prints out the File Header for a Stub File.
109 * StubFile - Stub File to which to write the header.
111 * FileDescription - Description of the Stub file to which to write the header.
113 * FileLocation - Name of the Stub file to which to write the header.
119 * FileLocation is only used for printing the header.
123 WriteFileHeader(FILE * StubFile
,
124 char* FileDescription
,
127 /* This prints out the file header */
130 " * COPYRIGHT: See COPYING in the top level directory\n"
132 " * PROGRAMMER: Computer Generated File. See tools/nci/ncitool.c\n"
133 " * REMARK: DO NOT EDIT OR COMMIT MODIFICATIONS TO THIS FILE\n"
135 "#include <ndk/asm.h>\n\n",
143 * Prints out the File Header for a Stub File.
146 * StubFile - Stub File to which to write the header.
148 * FileDescription - Description of the Stub file to which to write the header.
150 * FileLocation - Name of the Stub file to which to write the header.
156 * FileLocation is only used for printing the header.
160 WriteStubHeader(FILE* StubFile
,
164 /* Export the function */
165 fprintf(StubFile
, ".global _%s@%d\n", SyscallName
, StackBytes
);
168 fprintf(StubFile
, "_%s@%d:\n\n", SyscallName
, StackBytes
);
173 * WriteKernelModeStub
175 * Prints out the Kernel Mode Stub for a System Call.
178 * StubFile - Stub File to which to write the header.
180 * SyscallName - Name of System Call for which to add the stub.
182 * StackBytes - Number of bytes on the stack to return after doing the system call.
184 * SyscallId - Service Descriptor Table ID for this System Call.
190 * On i386, StackBytes is the number of arguments x 4.
194 WriteKernelModeStub(FILE* StubFile
,
197 unsigned int SyscallId
)
199 /* Write the Stub Header and export the Function */
200 WriteStubHeader(StubFile
, SyscallName
, StackBytes
);
202 /* Write the Stub Code */
203 fprintf(StubFile
, KernelModeStub
, SyscallId
, StackBytes
);
209 * Prints out the User Mode Stub for a System Call.
212 * StubFile - Stub File to which to write the header.
214 * SyscallName - Name of System Call for which to add the stub.
216 * StackBytes - Number of bytes on the stack to return after doing the system call.
218 * SyscallId - Service Descriptor Table ID for this System Call.
224 * On i386, StackBytes is the number of arguments x 4.
228 WriteUserModeStub(FILE* StubFile
,
231 unsigned int SyscallId
)
233 /* Write the Stub Header and export the Function */
234 WriteStubHeader(StubFile
, SyscallName
, StackBytes
);
236 /* Write the Stub Code */
237 fprintf(StubFile
, UserModeStub
, SyscallId
, StackBytes
);
241 * GetNameAndArgumentsFromDb
243 * Parses an entry from a System Call Database, extracting
244 * the function's name and arguments that it takes.
247 * Line - Entry from the Database to parse.
249 * NtSyscallName - Output string to which to save the Function Name
251 * SyscallArguments - Output string to which to save the number of
252 * arguments that the function takes.
258 * On i386, StackBytes is the number of arguments x 4.
262 GetNameAndArgumentsFromDb(char Line
[],
263 char ** NtSyscallName
,
264 char ** SyscallArguments
)
269 /* Remove new line */
270 if ((s
= (char *) strchr(Line
,'\r')) != NULL
) {
274 /* Skip comments (#) and empty lines */
276 if ((*s
) != '#' && (*s
) != '\0') {
278 /* Extract the NtXXX name */
279 *NtSyscallName
= (char *)strtok(s
," \t");
281 /* Extract the argument count */
282 *SyscallArguments
= (char *)strtok(NULL
," \t");
284 /* Remove, if present, the trailing LF */
285 if ((stmp
= strchr(*SyscallArguments
, '\n')) != NULL
) {
291 /* Skip this entry */
292 *NtSyscallName
= NULL
;
293 *SyscallArguments
= NULL
;
300 * Parses a System Call Database and creates stubs for all the entries.
303 * SyscallDb - System Call Database to parse.
305 * UserModeFiles - Array of Usermode Stub Files to which to write the stubs.
307 * KernelModeFile - Kernelmode Stub Files to which to write the stubs.
309 * Index - Name of System Call for which to add the stub.
311 * UserFiles - Number of bytes on the stack to return after doing the system call.
313 * NeedsZw - Service Descriptor Table ID for this System Call.
323 CreateStubs(FILE * SyscallDb
,
324 FILE * UserModeFiles
[],
325 FILE * KernelModeFile
,
330 char Line
[INPUT_BUFFER_SIZE
];
332 char *SyscallArguments
;
336 /* We loop, incrementing the System Call Index, until the end of the file */
337 for (SyscallId
= 0; ((!feof(SyscallDb
)) && (fgets(Line
, sizeof(Line
), SyscallDb
) != NULL
));) {
339 /* Extract the Name and Arguments */
340 GetNameAndArgumentsFromDb(Line
, &NtSyscallName
, &SyscallArguments
);
341 if (SyscallArguments
!= NULL
)
342 StackBytes
= ARGS_TO_BYTES(strtoul(SyscallArguments
, NULL
, 0));
346 /* Make sure we really extracted something */
349 /* Create Usermode Stubs for Nt/Zw syscalls in each Usermode file */
351 for (i
= 0; i
< UserFiles
; i
++) {
353 /* Write the Nt Version */
354 WriteUserModeStub(UserModeFiles
[i
],
359 /* If a Zw Version is needed (was specified), write it too */
362 NtSyscallName
[0] = 'Z';
363 NtSyscallName
[1] = 'w';
364 WriteUserModeStub(UserModeFiles
[i
],
372 /* Create the Kernel coutnerparts (only Zw*, Nt* are the real functions!) */
373 if (KernelModeFile
) {
375 NtSyscallName
[0] = 'Z';
376 NtSyscallName
[1] = 'w';
377 WriteKernelModeStub(KernelModeFile
,
383 /* Only increase if we actually added something */
390 * CreateSystemServiceTable
392 * Parses a System Call Database and creates a System Call Service Table for it.
395 * SyscallDb - System Call Database to parse.
397 * SyscallTable - File in where to create System Call Service Table.
399 * Name - Name of the Service Table.
401 * FileLocation - Filename containing the Table.
407 * FileLocation is only used for the header generation.
411 CreateSystemServiceTable(FILE *SyscallDb
,
416 char Line
[INPUT_BUFFER_SIZE
];
418 char *SyscallArguments
;
421 /* Print the Header */
422 WriteFileHeader(SyscallTable
, "System Call Table for Native API", FileLocation
);
424 /* First we build the SSDT */
425 fprintf(SyscallTable
,"\n\n\n");
426 fprintf(SyscallTable
,"ULONG_PTR %sSSDT[] = {\n", Name
);
428 /* We loop, incrementing the System Call Index, until the end of the file */
429 for (SyscallId
= 0; ((!feof(SyscallDb
)) && (fgets(Line
, sizeof(Line
), SyscallDb
) != NULL
));) {
431 /* Extract the Name and Arguments */
432 GetNameAndArgumentsFromDb(Line
, &NtSyscallName
, &SyscallArguments
);
434 /* Make sure we really extracted something */
438 if (SyscallId
> 0) fprintf(SyscallTable
,",\n");
440 /* Write the syscall name in the service table. */
441 fprintf(SyscallTable
,"\t\t(ULONG_PTR)%s", NtSyscallName
);
443 /* Only increase if we actually added something */
448 /* Close the service table (C syntax) */
449 fprintf(SyscallTable
,"\n};\n");
451 /* Now we build the SSPT */
453 fprintf(SyscallTable
,"\n\n\n");
454 fprintf(SyscallTable
,"UCHAR %sSSPT[] = {\n", Name
);
456 for (SyscallId
= 0; ((!feof(SyscallDb
)) && (fgets(Line
, sizeof(Line
), SyscallDb
) != NULL
));) {
458 /* Extract the Name and Arguments */
459 GetNameAndArgumentsFromDb(Line
, &NtSyscallName
, &SyscallArguments
);
461 /* Make sure we really extracted something */
465 if (SyscallId
> 0) fprintf(SyscallTable
,",\n");
467 /* Write the syscall arguments in the argument table. */
468 if (SyscallArguments
!= NULL
)
469 fprintf(SyscallTable
,"\t\t%lu * sizeof(void *)",strtoul(SyscallArguments
, NULL
, 0));
471 fprintf(SyscallTable
,"\t\t0");
473 /* Only increase if we actually added something */
478 /* Close the service table (C syntax) */
479 fprintf(SyscallTable
,"\n};\n");
482 * We write some useful defines
484 fprintf(SyscallTable
, "\n\n#define MIN_SYSCALL_NUMBER 0\n");
485 fprintf(SyscallTable
, "#define MAX_SYSCALL_NUMBER %d\n", SyscallId
- 1);
486 fprintf(SyscallTable
, "#define NUMBER_OF_SYSCALLS %d\n", SyscallId
);
487 fprintf(SyscallTable
, "ULONG %sNumberOfSysCalls = %d;\n", Name
, SyscallId
);
490 void usage(char * argv0
)
492 printf("Usage: %s sysfuncs.lst w32ksvc.db napi.h ssdt.h napi.S zw.S win32k.S win32k.S\n"
493 " sysfuncs.lst native system functions database\n"
494 " w32ksvc.db native graphic functions database\n"
495 " napi.h NTOSKRNL service table\n"
496 " ssdt.h WIN32K service table\n"
497 " napi.S NTDLL stubs\n"
498 " zw.S NTOSKRNL Zw stubs\n"
499 " win32k.S GDI32 stubs\n"
500 " win32k.S USER32 stubs\n",
505 int main(int argc
, char* argv
[])
507 FILE * Files
[Arguments
];
509 char * OpenType
= "r";
511 /* Make sure all arguments all there */
512 if (argc
!= Arguments
+ 1) {
517 /* Open all Output and bail out if any fail */
518 for (FileNumber
= 0; FileNumber
< Arguments
; FileNumber
++) {
521 if (FileNumber
== 2) OpenType
= "wb";
522 Files
[FileNumber
] = fopen(argv
[FileNumber
+ 1], OpenType
);
524 /* Check for failure and error out if so */
525 if (!Files
[FileNumber
]) {
526 perror(argv
[FileNumber
+ 1]);
532 /* Write the File Headers */
533 WriteFileHeader(Files
[NtosUserStubs
],
534 "System Call Stubs for Native API",
535 argv
[NtosUserStubs
+ 1]);
537 WriteFileHeader(Files
[NtosKernelStubs
],
538 "System Call Stubs for Native API",
539 argv
[NtosKernelStubs
+ 1]);
540 fputs("#include <ndk/asm.h>\n\n", Files
[NtosKernelStubs
]);
542 WriteFileHeader(Files
[Win32kGdiStubs
],
543 "System Call Stubs for Native API",
544 argv
[Win32kGdiStubs
+ 1]);
546 WriteFileHeader(Files
[Win32kUserStubs
],
547 "System Call Stubs for Native API",
548 argv
[Win32kUserStubs
+ 1]);
551 /* Create the System Stubs */
552 CreateStubs(Files
[NativeSystemDb
],
553 &Files
[NtosUserStubs
],
554 Files
[NtosKernelStubs
],
559 /* Create the Graphics Stubs */
560 CreateStubs(Files
[NativeGuiDb
],
561 &Files
[Win32kGdiStubs
],
567 /* Rewind the databases */
568 rewind(Files
[NativeSystemDb
]);
569 rewind(Files
[NativeGuiDb
]);
571 /* Create the Service Tables */
572 CreateSystemServiceTable(Files
[NativeSystemDb
],
573 Files
[NtosServiceTable
],
575 argv
[NtosServiceTable
+ 1]);
577 CreateSystemServiceTable(Files
[NativeGuiDb
],
578 Files
[Win32kServiceTable
],
580 argv
[Win32kServiceTable
+ 1]);
582 /* Close all files */
583 for (FileNumber
= 0; FileNumber
< Arguments
; FileNumber
++) {
586 fclose(Files
[FileNumber
]);