mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
First hack at KMDLLs
svn path=/trunk/; revision=523
This commit is contained in:
parent
9377d51b1a
commit
d415ba8508
15 changed files with 610 additions and 118 deletions
|
@ -3,12 +3,12 @@
|
||||||
:
|
:
|
||||||
: copy files to HD...
|
: copy files to HD...
|
||||||
:
|
:
|
||||||
COPY /Y BLUE.SYS C:\reactos\system\drivers\blue.SYS
|
COPY /Y BLUE.SYS C:\reactos\system\drivers\blue.SYS > NUL:
|
||||||
COPY /Y KEYBOARD.SYS C:\reactos\system\drivers\KEYBOARD.SYS
|
COPY /Y KEYBOARD.SYS C:\reactos\system\drivers\KEYBOARD.SYS > NUL:
|
||||||
COPY /Y NTDLL.DLL C:\reactos\system\NTDLL.DLL
|
COPY /Y NTDLL.DLL C:\reactos\system\NTDLL.DLL > NUL:
|
||||||
COPY /Y KERNEL32.DLL C:\reactos\system\KERNEL32.DLL
|
COPY /Y KERNEL32.DLL C:\reactos\system\KERNEL32.DLL > NUL:
|
||||||
: COPY /Y CRTDLL.DLL C:\reactos\system\CRTDLL.DLL
|
: COPY /Y CRTDLL.DLL C:\reactos\system\CRTDLL.DLL > NUL:
|
||||||
COPY /Y SHELL.EXE C:\reactos\system\SHELL.EXE
|
COPY /Y SHELL.EXE C:\reactos\system\SHELL.EXE > NUL:
|
||||||
|
|
||||||
:
|
:
|
||||||
: present a menu to the booter...
|
: present a menu to the booter...
|
||||||
|
|
25
reactos/include/ddk/miniport.h
Normal file
25
reactos/include/ddk/miniport.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* MINIPORT.H - miniport driver interface header
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define EMULATOR_READ_ACCESS 0x00000001
|
||||||
|
#define EMULATOR_WRITE_ACCESS 0x00000002
|
||||||
|
|
||||||
|
typedef enum _EMULATOR_PORT_ACCESS_TYPE
|
||||||
|
{
|
||||||
|
Uchar,
|
||||||
|
Ushort,
|
||||||
|
Ulong
|
||||||
|
} EMULATOR_PORT_ACCESS_TYPE, *PEMULATOR_PORT_ACCESS_TYPE;
|
||||||
|
|
||||||
|
typedef struct _EMULATOR_ACCESS_ENTRY
|
||||||
|
{
|
||||||
|
ULONG BasePort;
|
||||||
|
ULONG NumConsecutivePorts;
|
||||||
|
EMULATOR_PORT_ACCESS_TYPE AccessType;
|
||||||
|
UCHAR AccessMode;
|
||||||
|
UCHAR StringSupport;
|
||||||
|
PVOID Routine;
|
||||||
|
} EMULATOR_ACCESS_ENTRY, *PEMULATOR_ACCESS_ENTRY;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#ifndef __MODULE_H
|
#ifndef __MODULE_H
|
||||||
#define __MODULE_H
|
#define __MODULE_H
|
||||||
|
|
||||||
|
#include <ddk/ntddk.h>
|
||||||
#include <coff.h>
|
#include <coff.h>
|
||||||
#include <pe.h>
|
#include <pe.h>
|
||||||
|
|
||||||
|
@ -30,11 +31,13 @@ typedef struct _module
|
||||||
|
|
||||||
typedef SCNHDR COFF_SECTION_HEADER, *PCOFF_SECTION_HEADER;
|
typedef SCNHDR COFF_SECTION_HEADER, *PCOFF_SECTION_HEADER;
|
||||||
|
|
||||||
typedef struct _MODULE
|
typedef struct _MODULE_OBJECT
|
||||||
{
|
{
|
||||||
PVOID Base;
|
CSHORT ObjectType;
|
||||||
unsigned int Size;
|
CSHORT ObjectSize;
|
||||||
unsigned int Flags;
|
PVOID Base;
|
||||||
|
unsigned int Flags;
|
||||||
|
PVOID EntryPoint;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
|
@ -51,10 +54,12 @@ typedef struct _MODULE
|
||||||
{
|
{
|
||||||
PIMAGE_FILE_HEADER FileHeader;
|
PIMAGE_FILE_HEADER FileHeader;
|
||||||
PIMAGE_OPTIONAL_HEADER OptionalHeader;
|
PIMAGE_OPTIONAL_HEADER OptionalHeader;
|
||||||
PCOFF_SECTION_HEADER SectionList;
|
PIMAGE_SECTION_HEADER SectionList;
|
||||||
} PE;
|
} PE;
|
||||||
} Image;
|
} Image;
|
||||||
} MODULE, *PMODULE;
|
} MODULE_OBJECT, *PMODULE_OBJECT;
|
||||||
|
|
||||||
|
typedef MODULE_OBJECT MODULE, *PMODULE;
|
||||||
|
|
||||||
#define MODULE_FLAG_BIN 0x0001
|
#define MODULE_FLAG_BIN 0x0001
|
||||||
#define MODULE_FLAG_MZ 0x0002
|
#define MODULE_FLAG_MZ 0x0002
|
||||||
|
@ -64,7 +69,7 @@ typedef struct _MODULE
|
||||||
|
|
||||||
typedef struct _INSTANCE
|
typedef struct _INSTANCE
|
||||||
{
|
{
|
||||||
HANDLE ModuleHandle;
|
HANDLE ModuleHandle;
|
||||||
} INSTANCE, *PINSTANCE;
|
} INSTANCE, *PINSTANCE;
|
||||||
|
|
||||||
BOOLEAN process_boot_module(unsigned int start);
|
BOOLEAN process_boot_module(unsigned int start);
|
||||||
|
|
|
@ -554,6 +554,8 @@ typedef struct _IMAGE_SEPARATE_DEBUG_HEADER {
|
||||||
sizeof (IMAGE_FILE_HEADER) + \
|
sizeof (IMAGE_FILE_HEADER) + \
|
||||||
sizeof (IMAGE_OPTIONAL_HEADER)))
|
sizeof (IMAGE_OPTIONAL_HEADER)))
|
||||||
|
|
||||||
|
#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr) + (DWORD)(addValue))
|
||||||
|
|
||||||
typedef struct _IMAGE_IMPORT_MODULE_DIRECTORY
|
typedef struct _IMAGE_IMPORT_MODULE_DIRECTORY
|
||||||
{
|
{
|
||||||
DWORD dwRVAFunctionNameList;
|
DWORD dwRVAFunctionNameList;
|
||||||
|
|
2
reactos/lib/crtdll/.cvsignore
Normal file
2
reactos/lib/crtdll/.cvsignore
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
crtdll.coff
|
||||||
|
crtdll.dll
|
2
reactos/lib/fmifs/.cvsignore
Normal file
2
reactos/lib/fmifs/.cvsignore
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
fmifs.coff
|
||||||
|
fmifs.dll
|
|
@ -1,7 +1,8 @@
|
||||||
|
base.tmp
|
||||||
|
junk.tmp
|
||||||
napi.asm
|
napi.asm
|
||||||
napi.c
|
napi.c
|
||||||
ntdll.lib
|
ntdll.lib
|
||||||
base.tmp
|
ntdll.coff
|
||||||
junk.tmp
|
|
||||||
ntdll.dll
|
ntdll.dll
|
||||||
temp.exp
|
temp.exp
|
||||||
|
|
2
reactos/lib/user32/.cvsignore
Normal file
2
reactos/lib/user32/.cvsignore
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
user32.coff
|
||||||
|
user32.dll
|
|
@ -1,13 +1,27 @@
|
||||||
@echo off
|
@echo off
|
||||||
echo copying latest files to a:...
|
echo copying latest files to a:...
|
||||||
copy /Y bootflop.bat a:\autoexec.bat
|
copy /Y bootflop.bat a:\autoexec.bat > NUL:
|
||||||
copy /Y loaders\dos\loadros.com a:
|
echo bootflop.bat to a:\autoexec.bat
|
||||||
copy /Y apps\shell\shell.exe a:
|
copy /Y loaders\dos\loadros.com a: > NUL:
|
||||||
copy /Y ntoskrnl\ntoskrnl.exe a:
|
echo loadros.com
|
||||||
copy /Y services\dd\blue\blue.sys a:
|
copy /Y ntoskrnl\ntoskrnl.exe a: > NUL:
|
||||||
copy /Y services\dd\keyboard\keyboard.sys a:
|
echo ntoskrnl.exe
|
||||||
copy /Y services\dd\ide\ide.sys a:
|
copy /Y services\dd\ide\ide.sys a: > NUL:
|
||||||
copy /Y services\fs\vfat\vfatfsd.sys a:
|
echo ide.sys
|
||||||
copy /Y lib\ntdll\ntdll.dll a:
|
copy /Y services\fs\vfat\vfatfsd.sys a: > NUL:
|
||||||
copy /Y lib\kernel32\kernel32.dll a:
|
echo vfatfsd.sys
|
||||||
: copy /Y lib\crtdll\crtdll.dll a:
|
copy /Y services\dd\blue\blue.sys a: > NUL:
|
||||||
|
echo blue.sys
|
||||||
|
copy /Y services\dd\keyboard\keyboard.sys a: > NUL:
|
||||||
|
echo keyboard.sys
|
||||||
|
copy /Y lib\ntdll\ntdll.dll a: > NUL:
|
||||||
|
echo ntdll.dll
|
||||||
|
copy /Y lib\kernel32\kernel32.dll a: > NUL:
|
||||||
|
echo kernel32.dll
|
||||||
|
copy /Y apps\shell\shell.exe a: > NUL:
|
||||||
|
echo shell.exe
|
||||||
|
: copy /Y lib\crtdll\crtdll.dll a: > NUL:
|
||||||
|
: echo lib\crtdll\crtdll.dll a:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ include rules.mak
|
||||||
COMPONENTS = iface_native ntoskrnl
|
COMPONENTS = iface_native ntoskrnl
|
||||||
DLLS = ntdll kernel32 crtdll user32 fmifs gdi32
|
DLLS = ntdll kernel32 crtdll user32 fmifs gdi32
|
||||||
#DLLS = crtdll mingw32
|
#DLLS = crtdll mingw32
|
||||||
|
SUBSYS = win32k
|
||||||
|
|
||||||
#
|
#
|
||||||
# Select the server(s) you want to build
|
# Select the server(s) you want to build
|
||||||
|
@ -41,7 +42,7 @@ KERNEL_SERVICES = $(DEVICE_DRIVERS) $(FS_DRIVERS)
|
||||||
APPS = args hello shell test cat bench
|
APPS = args hello shell test cat bench
|
||||||
# APPS = cmd
|
# APPS = cmd
|
||||||
|
|
||||||
all: $(COMPONENTS) $(DLLS) $(LOADERS) $(KERNEL_SERVICES) $(APPS)
|
all: $(COMPONENTS) $(DLLS) $(SUBSYS) $(LOADERS) $(KERNEL_SERVICES) $(APPS)
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
|
|
||||||
clean: $(COMPONENTS:%=%_clean) $(DLLS:%=%_clean) $(LOADERS:%=%_clean) \
|
clean: $(COMPONENTS:%=%_clean) $(DLLS:%=%_clean) $(LOADERS:%=%_clean) \
|
||||||
|
@ -125,4 +126,15 @@ $(DLLS:%=%_clean): %_clean:
|
||||||
|
|
||||||
.PHONY: $(DLLS) $(DLLS:%=%_clean)
|
.PHONY: $(DLLS) $(DLLS:%=%_clean)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Kernel Subsystems
|
||||||
|
#
|
||||||
|
$(SUBSYS): %:
|
||||||
|
make -C subsys/$*
|
||||||
|
|
||||||
|
$(SUBSYS:%=%_clean): %_clean:
|
||||||
|
make -C lib/$* clean
|
||||||
|
|
||||||
|
.PHONY: $(SUBSYS) $(SUBSYS:%=%_clean)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ include rules.mak
|
||||||
COMPONENTS = iface_native ntoskrnl
|
COMPONENTS = iface_native ntoskrnl
|
||||||
DLLS = ntdll kernel32 crtdll user32 fmifs
|
DLLS = ntdll kernel32 crtdll user32 fmifs
|
||||||
#DLLS = crtdll mingw32
|
#DLLS = crtdll mingw32
|
||||||
|
SUBSYS = win32k
|
||||||
|
|
||||||
#
|
#
|
||||||
# Select the server(s) you want to build
|
# Select the server(s) you want to build
|
||||||
|
@ -41,7 +42,7 @@ KERNEL_SERVICES = $(DEVICE_DRIVERS) $(FS_DRIVERS)
|
||||||
APPS = args hello shell test cat bench
|
APPS = args hello shell test cat bench
|
||||||
# APPS = cmd
|
# APPS = cmd
|
||||||
|
|
||||||
all: $(COMPONENTS) $(DLLS) $(LOADERS) $(KERNEL_SERVICES) $(APPS)
|
all: $(COMPONENTS) $(DLLS) $(SUBSYS) $(LOADERS) $(KERNEL_SERVICES) $(APPS)
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
|
|
||||||
clean: $(COMPONENTS:%=%_clean) $(DLLS:%=%_clean) $(LOADERS:%=%_clean) \
|
clean: $(COMPONENTS:%=%_clean) $(DLLS:%=%_clean) $(LOADERS:%=%_clean) \
|
||||||
|
@ -125,4 +126,15 @@ $(DLLS:%=%_clean): %_clean:
|
||||||
|
|
||||||
.PHONY: $(DLLS) $(DLLS:%=%_clean)
|
.PHONY: $(DLLS) $(DLLS:%=%_clean)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Kernel Subsystems
|
||||||
|
#
|
||||||
|
$(SUBSYS): %:
|
||||||
|
make -C subsys/$*
|
||||||
|
|
||||||
|
$(SUBSYS:%=%_clean): %_clean:
|
||||||
|
make -C lib/$* clean
|
||||||
|
|
||||||
|
.PHONY: $(SUBSYS) $(SUBSYS:%=%_clean)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <internal/linkage.h>
|
#include <internal/linkage.h>
|
||||||
#include <internal/module.h>
|
#include <internal/module.h>
|
||||||
#include <internal/ntoskrnl.h>
|
#include <internal/ntoskrnl.h>
|
||||||
|
#include <internal/mmhal.h>
|
||||||
#include <internal/ob.h>
|
#include <internal/ob.h>
|
||||||
#include <internal/ps.h>
|
#include <internal/ps.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -38,6 +39,8 @@ NTSTATUS IoInitializeDriver(PDRIVER_INITIALIZE DriverEntry);
|
||||||
|
|
||||||
/* MACROS ********************************************************************/
|
/* MACROS ********************************************************************/
|
||||||
|
|
||||||
|
#define MODULE_ROOT_NAME L"\\Modules\\"
|
||||||
|
|
||||||
/* GLOBALS *******************************************************************/
|
/* GLOBALS *******************************************************************/
|
||||||
|
|
||||||
POBJECT_TYPE ObModuleType = NULL;
|
POBJECT_TYPE ObModuleType = NULL;
|
||||||
|
@ -47,12 +50,25 @@ POBJECT_TYPE ObModuleType = NULL;
|
||||||
NTSTATUS LdrLoadDriver(PUNICODE_STRING Filename);
|
NTSTATUS LdrLoadDriver(PUNICODE_STRING Filename);
|
||||||
NTSTATUS LdrProcessDriver(PVOID ModuleLoadBase);
|
NTSTATUS LdrProcessDriver(PVOID ModuleLoadBase);
|
||||||
|
|
||||||
|
PMODULE_OBJECT LdrLoadModule(PUNICODE_STRING Filename);
|
||||||
|
PMODULE_OBJECT LdrProcessModule(PVOID ModuleLoadBase);
|
||||||
|
PVOID LdrGetExportAddress(PMODULE_OBJECT ModuleObject, char *Name, unsigned short Hint);
|
||||||
|
static PIMAGE_SECTION_HEADER LdrPEGetEnclosingSectionHeader(DWORD RVA,
|
||||||
|
PMODULE_OBJECT ModuleObject);
|
||||||
|
static NTSTATUS LdrCreateModule(PVOID ObjectBody,
|
||||||
|
PVOID Parent,
|
||||||
|
PWSTR RemainingPath,
|
||||||
|
POBJECT_ATTRIBUTES ObjectAttributes);
|
||||||
|
|
||||||
/* PE Driver load support */
|
/* PE Driver load support */
|
||||||
static NTSTATUS LdrPEProcessDriver(PVOID ModuleLoadBase);
|
static PMODULE_OBJECT LdrPEProcessModule(PVOID ModuleLoadBase);
|
||||||
|
static PVOID LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
|
||||||
|
char *Name,
|
||||||
|
unsigned short Hint);
|
||||||
static unsigned int LdrGetKernelSymbolAddr(char *Name);
|
static unsigned int LdrGetKernelSymbolAddr(char *Name);
|
||||||
|
|
||||||
/* COFF Driver load support */
|
/* COFF Driver load support */
|
||||||
static NTSTATUS LdrCOFFProcessDriver(PVOID ModuleLoadBase);
|
static PMODULE_OBJECT LdrCOFFProcessModule(PVOID ModuleLoadBase);
|
||||||
static BOOLEAN LdrCOFFDoRelocations(module *Module, unsigned int SectionIndex);
|
static BOOLEAN LdrCOFFDoRelocations(module *Module, unsigned int SectionIndex);
|
||||||
static BOOLEAN LdrCOFFDoAddr32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation);
|
static BOOLEAN LdrCOFFDoAddr32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation);
|
||||||
static BOOLEAN LdrCOFFDoReloc32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation);
|
static BOOLEAN LdrCOFFDoReloc32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation);
|
||||||
|
@ -64,7 +80,14 @@ static unsigned int LdrCOFFGetSymbolValueByName(module *Module, char *SymbolName
|
||||||
|
|
||||||
VOID LdrInitModuleManagement(VOID)
|
VOID LdrInitModuleManagement(VOID)
|
||||||
{
|
{
|
||||||
|
HANDLE DirHandle, ModuleHandle;
|
||||||
|
NTSTATUS Status;
|
||||||
|
WCHAR NameBuffer[60];
|
||||||
ANSI_STRING AnsiString;
|
ANSI_STRING AnsiString;
|
||||||
|
UNICODE_STRING ModuleName;
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
PIMAGE_DOS_HEADER DosHeader;
|
||||||
|
PMODULE_OBJECT ModuleObject;
|
||||||
|
|
||||||
/* Register the process object type */
|
/* Register the process object type */
|
||||||
ObModuleType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
|
ObModuleType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
|
||||||
|
@ -82,8 +105,85 @@ VOID LdrInitModuleManagement(VOID)
|
||||||
ObModuleType->Security = NULL;
|
ObModuleType->Security = NULL;
|
||||||
ObModuleType->QueryName = NULL;
|
ObModuleType->QueryName = NULL;
|
||||||
ObModuleType->OkayToClose = NULL;
|
ObModuleType->OkayToClose = NULL;
|
||||||
|
ObModuleType->Create = LdrCreateModule;
|
||||||
RtlInitAnsiString(&AnsiString, "Module");
|
RtlInitAnsiString(&AnsiString, "Module");
|
||||||
RtlAnsiStringToUnicodeString(&ObModuleType->TypeName, &AnsiString, TRUE);
|
RtlAnsiStringToUnicodeString(&ObModuleType->TypeName, &AnsiString, TRUE);
|
||||||
|
|
||||||
|
/* Create Modules object directory */
|
||||||
|
wcscpy(NameBuffer, MODULE_ROOT_NAME);
|
||||||
|
*(wcsrchr(NameBuffer, L'\\')) = 0;
|
||||||
|
ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
|
||||||
|
ModuleName.Buffer = NameBuffer;
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&ModuleName,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
DPRINT("Create dir: %W\n", &ModuleName);
|
||||||
|
Status = ZwCreateDirectoryObject(&DirHandle, 0, &ObjectAttributes);
|
||||||
|
assert(NT_SUCCESS(Status));
|
||||||
|
|
||||||
|
/* Add module entry for NTOSKRNL */
|
||||||
|
wcscpy(NameBuffer, MODULE_ROOT_NAME);
|
||||||
|
wcscat(NameBuffer, L"ntoskrnl.exe");
|
||||||
|
ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
|
||||||
|
ModuleName.Buffer = NameBuffer;
|
||||||
|
DPRINT("Kernel's Module name is: %W\n", &ModuleName);
|
||||||
|
|
||||||
|
/* Initialize ObjectAttributes for ModuleObject */
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&ModuleName,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* Create module object */
|
||||||
|
ModuleHandle = 0;
|
||||||
|
ModuleObject = ObCreateObject(&ModuleHandle,
|
||||||
|
STANDARD_RIGHTS_REQUIRED,
|
||||||
|
&ObjectAttributes,
|
||||||
|
ObModuleType);
|
||||||
|
assert(ModuleObject != NULL);
|
||||||
|
|
||||||
|
/* Initialize ModuleObject data */
|
||||||
|
ModuleObject->Base = (PVOID) KERNEL_BASE;
|
||||||
|
ModuleObject->Flags = MODULE_FLAG_PE;
|
||||||
|
DosHeader = (PIMAGE_DOS_HEADER) KERNEL_BASE;
|
||||||
|
ModuleObject->Image.PE.FileHeader =
|
||||||
|
(PIMAGE_FILE_HEADER) ((DWORD) ModuleObject->Base +
|
||||||
|
DosHeader->e_lfanew + sizeof(ULONG));
|
||||||
|
ModuleObject->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
|
||||||
|
((DWORD)ModuleObject->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
|
||||||
|
ModuleObject->Image.PE.SectionList = (PIMAGE_SECTION_HEADER)
|
||||||
|
((DWORD)ModuleObject->Image.PE.OptionalHeader + sizeof(IMAGE_OPTIONAL_HEADER));
|
||||||
|
ModuleObject->EntryPoint = (PVOID) ((DWORD) ModuleObject->Base +
|
||||||
|
ModuleObject->Image.PE.OptionalHeader->AddressOfEntryPoint);
|
||||||
|
DPRINT("ModuleObject:%08x entrypoint at %x\n", ModuleObject, ModuleObject->EntryPoint);
|
||||||
|
|
||||||
|
/* FIXME: Add fake module entry for HAL */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS
|
||||||
|
LdrCreateModule(PVOID ObjectBody,
|
||||||
|
PVOID Parent,
|
||||||
|
PWSTR RemainingPath,
|
||||||
|
POBJECT_ATTRIBUTES ObjectAttributes)
|
||||||
|
{
|
||||||
|
DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %w)\n",
|
||||||
|
ObjectBody,
|
||||||
|
Parent,
|
||||||
|
RemainingPath);
|
||||||
|
if (RemainingPath != NULL && wcschr(RemainingPath + 1, '\\') != NULL)
|
||||||
|
{
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
if (Parent != NULL && RemainingPath != NULL)
|
||||||
|
{
|
||||||
|
ObAddEntryDirectory(Parent, ObjectBody, RemainingPath + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -125,17 +225,68 @@ VOID LdrLoadAutoConfigDrivers(VOID)
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
LdrLoadDriver(PUNICODE_STRING Filename)
|
LdrLoadDriver(PUNICODE_STRING Filename)
|
||||||
|
{
|
||||||
|
PMODULE_OBJECT ModuleObject;
|
||||||
|
|
||||||
|
ModuleObject = LdrLoadModule(Filename);
|
||||||
|
if (ModuleObject == 0)
|
||||||
|
{
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: should we dereference the ModuleObject here? */
|
||||||
|
|
||||||
|
return IoInitializeDriver(ModuleObject->EntryPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
PMODULE_OBJECT
|
||||||
|
LdrLoadModule(PUNICODE_STRING Filename)
|
||||||
{
|
{
|
||||||
PVOID ModuleLoadBase;
|
PVOID ModuleLoadBase;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
HANDLE FileHandle;
|
HANDLE FileHandle;
|
||||||
OBJECT_ATTRIBUTES FileObjectAttributes;
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
PMODULE_OBJECT ModuleObject;
|
||||||
FILE_STANDARD_INFORMATION FileStdInfo;
|
FILE_STANDARD_INFORMATION FileStdInfo;
|
||||||
|
WCHAR NameBuffer[60];
|
||||||
|
PWSTR RemainingPath;
|
||||||
|
UNICODE_STRING ModuleName;
|
||||||
|
|
||||||
DbgPrint("Loading Driver %W...\n", Filename);
|
DPRINT("Loading Module %W...\n", Filename);
|
||||||
|
|
||||||
/* Open the Driver */
|
/* Check for module already loaded */
|
||||||
InitializeObjectAttributes(&FileObjectAttributes,
|
wcscpy(NameBuffer, MODULE_ROOT_NAME);
|
||||||
|
if (wcsrchr(Filename->Buffer, '\\') != 0)
|
||||||
|
{
|
||||||
|
wcscat(NameBuffer, wcsrchr(Filename->Buffer, '\\') + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wcscat(NameBuffer, Filename->Buffer);
|
||||||
|
}
|
||||||
|
ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
|
||||||
|
ModuleName.Buffer = NameBuffer;
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&ModuleName,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
Status = ObFindObject(&ObjectAttributes,
|
||||||
|
(PVOID *) &ModuleObject,
|
||||||
|
&RemainingPath);
|
||||||
|
CHECKPOINT;
|
||||||
|
if (NT_SUCCESS(Status) && *RemainingPath == 0)
|
||||||
|
{
|
||||||
|
return ModuleObject;
|
||||||
|
}
|
||||||
|
CHECKPOINT;
|
||||||
|
if (!wcsncmp(Filename->Buffer, MODULE_ROOT_NAME, wcslen(MODULE_ROOT_NAME)))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open the Module */
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
Filename,
|
Filename,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -143,12 +294,13 @@ LdrLoadDriver(PUNICODE_STRING Filename)
|
||||||
CHECKPOINT;
|
CHECKPOINT;
|
||||||
Status = ZwOpenFile(&FileHandle,
|
Status = ZwOpenFile(&FileHandle,
|
||||||
FILE_ALL_ACCESS,
|
FILE_ALL_ACCESS,
|
||||||
&FileObjectAttributes,
|
&ObjectAttributes,
|
||||||
NULL, 0, 0);
|
NULL, 0, 0);
|
||||||
CHECKPOINT;
|
CHECKPOINT;
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
return Status;
|
DbgPrint("Could not open module file: %W\n", Filename);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
CHECKPOINT;
|
CHECKPOINT;
|
||||||
|
|
||||||
|
@ -160,7 +312,8 @@ LdrLoadDriver(PUNICODE_STRING Filename)
|
||||||
FileStandardInformation);
|
FileStandardInformation);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
return Status;
|
DbgPrint("Could not get file size\n");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
CHECKPOINT;
|
CHECKPOINT;
|
||||||
|
|
||||||
|
@ -169,7 +322,8 @@ LdrLoadDriver(PUNICODE_STRING Filename)
|
||||||
FileStdInfo.EndOfFile.u.LowPart);
|
FileStdInfo.EndOfFile.u.LowPart);
|
||||||
if (ModuleLoadBase == NULL)
|
if (ModuleLoadBase == NULL)
|
||||||
{
|
{
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
DbgPrint("could not allocate memory for module");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
CHECKPOINT;
|
CHECKPOINT;
|
||||||
|
|
||||||
|
@ -181,23 +335,41 @@ LdrLoadDriver(PUNICODE_STRING Filename)
|
||||||
0, 0);
|
0, 0);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
|
DbgPrint("could not read module file into memory");
|
||||||
ExFreePool(ModuleLoadBase);
|
ExFreePool(ModuleLoadBase);
|
||||||
return Status;
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
CHECKPOINT;
|
CHECKPOINT;
|
||||||
|
|
||||||
ZwClose(FileHandle);
|
ZwClose(FileHandle);
|
||||||
|
|
||||||
Status = LdrProcessDriver(ModuleLoadBase);
|
ModuleObject = LdrProcessModule(ModuleLoadBase);
|
||||||
|
|
||||||
/* Cleanup */
|
/* Cleanup */
|
||||||
ExFreePool(ModuleLoadBase);
|
ExFreePool(ModuleLoadBase);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return ModuleObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
LdrProcessDriver(PVOID ModuleLoadBase)
|
LdrProcessDriver(PVOID ModuleLoadBase)
|
||||||
|
{
|
||||||
|
PMODULE_OBJECT ModuleObject;
|
||||||
|
|
||||||
|
ModuleObject = LdrProcessModule(ModuleLoadBase);
|
||||||
|
if (ModuleObject == 0)
|
||||||
|
{
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: should we dereference the ModuleObject here? */
|
||||||
|
|
||||||
|
return IoInitializeDriver(ModuleObject->EntryPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
PMODULE_OBJECT
|
||||||
|
LdrProcessModule(PVOID ModuleLoadBase)
|
||||||
{
|
{
|
||||||
PIMAGE_DOS_HEADER PEDosHeader;
|
PIMAGE_DOS_HEADER PEDosHeader;
|
||||||
|
|
||||||
|
@ -205,42 +377,66 @@ LdrProcessDriver(PVOID ModuleLoadBase)
|
||||||
PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
|
PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
|
||||||
if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L)
|
if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC && PEDosHeader->e_lfanew != 0L)
|
||||||
{
|
{
|
||||||
return LdrPEProcessDriver(ModuleLoadBase);
|
return LdrPEProcessModule(ModuleLoadBase);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC)
|
if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC)
|
||||||
{
|
{
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return 0;
|
||||||
}
|
}
|
||||||
else /* Assume COFF format and load */
|
else /* Assume COFF format and load */
|
||||||
{
|
{
|
||||||
return LdrCOFFProcessDriver(ModuleLoadBase);
|
return LdrCOFFProcessModule(ModuleLoadBase);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
LdrGetExportAddress(PMODULE_OBJECT ModuleObject,
|
||||||
|
char *Name,
|
||||||
|
unsigned short Hint)
|
||||||
|
{
|
||||||
|
if (ModuleObject->Flags & MODULE_FLAG_PE)
|
||||||
|
{
|
||||||
|
return LdrPEGetExportAddress(ModuleObject, Name, Hint);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
/* ---------------------------------------------- PE Module support */
|
||||||
LdrPEProcessDriver(PVOID ModuleLoadBase)
|
|
||||||
|
PMODULE_OBJECT
|
||||||
|
LdrPEProcessModule(PVOID ModuleLoadBase)
|
||||||
{
|
{
|
||||||
unsigned int DriverSize, Idx;
|
unsigned int DriverSize, Idx, Idx2;
|
||||||
ULONG RelocDelta, NumRelocs;
|
ULONG RelocDelta, NumRelocs;
|
||||||
DWORD CurrentSize, TotalRelocs;
|
DWORD CurrentSize, TotalRelocs;
|
||||||
PVOID DriverBase, CurrentBase, EntryPoint;
|
PVOID DriverBase, CurrentBase;
|
||||||
PULONG PEMagic;
|
PULONG PEMagic;
|
||||||
PIMAGE_DOS_HEADER PEDosHeader;
|
PIMAGE_DOS_HEADER PEDosHeader;
|
||||||
PIMAGE_FILE_HEADER PEFileHeader;
|
PIMAGE_FILE_HEADER PEFileHeader;
|
||||||
PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
|
PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
|
||||||
PIMAGE_SECTION_HEADER PESectionHeaders;
|
PIMAGE_SECTION_HEADER PESectionHeaders;
|
||||||
|
PIMAGE_EXPORT_DIRECTORY ExportDirectory;
|
||||||
PRELOCATION_DIRECTORY RelocDir;
|
PRELOCATION_DIRECTORY RelocDir;
|
||||||
PRELOCATION_ENTRY RelocEntry;
|
PRELOCATION_ENTRY RelocEntry;
|
||||||
PMODULE Library;
|
PMODULE_OBJECT LibraryModuleObject;
|
||||||
|
HANDLE ModuleHandle;
|
||||||
|
PMODULE_OBJECT ModuleObject;
|
||||||
PVOID *ImportAddressList;
|
PVOID *ImportAddressList;
|
||||||
PULONG FunctionNameList;
|
PULONG FunctionNameList;
|
||||||
PCHAR pName, SymbolNameBuf;
|
PCHAR pName, SymbolNameBuf;
|
||||||
PWORD pHint;
|
WORD Hint;
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
UNICODE_STRING ModuleName;
|
||||||
|
WCHAR NameBuffer[60];
|
||||||
|
|
||||||
/* FIXME: this could be used to load kernel DLLs also, however */
|
DPRINT("Processing PE Module at module base:%08lx\n", ModuleLoadBase);
|
||||||
/* the image headers should be preserved in such a case */
|
|
||||||
|
|
||||||
DPRINT("Processing PE Driver at module base:%08lx\n", ModuleLoadBase);
|
|
||||||
|
|
||||||
/* Get header pointers */
|
/* Get header pointers */
|
||||||
PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
|
PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
|
||||||
|
@ -258,23 +454,23 @@ LdrPEProcessDriver(PVOID ModuleLoadBase)
|
||||||
/* Check file magic numbers */
|
/* Check file magic numbers */
|
||||||
if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
|
if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
|
||||||
{
|
{
|
||||||
DPRINT("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
|
DbgPrint("Incorrect MZ magic: %04x\n", PEDosHeader->e_magic);
|
||||||
return STATUS_UNSUCCESSFUL;
|
return 0;
|
||||||
}
|
}
|
||||||
if (PEDosHeader->e_lfanew == 0)
|
if (PEDosHeader->e_lfanew == 0)
|
||||||
{
|
{
|
||||||
DPRINT("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
|
DbgPrint("Invalid lfanew offset: %08x\n", PEDosHeader->e_lfanew);
|
||||||
return STATUS_UNSUCCESSFUL;
|
return 0;
|
||||||
}
|
}
|
||||||
if (*PEMagic != IMAGE_PE_MAGIC)
|
if (*PEMagic != IMAGE_PE_MAGIC)
|
||||||
{
|
{
|
||||||
DPRINT("Incorrect PE magic: %08x\n", *PEMagic);
|
DbgPrint("Incorrect PE magic: %08x\n", *PEMagic);
|
||||||
return STATUS_UNSUCCESSFUL;
|
return 0;
|
||||||
}
|
}
|
||||||
if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
|
if (PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
|
||||||
{
|
{
|
||||||
DPRINT("Incorrect Architechture: %04x\n", PEFileHeader->Machine);
|
DbgPrint("Incorrect Architechture: %04x\n", PEFileHeader->Machine);
|
||||||
return STATUS_UNSUCCESSFUL;
|
return 0;
|
||||||
}
|
}
|
||||||
CHECKPOINT;
|
CHECKPOINT;
|
||||||
|
|
||||||
|
@ -299,10 +495,10 @@ LdrPEProcessDriver(PVOID ModuleLoadBase)
|
||||||
if (DriverBase == 0)
|
if (DriverBase == 0)
|
||||||
{
|
{
|
||||||
DbgPrint("Failed to allocate a virtual section for driver\n");
|
DbgPrint("Failed to allocate a virtual section for driver\n");
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return 0;
|
||||||
}
|
}
|
||||||
CHECKPOINT;
|
CHECKPOINT;
|
||||||
DbgPrint("Module is at base %x\n",DriverBase);
|
DPRINT("Module is at base %x\n",DriverBase);
|
||||||
|
|
||||||
/* Copy image sections into virtual section */
|
/* Copy image sections into virtual section */
|
||||||
memcpy(DriverBase, ModuleLoadBase, PESectionHeaders[0].PointerToRawData);
|
memcpy(DriverBase, ModuleLoadBase, PESectionHeaders[0].PointerToRawData);
|
||||||
|
@ -390,8 +586,8 @@ LdrPEProcessDriver(PVOID ModuleLoadBase)
|
||||||
}
|
}
|
||||||
else if (Type != 0)
|
else if (Type != 0)
|
||||||
{
|
{
|
||||||
DPRINT("Unknown relocation type %x\n",Type);
|
DbgPrint("Unknown relocation type %x\n",Type);
|
||||||
return STATUS_UNSUCCESSFUL;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TotalRelocs += RelocDir->SizeOfBlock;
|
TotalRelocs += RelocDir->SizeOfBlock;
|
||||||
|
@ -415,21 +611,36 @@ LdrPEProcessDriver(PVOID ModuleLoadBase)
|
||||||
ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
|
ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
|
||||||
((DWORD)DriverBase + PEOptionalHeader->
|
((DWORD)DriverBase + PEOptionalHeader->
|
||||||
DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
|
DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
|
||||||
|
DPRINT("Processeing import directory at %p\n", ImportModuleDirectory);
|
||||||
while (ImportModuleDirectory->dwRVAModuleName)
|
while (ImportModuleDirectory->dwRVAModuleName)
|
||||||
{
|
{
|
||||||
/* FIXME: handle kernel mode DLLs */
|
|
||||||
|
|
||||||
/* Check to make sure that import lib is kernel */
|
/* Check to make sure that import lib is kernel */
|
||||||
Library = NULL;
|
|
||||||
pName = (PCHAR) DriverBase +
|
pName = (PCHAR) DriverBase +
|
||||||
ImportModuleDirectory->dwRVAModuleName;
|
ImportModuleDirectory->dwRVAModuleName;
|
||||||
// DPRINT("Import module: %s\n", pName);
|
if (!strcmp(pName, "ntoskrnl.exe") || !strcmp(pName, "HAL.dll"))
|
||||||
if (strcmp(pName, "ntoskrnl.exe")!=0 &&
|
|
||||||
strcmp(pName, "HAL.dll")!=0)
|
|
||||||
{
|
{
|
||||||
DPRINT("Kernel mode DLLs are currently unsupported\n");
|
LibraryModuleObject = NULL;
|
||||||
|
DPRINT("Kernel imports\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wcscpy(NameBuffer, MODULE_ROOT_NAME);
|
||||||
|
for (Idx = 0; NameBuffer[Idx] != 0; Idx++)
|
||||||
|
;
|
||||||
|
for (Idx2 = 0; pName[Idx2] != '\0'; Idx2++)
|
||||||
|
{
|
||||||
|
NameBuffer[Idx + Idx2] = (WCHAR) pName[Idx2];
|
||||||
|
}
|
||||||
|
NameBuffer[Idx + Idx2] = 0;
|
||||||
|
ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
|
||||||
|
ModuleName.Buffer = NameBuffer;
|
||||||
|
DPRINT("Import module: %W\n", &ModuleName);
|
||||||
|
LibraryModuleObject = LdrLoadModule(&ModuleName);
|
||||||
|
if (LibraryModuleObject == 0)
|
||||||
|
{
|
||||||
|
DbgPrint("Unknown import module: %W\n", &ModuleName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the import address list */
|
/* Get the import address list */
|
||||||
ImportAddressList = (PVOID *) ((DWORD)DriverBase +
|
ImportAddressList = (PVOID *) ((DWORD)DriverBase +
|
||||||
ImportModuleDirectory->dwRVAFunctionAddressList);
|
ImportModuleDirectory->dwRVAFunctionAddressList);
|
||||||
|
@ -445,35 +656,38 @@ LdrPEProcessDriver(PVOID ModuleLoadBase)
|
||||||
FunctionNameList = (PULONG) ((DWORD)DriverBase +
|
FunctionNameList = (PULONG) ((DWORD)DriverBase +
|
||||||
ImportModuleDirectory->dwRVAFunctionAddressList);
|
ImportModuleDirectory->dwRVAFunctionAddressList);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Walk through function list and fixup addresses */
|
/* Walk through function list and fixup addresses */
|
||||||
while(*FunctionNameList != 0L)
|
while (*FunctionNameList != 0L)
|
||||||
{
|
{
|
||||||
if ((*FunctionNameList) & 0x80000000) // hint
|
if ((*FunctionNameList) & 0x80000000) // hint
|
||||||
{
|
{
|
||||||
// DPRINT(" Hint: %08lx\n", *FunctionNameList);
|
pName = NULL;
|
||||||
if (Library == NULL)
|
Hint = (*FunctionNameList) & 0xffff;
|
||||||
{
|
|
||||||
DPRINT("Hints for kernel symbols are not handled.\n");
|
|
||||||
*ImportAddressList = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else // hint-name
|
else // hint-name
|
||||||
{
|
{
|
||||||
pName = (PCHAR)((DWORD)DriverBase+
|
pName = (PCHAR)((DWORD)DriverBase +
|
||||||
*FunctionNameList + 2);
|
*FunctionNameList + 2);
|
||||||
pHint = (PWORD)((DWORD)DriverBase + *FunctionNameList);
|
Hint = *(PWORD)((DWORD)DriverBase + *FunctionNameList);
|
||||||
// DPRINT(" Hint:%04x Name:%s\n", pHint, pName);
|
}
|
||||||
|
DPRINT(" Hint:%04x Name:%s\n", Hint, pName);
|
||||||
|
|
||||||
|
/* Fixup the current import symbol */
|
||||||
|
if (LibraryModuleObject != NULL)
|
||||||
|
{
|
||||||
|
*ImportAddressList = LdrGetExportAddress(LibraryModuleObject,
|
||||||
|
pName,
|
||||||
|
Hint);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* Get address for symbol */
|
/* Get address for symbol */
|
||||||
if (Library == NULL)
|
*SymbolNameBuf = '_';
|
||||||
|
strcpy(SymbolNameBuf + 1, pName);
|
||||||
|
*ImportAddressList = (PVOID) LdrGetKernelSymbolAddr(SymbolNameBuf);
|
||||||
|
if (*ImportAddressList == 0L)
|
||||||
{
|
{
|
||||||
*SymbolNameBuf = '_';
|
DbgPrint("Unresolved kernel symbol: %s\n", pName);
|
||||||
strcpy(SymbolNameBuf + 1, pName);
|
|
||||||
*ImportAddressList = (PVOID) LdrGetKernelSymbolAddr(SymbolNameBuf); if (*ImportAddressList == 0L)
|
|
||||||
{
|
|
||||||
DPRINT("Unresolved kernel symbol: %s\n", pName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImportAddressList++;
|
ImportAddressList++;
|
||||||
|
@ -485,15 +699,165 @@ LdrPEProcessDriver(PVOID ModuleLoadBase)
|
||||||
ExFreePool(SymbolNameBuf);
|
ExFreePool(SymbolNameBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute address of entry point */
|
/* Create ModuleName string */
|
||||||
EntryPoint = (PVOID) ((DWORD)DriverBase + PEOptionalHeader->AddressOfEntryPoint);
|
wcscpy(NameBuffer, MODULE_ROOT_NAME);
|
||||||
DbgPrint("Calling entrypoint at %x\n",EntryPoint);
|
if (PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
|
||||||
|
.VirtualAddress != 0)
|
||||||
|
{
|
||||||
|
ExportDirectory = (PIMAGE_EXPORT_DIRECTORY) (DriverBase +
|
||||||
|
PEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
|
||||||
|
.VirtualAddress);
|
||||||
|
wcscat(NameBuffer, DriverBase + ExportDirectory->Name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char buf[12];
|
||||||
|
|
||||||
return IoInitializeDriver(EntryPoint);
|
sprintf(buf, "%08X", (DWORD) DriverBase);
|
||||||
|
for (Idx = 0; NameBuffer[Idx] != 0; Idx++)
|
||||||
|
;
|
||||||
|
Idx2 = 0;
|
||||||
|
while ((NameBuffer[Idx + Idx2] = (WCHAR) buf[Idx2]) != 0)
|
||||||
|
Idx2++;
|
||||||
|
}
|
||||||
|
ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
|
||||||
|
ModuleName.Buffer = NameBuffer;
|
||||||
|
DPRINT("Module name is: %W\n", &ModuleName);
|
||||||
|
|
||||||
|
/* Initialize ObjectAttributes for ModuleObject */
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&ModuleName,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* Create module object */
|
||||||
|
ModuleHandle = 0;
|
||||||
|
ModuleObject = ObCreateObject(&ModuleHandle,
|
||||||
|
STANDARD_RIGHTS_REQUIRED,
|
||||||
|
&ObjectAttributes,
|
||||||
|
ObModuleType);
|
||||||
|
|
||||||
|
/* Initialize ModuleObject data */
|
||||||
|
ModuleObject->Base = DriverBase;
|
||||||
|
ModuleObject->Flags = MODULE_FLAG_PE;
|
||||||
|
ModuleObject->EntryPoint = (PVOID) ((DWORD)DriverBase +
|
||||||
|
PEOptionalHeader->AddressOfEntryPoint);
|
||||||
|
DPRINT("entrypoint at %x\n", ModuleObject->EntryPoint);
|
||||||
|
ModuleObject->Image.PE.FileHeader =
|
||||||
|
(PIMAGE_FILE_HEADER) ((unsigned int) DriverBase +
|
||||||
|
PEDosHeader->e_lfanew + sizeof(ULONG));
|
||||||
|
DPRINT("FileHeader at %x\n", ModuleObject->Image.PE.FileHeader);
|
||||||
|
ModuleObject->Image.PE.OptionalHeader =
|
||||||
|
(PIMAGE_OPTIONAL_HEADER) ((unsigned int) DriverBase +
|
||||||
|
PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
|
||||||
|
DPRINT("OptionalHeader at %x\n", ModuleObject->Image.PE.OptionalHeader);
|
||||||
|
ModuleObject->Image.PE.SectionList =
|
||||||
|
(PIMAGE_SECTION_HEADER) ((unsigned int) DriverBase +
|
||||||
|
PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
|
||||||
|
sizeof(IMAGE_OPTIONAL_HEADER));
|
||||||
|
DPRINT("SectionList at %x\n", ModuleObject->Image.PE.SectionList);
|
||||||
|
|
||||||
|
return ModuleObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS
|
static PVOID
|
||||||
LdrCOFFProcessDriver(PVOID ModuleLoadBase)
|
LdrPEGetExportAddress(PMODULE_OBJECT ModuleObject,
|
||||||
|
char *Name,
|
||||||
|
unsigned short Hint)
|
||||||
|
{
|
||||||
|
WORD Idx;
|
||||||
|
DWORD ExportsStartRVA, ExportsEndRVA, Delta;
|
||||||
|
PVOID ExportAddress;
|
||||||
|
PWORD OrdinalList;
|
||||||
|
PDWORD FunctionList, NameList;
|
||||||
|
PIMAGE_SECTION_HEADER SectionHeader;
|
||||||
|
PIMAGE_EXPORT_DIRECTORY ExportDirectory;
|
||||||
|
|
||||||
|
ExportsStartRVA = ModuleObject->Image.PE.OptionalHeader->DataDirectory
|
||||||
|
[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||||
|
ExportsEndRVA = ExportsStartRVA +
|
||||||
|
ModuleObject->Image.PE.OptionalHeader->DataDirectory
|
||||||
|
[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
|
||||||
|
/* Get the IMAGE_SECTION_HEADER that contains the exports. This is
|
||||||
|
usually the .edata section, but doesn't have to be. */
|
||||||
|
SectionHeader = LdrPEGetEnclosingSectionHeader(ExportsStartRVA, ModuleObject);
|
||||||
|
if (!SectionHeader)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Delta = (DWORD)(SectionHeader->VirtualAddress -
|
||||||
|
SectionHeader->PointerToRawData);
|
||||||
|
ExportDirectory = MakePtr(PIMAGE_EXPORT_DIRECTORY,
|
||||||
|
ModuleObject->Base,
|
||||||
|
ExportsStartRVA - Delta);
|
||||||
|
|
||||||
|
FunctionList = (PDWORD)((DWORD)ExportDirectory->AddressOfFunctions -
|
||||||
|
Delta + ModuleObject->Base);
|
||||||
|
NameList = (PDWORD)((DWORD)ExportDirectory->AddressOfNames -
|
||||||
|
Delta + ModuleObject->Base);
|
||||||
|
OrdinalList = (PWORD)((DWORD)ExportDirectory->AddressOfNameOrdinals -
|
||||||
|
Delta + ModuleObject->Base);
|
||||||
|
DPRINT("Delta:%08x\n", Delta);
|
||||||
|
DPRINT("Func:%08x RVA:%08x Name:%08x RVA:%08x Ord:%08x RVA:%08x\n", FunctionList,
|
||||||
|
ExportDirectory->AddressOfFunctions, NameList,
|
||||||
|
ExportDirectory->AddressOfNames, OrdinalList,
|
||||||
|
ExportDirectory->AddressOfNameOrdinals);
|
||||||
|
DPRINT("NumNames:%d NumFuncs:%d\n", ExportDirectory->NumberOfNames,
|
||||||
|
ExportDirectory->NumberOfFunctions);
|
||||||
|
for(;;);
|
||||||
|
ExportAddress = 0;
|
||||||
|
if (Name != NULL)
|
||||||
|
{
|
||||||
|
for (Idx = 0; Idx < ExportDirectory->NumberOfNames; Idx++)
|
||||||
|
{
|
||||||
|
DPRINT(" Name:%s NameList[%d]:%s\n", Name, Idx, NameList[Idx]);
|
||||||
|
if (!strcmp(Name, (PCHAR) ((DWORD)ModuleObject->Base + NameList[Idx])))
|
||||||
|
{
|
||||||
|
ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
|
||||||
|
FunctionList[OrdinalList[Idx]]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* use hint */
|
||||||
|
{
|
||||||
|
ExportAddress = (PVOID) ((DWORD)ModuleObject->Base +
|
||||||
|
FunctionList[Hint - ExportDirectory->Base]);
|
||||||
|
}
|
||||||
|
if (ExportAddress == 0)
|
||||||
|
{
|
||||||
|
DbgPrint("Export not found for %d:%s\n", Hint, Name != NULL ? Name : "(Ordinal)");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ExportAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PIMAGE_SECTION_HEADER
|
||||||
|
LdrPEGetEnclosingSectionHeader(DWORD RVA,
|
||||||
|
PMODULE_OBJECT ModuleObject)
|
||||||
|
{
|
||||||
|
PIMAGE_SECTION_HEADER SectionHeader = SECHDROFFSET(ModuleObject->Base);
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < ModuleObject->Image.PE.FileHeader->NumberOfSections;
|
||||||
|
i++, SectionHeader++)
|
||||||
|
{
|
||||||
|
/* Is the RVA within this section? */
|
||||||
|
if ((RVA >= SectionHeader->VirtualAddress) &&
|
||||||
|
(RVA < (SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize)))
|
||||||
|
{
|
||||||
|
return SectionHeader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------- COFF Module support */
|
||||||
|
|
||||||
|
PMODULE_OBJECT
|
||||||
|
LdrCOFFProcessModule(PVOID ModuleLoadBase)
|
||||||
{
|
{
|
||||||
BOOLEAN FoundEntry;
|
BOOLEAN FoundEntry;
|
||||||
char SymbolName[255];
|
char SymbolName[255];
|
||||||
|
@ -502,7 +866,12 @@ LdrCOFFProcessDriver(PVOID ModuleLoadBase)
|
||||||
FILHDR *FileHeader;
|
FILHDR *FileHeader;
|
||||||
AOUTHDR *AOUTHeader;
|
AOUTHDR *AOUTHeader;
|
||||||
module *Module;
|
module *Module;
|
||||||
PDRIVER_INITIALIZE EntryRoutine;
|
PVOID EntryRoutine;
|
||||||
|
HANDLE ModuleHandle;
|
||||||
|
PMODULE_OBJECT ModuleObject;
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
UNICODE_STRING ModuleName;
|
||||||
|
WCHAR NameBuffer[60];
|
||||||
|
|
||||||
/* Get header pointers */
|
/* Get header pointers */
|
||||||
FileHeader = ModuleLoadBase;
|
FileHeader = ModuleLoadBase;
|
||||||
|
@ -514,7 +883,7 @@ LdrCOFFProcessDriver(PVOID ModuleLoadBase)
|
||||||
{
|
{
|
||||||
DbgPrint("Module has bad magic value (%x)\n",
|
DbgPrint("Module has bad magic value (%x)\n",
|
||||||
FileHeader->f_magic);
|
FileHeader->f_magic);
|
||||||
return STATUS_UNSUCCESSFUL;
|
return 0;
|
||||||
}
|
}
|
||||||
CHECKPOINT;
|
CHECKPOINT;
|
||||||
|
|
||||||
|
@ -522,7 +891,7 @@ LdrCOFFProcessDriver(PVOID ModuleLoadBase)
|
||||||
Module = (module *) ExAllocatePool(NonPagedPool, sizeof(module));
|
Module = (module *) ExAllocatePool(NonPagedPool, sizeof(module));
|
||||||
if (Module == NULL)
|
if (Module == NULL)
|
||||||
{
|
{
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return 0;
|
||||||
}
|
}
|
||||||
Module->sym_list = (SYMENT *)(ModuleLoadBase + FileHeader->f_symptr);
|
Module->sym_list = (SYMENT *)(ModuleLoadBase + FileHeader->f_symptr);
|
||||||
Module->str_tab = (char *)(ModuleLoadBase + FileHeader->f_symptr +
|
Module->str_tab = (char *)(ModuleLoadBase + FileHeader->f_symptr +
|
||||||
|
@ -569,7 +938,7 @@ LdrCOFFProcessDriver(PVOID ModuleLoadBase)
|
||||||
{
|
{
|
||||||
DbgPrint("Failed to alloc section for module\n");
|
DbgPrint("Failed to alloc section for module\n");
|
||||||
ExFreePool(Module);
|
ExFreePool(Module);
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return 0;
|
||||||
}
|
}
|
||||||
CHECKPOINT;
|
CHECKPOINT;
|
||||||
|
|
||||||
|
@ -589,14 +958,14 @@ LdrCOFFProcessDriver(PVOID ModuleLoadBase)
|
||||||
Module->scn_list[i].s_size);
|
Module->scn_list[i].s_size);
|
||||||
if (!LdrCOFFDoRelocations(Module, i))
|
if (!LdrCOFFDoRelocations(Module, i))
|
||||||
{
|
{
|
||||||
DPRINT("Relocation failed for section %s\n",
|
DbgPrint("Relocation failed for section %s\n",
|
||||||
Module->scn_list[i].s_name);
|
Module->scn_list[i].s_name);
|
||||||
|
|
||||||
/* FIXME: unallocate all sections here */
|
/* FIXME: unallocate all sections here */
|
||||||
|
|
||||||
ExFreePool(Module);
|
ExFreePool(Module);
|
||||||
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Module->scn_list[i].s_flags & STYP_BSS)
|
if (Module->scn_list[i].s_flags & STYP_BSS)
|
||||||
|
@ -607,7 +976,7 @@ LdrCOFFProcessDriver(PVOID ModuleLoadBase)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DbgPrint("Module base: %x\n", Module->base);
|
DPRINT("Module base: %x\n", Module->base);
|
||||||
|
|
||||||
/* Find the entry point */
|
/* Find the entry point */
|
||||||
EntryOffset = 0L;
|
EntryOffset = 0L;
|
||||||
|
@ -629,16 +998,46 @@ LdrCOFFProcessDriver(PVOID ModuleLoadBase)
|
||||||
|
|
||||||
/* FIXME: unallocate all sections here */
|
/* FIXME: unallocate all sections here */
|
||||||
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the address of the module initalization routine */
|
/* Get the address of the module initalization routine */
|
||||||
EntryRoutine = (PDRIVER_INITIALIZE)(Module->base + EntryOffset);
|
EntryRoutine = (PVOID)(Module->base + EntryOffset);
|
||||||
|
|
||||||
|
/* Create ModuleName string */
|
||||||
|
wcscpy(NameBuffer, MODULE_ROOT_NAME);
|
||||||
|
/* FIXME: someone who is interested needs to fix this. */
|
||||||
|
wcscat(NameBuffer, L"BOGUS.o");
|
||||||
|
ModuleName.Length = ModuleName.MaximumLength = wcslen(NameBuffer);
|
||||||
|
ModuleName.Buffer = NameBuffer;
|
||||||
|
DPRINT("Module name is: %w", NameBuffer);
|
||||||
|
|
||||||
|
/* Initialize ObjectAttributes for ModuleObject */
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&ModuleName,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* Create module object */
|
||||||
|
ModuleHandle = 0;
|
||||||
|
ModuleObject = ObCreateObject(&ModuleHandle,
|
||||||
|
OBJECT_TYPE_ALL_ACCESS,
|
||||||
|
&ObjectAttributes,
|
||||||
|
ObModuleType);
|
||||||
|
|
||||||
|
/* Initialize ModuleObject data */
|
||||||
|
ModuleObject->Base = (PVOID) Module->base;
|
||||||
|
ModuleObject->Flags = MODULE_FLAG_COFF;
|
||||||
|
ModuleObject->EntryPoint = (PVOID) (Module->base + EntryOffset);
|
||||||
|
DPRINT("entrypoint at %x\n", ModuleObject->EntryPoint);
|
||||||
|
/* FIXME: the COFF headers need to be copied into the module
|
||||||
|
space, and the ModuleObject needs to be set to point to them */
|
||||||
|
|
||||||
/* Cleanup */
|
/* Cleanup */
|
||||||
ExFreePool(Module);
|
ExFreePool(Module);
|
||||||
|
|
||||||
return IoInitializeDriver(EntryRoutine);
|
return ModuleObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* LdrCOFFDoRelocations
|
/* LdrCOFFDoRelocations
|
||||||
|
@ -684,7 +1083,7 @@ LdrCOFFDoRelocations(module *Module, unsigned int SectionIndex)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DPRINT("%.8s: Unknown relocation type %x at %d in module\n",
|
DbgPrint("%.8s: Unknown relocation type %x at %d in module\n",
|
||||||
Module->scn_list[SectionIndex].s_name,
|
Module->scn_list[SectionIndex].s_name,
|
||||||
Relocation->r_type,
|
Relocation->r_type,
|
||||||
j);
|
j);
|
||||||
|
@ -846,7 +1245,7 @@ LdrGetKernelSymbolAddr(char *Name)
|
||||||
if ((s=strchr(Name,'@'))!=NULL)
|
if ((s=strchr(Name,'@'))!=NULL)
|
||||||
{
|
{
|
||||||
*s=0;
|
*s=0;
|
||||||
DbgPrint("Name %s ",Name);
|
DPRINT("Name %s ",Name);
|
||||||
}
|
}
|
||||||
while (symbol_table[i].name != NULL)
|
while (symbol_table[i].name != NULL)
|
||||||
{
|
{
|
||||||
|
@ -855,7 +1254,7 @@ LdrGetKernelSymbolAddr(char *Name)
|
||||||
if (s!=NULL)
|
if (s!=NULL)
|
||||||
{
|
{
|
||||||
*s=0;
|
*s=0;
|
||||||
DbgPrint("Matched with %s\n",symbol_table[i].name);
|
DPRINT("Matched with %s\n",symbol_table[i].name);
|
||||||
}
|
}
|
||||||
return symbol_table[i].value;
|
return symbol_table[i].value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,17 +133,19 @@ else
|
||||||
endif
|
endif
|
||||||
$(CC) $(CFLAGS) -c ke/exports.c -o ke/exports.o
|
$(CC) $(CFLAGS) -c ke/exports.c -o ke/exports.o
|
||||||
|
|
||||||
ntoskrnl.exe: $(OBJECTS) ntoskrnl.def
|
all: ntoskrnl.a ntoskrnl.exe ntoskrnl.sym
|
||||||
$(LD) -r $(OBJECTS) -o ntoskrnl.o
|
|
||||||
$(DLLTOOL) --dllname ntoskrnl.exe --def ntoskrnl.def \
|
.PHONY: all
|
||||||
--output-lib ntoskrnl.a
|
|
||||||
|
ntoskrnl.exe: ntoskrnl.o ntoskrnl.def
|
||||||
$(CC) -specs=../specs -mdll -o junk.tmp \
|
$(CC) -specs=../specs -mdll -o junk.tmp \
|
||||||
-Wl,--image-base,0xc0000000 \
|
-Wl,--image-base,0xc0000000 \
|
||||||
-Wl,--file-alignment,0x1000 \
|
-Wl,--file-alignment,0x1000 \
|
||||||
-Wl,--section-alignment,0x1000 \
|
-Wl,--section-alignment,0x1000 \
|
||||||
-Wl,--defsym,_end=end \
|
-Wl,--defsym,_end=end \
|
||||||
-Wl,--defsym,_edata=__data_end__ \
|
-Wl,--defsym,_edata=__data_end__ \
|
||||||
-Wl,--defsym,_etext=etext -Wl,--base-file,base.tmp ntoskrnl.o
|
-Wl,--defsym,_etext=etext -Wl,--base-file,base.tmp \
|
||||||
|
ntoskrnl.o
|
||||||
- $(RM) junk.tmp
|
- $(RM) junk.tmp
|
||||||
$(DLLTOOL) --dllname ntoskrnl.exe --base-file base.tmp \
|
$(DLLTOOL) --dllname ntoskrnl.exe --base-file base.tmp \
|
||||||
--output-exp temp.exp --def ntoskrnl.def
|
--output-exp temp.exp --def ntoskrnl.def
|
||||||
|
@ -158,6 +160,13 @@ ntoskrnl.exe: $(OBJECTS) ntoskrnl.def
|
||||||
- $(RM) temp.exp
|
- $(RM) temp.exp
|
||||||
$(NM) --numeric-sort ntoskrnl.exe > ntoskrnl.sym
|
$(NM) --numeric-sort ntoskrnl.exe > ntoskrnl.sym
|
||||||
|
|
||||||
|
ntoskrnl.o: $(OBJECTS)
|
||||||
|
$(LD) -r $(OBJECTS) -o ntoskrnl.o
|
||||||
|
|
||||||
|
ntoskrnl.a: ntoskrnl.def
|
||||||
|
$(DLLTOOL) --dllname ntoskrnl.exe --def ntoskrnl.def \
|
||||||
|
--output-lib ntoskrnl.a
|
||||||
|
|
||||||
clean: $(CLEAN_FILES:%=%_clean)
|
clean: $(CLEAN_FILES:%=%_clean)
|
||||||
|
|
||||||
$(CLEAN_FILES:%=%_clean): %_clean:
|
$(CLEAN_FILES:%=%_clean): %_clean:
|
||||||
|
|
|
@ -137,7 +137,12 @@ wcsncat(wchar_t *dest, const wchar_t *src, size_t count)
|
||||||
int
|
int
|
||||||
wcsncmp(const wchar_t *cs, const wchar_t *ct, size_t count)
|
wcsncmp(const wchar_t *cs, const wchar_t *ct, size_t count)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
while (*cs != '\0' && *ct != '\0' && *cs == *ct && --count)
|
||||||
|
{
|
||||||
|
cs++;
|
||||||
|
ct++;
|
||||||
|
}
|
||||||
|
return *cs - *ct;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
2
reactos/subsys/win32k/.cvsignore
Normal file
2
reactos/subsys/win32k/.cvsignore
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
win32k.coff
|
||||||
|
win32k.sys
|
Loading…
Reference in a new issue