source multi file programming
I. multiple documents
1.1 purpose introduction
People who write windows kernel drivers may now use advanced WDK For example, WDK is automatically integrated into VS
But I still like WDK 7600 because the compiled drivers are very compatible And you can use the path under vscode configuration
But WDK 7600 is more troublesome to write For example, how to program multiple files How to include libraries How to compile into a library
How to use C/C + + code to write So this blog or this post is also a record When a new problem is encountered, the addition will continue
1.2 known SOURCES fields
II. Main topic
2.1 separation of include file and CPP file
The first way is to separate the inclusion file from the cpp/c file
Directory A stores your XXX H file
Directory B (main directory) stores XXX H implementation file
Then, the sources in directory B should be changed as follows
TARGETNAME=testDriver1 TARGETPATH=. TARGETTYPE=DRIVER MSC_WARNING_LEVEL= /W3 /WX INCLUDES= \ ./test1 SOURCES= Driver.cpp\ test.cpp
INCLUDES indicates the path you include You can also use the path of the system
For example:
example: INCLUDES= $(INCLUDES) \ $(DDK_INC_PATH); \ ..\common; \ ..\..\util; INCLUDES = $(DDK_INC_PATH);\ DDK_INC_PATH == WDKROOT\inc\ddk
Directory B holds driver CPP and test CPP, and test. Is stored in directory A h
Driver.cpp is the main entrance Test. Is referenced in DriverEntry h
- Test. In directory A H code
#ifdef __cplusplus extern "C" { #endif #include <ntifs.h> #include <ntddk.h> #include <Ntstrsafe.h> #include "ntimage.h" #ifdef __cplusplus } #endif PVOID testprint();
- Driver in directory B CPP and test Implementation of CPP
Driver.cpp
#include <ntifs.h> #include <ntddk.h> #include "test.h" VOID DriverUnLoad( PDRIVER_OBJECT DriverObject) { KdPrint(("Exit")); } extern "C" NTSTATUS DriverEntry( PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pReg) { UNREFERENCED_PARAMETER(pDriverObj); UNREFERENCED_PARAMETER(pReg); KdBreakPoint(); testprint(); //Referenced test Functions in H return STATUS_SUCCESS; }
test.cpp
#include "test.h" PVOID testprint() { DbgPrint("testprint"); return NULL; }
If it is not added in sources
INCLUDES= \ ./test1
Then it will be reported that XXX cannot be found h
Of course, if it's in your home directory h.cpp are all in the same directory Then just specify what you want to compile cpp is enough
2.2 32-bit driver uses 32-bit inline assembly
Drivers can use inline assembly when compiling 32 - bit drivers
The contents of the sources file are as follows:
TARGETNAME=testDriver1 TARGETPATH=. TARGETTYPE=DRIVER DRIVERTYPE=FS MSC_WARNING_LEVEL= /W3 /WX i386_SOURCES= \ test386.cpp SOURCES=Driver.cpp\
New field i386 used_ SOURCES
Because of our test cpp test. h Driver. CPP is in the same directory Therefore, there is no need to use the scheme of 2.1 to add inicloud path
Examples are as follows:
Driver.cpp
#include <ntifs.h> #include <ntddk.h> #include "test.h" VOID DriverUnLoad( PDRIVER_OBJECT DriverObject) { KdPrint(("Exit")); } extern "C" NTSTATUS DriverEntry( PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pReg) { UNREFERENCED_PARAMETER(pDriverObj); UNREFERENCED_PARAMETER(pReg); KdBreakPoint(); test(); return STATUS_SUCCESS; }
test.h
#ifdef __cplusplus extern "C" { #endif #include <ntifs.h> #include <ntddk.h> #include <Ntstrsafe.h> #include "ntimage.h" #ifdef __cplusplus } #endif PVOID test();
test.cpp
#include "test.h" PVOID __declspec(naked) test() { _asm { mov eax,eax ret } }
2.3 assembly under 64 bit
Reserved for solution
2.4 multi directory programming
If you have multiple driver projects that you want to compile together, the method is as follows
First, create a DIRS file The content of the file indicates the file directory of the driver you want to compile
But you should indicate the sources file in your directory Or the new DIRS
DIRS
DIRS= \ A \ B \ C
The above meaning means to compile the driver under the three file directories a, B and C
If there are SOURCES in directory a, the SOURCES file will be read and compiled A table of contents If directory B has embedded folders and DIRS, DIRS will be read first and continue to search for embedded folders in directory B Compile until you find a directory where SOURCES exists
2.5 compilation level
If you want to make your driver compile more strictly The following fields can be defined in SOURCES
MSC_WARNING_LEVEL= /W3 /WX
/W3 is the warning level / W1 / W2 / W3 / W4 / W4 is the most stringent If the parameter is not used, it needs to be used
UNREFERENCED_PARAMETER(pDriverObj); To include
/WX should be warning or error
2.6 compiling into Library
We can compile our drivers into libraries This involves library development
namely:
- How to generate Library in driver
- How to use custom libraries in drivers
2.6.1 how to generate Library in driver
First of all, if you are developing in C/C + +, you should give one h and a cpp file
Assume test h test. CPP as an example
The contents of the driver's sources file should be as follows:
TARGETNAME=test TARGETPATH=. TARGETTYPE=LIBRARY DRIVERTYPE=FS MSC_WARNING_LEVEL= /W3 /WX INCLUDES= \ ./test SOURCES= test.cpp
My directory structure is:
ROOTDIR test(DIR) test.h test.cpp
test.h as follows:
#ifdef __cplusplus extern "C" { #endif #include <ntddk.h> #ifdef __cplusplus } #endif class test { private: /* data */ public: test(/* args */); ~test(); PVOID testprint(); };
test.cpp
#include "test.h" test::test(/* args */) { } test::~test() { } PVOID test::testprint() { DbgPrint("testprint"); return NULL; }
After generation, a test. Is generated Lib Library
2.6.2 library used in driver
Using the library is simple Copy the header file
Then indicate it in SOURCE
The sources are as follows:
TARGETNAME=test1 TARGETPATH=. TARGETTYPE=DRIVER MSC_WARNING_LEVEL= /W3 /WX INCLUDES= \ ./test TARGETLIBS = .\libs\test.lib SOURCES= Driver.cpp
test.h same as above
Driver.cpp is as follows:
#include "test\test.h" VOID DriverUnLoad( PDRIVER_OBJECT DriverObject) { KdPrint(("Exit")); } extern "C" NTSTATUS DriverEntry( PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pReg) { UNREFERENCED_PARAMETER(pDriverObj); UNREFERENCED_PARAMETER(pReg); KdBreakPoint(); pDriverObj->DriverUnload = DriverUnLoad; test t; t.testprint(); return STATUS_SUCCESS; }
If it is C language, it can be compiled directly
About TARGETLIBS, you can also include paths
For example:
TARGETLIBS = $(DDK_LIB_PATH)\xxx1.lib\ $(DDK_LIB_PATH)\xxx2.lib\ For example, include ntstrsafe.lib library TARGETLIBS= $(DDK_LIB_PATH)\ntstrsafe.lib The paths provided by the system are as follows: DDK_LIB_PATH == WDKROOT\lib\Version\* SDK_LIB_PATH == WDKROOT\lib\Version\* CRT_LIB_PATH
2.7 definition of C constant
C can be used in the SOURCES file_ DEFINES
It means equivalent to you in the world c file uses #define to declare macros
TARGETNAME=test1 TARGETPATH=. TARGETTYPE=DRIVER MSC_WARNING_LEVEL= /W3 /WX !IFDEF DDKBUILDENV C_DEFINES=$(C_DEFINES) -DDDK_BUILD !ENDIF INCLUDES= \ ./test TARGETLIBS = .\libs\test.lib SOURCES= Driver.cpp
Example 2:
C_DEFINES=$(C_DEFINES) /wd4996
2.8 SOURCES indicates the compiled files and condition macros
Found in WDK You can compile resources for the driver. You can define two sources to point to the file to be compiled
Then the final reference
example:
!if $(IA64) xxxxx Conditional use IA64 !endif DIR_SOURCES=wacompen.c \ wacompen.rc \ oempen.c \ errcodes.mc STB_SOURCES=hid.c \ pnp.c \ serial.c \ errlog.c SOURCES= $(DIR_SOURCES) $(STB_SOURCES)