From f6559e22c4aff0e8d8c09a4bb4f11dbd3d1a54ce Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Mon, 17 Jan 2005 07:10:34 +0000 Subject: [PATCH] SYSENTER support, INT2E Optimization, new Syscall Table/Stub generator and svn:ignore fixes. Please read associated Mailing List Post. svn path=/trunk/; revision=13090 --- reactos/Makefile | 26 +- reactos/config | 2 +- reactos/iface/addsys/genw32k.c | 363 ------------ reactos/iface/addsys/makefile | 51 -- reactos/iface/native/genntdll.c | 400 ------------- reactos/iface/native/makefile | 40 -- reactos/iface/native/sysfuncs.lst | 235 -------- reactos/include/napi/shared_data.h | 8 +- reactos/ntoskrnl/Makefile | 2 +- reactos/ntoskrnl/include/internal/i386/ke.h | 1 + reactos/ntoskrnl/include/internal/i386/ps.h | 1 + reactos/ntoskrnl/ke/i386/bthread.S | 2 +- reactos/ntoskrnl/ke/i386/exp.c | 42 +- reactos/ntoskrnl/ke/i386/gdt.c | 6 +- reactos/ntoskrnl/ke/i386/kernel.c | 115 +++- reactos/ntoskrnl/ke/i386/stkswitch.S | 2 +- reactos/ntoskrnl/ke/i386/syscall.S | 539 +++++++++-------- reactos/ntoskrnl/ke/i386/usercall.c | 121 ---- reactos/ntoskrnl/ke/kthread.c | 15 + reactos/ntoskrnl/ke/process.c | 42 ++ reactos/ntoskrnl/ps/i386/continue.c | 19 +- reactos/subsys/system/vmwinst/vmwinst.c | 42 ++ reactos/tools/nci/makefile | 56 ++ reactos/tools/nci/ncitool.c | 556 ++++++++++++++++++ reactos/tools/nci/sysfuncs.lst | 235 ++++++++ .../{iface/addsys => tools/nci}/w32ksvc.db | 0 26 files changed, 1361 insertions(+), 1560 deletions(-) delete mode 100644 reactos/iface/addsys/genw32k.c delete mode 100644 reactos/iface/addsys/makefile delete mode 100644 reactos/iface/native/genntdll.c delete mode 100644 reactos/iface/native/makefile delete mode 100644 reactos/iface/native/sysfuncs.lst create mode 100644 reactos/tools/nci/makefile create mode 100644 reactos/tools/nci/ncitool.c create mode 100644 reactos/tools/nci/sysfuncs.lst rename reactos/{iface/addsys => tools/nci}/w32ksvc.db (100%) diff --git a/reactos/Makefile b/reactos/Makefile index 1ef2941fd5e..3c285fc35ad 100644 --- a/reactos/Makefile +++ b/reactos/Makefile @@ -130,7 +130,7 @@ REGTESTS = regtests all: bootstrap $(BOOT_LOADERS) $(COMPONENTS) $(REGTESTS) $(HALS) $(BUS) $(LIB_FSLIB) \ $(DLLS) $(SUBSYS) $(KERNEL_DRIVERS) $(SYS_APPS) $(SYS_SVC) $(APPS) $(EXT_MODULES) -bootstrap: dk implib iface_native iface_additional +bootstrap: dk implib iface_native depends: $(LIB_STATIC:%=%_depends) $(LIB_FSLIB:%=%_depends) msvcrt_depends $(DLLS:%=%_depends) \ $(SUBSYS:%=%_depends) $(SYS_SVC:%=%_depends) \ @@ -147,7 +147,7 @@ test: $(BOOT_LOADERS:%=%_test) $(COMPONENTS:%=%_test) $(HALS:%=%_test) $(BUS:%=% $(KERNEL_DRIVERS:%=%_test) $(SUBSYS:%=%_test) \ $(SYS_SVC:%=%_test) $(EXT_MODULES:%=%_test) -clean: tools dk_clean iface_native_clean iface_additional_clean hallib_clean \ +clean: tools dk_clean iface_native_clean hallib_clean \ $(BOOT_LOADERS:%=%_clean) $(HALS:%=%_clean) $(COMPONENTS:%=%_clean) \ $(BUS:%=%_clean) $(LIB_STATIC:%=%_clean) $(LIB_FSLIB:%=%_clean) \ msvcrt_clean $(DLLS:%=%_clean) $(KERNEL_DRIVERS:%=%_clean) \ @@ -462,37 +462,21 @@ dk_install: # Interfaces # iface_native: - $(MAKE) --silent -C iface/native + $(MAKE) --silent -C tools/nci iface_native_implib: iface_native_test: iface_native_clean: - $(MAKE) --silent -C iface/native clean + $(MAKE) --silent -C tools/nci clean iface_native_install: iface_native_bootcd: -iface_additional: - $(MAKE) --silent -C iface/addsys - -iface_additional_implib: - -iface_additional_test: - -iface_additional_clean: - $(MAKE) --silent -C iface/addsys clean - -iface_additional_install: - -iface_additional_bootcd: - .PHONY: iface_native iface_native_implib iface_native_test iface_native_clean \ - iface_native_install iface_native_bootcd iface_additional \ - iface_additional_implib iface_additional_test iface_additional_clean \ - iface_additional_install iface_additional_bootcd + iface_native_install iface_native_bootcd # diff --git a/reactos/config b/reactos/config index 8115d3ad193..2057c17290d 100644 --- a/reactos/config +++ b/reactos/config @@ -25,7 +25,7 @@ KDBG := 0 # # Whether to compile for debugging # -DBG := 0 +DBG := 0 # # Whether to compile with optimizations diff --git a/reactos/iface/addsys/genw32k.c b/reactos/iface/addsys/genw32k.c deleted file mode 100644 index 7e5b5bd9612..00000000000 --- a/reactos/iface/addsys/genw32k.c +++ /dev/null @@ -1,363 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS version of ntdll - * FILE: iface/native/genntdll.c - * PURPOSE: Generates the system call stubs in ntdll - * CHANGE HISTORY: Added a '@xx' to deal with stdcall [ Ariadne ] - * 19990616 (ea) - * Four arguments now required; 4th is the file - * for ntoskrnl ZwXXX functions (which are merely calls - * to twin NtXXX calls, via int 0x2e (x86). - * 19990617 (ea) - * Fixed a bug in function numbers in kernel ZwXXX stubs. - * - */ - -/* INCLUDE ******************************************************************/ - -#include -#include -#include - -#define PARAMETERIZED_LIBS - -#define INPUT_BUFFER_SIZE 255 - -#define INDEX 0x1000 /* SSDT index 1 */ - - -/* FUNCTIONS ****************************************************************/ - -void write_stub_header(FILE * out) -{ - fputs - ( - "/* Machine generated, don't edit */\n" - "\n" - "#ifdef __cplusplus\n" - "#define EXTERN_C extern \"C\"\n" - "#else\n" - "#define EXTERN_C\n" - "#endif\n" - "\n" - "EXTERN_C static __inline__ __attribute__((regparm(2)))" - "void*ZwRosSystemServiceThunk(long n,void*a)" - "{" - "void*ret;" - "__asm__" - "(" - "\"int $0x2E\":" - "\"=a\"(ret):" - "\"a\"(n),\"d\"(a)" - ");" - "return ret;" - "}\n", - out - ); -} - -void write_syscall_stub_func(FILE* out, char* name, unsigned nr_args, - unsigned int sys_call_idx) -{ - unsigned i; - - fprintf(out, "EXTERN_C void*__stdcall %s(", name); - - if(nr_args == 0) - fputs("void", out); - else - for(i = 0; i < nr_args; ++ i) - { - if(i > 0) - fputs(",", out); - - fprintf(out, "void*a%u", i); - } - - fputs("){", out); - - if(nr_args > 1) - for(i = 1; i < nr_args; ++ i) - fprintf(out, "(void)a%u;", i); - - fprintf(out, "return ZwRosSystemServiceThunk(%u,", sys_call_idx); - - if(nr_args == 0) - fputs("0", out); - else - fputs("&a0", out); - - fputs(");}\n", out); -} - -void write_syscall_stub(FILE* out1, FILE* out2, char* name, - unsigned nr_args, unsigned int sys_call_idx) -{ - write_syscall_stub_func(out1, name, nr_args, sys_call_idx); - write_syscall_stub_func(out2, name, nr_args, sys_call_idx); -} - -int makeSystemServiceTable(FILE *in, FILE *out) -{ -char line [INPUT_BUFFER_SIZE]; -char *s; -char *name; -int sys_call_idx; -char *snr_args; - - /* - * Main SSDT Header - */ - fprintf(out,"// Machine generated, don't edit\n"); - fprintf(out,"\n\n"); - - /* - * First we build the Win32k SSDT - */ - fprintf(out,"SSDT Win32kSSDT[] = {\n"); - - /* First system call has index zero */ - sys_call_idx = 0; - - /* Go on until EOF or read zero bytes */ - while ((!feof(in))&& (fgets(line, sizeof line, in) != NULL)) - { - if ((s = (char *) strchr(line,'\r')) != NULL) - { - *s = '\0'; - } - /* - * Skip comments (#) and empty lines. - */ - s = & line[0]; - if ((*s) != '#' && (*s) != '\0') - { - /* Extract the NtXXX name */ - name = (char *)strtok(s," \t"); - -#ifdef VERBOSE - printf("%3d \"%s\"\n",sys_call_idx | INDEX,name); -#endif - - if (sys_call_idx > 0) - { - fprintf(out,",\n"); - } - /* - * Now write the current system call's name - * in the service table. - */ - fprintf(out,"\t\t(PVOID (NTAPI *)(VOID))%s",name); - - /* Next system call index */ - sys_call_idx++; - } - } - /* Close the service table (C syntax) */ - fprintf(out,"\n};\n"); - - /* - * Now we build the Win32k SSPT - */ - rewind(in); - fprintf(out,"\n\n"); - fprintf(out,"SSPT Win32kSSPT[] = {\n"); - - /* First system call has index zero */ - sys_call_idx = 0; - - /* Go on until EOF or read zero bytes */ - while ((!feof(in))&& (fgets(line, sizeof line, in) != NULL)) - { - if ((s = (char *) strchr(line,'\r')) != NULL) - { - *s = '\0'; - } - /* - * Skip comments (#) and empty lines. - */ - s = & line[0]; - if ((*s) != '#' && (*s) != '\0') - { - /* Extract the NtXXX name */ - name = (char *)strtok(s," \t"); - /* Extract the stack size */ - snr_args = (char *)strtok(NULL," \t"); - -#ifdef VERBOSE - printf("%3d \"%s\"\n",sys_call_idx|INDEX,name); -#endif - - if (sys_call_idx > 0) - { - fprintf(out,",\n"); - } - /* - * Now write the current system call's ID - * in the service table along with its Parameters Size. - */ - fprintf(out,"\t\t%lu * sizeof(void*)", strtoul(snr_args, NULL, 0)); - - /* Next system call index */ - sys_call_idx++; - } - } - /* - * Close the service table (C syntax) - */ - fprintf(out,"\n};\n"); - - /* - * We write some useful defines - */ - fprintf(out, "\n\n#define MIN_SYSCALL_NUMBER 0\n"); - fprintf(out, "#define MAX_SYSCALL_NUMBER %d\n", sys_call_idx-1); - fprintf(out, "#define NUMBER_OF_SYSCALLS %d\n", sys_call_idx); - fprintf(out, "ULONG Win32kNumberOfSysCalls = %d;\n", sys_call_idx); - - return(0); -} - - -int -process( - FILE * in, - FILE * out1, - FILE * out2 - ) -{ - char line [INPUT_BUFFER_SIZE]; - char * s; - char * name; /* NtXXX name */ - int sys_call_idx; /* NtXXX index number in the service table */ - char * snr_args; /* stack_size / machine_word_size */ - - /* - * GDI32 stubs file header - */ - write_stub_header(out1); - - /* - * USER32 stubs file header - */ - write_stub_header(out2); - - /* - * Scan the database. DB is a text file; each line - * is a record, which contains data for one system - * function. Each record has three columns: - * - * NT_NAME (e.g. NtCreateProcess) - * ZW_NAME (e.g. ZwCreateProcess) - * STACK_SIZE (in machine words: for x[3456]86 - * processors a machine word is 4 bytes) - */ - - /* First system call has index zero */ - sys_call_idx = 0; - while ( - /* Go on until EOF or read zero bytes */ - ( (!feof(in)) - && (fgets(line, sizeof line, in) != NULL) - ) - ) - { - /* - * Remove, if present, the trailing CR. - * (os specific?) - */ - if ((s = (char *) strchr(line,'\r')) != NULL) - { - *s = '\0'; - } - /* - * Skip comments (#) and empty lines. - */ - s = & line[0]; - if ((*s) != '#' && (*s) != '\0') - { - /* Extract the NtXXX name */ - name = (char *)strtok(s," \t"); - /* Extract the stack size */ - snr_args = (char *)strtok(NULL," \t"); - -#ifdef VERBOSE - printf("%3d \"%s\"\n",sys_call_idx | INDEX,name); -#endif - - write_syscall_stub(out1, out2, name, strtoul(snr_args, NULL, 0), sys_call_idx | INDEX); - - /* Next system call index */ - sys_call_idx++; - } - } - - return(0); -} - -void usage(char * argv0) -{ - printf("Usage: %s w32ksvc.db w32k.lst ssdt.h win32k.c win32k.c\n" - " w32ksvc.db input file(system calls database)\n" - " w32k.lst system functions database\n" - " ssdt.h WIN32K service table\n" - " win32k.c GDI32 stubs\n" - " win32k.c USER32 stubs\n", - argv0 - ); -} - -int main(int argc, char* argv[]) -{ - FILE * in; /* System calls database */ - FILE * out1; /* SERVICE_TABLE */ - FILE * out2; /* GDI32 stubs */ - FILE * out3; /* USER32 stubs */ - int ret; - - if (argc != 5) - { - usage(argv[0]); - return(1); - } - - in = fopen(argv[1],"rb"); - if (in == NULL) - { - perror("Failed to open input file (system calls database)"); - return(1); - } - - out1 = fopen(argv[2],"wb"); - if (out1 == NULL) - { - perror("Failed to open output file (WIN32K service table)"); - return(1); - } - - out2 = fopen(argv[3],"wb"); - if (out2 == NULL) - { - perror("Failed to open output file (GDI32 stubs)"); - return(1); - } - - out3 = fopen(argv[4],"wb"); - if (out3 == NULL) - { - perror("Failed to open output file (USER32 stubs)"); - return(1); - } - - ret = process(in,out2,out3); - rewind(in); - ret = makeSystemServiceTable(in, out1); - - fclose(in); - fclose(out1); - fclose(out2); - fclose(out3); - - return(ret); -} diff --git a/reactos/iface/addsys/makefile b/reactos/iface/addsys/makefile deleted file mode 100644 index c7024e2dc85..00000000000 --- a/reactos/iface/addsys/makefile +++ /dev/null @@ -1,51 +0,0 @@ -# $Id$ -# -# ReactOS Operating System -# -# Generate files for a kernel module that needs to add a service table. -# -PATH_TO_TOP = ../.. - -#TARGETNAME = mktab -TARGETNAME = genw32k - -# WIN32K.SYS -SVC_DB=w32ksvc.db -SVC_MASK=0x1000 - -# DOS and Win32 kernels handle Unix paths too. -SVC_SERVICE_TABLE=../../subsys/win32k/main/svctab.c -SVC_GDI_STUBS=../../lib/gdi32/misc/win32k.c -SVC_USER_STUBS=../../lib/user32/misc/win32k.c - -SVC_FILES = $(SVC_GDI_STUBS) $(SVC_USER_STUBS) $(SVC_SERVICE_TABLE) - -CLEAN_FILES = $(TARGETNAME)$(EXE_POSTFIX) $(SVC_FILES) - -BASE_CFLAGS = -I../../include - -CFLAGS += -Wall -Werror - -all: $(SVC_FILES) - -$(TARGETNAME)$(EXE_POSTFIX): $(TARGETNAME).c - $(HOST_CC) \ - $(CFLAGS) \ - -o $(TARGETNAME) \ - -O2 \ - $(TARGETNAME).c - -$(SVC_FILES): $(SVC_DB) $(TARGETNAME)$(EXE_POSTFIX) - @./$(TARGETNAME)$(EXE_POSTFIX) \ - $(SVC_DB) \ - $(SVC_SERVICE_TABLE) \ - $(SVC_GDI_STUBS) \ - $(SVC_USER_STUBS) - - -clean: - - $(RM) $(CLEAN_FILES) - -.PHONY: all clean - -include ../../rules.mak diff --git a/reactos/iface/native/genntdll.c b/reactos/iface/native/genntdll.c deleted file mode 100644 index 3abaee83303..00000000000 --- a/reactos/iface/native/genntdll.c +++ /dev/null @@ -1,400 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS version of ntdll - * FILE: iface/native/genntdll.c - * PURPOSE: Generates the system call stubs in ntdll - * CHANGE HISTORY: Added a '@xx' to deal with stdcall [ Ariadne ] - * 19990616 (ea) - * Four arguments now required; 4th is the file - * for ntoskrnl ZwXXX functions (which are merely calls - * to twin NtXXX calls, via int 0x2e (x86). - * 19990617 (ea) - * Fixed a bug in function numbers in kernel ZwXXX stubs. - * 20040406 (kjkh) - * The sysfuncs.lst file now specifies the number of parameters, - * not their stack size, for obvious portability reastons. Also, we - * now generate real C functions to let the compiler do the correct - * name decoration and whatever else (this also makes this tool - * marginally more portable). - * - */ - -/* INCLUDE ******************************************************************/ - -#include -#include -#include - -#define PARAMETERIZED_LIBS - -/* #define VERBOSE */ - -#define INPUT_BUFFER_SIZE 255 - -/* FUNCTIONS ****************************************************************/ - -void write_stub_header(FILE * out) -{ - fputs - ( - "/* Machine generated, don't edit */\n" - "\n" - "#ifdef __cplusplus\n" - "#define EXTERN_C extern \"C\"\n" - "#else\n" - "#define EXTERN_C\n" - "#endif\n" - "\n" - "EXTERN_C static __inline__ __attribute__((regparm(2)))" - "void*ZwRosSystemServiceThunk(long n,void*a)" - "{" - "void*ret;" - "__asm__" - "(" - "\"int $0x2E\":" - "\"=a\"(ret):" - "\"a\"(n),\"d\"(a)" - ");" - "return ret;" - "}\n", - out - ); -} - -void write_syscall_stub_func(FILE* out, char* name, unsigned nr_args, - unsigned int sys_call_idx) -{ - unsigned i; - - fprintf(out, "EXTERN_C void*__stdcall %s(", name); - - if(nr_args == 0) - fputs("void", out); - else - for(i = 0; i < nr_args; ++ i) - { - if(i > 0) - fputs(",", out); - - fprintf(out, "void*a%u", i); - } - - fputs("){", out); - - if(nr_args > 1) - for(i = 1; i < nr_args; ++ i) - fprintf(out, "(void)a%u;", i); - - fprintf(out, "return ZwRosSystemServiceThunk(%u,", sys_call_idx); - - if(nr_args == 0) - fputs("0", out); - else - fputs("&a0", out); - - fputs(");}\n", out); -} - -void write_syscall_stub(FILE* out, FILE* out3, char* name, char* name2, - unsigned nr_args, unsigned int sys_call_idx) -{ - write_syscall_stub_func(out, name, nr_args, sys_call_idx); - write_syscall_stub_func(out, name2, nr_args, sys_call_idx); - - /* - * Now write the NTOSKRNL stub for the - * current system call. ZwXXX does NOT - * alias the corresponding NtXXX call. - */ - write_syscall_stub_func(out3, name2, nr_args, sys_call_idx); -} - -int makeSystemServiceTable(FILE *in, FILE *out) -{ -char line [INPUT_BUFFER_SIZE]; -char *s; -char *name; -char *name2; -int sys_call_idx; -char *snr_args; -char *stmp; - - /* - * Main SSDT Header - */ - fprintf(out,"/* Machine generated, don't edit */\n"); - fprintf(out,"\n\n"); - - /* - * First we build the Main SSDT - */ - fprintf(out,"\n\n\n"); - fprintf(out,"SSDT MainSSDT[] = {\n"); - - for ( /* First system call has index zero */ - sys_call_idx = 0; - /* Go on until EOF or read zero bytes */ - ( (!feof(in)) - && (fgets(line, sizeof line, in) != NULL) - ); - /* Next system call index */ - sys_call_idx++ - ) - { - if ((s = (char *) strchr(line,'\r')) != NULL) - { - *s = '\0'; - } - /* - * Skip comments (#) and empty lines. - */ - s = & line[0]; - if ((*s) != '#' && (*s) != '\0') - { - /* Extract the NtXXX name */ - name = (char *)strtok(s," \t"); - /* Extract the ZwXXX name */ - name2 = (char *)strtok(NULL," \t"); - //value = strtok(NULL," \t"); - /* Extract the argument count */ - snr_args = (char *)strtok(NULL," \t"); - /* - * Remove, if present, the trailing LF. - */ - if ((stmp = strchr(snr_args, '\n')) != NULL) - { - *stmp = '\0'; - } -#ifdef VERBOSE - printf("%3d \"%s\"\n",sys_call_idx,name); -#endif - - if (sys_call_idx > 0) - { - fprintf(out,",\n"); - } - /* - * Now write the current system call's name - * in the service table. - */ - fprintf(out,"\t\t(PVOID (NTAPI *)(VOID))%s",name); - } - } - /* Close the service table (C syntax) */ - fprintf(out,"\n};\n"); - - /* - * Now we build the Main SSPT - */ - rewind(in); - fprintf(out,"\n\n\n"); - fprintf(out,"SSPT MainSSPT[] = {\n"); - - for ( /* First system call has index zero */ - sys_call_idx = 0; - /* Go on until EOF or read zero bytes */ - ( (!feof(in)) - && (fgets(line, sizeof line, in) != NULL) - ); - /* Next system call index */ - sys_call_idx++ - ) - { - if ((s = (char *) strchr(line,'\r')) != NULL) - { - *s = '\0'; - } - /* - * Skip comments (#) and empty lines. - */ - s = & line[0]; - if ((*s) != '#' && (*s) != '\0') - { - /* Extract the NtXXX name */ - name = (char *)strtok(s," \t"); - /* Extract the ZwXXX name */ - name2 = (char *)strtok(NULL," \t"); - //value = strtok(NULL," \t"); - /* Extract the argument count */ - snr_args = (char *)strtok(NULL," \t"); -#ifdef VERBOSE - printf("%3d \"%s\"\n",sys_call_idx,name); -#endif - - if (sys_call_idx > 0) - { - fprintf(out,",\n"); - } - /* - * Now write the current system call's ID - * in the service table along with its Parameters Size. - */ - fprintf(out,"\t\t%lu * sizeof(void *)",strtoul(snr_args, NULL, 0)); - } - } - /* - * Close the service table (C syntax) - */ - fprintf(out,"\n};\n"); - - /* - * We write some useful defines - */ - fprintf(out, "\n\n#define MIN_SYSCALL_NUMBER 0\n"); - fprintf(out, "#define MAX_SYSCALL_NUMBER %d\n", sys_call_idx-1); - fprintf(out, "#define NUMBER_OF_SYSCALLS %d\n", sys_call_idx); - - return(0); -} - - -int -process( - FILE * in, - FILE * out, - FILE * out2, - FILE * out3 - ) -{ - char line [INPUT_BUFFER_SIZE]; - char * s; - char * name; /* NtXXX name */ - char * name2; /* ZwXXX name */ - int sys_call_idx; /* NtXXX index number in the service table */ - char * snr_args; /* stack_size / machine_word_size */ - - /* - * NTDLL stubs file header - */ - write_stub_header(out); - - /* - * NTOSKRNL Zw functions stubs header - */ - write_stub_header(out3); - - /* - * Scan the database. DB is a text file; each line - * is a record, which contains data for one system - * function. Each record has three columns: - * - * NT_NAME (e.g. NtCreateProcess) - * ZW_NAME (e.g. ZwCreateProcess) - * STACK_SIZE (in machine words: for x[3456]86 - * processors a machine word is 4 bytes) - */ - for ( /* First system call has index zero */ - sys_call_idx = 0; - /* Go on until EOF or read zero bytes */ - ( (!feof(in)) - && (fgets(line, sizeof line, in) != NULL) - ); - /* Next system call index */ - sys_call_idx++ - ) - { - /* - * Remove, if present, the trailing CR. - * (os specific?) - */ - if ((s = (char *) strchr(line,'\r')) != NULL) - { - *s = '\0'; - } - /* - * Skip comments (#) and empty lines. - */ - s = & line[0]; - if ((*s) != '#' && (*s) != '\0') - { - unsigned nr_args; - - /* Extract the NtXXX name */ - name = (char *)strtok(s," \t"); - /* Extract the ZwXXX name */ - name2 = (char *)strtok(NULL," \t"); - //value = strtok(NULL," \t"); - /* Extract the argument count */ - snr_args = (char *)strtok(NULL," \t"); - nr_args = strtoul(snr_args, NULL, 0); -#ifdef VERBOSE - printf("%3d \"%s\"\n",sys_call_idx,name); -#endif - /* - * Write the NTDLL stub for the current - * system call: NtXXX and ZwXXX symbols - * are aliases. - */ - write_syscall_stub(out, out3, name, name2, - nr_args, sys_call_idx); - } - } - - return(0); -} - -void usage(char * argv0) -{ - printf("Usage: %s sysfuncs.lst napi.c napi.h zw.c\n" - " sysfuncs.lst system functions database\n" - " napi.c NTDLL stubs\n" - " napi.h NTOSKRNL service table\n" - " zw.c NTOSKRNL Zw stubs\n", - argv0 - ); -} - -int main(int argc, char* argv[]) -{ - FILE * in; /* System calls database */ - FILE * out1; /* NTDLL stubs */ - FILE * out2; /* SERVICE_TABLE */ - FILE * out3; /* NTOSKRNL Zw stubs */ - int ret; - - if (argc != 5) - { - usage(argv[0]); - return(1); - } - - in = fopen(argv[1],"rb"); - if (in == NULL) - { - perror("Failed to open input file (system calls database)"); - return(1); - } - - out1 = fopen(argv[2],"wb"); - if (out1 == NULL) - { - perror("Failed to open output file (NTDLL stubs)"); - return(1); - } - - out2 = fopen(argv[3],"wb"); - if (out2 == NULL) - { - perror("Failed to open output file (NTOSKRNL service table)"); - return(1); - } - - out3 = fopen(argv[4],"wb"); - if (out3 == NULL) - { - perror("Failed to open output file (NTOSKRNL Zw stubs)"); - return(1); - } - - ret = process(in,out1,out2,out3); - rewind(in); - ret = makeSystemServiceTable(in, out2); - - fclose(in); - fclose(out1); - fclose(out2); - fclose(out3); - - return(ret); -} diff --git a/reactos/iface/native/makefile b/reactos/iface/native/makefile deleted file mode 100644 index 673de20552e..00000000000 --- a/reactos/iface/native/makefile +++ /dev/null @@ -1,40 +0,0 @@ -# $Id$ -# -# ReactOS Operating System -# -# Generate: -# - genntdll -# - ntoskrnl.exe service table; -# - ntoskrnl.exe Zw functions stubs to call Nt functions from kernel mode; -# - ntdll.dll stubs to call system functions from user mode applications. -# -PATH_TO_TOP = ../.. - -TARGET = genntdll -SYSTEM_CALLS_DB = sysfuncs.lst -NTDLL_STUBS = ../../lib/ntdll/napi.c -KERNEL_SERVICE_TABLE = ../../include/ntdll/napi.h -KERNEL_ZW_CALLS = ../../ntoskrnl/ex/zw.c -NAPI_FILES = $(NTDLL_STUBS) $(KERNEL_SERVICE_TABLE) $(KERNEL_ZW_CALLS) - -BASE_CFLAGS = -I../../include - -all: $(TARGET)$(EXE_POSTFIX) $(NAPI_FILES) - -$(NAPI_FILES): $(SYSTEM_CALLS_DB) $(TARGET)$(EXE_POSTFIX) - @./$(TARGET)$(EXE_POSTFIX) \ - $(SYSTEM_CALLS_DB) \ - $(NTDLL_STUBS) \ - $(KERNEL_SERVICE_TABLE) \ - $(KERNEL_ZW_CALLS) - -# (rjj) i removed the following option from line below: -If:\gnu\mingw32\include -$(TARGET)$(EXE_POSTFIX): $(TARGET).c - $(HOST_CC) -g -Wall -Werror $(TARGET).c -o $(TARGET)$(EXE_POSTFIX) - -clean: - - $(RM) $(TARGET)$(EXE_POSTFIX) $(NTDLL_STUBS) $(KERNEL_SERVICE_TABLE) $(KERNEL_ZW_CALLS) - -.PHONY: all clean - -include ../../rules.mak diff --git a/reactos/iface/native/sysfuncs.lst b/reactos/iface/native/sysfuncs.lst deleted file mode 100644 index 83e776aeb57..00000000000 --- a/reactos/iface/native/sysfuncs.lst +++ /dev/null @@ -1,235 +0,0 @@ -NtAcceptConnectPort ZwAcceptConnectPort 6 -NtAccessCheck ZwAccessCheck 8 -NtAccessCheckAndAuditAlarm ZwAccessCheckAndAuditAlarm 11 -NtAddAtom ZwAddAtom 3 -NtAddBootEntry ZwAddBootEntry 2 -NtAdjustGroupsToken ZwAdjustGroupsToken 6 -NtAdjustPrivilegesToken ZwAdjustPrivilegesToken 6 -NtAlertResumeThread ZwAlertResumeThread 2 -NtAlertThread ZwAlertThread 1 -NtAllocateLocallyUniqueId ZwAllocateLocallyUniqueId 1 -NtAllocateUuids ZwAllocateUuids 4 -NtAllocateVirtualMemory ZwAllocateVirtualMemory 6 -NtAssignProcessToJobObject ZwAssignProcessToJobObject 2 -NtCallbackReturn ZwCallbackReturn 3 -NtCancelIoFile ZwCancelIoFile 2 -NtCancelTimer ZwCancelTimer 2 -NtClearEvent ZwClearEvent 1 -NtClose ZwClose 1 -NtCloseObjectAuditAlarm ZwCloseObjectAuditAlarm 3 -NtCompleteConnectPort ZwCompleteConnectPort 1 -NtConnectPort ZwConnectPort 8 -NtContinue ZwContinue 2 -NtCreateDirectoryObject ZwCreateDirectoryObject 3 -NtCreateEvent ZwCreateEvent 5 -NtCreateEventPair ZwCreateEventPair 3 -NtCreateFile ZwCreateFile 11 -NtCreateIoCompletion ZwCreateIoCompletion 4 -NtCreateJobObject ZwCreateJobObject 3 -NtCreateKey ZwCreateKey 7 -NtCreateMailslotFile ZwCreateMailslotFile 8 -NtCreateMutant ZwCreateMutant 4 -NtCreateNamedPipeFile ZwCreateNamedPipeFile 14 -NtCreatePagingFile ZwCreatePagingFile 4 -NtCreatePort ZwCreatePort 5 -NtCreateProcess ZwCreateProcess 8 -NtCreateProfile ZwCreateProfile 9 -NtCreateSection ZwCreateSection 7 -NtCreateSemaphore ZwCreateSemaphore 5 -NtCreateSymbolicLinkObject ZwCreateSymbolicLinkObject 4 -NtCreateThread ZwCreateThread 8 -NtCreateTimer ZwCreateTimer 4 -NtCreateToken ZwCreateToken 13 -NtCreateWaitablePort ZwCreateWaitablePort 5 -NtDelayExecution ZwDelayExecution 2 -NtDeleteAtom ZwDeleteAtom 1 -NtDeleteBootEntry ZwDeleteBootEntry 2 -NtDeleteFile ZwDeleteFile 1 -NtDeleteKey ZwDeleteKey 1 -NtDeleteObjectAuditAlarm ZwDeleteObjectAuditAlarm 3 -NtDeleteValueKey ZwDeleteValueKey 2 -NtDeviceIoControlFile ZwDeviceIoControlFile 10 -NtDisplayString ZwDisplayString 1 -NtDuplicateObject ZwDuplicateObject 7 -NtDuplicateToken ZwDuplicateToken 6 -NtEnumerateBootEntries ZwEnumerateBootEntries 2 -NtEnumerateKey ZwEnumerateKey 6 -NtEnumerateValueKey ZwEnumerateValueKey 6 -NtExtendSection ZwExtendSection 2 -NtFindAtom ZwFindAtom 3 -NtFlushBuffersFile ZwFlushBuffersFile 2 -NtFlushInstructionCache ZwFlushInstructionCache 3 -NtFlushKey ZwFlushKey 1 -NtFlushVirtualMemory ZwFlushVirtualMemory 4 -NtFlushWriteBuffer ZwFlushWriteBuffer 0 -NtFreeVirtualMemory ZwFreeVirtualMemory 4 -NtFsControlFile ZwFsControlFile 10 -NtGetContextThread ZwGetContextThread 2 -NtGetPlugPlayEvent ZwGetPlugPlayEvent 4 -NtGetTickCount ZwGetTickCount 0 -NtImpersonateClientOfPort ZwImpersonateClientOfPort 2 -NtImpersonateThread ZwImpersonateThread 3 -NtInitializeRegistry ZwInitializeRegistry 1 -NtInitiatePowerAction ZwInitiatePowerAction 4 -NtIsProcessInJob ZwIsProcessInJob 2 -NtListenPort ZwListenPort 2 -NtLoadDriver ZwLoadDriver 1 -NtLoadKey ZwLoadKey 2 -NtLoadKey2 ZwLoadKey2 3 -NtLockFile ZwLockFile 10 -NtLockVirtualMemory ZwLockVirtualMemory 4 -NtMakePermanentObject ZwMakePermanentObject 1 -NtMakeTemporaryObject ZwMakeTemporaryObject 1 -NtMapViewOfSection ZwMapViewOfSection 10 -NtNotifyChangeDirectoryFile ZwNotifyChangeDirectoryFile 9 -NtNotifyChangeKey ZwNotifyChangeKey 10 -NtOpenDirectoryObject ZwOpenDirectoryObject 3 -NtOpenEvent ZwOpenEvent 3 -NtOpenEventPair ZwOpenEventPair 3 -NtOpenFile ZwOpenFile 6 -NtOpenIoCompletion ZwOpenIoCompletion 3 -NtOpenJobObject ZwOpenJobObject 3 -NtOpenKey ZwOpenKey 3 -NtOpenMutant ZwOpenMutant 3 -NtOpenObjectAuditAlarm ZwOpenObjectAuditAlarm 12 -NtOpenProcess ZwOpenProcess 4 -NtOpenProcessToken ZwOpenProcessToken 3 -NtOpenProcessTokenEx ZwOpenProcessTokenEx 4 -NtOpenSection ZwOpenSection 3 -NtOpenSemaphore ZwOpenSemaphore 3 -NtOpenSymbolicLinkObject ZwOpenSymbolicLinkObject 3 -NtOpenThread ZwOpenThread 4 -NtOpenThreadToken ZwOpenThreadToken 4 -NtOpenThreadTokenEx ZwOpenThreadTokenEx 5 -NtOpenTimer ZwOpenTimer 3 -NtPlugPlayControl ZwPlugPlayControl 4 -NtPowerInformation ZwPowerInformation 5 -NtPrivilegeCheck ZwPrivilegeCheck 3 -NtPrivilegedServiceAuditAlarm ZwPrivilegedServiceAuditAlarm 5 -NtPrivilegeObjectAuditAlarm ZwPrivilegeObjectAuditAlarm 6 -NtProtectVirtualMemory ZwProtectVirtualMemory 5 -NtPulseEvent ZwPulseEvent 2 -NtQueryInformationAtom ZwQueryInformationAtom 5 -NtQueryAttributesFile ZwQueryAttributesFile 2 -NtQueryBootEntryOrder ZwQueryBootEntryOrder 2 -NtQueryBootOptions ZwQueryBootOptions 2 -NtQueryDefaultLocale ZwQueryDefaultLocale 2 -NtQueryDefaultUILanguage ZwQueryDefaultUILanguage 1 -NtQueryDirectoryFile ZwQueryDirectoryFile 11 -NtQueryDirectoryObject ZwQueryDirectoryObject 7 -NtQueryEaFile ZwQueryEaFile 9 -NtQueryEvent ZwQueryEvent 5 -NtQueryFullAttributesFile ZwQueryFullAttributesFile 2 -NtQueryInformationFile ZwQueryInformationFile 5 -NtQueryInformationJobObject ZwQueryInformationJobObject 5 -NtQueryInformationPort ZwQueryInformationPort 5 -NtQueryInformationProcess ZwQueryInformationProcess 5 -NtQueryInformationThread ZwQueryInformationThread 5 -NtQueryInformationToken ZwQueryInformationToken 5 -NtQueryInstallUILanguage ZwQueryInstallUILanguage 1 -NtQueryIntervalProfile ZwQueryIntervalProfile 2 -NtQueryIoCompletion ZwQueryIoCompletion 5 -NtQueryKey ZwQueryKey 5 -NtQueryMultipleValueKey ZwQueryMultipleValueKey 6 -NtQueryMutant ZwQueryMutant 5 -NtQueryObject ZwQueryObject 5 -NtQueryOleDirectoryFile ZwQueryOleDirectoryFile 11 -NtQueryPerformanceCounter ZwQueryPerformanceCounter 2 -NtQueryQuotaInformationFile ZwQueryQuotaInformationFile 9 -NtQuerySection ZwQuerySection 5 -NtQuerySecurityObject ZwQuerySecurityObject 5 -NtQuerySemaphore ZwQuerySemaphore 5 -NtQuerySymbolicLinkObject ZwQuerySymbolicLinkObject 3 -NtQuerySystemEnvironmentValue ZwQuerySystemEnvironmentValue 4 -NtQuerySystemInformation ZwQuerySystemInformation 4 -NtQuerySystemTime ZwQuerySystemTime 1 -NtQueryTimer ZwQueryTimer 5 -NtQueryTimerResolution ZwQueryTimerResolution 3 -NtQueryValueKey ZwQueryValueKey 6 -NtQueryVirtualMemory ZwQueryVirtualMemory 6 -NtQueryVolumeInformationFile ZwQueryVolumeInformationFile 5 -NtQueueApcThread ZwQueueApcThread 5 -NtRaiseException ZwRaiseException 3 -NtRaiseHardError ZwRaiseHardError 6 -NtReadFile ZwReadFile 9 -NtReadFileScatter ZwReadFileScatter 9 -NtReadRequestData ZwReadRequestData 6 -NtReadVirtualMemory ZwReadVirtualMemory 5 -NtRegisterThreadTerminatePort ZwRegisterThreadTerminatePort 1 -NtReleaseMutant ZwReleaseMutant 2 -NtReleaseSemaphore ZwReleaseSemaphore 3 -NtRemoveIoCompletion ZwRemoveIoCompletion 5 -NtReplaceKey ZwReplaceKey 3 -NtReplyPort ZwReplyPort 2 -NtReplyWaitReceivePort ZwReplyWaitReceivePort 4 -NtReplyWaitReplyPort ZwReplyWaitReplyPort 2 -NtRequestPort ZwRequestPort 2 -NtRequestWaitReplyPort ZwRequestWaitReplyPort 3 -NtResetEvent ZwResetEvent 2 -NtRestoreKey ZwRestoreKey 3 -NtResumeThread ZwResumeThread 2 -NtSaveKey ZwSaveKey 2 -NtSaveKeyEx ZwSaveKeyEx 3 -NtSetBootEntryOrder ZwSetBootEntryOrder 2 -NtSetBootOptions ZwSetBootOptions 2 -NtSetIoCompletion ZwSetIoCompletion 5 -NtSetContextThread ZwSetContextThread 2 -NtSetDefaultHardErrorPort ZwSetDefaultHardErrorPort 1 -NtSetDefaultLocale ZwSetDefaultLocale 2 -NtSetDefaultUILanguage ZwSetDefaultUILanguage 1 -NtSetEaFile ZwSetEaFile 4 -NtSetEvent ZwSetEvent 2 -NtSetHighEventPair ZwSetHighEventPair 1 -NtSetHighWaitLowEventPair ZwSetHighWaitLowEventPair 1 -NtSetHighWaitLowThread ZwSetHighWaitLowThread 0 -NtSetInformationFile ZwSetInformationFile 5 -NtSetInformationKey ZwSetInformationKey 4 -NtSetInformationJobObject ZwSetInformationJobObject 4 -NtSetInformationObject ZwSetInformationObject 4 -NtSetInformationProcess ZwSetInformationProcess 4 -NtSetInformationThread ZwSetInformationThread 4 -NtSetInformationToken ZwSetInformationToken 4 -NtSetIntervalProfile ZwSetIntervalProfile 2 -NtSetLdtEntries ZwSetLdtEntries 6 -NtSetLowEventPair ZwSetLowEventPair 1 -NtSetLowWaitHighEventPair ZwSetLowWaitHighEventPair 1 -NtSetLowWaitHighThread ZwSetLowWaitHighThread 0 -NtSetQuotaInformationFile ZwSetQuotaInformationFile 4 -NtSetSecurityObject ZwSetSecurityObject 3 -NtSetSystemEnvironmentValue ZwSetSystemEnvironmentValue 2 -NtSetSystemInformation ZwSetSystemInformation 3 -NtSetSystemPowerState ZwSetSystemPowerState 3 -NtSetSystemTime ZwSetSystemTime 2 -NtSetTimer ZwSetTimer 7 -NtSetTimerResolution ZwSetTimerResolution 3 -NtSetUuidSeed ZwSetUuidSeed 1 -NtSetValueKey ZwSetValueKey 6 -NtSetVolumeInformationFile ZwSetVolumeInformationFile 5 -NtShutdownSystem ZwShutdownSystem 1 -NtSignalAndWaitForSingleObject ZwSignalAndWaitForSingleObject 4 -NtStartProfile ZwStartProfile 1 -NtStopProfile ZwStopProfile 1 -NtSuspendThread ZwSuspendThread 2 -NtSystemDebugControl ZwSystemDebugControl 6 -NtTerminateJobObject ZwTerminateJobObject 2 -NtTerminateProcess ZwTerminateProcess 2 -NtTerminateThread ZwTerminateThread 2 -NtTestAlert ZwTestAlert 0 -NtTraceEvent ZwTraceEvent 4 -NtTranslateFilePath ZwTranslateFilePath 3 -NtUnloadDriver ZwUnloadDriver 1 -NtUnloadKey ZwUnloadKey 1 -NtUnlockFile ZwUnlockFile 5 -NtUnlockVirtualMemory ZwUnlockVirtualMemory 4 -NtUnmapViewOfSection ZwUnmapViewOfSection 2 -NtVdmControl ZwVdmControl 2 -NtWaitForMultipleObjects ZwWaitForMultipleObjects 5 -NtWaitForSingleObject ZwWaitForSingleObject 3 -NtWaitHighEventPair ZwWaitHighEventPair 1 -NtWaitLowEventPair ZwWaitLowEventPair 1 -NtWriteFile ZwWriteFile 9 -NtWriteFileGather ZwWriteFileGather 9 -NtWriteRequestData ZwWriteRequestData 6 -NtWriteVirtualMemory ZwWriteVirtualMemory 5 -NtW32Call ZwW32Call 5 -NtYieldExecution ZwYieldExecution 0 diff --git a/reactos/include/napi/shared_data.h b/reactos/include/napi/shared_data.h index acb1baa2956..10e5209dcb5 100644 --- a/reactos/include/napi/shared_data.h +++ b/reactos/include/napi/shared_data.h @@ -13,6 +13,8 @@ #define PF_PAE_ENABLED 9 #define PF_XMMI64_INSTRUCTIONS_AVAILABLE 10 +#ifndef __ASM__ + typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE { StandardDesign, @@ -62,13 +64,15 @@ typedef struct _KUSER_SHARED_DATA { BOOLEAN SafeBootMode; ULONG TraceLogging; ULONGLONG Fill0; - ULONGLONG SystemCall[4]; + UCHAR SystemCall[16]; union { volatile KSYSTEM_TIME TickCount; volatile ULONG64 TickCountQuad; }; } KUSER_SHARED_DATA, *PKUSER_SHARED_DATA; +#endif + /* Values for DosDeviceDriveType */ #define DOSDEVICE_DRIVE_UNKNOWN 0 #define DOSDEVICE_DRIVE_CALCULATE 1 @@ -102,5 +106,7 @@ typedef struct _KUSER_SHARED_DATA { #define SharedUserData ((KUSER_SHARED_DATA * const)USER_SHARED_DATA) #endif +#define KUSER_SHARED_SYSCALL 0x7FFE0300 +#define KUSER_SHARED_SYSCALL_RET 0x7FFE0304 #endif /* __INCLUDE_NAPI_SHARED_DATA_H */ diff --git a/reactos/ntoskrnl/Makefile b/reactos/ntoskrnl/Makefile index 5c3484108a5..b5c94b6e8c5 100644 --- a/reactos/ntoskrnl/Makefile +++ b/reactos/ntoskrnl/Makefile @@ -550,7 +550,7 @@ TARGET_CLEAN = \ $(PATH_TO_TOP)/include/reactos/bugcodes.h \ $(DEP_OBJECTS) $(DEP_FILES) MSG00409.bin bugcodes.rc -ex/napi.o: ex/napi.c $(PATH_TO_TOP)/include/ntdll/napi.h +ex/napi.o: ex/zw.S $(PATH_TO_TOP)/include/ntdll/napi.h ke/main.o: ke/main.c $(PATH_TO_TOP)/include/reactos/buildno.h diff --git a/reactos/ntoskrnl/include/internal/i386/ke.h b/reactos/ntoskrnl/include/internal/i386/ke.h index 23d7d1c4b37..9f0bf8d86e4 100644 --- a/reactos/ntoskrnl/include/internal/i386/ke.h +++ b/reactos/ntoskrnl/include/internal/i386/ke.h @@ -88,6 +88,7 @@ #define X86_FEATURE_TSC 0x00000010 /* time stamp counters are present */ #define X86_FEATURE_PAE 0x00000040 /* physical address extension is present */ #define X86_FEATURE_CX8 0x00000100 /* CMPXCHG8B instruction present */ +#define X86_FEATURE_SYSCALL 0x00000800 /* SYSCALL/SYSRET support present */ #define X86_FEATURE_PGE 0x00002000 /* Page Global Enable */ #define X86_FEATURE_MMX 0x00800000 /* MMX extension present */ #define X86_FEATURE_FXSR 0x01000000 /* FXSAVE/FXRSTOR instructions present */ diff --git a/reactos/ntoskrnl/include/internal/i386/ps.h b/reactos/ntoskrnl/include/internal/i386/ps.h index c379029a83c..f6cf2dc6bc7 100644 --- a/reactos/ntoskrnl/include/internal/i386/ps.h +++ b/reactos/ntoskrnl/include/internal/i386/ps.h @@ -27,6 +27,7 @@ #define KTHREAD_TEB 0x20 #define KTHREAD_KERNEL_STACK 0x28 #define KTHREAD_NPX_STATE 0x31 +#define KTHREAD_PENDING_USER_APC 0x34 + 0x16 #define KTHREAD_APCSTATE_PROCESS 0x44 #define KTHREAD_SERVICE_TABLE 0xDC #define KTHREAD_PREVIOUS_MODE 0x137 diff --git a/reactos/ntoskrnl/ke/i386/bthread.S b/reactos/ntoskrnl/ke/i386/bthread.S index 54b6abc1714..b0139e9e491 100644 --- a/reactos/ntoskrnl/ke/i386/bthread.S +++ b/reactos/ntoskrnl/ke/i386/bthread.S @@ -143,4 +143,4 @@ _PsBeginThreadWithContextInternal: /* Load the rest of the thread's user mode context. */ movl $0, %eax - jmp KeReturnFromSystemCallWithHook + jmp _KiServiceExit diff --git a/reactos/ntoskrnl/ke/i386/exp.c b/reactos/ntoskrnl/ke/i386/exp.c index 31cb44aa2b9..97c451ddd18 100644 --- a/reactos/ntoskrnl/ke/i386/exp.c +++ b/reactos/ntoskrnl/ke/i386/exp.c @@ -45,7 +45,7 @@ # define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0])) #endif -extern void interrupt_handler2e(void); +extern void KiSystemService(void); extern void interrupt_handler2d(void); extern VOID KiTrap0(VOID); @@ -850,7 +850,7 @@ KeInitExceptions(VOID) } set_system_call_gate(0x2d,(int)interrupt_handler2d); - set_system_call_gate(0x2e,(int)interrupt_handler2e); + set_system_call_gate(0x2e,(int)KiSystemService); } /* @@ -873,30 +873,32 @@ KeRaiseUserException(IN NTSTATUS ExceptionCode) return((NTSTATUS)OldEip); } -VOID -FASTCALL -KeRosTrapReturn ( PKTRAP_FRAME TrapFrame, PKTRAP_FRAME PrevTrapFrame ); - /* * @implemented */ -NTSTATUS STDCALL +NTSTATUS +STDCALL NtRaiseException ( - IN PEXCEPTION_RECORD ExceptionRecord, - IN PCONTEXT Context, - IN BOOLEAN SearchFrames) + IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT Context, + IN BOOLEAN SearchFrames) { - PKTRAP_FRAME TrapFrame = KeGetCurrentThread()->TrapFrame; - PKTRAP_FRAME PrevTrapFrame = (PKTRAP_FRAME)TrapFrame->Edx; + PKTHREAD Thread = KeGetCurrentThread(); + PKTRAP_FRAME TrapFrame = Thread->TrapFrame; + PKTRAP_FRAME PrevTrapFrame = (PKTRAP_FRAME)TrapFrame->Edx; - KeGetCurrentKPCR()->Tib.ExceptionList = TrapFrame->ExceptionList; + KeGetCurrentKPCR()->Tib.ExceptionList = TrapFrame->ExceptionList; - KiDispatchException(ExceptionRecord, - Context, - PsGetCurrentThread()->Tcb.TrapFrame, - (KPROCESSOR_MODE)ExGetPreviousMode(), - SearchFrames); + KiDispatchException(ExceptionRecord, + Context, + TrapFrame, + KeGetPreviousMode(), + SearchFrames); - KeRosTrapReturn ( TrapFrame, PrevTrapFrame ); - return(STATUS_SUCCESS); + /* Restore the user context */ + Thread->TrapFrame = PrevTrapFrame; + __asm__("mov %%ebx, %%esp;\n" "jmp _KiServiceExit": : "b" (TrapFrame)); + + /* We never get here */ + return(STATUS_SUCCESS); } diff --git a/reactos/ntoskrnl/ke/i386/gdt.c b/reactos/ntoskrnl/ke/i386/gdt.c index ac06f5c1b22..e98b138ecf4 100644 --- a/reactos/ntoskrnl/ke/i386/gdt.c +++ b/reactos/ntoskrnl/ke/i386/gdt.c @@ -40,10 +40,10 @@ USHORT KiBootGdt[11 * 4] = 0x0, 0x0, 0x0, 0x0, /* Null */ 0xffff, 0x0, 0x9a00, 0xcf, /* Kernel CS */ 0xffff, 0x0, 0x9200, 0xcf, /* Kernel DS */ - 0x0, 0x0, 0xfa00, 0xcc, /* User CS */ - 0x0, 0x0, 0xf200, 0xcc, /* User DS */ + 0x0, 0x0, 0xfa00, 0xcf, /* User CS */ + 0x0, 0x0, 0xf200, 0xcf, /* User DS */ 0x0, 0x0, 0x0, 0x0, /* TSS */ - 0x1000, 0x0000, 0x9200, 0xff00, /* PCR */ + 0x1000, 0x0000, 0x9200, 0xffc0, /* PCR */ 0x1000, 0x0, 0xf200, 0x0, /* TEB */ 0x0, 0x0, 0x0, 0x0, /* Reserved */ 0x0, 0x0, 0x0, 0x0, /* LDT */ diff --git a/reactos/ntoskrnl/ke/i386/kernel.c b/reactos/ntoskrnl/ke/i386/kernel.c index fc0eba13e61..c719aae7ff8 100644 --- a/reactos/ntoskrnl/ke/i386/kernel.c +++ b/reactos/ntoskrnl/ke/i386/kernel.c @@ -43,6 +43,7 @@ BOOLEAN Ke386NoExecute = FALSE; BOOLEAN Ke386Pae = FALSE; BOOLEAN Ke386PaeEnabled = FALSE; BOOLEAN Ke386GlobalPagesEnabled = FALSE; +ULONG KiFastSystemCallDisable = 0; /* FUNCTIONS *****************************************************************/ @@ -323,6 +324,18 @@ KeInit1(PCHAR CommandLine, PULONG LastKernelAddress) MiEnablePAE((PVOID*)LastKernelAddress); Ke386PaeEnabled = TRUE; } + + if (KPCR->PrcbData.FeatureBits & X86_FEATURE_SYSCALL) + { + extern void KiFastCallEntry(void); + + /* CS Selector of the target segment. */ + Ke386Wrmsr(0x174, KERNEL_CS, 0); + /* Target ESP. */ + Ke386Wrmsr(0x175, 0, 0); + /* Target EIP. */ + Ke386Wrmsr(0x176, (ULONG_PTR)KiFastCallEntry, 0); + } } VOID INIT_FUNCTION @@ -391,23 +404,89 @@ KeInit2(VOID) VOID INIT_FUNCTION Ki386SetProcessorFeatures(VOID) { - PKPCR Pcr = KeGetCurrentKPCR(); + PKPCR Pcr = KeGetCurrentKPCR(); + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING KeyName; + UNICODE_STRING ValueName; + HANDLE KeyHandle; + ULONG ResultLength; + KEY_VALUE_PARTIAL_INFORMATION ValueData; + NTSTATUS Status; - SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = FALSE; - SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = FALSE; - SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = - (Pcr->PrcbData.FeatureBits & X86_FEATURE_CX8); - SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = - (Pcr->PrcbData.FeatureBits & X86_FEATURE_MMX); - SharedUserData->ProcessorFeatures[PF_PPC_MOVEMEM_64BIT_OK] = FALSE; - SharedUserData->ProcessorFeatures[PF_ALPHA_BYTE_INSTRUCTIONS] = FALSE; - SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] = - (Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE); - SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] = - (Ke386CpuidExFlags & X86_EXT_FEATURE_3DNOW); - SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = - (Pcr->PrcbData.FeatureBits & X86_FEATURE_TSC); - SharedUserData->ProcessorFeatures[PF_PAE_ENABLED] = Ke386PaeEnabled; - SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = - (Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE2); + SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = FALSE; + SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = FALSE; + SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = + (Pcr->PrcbData.FeatureBits & X86_FEATURE_CX8); + SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = + (Pcr->PrcbData.FeatureBits & X86_FEATURE_MMX); + SharedUserData->ProcessorFeatures[PF_PPC_MOVEMEM_64BIT_OK] = FALSE; + SharedUserData->ProcessorFeatures[PF_ALPHA_BYTE_INSTRUCTIONS] = FALSE; + SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] = + (Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE); + SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] = + (Ke386CpuidExFlags & X86_EXT_FEATURE_3DNOW); + SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = + (Pcr->PrcbData.FeatureBits & X86_FEATURE_TSC); + SharedUserData->ProcessorFeatures[PF_PAE_ENABLED] = Ke386PaeEnabled; + SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = + (Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE2); + + /* Does the CPU Support Fast System Call? */ + if (Pcr->PrcbData.FeatureBits & X86_FEATURE_SYSCALL) { + + /* FIXME: Check for Family == 6, Model < 3 and Stepping < 3 and disable */ + + /* Make sure it's not disabled in registry */ + RtlRosInitUnicodeStringFromLiteral(&KeyName, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager\\Kernel"); + RtlRosInitUnicodeStringFromLiteral(&ValueName, + L"FastSystemCallDisable"); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtOpenKey(&KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes); + + if (NT_SUCCESS(Status)) { + + /* Read the Value then Close the Key */ + Status = NtQueryValueKey(KeyHandle, + &ValueName, + KeyValuePartialInformation, + &ValueData, + sizeof(ValueData), + &ResultLength); + RtlMoveMemory(&KiFastSystemCallDisable, ValueData.Data, sizeof(ULONG)); + + NtClose(KeyHandle); + } + + } else { + + /* Disable SYSENTER/SYSEXIT, because the CPU doesn't support it */ + KiFastSystemCallDisable = 1; + + } + + if (!KiFastSystemCallDisable) { + + /* Use SYSENTER */ + SharedUserData->SystemCall[0] = 0x8B; + SharedUserData->SystemCall[1] = 0xD4; + SharedUserData->SystemCall[2] = 0x0F; + SharedUserData->SystemCall[3] = 0x34; + SharedUserData->SystemCall[4] = 0xC3; + + } else { + + /* Use INT2E */ + SharedUserData->SystemCall[0] = 0x8D; + SharedUserData->SystemCall[1] = 0x54; + SharedUserData->SystemCall[2] = 0x24; + SharedUserData->SystemCall[3] = 0x08; + SharedUserData->SystemCall[4] = 0xCD; + SharedUserData->SystemCall[5] = 0x2E; + SharedUserData->SystemCall[6] = 0xC3; + } } diff --git a/reactos/ntoskrnl/ke/i386/stkswitch.S b/reactos/ntoskrnl/ke/i386/stkswitch.S index 73f22f6e4b4..d37c46abd45 100644 --- a/reactos/ntoskrnl/ke/i386/stkswitch.S +++ b/reactos/ntoskrnl/ke/i386/stkswitch.S @@ -78,5 +78,5 @@ _KePushAndStackSwitchAndSysRet@8: push $0 call _KeLowerIrql@4 - jmp KeReturnFromSystemCall + jmp _KiServiceExit diff --git a/reactos/ntoskrnl/ke/i386/syscall.S b/reactos/ntoskrnl/ke/i386/syscall.S index 29824d078b4..6858c95a55e 100644 --- a/reactos/ntoskrnl/ke/i386/syscall.S +++ b/reactos/ntoskrnl/ke/i386/syscall.S @@ -1,324 +1,317 @@ -/* - * ReactOS kernel - * Copyright (C) 2000 David Welch - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ /* $Id$ * * FILE: ntoskrnl/ke/i386/syscall.S - * PURPOSE: 2E trap handler - * PROGRAMMER: David Welch (david.welch@seh.ox.ac.uk) + * COPYRIGHT: See COPYING in the top level directory + * PURPOSE: System Call Handler + * PROGRAMMER: Alex Ionescu (alex@relsoft.net) * UPDATE HISTORY: - * ??? + * ??-??-??: Original Version - David Welch(?) + * 13-01-05: Complete rewrite, added support for SYSENTER, direct kmode syscalls + * and re-wrote most of handler code. - Alex Ionescu */ #include #include #include #include +#include +#include #include -#define KernelMode (0) -#define UserMode (1) +#define UserMode (1) -/* - * - */ -.globl KeReturnFromSystemCall .globl KeReturnFromSystemCallWithHook -.globl _interrupt_handler2e -_interrupt_handler2e: +.globl _KiServiceExit +.globl _KiFastCallEntry +.globl _KiSystemService - /* Construct a trap frame on the stack */ +_KiFastCallEntry: - /* Error code */ - pushl $0 - pushl %ebp - pushl %ebx - pushl %esi - pushl %edi - pushl %fs - /* Load PCR selector into fs */ - movl $PCR_SELECTOR, %ebx - movl %ebx, %fs + /* Set FS to PCR */ + movl $PCR_SELECTOR, %ecx + movw %cx, %fs + + /* Set the current stack to Kernel Stack */ + movl %fs:KPCR_TSS, %ecx + movl KTSS_ESP0(%ecx), %ecx + movl %ecx, %esp + + /* Set up a fake INT Stack. */ + pushl $USER_DS + pushl %edx /* Ring 3 SS:ESP */ + pushfl + orl $200, (%esp) /* Re-enable IRQs in EFLAGS, to fake INT */ + pushl $USER_CS + pushl $KUSER_SHARED_SYSCALL_RET + + /* User Parameter List */ + add $8, %edx + +_KiSystemService: - /* Save the old exception list */ - movl %fs:KPCR_EXCEPTION_LIST, %ebx - pushl %ebx - /* Set the exception handler chain terminator */ - movl $0xffffffff, %fs:KPCR_EXCEPTION_LIST - /* Get a pointer to the current thread */ - movl %fs:KPCR_CURRENT_THREAD, %esi - /* Save the old previous mode */ - movl $0, %ebx - movb %ss:KTHREAD_PREVIOUS_MODE(%esi), %bl - pushl %ebx - /* Set the new previous mode based on the saved CS selector */ - movl 0x24(%esp), %ebx - andl $0x0000FFFF, %ebx - cmpl $KERNEL_CS, %ebx - jne L1 - movb $KernelMode, %ss:KTHREAD_PREVIOUS_MODE(%esi) - jmp L3 -L1: - movb $UserMode, %ss:KTHREAD_PREVIOUS_MODE(%esi) -L3: + /* + * Construct a trap frame on the stack. + * The following are already on the stack. + */ + // SS + 0x0 + // ESP + 0x4 + // EFLAGS + 0x8 + // CS + 0xC + // EIP + 0x10 + pushl $0 // + 0x14 + pushl %ebp // + 0x18 + pushl %ebx // + 0x1C + pushl %esi // + 0x20 + pushl %edi // + 0x24 + pushl %fs // + 0x28 + + /* Load PCR Selector into fs */ + movw $PCR_SELECTOR, %bx + movw %bx, %fs + + /* Save the previous exception list */ + pushl %fs:KPCR_EXCEPTION_LIST // + 0x2C - /* Save other registers */ - pushl %eax - pushl %ecx - pushl %edx - pushl %ds - pushl %es - pushl %gs - pushl $0 /* DR7 */ - pushl $0 /* DR6 */ - pushl $0 /* DR3 */ - pushl $0 /* DR2 */ - pushl $0 /* DR1 */ - pushl $0 /* DR0 */ - pushl $0 /* XXX: TempESP */ - pushl $0 /* XXX: TempCS */ - pushl $0 /* XXX: DebugPointer */ - pushl $0 /* XXX: DebugArgMark */ + /* Set the exception handler chain terminator */ + movl $0xffffffff, %fs:KPCR_EXCEPTION_LIST + + /* Get a pointer to the current thread */ + movl %fs:KPCR_CURRENT_THREAD, %esi + + /* Save the old previous mode */ + pushl %ss:KTHREAD_PREVIOUS_MODE(%esi) // + 0x30 + + /* Set the new previous mode based on the saved CS selector */ + movl 0x24(%esp), %ebx + and $1, %ebx + movb %bl, %ss:KTHREAD_PREVIOUS_MODE(%esi) + + /* Save other registers */ + pushl %eax // + 0x34 + pushl %ecx // + 0x38 + pushl %edx // + 0x3C + pushl %ds // + 0x40 + pushl %es // + 0x44 + pushl %gs // + 0x48 + sub $0x28, %esp // + 0x70 #ifdef DBG - /* Trick gdb 6 into backtracing over the system call */ - movl 4(%ebp), %ebx - pushl %ebx /* DebugEIP */ - movl (%ebp), %ebx - pushl %ebx /* DebugEBP */ + /* Trick gdb 6 into backtracing over the system call */ + pushl 4(%ebp) /* DebugEIP */ // + 0x74 + pushl (%ebp) /* DebugEBP */ // + 0x78 #else - movl 0x60(%esp), %ebx - pushl %ebx /* DebugEIP */ - pushl %ebp /* DebugEBP */ + pushl 0x60(%esp) /* DebugEIP */ // + 0x74 + pushl %ebp /* DebugEBP */ // + 0x78 #endif - /* Load the segment registers */ - movl $KERNEL_DS, %ebx - movl %ebx, %ds - movl %ebx, %es - movl %ebx, %gs + /* Load the segment registers */ + movw $KERNEL_DS, %bx + movw %bx, %ds + movw %bx, %es + movw %bx, %gs - /* - * Save the old trap frame pointer over where we would save the EDX - * register. - */ - movl KTHREAD_TRAP_FRAME(%esi), %ebx - movl %ebx, KTRAP_FRAME_EDX(%esp) + /* Save the old trap frame pointer where EDX would be saved */ + movl KTHREAD_TRAP_FRAME(%esi), %ebx + movl %ebx, KTRAP_FRAME_EDX(%esp) - /* Allocate new Kernel stack frame */ - movl %esp,%ebp + /* Allocate new Kernel stack frame */ + movl %esp,%ebp - /* Save a pointer to the trap frame in the TCB */ - movl %ebp, KTHREAD_TRAP_FRAME(%esi) + /* Save a pointer to the trap frame in the TCB */ + movl %ebp, KTHREAD_TRAP_FRAME(%esi) - /* Set ES to kernel segment */ - movw $KERNEL_DS,%bx - movw %bx,%es - - /* Users's current stack frame pointer is source */ - movl %edx,%esi - - /* Determine system service table to use */ - cmpl $0x0fff, %eax - ja new_useShadowTable - - /* Check to see if EAX is valid/inrange */ - cmpl %es:_KeServiceDescriptorTable + 8, %eax - jbe new_serviceInRange - movl $STATUS_INVALID_SYSTEM_SERVICE, %eax - movl %eax, KTRAP_FRAME_EAX(%ebp) /* save our return value in PKTRAP_FRAME->Eax */ - jmp KeReturnFromSystemCall - -new_serviceInRange: +CheckValidCall: + /* + * Find out which table offset to use. Converts 0x1124 into 0x10. + * The offset is related to the Table Index as such: Offset = TableIndex x 10 + */ + movl %eax, %edi + shrl $8, %edi + andl $0x10, %edi + movl %edi, %ecx + + /* Now add the thread's base system table to the offset */ + addl KTHREAD_SERVICE_TABLE(%esi), %edi + + /* Get the true syscall ID and check it */ + movl %eax, %ebx + andl $0x0FFF, %eax + cmpl 8(%edi), %eax + + /* Invalid ID, try to load Win32K Table */ + jnb KiBBTUnexpectedRange + #ifdef DBG - /* GDB thinks the function starts here and - wants a standard prolog, so let's give it */ - pushl %ebp - movl %esp,%ebp - popl %ebp + /* + * GDB thinks the function starts here and + * wants a standard prolog, so let's give it + */ + pushl %ebp + movl %esp,%ebp + popl %ebp #endif - /* Allocate room for argument list from kernel stack */ - movl %es:_KeServiceDescriptorTable + 12, %ecx - movb %es:(%ecx, %eax), %cl - movzx %cl, %ecx - subl %ecx, %esp + /* Users's current stack frame pointer is source */ + movl %edx, %esi + + /* Allocate room for argument list from kernel stack */ + movl 12(%edi), %ecx + movb (%ecx, %eax), %cl + movzx %cl, %ecx + + /* Allocate space on our stack */ + subl %ecx, %esp + + /* Get pointer to function */ + movl (%edi), %edi + movl (%edi, %eax, 4), %eax - /* Copy the arguments from the user stack to the kernel stack */ - movl %esp,%edi - cld - rep movsb + /* Copy the arguments from the user stack to our stack */ + shr $2, %ecx + movl %esp, %edi + cld + rep movsd - /* DS is now also kernel segment */ - movw %bx, %ds + /* Do the System Call */ + call *%eax + movl %eax, KTRAP_FRAME_EAX(%ebp) - /* Call system call hook */ - pushl %eax - call _KiSystemCallHook - popl %eax - - /* Make the system service call */ - movl %es:_KeServiceDescriptorTable, %ecx - movl %es:(%ecx, %eax, 4), %eax - call *%eax - movl %eax, KTRAP_FRAME_EAX(%ebp) /* save our return value in PKTRAP_FRAME->Eax */ - -#if CHECKED - /* Bump Service Counter */ -#endif - - jmp KeDeallocateStackAndReturnFromSystemCallWithHook - -new_useShadowTable: - - subl $0x1000, %eax - - /* Check to see if EAX is valid/inrange */ - cmpl %es:_KeServiceDescriptorTableShadow + 24, %eax - jbe new_shadowServiceInRange - movl $STATUS_INVALID_SYSTEM_SERVICE, %eax - movl %eax, KTRAP_FRAME_EAX(%ebp) /* save our return value in PKTRAP_FRAME->Eax */ - jmp KeReturnFromSystemCall - -new_shadowServiceInRange: - -#ifdef DBG - /* - * GDB thinks the function starts here and - * wants a standard prolog, so let's give it - */ - pushl %ebp - movl %esp,%ebp - popl %ebp -#endif - - /* Allocate room for argument list from kernel stack */ - movl %es:_KeServiceDescriptorTableShadow + 28, %ecx - movb %es:(%ecx, %eax), %cl - movzx %cl, %ecx - subl %ecx, %esp - - /* Copy the arguments from the user stack to the kernel stack */ - movl %esp,%edi - cld - rep movsb - - /* DS is now also kernel segment */ - movw %bx,%ds - - /* Call system call hook */ -// pushl %eax -// call _KiSystemCallHook -// popl %eax - - /* Call service check routine */ - pushl %eax - call _KiServiceCheck - popl %eax - - /* Make the system service call */ - movl %es:_KeServiceDescriptorTableShadow + 16, %ecx - movl %es:(%ecx, %eax, 4), %eax - call *%eax - movl %eax, KTRAP_FRAME_EAX(%ebp) /* save our return value in PKTRAP_FRAME->Eax */ - -#if CHECKED - /* Bump Service Counter */ -#endif - -KeDeallocateStackAndReturnFromSystemCallWithHook: - /* Deallocate the kernel stack frame */ - movl %ebp,%esp - -KeReturnFromSystemCallWithHook: - /* Call the post system call hook and deliver any pending APCs */ - pushl %esp - call _KiAfterSystemCallHook - addl $4,%esp + /* Deallocate the kernel stack frame */ + movl %ebp, %esp KeReturnFromSystemCall: - /* Restore the user context */ - /* Get a pointer to the current thread */ - movl %fs:0x124, %esi + /* Get the Current Thread */ + movl %fs:KPCR_CURRENT_THREAD, %esi - /* Restore the old trap frame pointer */ - movl KTRAP_FRAME_EDX(%esp), %ebx - movl %ebx, KTHREAD_TRAP_FRAME(%esi) + /* Restore the old trap frame pointer */ + movl KTRAP_FRAME_EDX(%esp), %ebx + movl %ebx, KTHREAD_TRAP_FRAME(%esi) +_KiServiceExit: + + /* Get the Current Thread */ + movl %fs:KPCR_CURRENT_THREAD, %esi + + /* Deliver APCs only if we were called from user mode */ + testb $1, KTRAP_FRAME_CS(%esp) + je KiRosTrapReturn + + /* And only if any are actually pending */ + cmpb $0, KTHREAD_PENDING_USER_APC(%esi) + je KiRosTrapReturn + + /* Save pointer to Trap Frame */ + movl %esp, %ebx + + /* Raise IRQL to HIGH_LEVEL */ + movl $1, %ecx + call @KfRaiseIrql@4 + + /* Save old IRQL */ + pushl %eax + + /* Deliver APCs */ + pushl %ebx + pushl $0 + pushl $UserMode + call _KiDeliverApc@12 + + /* Return to old IRQL */ + popl %ecx + call @KfLowerIrql@4 + KiRosTrapReturn: + + /* Skip debug information and unsaved registers */ + addl $0x30, %esp // + 0x48 + popl %gs // + 0x44 + popl %es // + 0x40 + popl %ds // + 0x3C + popl %edx // + 0x38 + popl %ecx // + 0x34 + popl %eax // + 0x30 -#if 0 - mov KTRAP_FRAME_RESERVED1(%ebp), %ax - cmp %ax, SSIDX_NTCONTINUE - jnz KeNoEpilogPrint - movl KTRAP_FRAME_ESP(%ebp), %ecx - movl KTRAP_FRAME_EBP(%ebp), %edx - call @KeRosPrintEspEbp@8 -KeNoEpilogPrint: -#endif + /* Restore the old previous mode */ + popl %ebx // + 0x2C + movb %bl, %ss:KTHREAD_PREVIOUS_MODE(%esi) - /* Skip debug information and unsaved registers */ - addl $0x30, %esp - popl %gs - popl %es - popl %ds - popl %edx - popl %ecx - popl %eax + /* Restore the old exception handler list */ + popl %fs:KPCR_EXCEPTION_LIST // + 0x28 - /* Restore the old previous mode */ - popl %ebx - movb %bl, %ss:KTHREAD_PREVIOUS_MODE(%esi) + /* Restore final registers from trap frame */ + popl %fs // + 0x24 + popl %edi // + 0x20 + popl %esi // + 0x1C + popl %ebx // + 0x18 + popl %ebp // + 0x14 + add $4, %esp // + 0x10 - /* Restore the old exception handler list */ - popl %ebx - movl %ebx, %fs:KPCR_EXCEPTION_LIST + /* Check if previous CS is from user-mode */ + testl $1, 4(%esp) + + /* It is, so use Fast Exit */ + jnz FastRet + + /* + * Restore what the stub pushed, and return back to it. + * Note that we were CALLed, so the first thing on our stack is the ret EIP! + */ + pop %edx // + 0x0C + pop %ecx // + 0x08 + popf // + 0x04 + jmp *%edx + +IntRet: + + iret - popl %fs - popl %edi - popl %esi - popl %ebx - popl %ebp - addl $0x4, %esp /* Ignore error code */ +FastRet: - iret + /* Is SYSEXIT Supported/Wanted? */ + cmpl $1, _KiFastSystemCallDisable + je IntRet -/* R3: NOTE: This is part of my in-progress attempt at correcting NtContinue - * It is not being called, yet... - */ -.globl @KeRosTrapReturn@8 -@KeRosTrapReturn@8: + /* Restore FS to TIB */ + mov $TEB_SELECTOR, %ecx + mov %ecx, %fs + + /* We will be cleaning up the stack ourselves */ + popl %edx /* New Ring 3 EIP */ + add $0x4, %esp /* Skip Ring 3 DS */ + andl $0xFD, 9(%esp) /* Remove IRQ hack from EFLAGS */ + popfl /* Restore old EFLAGS */ + popl %ecx /* Old Ring 3 SS:ESP */ + + /* + * At this point: + * ECX points to the old User Stack. + * EDX points to the instruction to execute in usermode after the sysenter + */ + sti + sysexit - /* point %esp to the trap frame to restore */ - movl %ecx, %esp - movl %esp, %ebp +KiBBTUnexpectedRange: - /* Call the post system call hook and deliver any pending APCs */ - pushl %esp - call _KiAfterSystemCallHook - addl $4,%esp + /* If this isn't a Win32K call, fail */ + cmp $0x10, %ecx + jne InvalidCall - /* Restore the user context */ - /* Get a pointer to the current thread */ - movl %fs:0x124, %esi - /* Restore the old trap frame pointer */ - movl %edx, KTHREAD_TRAP_FRAME(%esi) + /* Set up Win32K Table */ + pushl %edx + pushl %ebx + call _KiServiceCheck + popl %eax + popl %edx + + /* Try the Call again */ + jmp CheckValidCall + +InvalidCall: - jmp KiRosTrapReturn; + /* Invalid System Call */ + int $3 + movl $STATUS_INVALID_SYSTEM_SERVICE, %eax + movl %eax, KTRAP_FRAME_EAX(%ebp) + jmp _KiServiceExit diff --git a/reactos/ntoskrnl/ke/i386/usercall.c b/reactos/ntoskrnl/ke/i386/usercall.c index 2f6e4ea5699..f60f0d3e3e1 100644 --- a/reactos/ntoskrnl/ke/i386/usercall.c +++ b/reactos/ntoskrnl/ke/i386/usercall.c @@ -17,127 +17,6 @@ /* FUNCTIONS *****************************************************************/ -VOID -KiSystemCallHook(ULONG Nr, ...) -{ -#if 0 - va_list ap; - ULONG i; - - va_start(ap, Nr); - - DbgPrint("%x/%d ", KeServiceDescriptorTable[0].SSDT[Nr].SysCallPtr, Nr); - DbgPrint("%x (", KeServiceDescriptorTable[0].SSPT[Nr].ParamBytes); - for (i = 0; i < KeServiceDescriptorTable[0].SSPT[Nr].ParamBytes / 4; i++) - { - DbgPrint("%x, ", va_arg(ap, ULONG)); - } - DbgPrint(")\n"); - ASSERT_IRQL(PASSIVE_LEVEL); - va_end(ap); -#endif -} - -VOID -KiAfterSystemCallHook(PKTRAP_FRAME TrapFrame) -{ - KIRQL oldIrql; - - /* If we are returning to umode, deliver one pending umode apc. - * Note that kmode apcs are also delivered, even if deliverymode is UserMode. - * This is because we can't return to umode with pending kmode apcs! - * FIXME: Should we deliver pending kmode apcs when returning from a - * kmode-to-kmode syscall (ZwXxx calls)????? - * -Gunnar - */ - if (TrapFrame->Cs != KERNEL_CS) - { - KeRaiseIrql(APC_LEVEL, &oldIrql); - KiDeliverApc(UserMode, NULL, TrapFrame); - KeLowerIrql(oldIrql); - } - -} - - -VOID -KiServiceCheck (ULONG Nr) -{ - PETHREAD Thread; - - Thread = PsGetCurrentThread(); - -#if 0 - DbgPrint ("KiServiceCheck(%p) called\n", Thread); - DbgPrint ("Service %d (%p)\n", Nr, KeServiceDescriptorTableShadow[1].SSDT[Nr].SysCallPtr); -#endif - - if (Thread->Tcb.ServiceTable != KeServiceDescriptorTableShadow) - { -#if 0 - DbgPrint ("Initialize Win32 thread\n"); -#endif - - PsInitWin32Thread (Thread); - - Thread->Tcb.ServiceTable = KeServiceDescriptorTableShadow; - } -} - -// This function should be used by win32k.sys to add its own user32/gdi32 services -// TableIndex is 0 based -// ServiceCountTable its not used at the moment -/* - * @implemented - */ -BOOLEAN STDCALL -KeAddSystemServiceTable ( - PSSDT SSDT, - PULONG ServiceCounterTable, - ULONG NumberOfServices, - PSSPT SSPT, - ULONG TableIndex - ) -{ - if (TableIndex > SSDT_MAX_ENTRIES - 1) - return FALSE; - - /* check if descriptor table entry is free */ - if ((KeServiceDescriptorTable[TableIndex].SSDT != NULL) || - (KeServiceDescriptorTableShadow[TableIndex].SSDT != NULL)) - return FALSE; - - /* initialize the shadow service descriptor table */ - KeServiceDescriptorTableShadow[TableIndex].SSDT = SSDT; - KeServiceDescriptorTableShadow[TableIndex].SSPT = SSPT; - KeServiceDescriptorTableShadow[TableIndex].NumberOfServices = NumberOfServices; - KeServiceDescriptorTableShadow[TableIndex].ServiceCounterTable = ServiceCounterTable; - - /* initialize the service descriptor table (not for win32k services) */ - if (TableIndex != 1) - { - KeServiceDescriptorTable[TableIndex].SSDT = SSDT; - KeServiceDescriptorTable[TableIndex].SSPT = SSPT; - KeServiceDescriptorTable[TableIndex].NumberOfServices = NumberOfServices; - KeServiceDescriptorTable[TableIndex].ServiceCounterTable = ServiceCounterTable; - } - - return TRUE; -} - -/* - * @unimplemented - */ -BOOLEAN -STDCALL -KeRemoveSystemServiceTable( - IN PUCHAR Number -) -{ - UNIMPLEMENTED; - return FALSE; -} - /* * @unimplemented */ diff --git a/reactos/ntoskrnl/ke/kthread.c b/reactos/ntoskrnl/ke/kthread.c index 29787c05301..bac75e241ba 100644 --- a/reactos/ntoskrnl/ke/kthread.c +++ b/reactos/ntoskrnl/ke/kthread.c @@ -33,6 +33,21 @@ /* FUNCTIONS *****************************************************************/ +VOID +KiServiceCheck (VOID) +{ + PETHREAD Thread; + + Thread = PsGetCurrentThread(); + + if (Thread->Tcb.ServiceTable != KeServiceDescriptorTableShadow) + { + PsInitWin32Thread (Thread); + + Thread->Tcb.ServiceTable = KeServiceDescriptorTableShadow; + } +} + /* * @unimplemented */ diff --git a/reactos/ntoskrnl/ke/process.c b/reactos/ntoskrnl/ke/process.c index 94c44cc08a9..9d8c575236b 100644 --- a/reactos/ntoskrnl/ke/process.c +++ b/reactos/ntoskrnl/ke/process.c @@ -270,4 +270,46 @@ KeUnstackDetachProcess ( KeReleaseDispatcherDatabaseLock(OldIrql); } +// This function should be used by win32k.sys to add its own user32/gdi32 services +// TableIndex is 0 based +// ServiceCountTable its not used at the moment +/* + * @implemented + */ +BOOLEAN STDCALL +KeAddSystemServiceTable ( + PSSDT SSDT, + PULONG ServiceCounterTable, + ULONG NumberOfServices, + PSSPT SSPT, + ULONG TableIndex + ) +{ + /* check if descriptor table entry is free */ + if ((TableIndex > SSDT_MAX_ENTRIES - 1) || + (KeServiceDescriptorTable[TableIndex].SSDT != NULL) || + (KeServiceDescriptorTableShadow[TableIndex].SSDT != NULL)) + return FALSE; + + /* initialize the shadow service descriptor table */ + KeServiceDescriptorTableShadow[TableIndex].SSDT = SSDT; + KeServiceDescriptorTableShadow[TableIndex].SSPT = SSPT; + KeServiceDescriptorTableShadow[TableIndex].NumberOfServices = NumberOfServices; + KeServiceDescriptorTableShadow[TableIndex].ServiceCounterTable = ServiceCounterTable; + + return TRUE; +} + +/* + * @unimplemented + */ +BOOLEAN +STDCALL +KeRemoveSystemServiceTable( + IN PUCHAR Number +) +{ + UNIMPLEMENTED; + return FALSE; +} /* EOF */ diff --git a/reactos/ntoskrnl/ps/i386/continue.c b/reactos/ntoskrnl/ps/i386/continue.c index 5b2cd8a027f..7a43a75459d 100644 --- a/reactos/ntoskrnl/ps/i386/continue.c +++ b/reactos/ntoskrnl/ps/i386/continue.c @@ -15,10 +15,6 @@ #define NDEBUG #include -VOID -FASTCALL -KeRosTrapReturn ( PKTRAP_FRAME TrapFrame, PKTRAP_FRAME PrevTrapFrame ); - VOID STDCALL KeRosDumpStackFrames ( PULONG Frame, ULONG FrameCount ); @@ -30,8 +26,9 @@ NtContinue ( IN PCONTEXT Context, IN BOOLEAN TestAlert) { - PKTRAP_FRAME TrapFrame = KeGetCurrentThread()->TrapFrame; - PKTRAP_FRAME PrevTrapFrame = (PKTRAP_FRAME)TrapFrame->Edx; + PKTHREAD Thread = KeGetCurrentThread(); + PKTRAP_FRAME TrapFrame = Thread->TrapFrame; + PKTRAP_FRAME PrevTrapFrame = (PKTRAP_FRAME)TrapFrame->Edx; PFX_SAVE_AREA FxSaveArea; KIRQL oldIrql; @@ -65,12 +62,12 @@ NtContinue ( /* Put the floating point context into the thread's FX_SAVE_AREA * and make sure it is reloaded when needed. */ - FxSaveArea = (PFX_SAVE_AREA)((ULONG_PTR)KeGetCurrentThread()->InitialStack - sizeof(FX_SAVE_AREA)); + FxSaveArea = (PFX_SAVE_AREA)((ULONG_PTR)Thread->InitialStack - sizeof(FX_SAVE_AREA)); if (KiContextToFxSaveArea(FxSaveArea, Context)) { - KeGetCurrentThread()->NpxState = NPX_STATE_VALID; + Thread->NpxState = NPX_STATE_VALID; KeRaiseIrql(DISPATCH_LEVEL, &oldIrql); - if (KeGetCurrentKPCR()->PrcbData.NpxThread == KeGetCurrentThread()) + if (KeGetCurrentKPCR()->PrcbData.NpxThread == Thread) { KeGetCurrentKPCR()->PrcbData.NpxThread = NULL; Ke386SetCr0(Ke386GetCr0() | X86_CR0_TS); @@ -82,7 +79,9 @@ NtContinue ( KeLowerIrql(oldIrql); } - KeRosTrapReturn ( TrapFrame, PrevTrapFrame ); + /* Restore the user context */ + Thread->TrapFrame = PrevTrapFrame; + __asm__("mov %%ebx, %%esp;\n" "jmp _KiServiceExit": : "b" (TrapFrame)); return STATUS_SUCCESS; /* this doesn't actually happen b/c KeRosTrapReturn() won't return */ } diff --git a/reactos/subsys/system/vmwinst/vmwinst.c b/reactos/subsys/system/vmwinst/vmwinst.c index 1797548ad19..f90e9f68f71 100644 --- a/reactos/subsys/system/vmwinst/vmwinst.c +++ b/reactos/subsys/system/vmwinst/vmwinst.c @@ -280,6 +280,8 @@ IsVmwSVGAEnabled(VOID) return (Value == 1); } + + BOOL SaveResolutionSettings(DWORD ResX, DWORD ResY, DWORD ColDepth) { @@ -313,6 +315,43 @@ SaveResolutionSettings(DWORD ResX, DWORD ResY, DWORD ColDepth) return TRUE; } +BOOL +DisableFastSystemCall(VOID) +{ + DWORD Value = 1; + HKEY hReg; + + /* Open or Create the Kernel Settings Key */ + if(RegCreateKeyEx(HKEY_LOCAL_MACHINE, + L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Kernel", + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_SET_VALUE, + NULL, + &hReg, + NULL) != ERROR_SUCCESS) { + DbgPrint("Failed to Disable Sysenter\n"); + return FALSE; + } + + /* Disable Fast System Call */ + if(RegSetValueEx(hReg, + L"FastSystemCallDisable", + 0, + REG_DWORD, + (BYTE*)&Value, + sizeof(DWORD)) != ERROR_SUCCESS) { + RegCloseKey(hReg); + DbgPrint("Failed to Disable Sysenter\n"); + return FALSE; + } + + /* Return Success */ + RegCloseKey(hReg); + return TRUE; +} + BOOL EnableDriver(WCHAR *Key, BOOL Enable) { @@ -1022,6 +1061,9 @@ WinMain(HINSTANCE hInstance, /* restore the exception handler */ SetUnhandledExceptionFilter(OldHandler); + /* Disable Fast System Call no matter what */ + DisableFastSystemCall(); + lc = DestinationPath; lc += GetSystemDirectory(DestinationPath, MAX_PATH) - 1; if(lc >= DestinationPath && *lc != L'\\') diff --git a/reactos/tools/nci/makefile b/reactos/tools/nci/makefile new file mode 100644 index 00000000000..483ac4c7032 --- /dev/null +++ b/reactos/tools/nci/makefile @@ -0,0 +1,56 @@ +# $Id: makefile 12852 2005-01-06 13:58:04Z mf $ +# +# ReactOS Operating System +# +# Generate files for a kernel module that needs to add a service table. +# +PATH_TO_TOP = ../.. + +TARGETNAME = ncitool + +# WIN32K.SYS +WIN32K_SVC_DB = w32ksvc.db +WIN32K_SERVICE_TABLE=../../subsys/win32k/main/svctab.c +WIN32K_GDI_STUBS=../../lib/gdi32/misc/win32k.S +WIN32K_USER_STUBS=../../lib/user32/misc/win32k.S + +# NTOSKRNL.EXE +KERNEL_SVC_DB = sysfuncs.lst +KERNEL_SERVICE_TABLE = ../../include/ntdll/napi.h +NTDLL_STUBS = ../../lib/ntdll/napi.S +KERNEL_STUBS = ../../ntoskrnl/ex/zw.S + +SVC_FILES = $(KERNEL_SERVICE_TABLE) $(WIN32K_SERVICE_TABLE) $(NTDLL_STUBS) $(KERNEL_STUBS) $(WIN32K_GDI_STUBS) $(WIN32K_USER_STUBS) + +CLEAN_FILES = $(TARGETNAME)$(EXE_POSTFIX) $(SVC_FILES) + +BASE_CFLAGS = -I../../include + +CFLAGS += -Wall -Werror + +all: $(SVC_FILES) + +$(TARGETNAME)$(EXE_POSTFIX): $(TARGETNAME).c + $(HOST_CC) \ + $(CFLAGS) \ + -o $(TARGETNAME) \ + -O2 \ + $(TARGETNAME).c + +$(SVC_FILES): $(TARGETNAME)$(EXE_POSTFIX) + @./$(TARGETNAME)$(EXE_POSTFIX) \ + $(KERNEL_SVC_DB) \ + $(WIN32K_SVC_DB) \ + $(KERNEL_SERVICE_TABLE) \ + $(WIN32K_SERVICE_TABLE) \ + $(NTDLL_STUBS) \ + $(KERNEL_STUBS) \ + $(WIN32K_GDI_STUBS) \ + $(WIN32K_USER_STUBS) + +clean: + - $(RM) $(CLEAN_FILES) + +.PHONY: all clean + +include ../../rules.mak diff --git a/reactos/tools/nci/ncitool.c b/reactos/tools/nci/ncitool.c new file mode 100644 index 00000000000..3c5c006834e --- /dev/null +++ b/reactos/tools/nci/ncitool.c @@ -0,0 +1,556 @@ +/* + * FILE: tools/nci/ncitool.c + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: Native Call Interface Support Tool + * PURPOSE: Generates NCI Tables and Stubs. + * PROGRAMMER; Alex Ionescu (alex@relsoft.net) + * CHANGE HISTORY: 14/01/05 - Created. Based on original code by + * KJK::Hyperion and Emanuelle Aliberti. + * + */ + +/* INCLUDE ******************************************************************/ + +#include +#include +#include + +/* DEFINES ****************************************************************/ + +#define INPUT_BUFFER_SIZE 255 +#define Arguments 8 + +/******* Table Indexes ************/ +#define MAIN_INDEX 0x0 +#define WIN32K_INDEX 0x1000 + +/******* Argument List ************/ +/* First, define the Databases */ +#define NativeSystemDb 0 +#define NativeGuiDb 1 + +/* Now the Service Tables */ +#define NtosServiceTable 2 +#define Win32kServiceTable 3 + +/* And finally, the stub files. */ +#define NtosUserStubs 4 +#define NtosKernelStubs 5 +#define Win32kGdiStubs 6 +#define Win32kUserStubs 7 + +/********** Stub Code ************/ + +/* + * This stubs calls into KUSER_SHARED_DATA where either a + * sysenter or interrupt is performed, depending on CPU support. + */ +#define UserModeStub_x86 " movl $0x%x, %%eax\n" \ + " movl $KUSER_SHARED_SYSCALL, %%ecx\n" \ + " call *%%ecx\n" \ + " ret $0x%x\n\n" + +/* + * This stub calls KiSystemService directly with a fake INT2E stack. + * Because EIP is pushed during the call, the handler will return here. + */ +#define KernelModeStub_x86 " movl $0x%x, %%eax\n" \ + " leal 4(%%esp), %%edx\n" \ + " pushfl\n" \ + " pushl $KERNEL_CS\n" \ + " call _KiSystemService\n" \ + " ret $0x%x\n\n" + +/***** Arch Dependent Stuff ******/ +//#ifdef _M_IX86 +#define ARGS_TO_BYTES(x) x*4 +#define UserModeStub UserModeStub_x86 +#define KernelModeStub KernelModeStub_x86 + +//#elseif +//#error Unsupported Architecture +//#endif + +/* FUNCTIONS ****************************************************************/ + +/*++ + * WriteFileHeader + * + * Prints out the File Header for a Stub File. + * + * Params: + * StubFile - Stub File to which to write the header. + * + * FileDescription - Description of the Stub file to which to write the header. + * + * FileLocation - Name of the Stub file to which to write the header. + * + * Returns: + * None. + * + * Remarks: + * FileLocation is only used for printing the header. + * + *--*/ +void +WriteFileHeader(FILE * StubFile, + char* FileDescription, + char* FileLocation) +{ + /* This prints out the file header */ + fprintf(StubFile, + "/* FILE: %s\n" + " * COPYRIGHT: See COPYING in the top level directory\n" + " * PURPOSE: %s\n" + " * PROGRAMMER: Computer Generated File. See tools/nci/ncitool.c\n" + " * REMARK: DO NOT EDIT OR COMMIT MODIFICATIONS TO THIS FILE\n" + " */\n\n\n" + "#include \n\n", + FileDescription, + FileLocation); +} + +/*++ + * WriteFileHeader + * + * Prints out the File Header for a Stub File. + * + * Params: + * StubFile - Stub File to which to write the header. + * + * FileDescription - Description of the Stub file to which to write the header. + * + * FileLocation - Name of the Stub file to which to write the header. + * + * Returns: + * None. + * + * Remarks: + * FileLocation is only used for printing the header. + * + *--*/ +void +WriteStubHeader(FILE* StubFile, + char* SyscallName, + unsigned StackBytes) +{ + /* Export the function */ + fprintf(StubFile, ".global _%s@%d\n", SyscallName, StackBytes); + + /* Define it */ + fprintf(StubFile, "_%s@%d:\n\n", SyscallName, StackBytes); +} + + +/*++ + * WriteKernelModeStub + * + * Prints out the Kernel Mode Stub for a System Call. + * + * Params: + * StubFile - Stub File to which to write the header. + * + * SyscallName - Name of System Call for which to add the stub. + * + * StackBytes - Number of bytes on the stack to return after doing the system call. + * + * SyscallId - Service Descriptor Table ID for this System Call. + * + * Returns: + * None. + * + * Remarks: + * On i386, StackBytes is the number of arguments x 4. + * + *--*/ +void +WriteKernelModeStub(FILE* StubFile, + char* SyscallName, + unsigned StackBytes, + unsigned int SyscallId) +{ + /* Write the Stub Header and export the Function */ + WriteStubHeader(StubFile, SyscallName, StackBytes); + + /* Write the Stub Code */ + fprintf(StubFile, KernelModeStub, SyscallId, StackBytes); +} + +/*++ + * WriteUserModeStub + * + * Prints out the User Mode Stub for a System Call. + * + * Params: + * StubFile - Stub File to which to write the header. + * + * SyscallName - Name of System Call for which to add the stub. + * + * StackBytes - Number of bytes on the stack to return after doing the system call. + * + * SyscallId - Service Descriptor Table ID for this System Call. + * + * Returns: + * None. + * + * Remarks: + * On i386, StackBytes is the number of arguments x 4. + * + *--*/ +void +WriteUserModeStub(FILE* StubFile, + char* SyscallName, + unsigned StackBytes, + unsigned int SyscallId) +{ + /* Write the Stub Header and export the Function */ + WriteStubHeader(StubFile, SyscallName, StackBytes); + + /* Write the Stub Code */ + fprintf(StubFile, UserModeStub, SyscallId, StackBytes); +} + +/*++ + * GetNameAndArgumentsFromDb + * + * Parses an entry from a System Call Database, extracting + * the function's name and arguments that it takes. + * + * Params: + * Line - Entry from the Database to parse. + * + * NtSyscallName - Output string to which to save the Function Name + * + * SyscallArguments - Output string to which to save the number of + * arguments that the function takes. + * + * Returns: + * None. + * + * Remarks: + * On i386, StackBytes is the number of arguments x 4. + * + *--*/ +void +GetNameAndArgumentsFromDb(char Line[], + char ** NtSyscallName, + char ** SyscallArguments) +{ + char *s; + char *stmp; + + /* Remove new line */ + if ((s = (char *) strchr(Line,'\r')) != NULL) { + *s = '\0'; + } + + /* Skip comments (#) and empty lines */ + s = &Line[0]; + if ((*s) != '#' && (*s) != '\0') { + + /* Extract the NtXXX name */ + *NtSyscallName = (char *)strtok(s," \t"); + + /* Extract the argument count */ + *SyscallArguments = (char *)strtok(NULL," \t"); + + /* Remove, if present, the trailing LF */ + if ((stmp = strchr(*SyscallArguments, '\n')) != NULL) { + *stmp = '\0'; + } + + } else { + + /* Skip this entry */ + *NtSyscallName = NULL; + } +} + +/*++ + * CreateStubs + * + * Parses a System Call Database and creates stubs for all the entries. + * + * Params: + * SyscallDb - System Call Database to parse. + * + * UserModeFiles - Array of Usermode Stub Files to which to write the stubs. + * + * KernelModeFile - Kernelmode Stub Files to which to write the stubs. + * + * Index - Name of System Call for which to add the stub. + * + * UserFiles - Number of bytes on the stack to return after doing the system call. + * + * NeedsZw - Service Descriptor Table ID for this System Call. + * + * Returns: + * None. + * + * Remarks: + * None. + * + *--*/ +void +CreateStubs(FILE * SyscallDb, + FILE * UserModeFiles[], + FILE * KernelModeFile, + unsigned Index, + unsigned UserFiles, + unsigned NeedsZw) +{ + char Line[INPUT_BUFFER_SIZE]; + char *NtSyscallName; + char *ZwSyscallName = NULL; + char *SyscallArguments; + int SyscallId; + unsigned StackBytes; + + /* We loop, incrementing the System Call Index, until the end of the file */ + for (SyscallId = 0; ((!feof(SyscallDb)) && (fgets(Line, sizeof(Line), SyscallDb) != NULL));) { + + /* Extract the Name and Arguments */ + GetNameAndArgumentsFromDb(Line, &NtSyscallName, &SyscallArguments); + StackBytes = ARGS_TO_BYTES(strtoul(SyscallArguments, NULL, 0)); + + /* Make sure we really extracted something */ + if (NtSyscallName) { + + /* Create the ZwXXX name, if requested */ + if (NeedsZw) { + ZwSyscallName = alloca(strlen(NtSyscallName)); + strcpy(ZwSyscallName, NtSyscallName); + ZwSyscallName[0] = 'Z'; + ZwSyscallName[1] = 'w'; + } + + /* Create Usermode Stubs for Nt/Zw syscalls in each Usermode file */ + int i; + for (i= 0; i < UserFiles; i++) { + + /* Write the Nt Version */ + WriteUserModeStub(UserModeFiles[i], + NtSyscallName, + StackBytes, + SyscallId | Index); + + /* If a Zw Version is needed (was specified), write it too */ + if (ZwSyscallName) WriteUserModeStub(UserModeFiles[i], + ZwSyscallName, + StackBytes, + SyscallId | Index); + + } + + /* Create the Kernel coutnerparts (only Zw*, Nt* are the real functions!) */ + if (KernelModeFile) WriteKernelModeStub(KernelModeFile, + ZwSyscallName, + StackBytes, + SyscallId | Index); + + /* Only increase if we actually added something */ + SyscallId++; + } + } +} + +/*++ + * CreateSystemServiceTable + * + * Parses a System Call Database and creates a System Call Service Table for it. + * + * Params: + * SyscallDb - System Call Database to parse. + * + * SyscallTable - File in where to create System Call Service Table. + * + * Name - Name of the Service Table. + * + * FileLocation - Filename containing the Table. + * + * Returns: + * None. + * + * Remarks: + * FileLocation is only used for the header generation. + * + *--*/ +void +CreateSystemServiceTable(FILE *SyscallDb, + FILE *SyscallTable, + char * Name, + char * FileLocation) +{ + char Line[INPUT_BUFFER_SIZE]; + char *NtSyscallName; + char *SyscallArguments; + int SyscallId; + + /* Print the Header */ + WriteFileHeader(SyscallTable, "System Call Table for Native API", FileLocation); + + /* First we build the SSDT */ + fprintf(SyscallTable,"\n\n\n"); + fprintf(SyscallTable,"SSDT %sSSDT[] = {\n", Name); + + /* We loop, incrementing the System Call Index, until the end of the file */ + for (SyscallId = 0; ((!feof(SyscallDb)) && (fgets(Line, sizeof(Line), SyscallDb) != NULL));) { + + /* Extract the Name and Arguments */ + GetNameAndArgumentsFromDb(Line, &NtSyscallName, &SyscallArguments); + + /* Make sure we really extracted something */ + if (NtSyscallName) { + + /* Add a new line */ + if (SyscallId > 0) fprintf(SyscallTable,",\n"); + + /* Write the syscall name in the service table. */ + fprintf(SyscallTable,"\t\t(PVOID (NTAPI *)(VOID))%s", NtSyscallName); + + /* Only increase if we actually added something */ + SyscallId++; + } + } + + /* Close the service table (C syntax) */ + fprintf(SyscallTable,"\n};\n"); + + /* Now we build the SSPT */ + rewind(SyscallDb); + fprintf(SyscallTable,"\n\n\n"); + fprintf(SyscallTable,"SSPT %sSSPT[] = {\n", Name); + + for (SyscallId = 0; ((!feof(SyscallDb)) && (fgets(Line, sizeof(Line), SyscallDb) != NULL));) { + + /* Extract the Name and Arguments */ + GetNameAndArgumentsFromDb(Line, &NtSyscallName, &SyscallArguments); + + /* Make sure we really extracted something */ + if (NtSyscallName) { + + /* Add a new line */ + if (SyscallId > 0) fprintf(SyscallTable,",\n"); + + /* Write the syscall arguments in the argument table. */ + fprintf(SyscallTable,"\t\t%lu * sizeof(void *)",strtoul(SyscallArguments, NULL, 0)); + + /* Only increase if we actually added something */ + SyscallId++; + } + } + + /* Close the service table (C syntax) */ + fprintf(SyscallTable,"\n};\n"); + + /* + * We write some useful defines + */ + fprintf(SyscallTable, "\n\n#define MIN_SYSCALL_NUMBER 0\n"); + fprintf(SyscallTable, "#define MAX_SYSCALL_NUMBER %d\n", SyscallId - 1); + fprintf(SyscallTable, "#define NUMBER_OF_SYSCALLS %d\n", SyscallId); + fprintf(SyscallTable, "ULONG %sNumberOfSysCalls = %d;\n", Name, SyscallId); +} + +void usage(char * argv0) +{ + printf("Usage: %s sysfuncs.lst w32ksvc.db napi.h ssdt.h napi.S zw.S win32k.S win32k.S\n" + " sysfuncs.lst native system functions database\n" + " w32ksvc.db native graphic functions database\n" + " napi.h NTOSKRNL service table\n" + " ssdt.h WIN32K service table\n" + " napi.S NTDLL stubs\n" + " zw.S NTOSKRNL Zw stubs\n" + " win32k.S GDI32 stubs\n" + " win32k.S USER32 stubs\n", + argv0 + ); +} + +int main(int argc, char* argv[]) +{ + FILE * Files[Arguments]; + int FileNumber; + char * OpenType = "r"; + + /* Make sure all arguments all there */ + if (argc != Arguments + 1) { + usage(argv[0]); + return(1); + } + + /* Open all Output and bail out if any fail */ + for (FileNumber = 0; FileNumber < Arguments; FileNumber++) { + + /* Open the File */ + if (FileNumber == 2) OpenType = "wb"; + Files[FileNumber] = fopen(argv[FileNumber + 1], OpenType); + + /* Check for failure and error out if so */ + if (!Files[FileNumber]) { + perror(argv[FileNumber + 1]); + return (1); + } + + } + + /* Write the File Headers */ + WriteFileHeader(Files[NtosUserStubs], + "System Call Stubs for Native API", + argv[NtosUserStubs + 1]); + + WriteFileHeader(Files[NtosKernelStubs], + "System Call Stubs for Native API", + argv[NtosKernelStubs + 1]); + fputs("#include \n\n", Files[NtosKernelStubs]); + + WriteFileHeader(Files[Win32kGdiStubs], + "System Call Stubs for Native API", + argv[Win32kGdiStubs + 1]); + + WriteFileHeader(Files[Win32kUserStubs], + "System Call Stubs for Native API", + argv[Win32kUserStubs + 1]); + + + /* Create the System Stubs */ + CreateStubs(Files[NativeSystemDb], + &Files[NtosUserStubs], + Files[NtosKernelStubs], + MAIN_INDEX, + 1, + 1); + + /* Create the Graphics Stubs */ + CreateStubs(Files[NativeGuiDb], + &Files[Win32kGdiStubs], + NULL, + WIN32K_INDEX, + 2, + 0); + + /* Rewind the databases */ + rewind(Files[NativeSystemDb]); + rewind(Files[NativeGuiDb]); + + /* Create the Service Tables */ + CreateSystemServiceTable(Files[NativeSystemDb], + Files[NtosServiceTable], + "Main", + argv[NtosServiceTable + 1]); + + CreateSystemServiceTable(Files[NativeGuiDb], + Files[Win32kServiceTable], + "Win32k", + argv[Win32kServiceTable + 1]); + + /* Close all files */ + for (FileNumber = 0; FileNumber < Arguments; FileNumber++) { + + /* Close the File */ + fclose(Files[FileNumber]); + + } + + return(0); +} diff --git a/reactos/tools/nci/sysfuncs.lst b/reactos/tools/nci/sysfuncs.lst new file mode 100644 index 00000000000..ebf608aed6c --- /dev/null +++ b/reactos/tools/nci/sysfuncs.lst @@ -0,0 +1,235 @@ +NtAcceptConnectPort 6 +NtAccessCheck 8 +NtAccessCheckAndAuditAlarm 11 +NtAddAtom 3 +NtAddBootEntry 2 +NtAdjustGroupsToken 6 +NtAdjustPrivilegesToken 6 +NtAlertResumeThread 2 +NtAlertThread 1 +NtAllocateLocallyUniqueId 1 +NtAllocateUuids 4 +NtAllocateVirtualMemory 6 +NtAssignProcessToJobObject 2 +NtCallbackReturn 3 +NtCancelIoFile 2 +NtCancelTimer 2 +NtClearEvent 1 +NtClose 1 +NtCloseObjectAuditAlarm 3 +NtCompleteConnectPort 1 +NtConnectPort 8 +NtContinue 2 +NtCreateDirectoryObject 3 +NtCreateEvent 5 +NtCreateEventPair 3 +NtCreateFile 11 +NtCreateIoCompletion 4 +NtCreateJobObject 3 +NtCreateKey 7 +NtCreateMailslotFile 8 +NtCreateMutant 4 +NtCreateNamedPipeFile 14 +NtCreatePagingFile 4 +NtCreatePort 5 +NtCreateProcess 8 +NtCreateProfile 9 +NtCreateSection 7 +NtCreateSemaphore 5 +NtCreateSymbolicLinkObject 4 +NtCreateThread 8 +NtCreateTimer 4 +NtCreateToken 13 +NtCreateWaitablePort 5 +NtDelayExecution 2 +NtDeleteAtom 1 +NtDeleteBootEntry 2 +NtDeleteFile 1 +NtDeleteKey 1 +NtDeleteObjectAuditAlarm 3 +NtDeleteValueKey 2 +NtDeviceIoControlFile 10 +NtDisplayString 1 +NtDuplicateObject 7 +NtDuplicateToken 6 +NtEnumerateBootEntries 2 +NtEnumerateKey 6 +NtEnumerateValueKey 6 +NtExtendSection 2 +NtFindAtom 3 +NtFlushBuffersFile 2 +NtFlushInstructionCache 3 +NtFlushKey 1 +NtFlushVirtualMemory 4 +NtFlushWriteBuffer 0 +NtFreeVirtualMemory 4 +NtFsControlFile 10 +NtGetContextThread 2 +NtGetPlugPlayEvent 4 +NtGetTickCount 0 +NtImpersonateClientOfPort 2 +NtImpersonateThread 3 +NtInitializeRegistry 1 +NtInitiatePowerAction 4 +NtIsProcessInJob 2 +NtListenPort 2 +NtLoadDriver 1 +NtLoadKey 2 +NtLoadKey2 3 +NtLockFile 10 +NtLockVirtualMemory 4 +NtMakePermanentObject 1 +NtMakeTemporaryObject 1 +NtMapViewOfSection 10 +NtNotifyChangeDirectoryFile 9 +NtNotifyChangeKey 10 +NtOpenDirectoryObject 3 +NtOpenEvent 3 +NtOpenEventPair 3 +NtOpenFile 6 +NtOpenIoCompletion 3 +NtOpenJobObject 3 +NtOpenKey 3 +NtOpenMutant 3 +NtOpenObjectAuditAlarm 12 +NtOpenProcess 4 +NtOpenProcessToken 3 +NtOpenProcessTokenEx 4 +NtOpenSection 3 +NtOpenSemaphore 3 +NtOpenSymbolicLinkObject 3 +NtOpenThread 4 +NtOpenThreadToken 4 +NtOpenThreadTokenEx 5 +NtOpenTimer 3 +NtPlugPlayControl 4 +NtPowerInformation 5 +NtPrivilegeCheck 3 +NtPrivilegedServiceAuditAlarm 5 +NtPrivilegeObjectAuditAlarm 6 +NtProtectVirtualMemory 5 +NtPulseEvent 2 +NtQueryInformationAtom 5 +NtQueryAttributesFile 2 +NtQueryBootEntryOrder 2 +NtQueryBootOptions 2 +NtQueryDefaultLocale 2 +NtQueryDefaultUILanguage 1 +NtQueryDirectoryFile 11 +NtQueryDirectoryObject 7 +NtQueryEaFile 9 +NtQueryEvent 5 +NtQueryFullAttributesFile 2 +NtQueryInformationFile 5 +NtQueryInformationJobObject 5 +NtQueryInformationPort 5 +NtQueryInformationProcess 5 +NtQueryInformationThread 5 +NtQueryInformationToken 5 +NtQueryInstallUILanguage 1 +NtQueryIntervalProfile 2 +NtQueryIoCompletion 5 +NtQueryKey 5 +NtQueryMultipleValueKey 6 +NtQueryMutant 5 +NtQueryObject 5 +NtQueryOleDirectoryFile 11 +NtQueryPerformanceCounter 2 +NtQueryQuotaInformationFile 9 +NtQuerySection 5 +NtQuerySecurityObject 5 +NtQuerySemaphore 5 +NtQuerySymbolicLinkObject 3 +NtQuerySystemEnvironmentValue 4 +NtQuerySystemInformation 4 +NtQuerySystemTime 1 +NtQueryTimer 5 +NtQueryTimerResolution 3 +NtQueryValueKey 6 +NtQueryVirtualMemory 6 +NtQueryVolumeInformationFile 5 +NtQueueApcThread 5 +NtRaiseException 3 +NtRaiseHardError 6 +NtReadFile 9 +NtReadFileScatter 9 +NtReadRequestData 6 +NtReadVirtualMemory 5 +NtRegisterThreadTerminatePort 1 +NtReleaseMutant 2 +NtReleaseSemaphore 3 +NtRemoveIoCompletion 5 +NtReplaceKey 3 +NtReplyPort 2 +NtReplyWaitReceivePort 4 +NtReplyWaitReplyPort 2 +NtRequestPort 2 +NtRequestWaitReplyPort 3 +NtResetEvent 2 +NtRestoreKey 3 +NtResumeThread 2 +NtSaveKey 2 +NtSaveKeyEx 3 +NtSetBootEntryOrder 2 +NtSetBootOptions 2 +NtSetIoCompletion 5 +NtSetContextThread 2 +NtSetDefaultHardErrorPort 1 +NtSetDefaultLocale 2 +NtSetDefaultUILanguage 1 +NtSetEaFile 4 +NtSetEvent 2 +NtSetHighEventPair 1 +NtSetHighWaitLowEventPair 1 +NtSetHighWaitLowThread 0 +NtSetInformationFile 5 +NtSetInformationKey 4 +NtSetInformationJobObject 4 +NtSetInformationObject 4 +NtSetInformationProcess 4 +NtSetInformationThread 4 +NtSetInformationToken 4 +NtSetIntervalProfile 2 +NtSetLdtEntries 6 +NtSetLowEventPair 1 +NtSetLowWaitHighEventPair 1 +NtSetLowWaitHighThread 0 +NtSetQuotaInformationFile 4 +NtSetSecurityObject 3 +NtSetSystemEnvironmentValue 2 +NtSetSystemInformation 3 +NtSetSystemPowerState 3 +NtSetSystemTime 2 +NtSetTimer 7 +NtSetTimerResolution 3 +NtSetUuidSeed 1 +NtSetValueKey 6 +NtSetVolumeInformationFile 5 +NtShutdownSystem 1 +NtSignalAndWaitForSingleObject 4 +NtStartProfile 1 +NtStopProfile 1 +NtSuspendThread 2 +NtSystemDebugControl 6 +NtTerminateJobObject 2 +NtTerminateProcess 2 +NtTerminateThread 2 +NtTestAlert 0 +NtTraceEvent 4 +NtTranslateFilePath 3 +NtUnloadDriver 1 +NtUnloadKey 1 +NtUnlockFile 5 +NtUnlockVirtualMemory 4 +NtUnmapViewOfSection 2 +NtVdmControl 2 +NtWaitForMultipleObjects 5 +NtWaitForSingleObject 3 +NtWaitHighEventPair 1 +NtWaitLowEventPair 1 +NtWriteFile 9 +NtWriteFileGather 9 +NtWriteRequestData 6 +NtWriteVirtualMemory 5 +NtW32Call 5 +NtYieldExecution 0 diff --git a/reactos/iface/addsys/w32ksvc.db b/reactos/tools/nci/w32ksvc.db similarity index 100% rename from reactos/iface/addsys/w32ksvc.db rename to reactos/tools/nci/w32ksvc.db