Windows内核开发
Windows内核开发
Unit01对话框
对话框是一种很特殊的窗口,体现在消息的处理上
//普通窗口处理消息:自定义函数调用缺省消息处理函数
WndProc(...){...DefWindowProc(...);
}//对话框窗口处理消息:缺省函数调用自定义函数
缺省函数(...){...自定义函数(...);....
}
01对话框原理
- 对话框的分类
- 模式对话框:当对话框显示时,会禁止本进程其他窗口和用户交互操作
- 无模式对话框:在对话框显示后,其他窗口仍然可以和用户交互操作
- 对话框基本使用
- 1.对话框处理函数
- 2.注册窗口类(不用程序员自己注册窗口类,系统已经注册好对话框的窗口类)
- 3.创建对话框
- 4.对话框的关闭
- 对话框窗口处理函数(并非真正的对话框窗口处理函数)
INT CALLBACK DialogProc(//函数名自定义HWND hwndDlg, //窗口句柄UINT uMsg, //消息IDWPARAM wParam, //消息参数LPARAM lParam//消息参数
);
//返回TRUE,缺省处理函数不需要处理
//返回FaLSE,交给缺省处理函数处理
//不需要调用缺省对话框处理函数
02模式对话框
- 创建模式对话框
int DialogBox(HINSTANCE hInstance,//应用程序实例句柄LPCTSTR lpTemplate,//对话框资源IDHWND hWndParent, //对话框窗口DLGPROC lpDialogFunc//自定义函数
);
//DialogBox是一个阻塞函数,只有当对话框关闭后,才会返回,继续执行后续代码
//返回值是通过EndDialog设置
- 关闭对话框
BOOL EndDialog(HWND hDlg,//关闭的对话框窗口句柄int nResult//关闭的返回值
);
//关闭模式对话框,只能适应EndDialog,不能使用DestoryWindow等函数
//nResult是DialogBox函数退出时的返回值
- 对话框的消息:
WM_INITDIALOG
对话框创建之后显示之前,通过对话框窗口处理函数,可以完成自己的初始化相关的操作
示例代码:
#include <windows.h>
#include "resource.h"HINSTANCE g_hInstance = 0;INT CALLBACK DlgProc(HWND hWndlg,UINT msgID,WPARAM wParam,LPARAM lParam){switch(msgID){case WM_INITDIALOG:MessageBox(hWndlg, "WM_INITDIALOG", "Infor", MB_OK);break;case WM_CREATE://为了验证对话框没有这个消息MessageBox(hWndlg, "WM_CREATE", "Infor", MB_OK);break;case WM_SYSCOMMAND:if(wParam == SC_CLOSE){//销毁对话框EndDialog(hWndlg,100);//两个功能销毁知名的对话框、解除DialogBox的阻塞//DestroyWindow(hWndlg);//只是销毁对话框,但是并没有解除解除DialogBox的阻塞,所以不能用}break;}return FALSE;//将消息交给真正的对话框窗口系统处理函数的后续代码帮我们处理
}void OnCommand(HWND hWnd, WPARAM wParam){switch(LOWORD(wParam)){case ID_MODEL:int nRet = DialogBox(g_hInstance, (char*)IDD_DIALOG1,hWnd,DlgProc);if(nRet == 100){MessageBox(hWnd, "successful", "Infor", MB_OK);}break;}
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{switch(msgID){case WM_COMMAND:OnCommand(hWnd, wParam);break;case WM_DESTROY:PostQuitMessage(0);//可以使GetMessage函数返回0break;}return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{g_hInstance = hIns;//注册窗口类WNDCLASS wc = {0};wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.hCursor = NULL;wc.hIcon = NULL;wc.hInstance = hIns;wc.lpfnWndProc = WndProc;wc.lpszClassName = "Main";//挂载菜单资源wc.lpszMenuName = (char*)IDR_MENU1;wc.style = CS_HREDRAW|CS_VREDRAW;RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核//在内存创建窗口HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);//显示窗口ShowWindow(hWnd,SW_SHOW);UpdateWindow(hWnd);//消息循环MSG nMsg = {0};while(GetMessage(&nMsg,NULL,0,0)){TranslateMessage(&nMsg);DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理}return 0;
}
03无模式对话框
- 创建无模式对话框
HWND CreateDialog(HINSTANCE hInstance,//应用程序实例句柄LPCTSTR lpTemplate, //模板资源IDHWND hWndParent,//父窗口DLGPROC lpDialogFunc//自定义函数
);
//非阻塞函数,创建成功返回窗口句柄,需要使用ShowWindow函数显示对话框
BOOL ShowWindow(HWND hWnd,int nCmdShow
);
- 对话框的关闭
- 关闭时使用
DestroyWindow
销毁窗口哦,不能使用EndDialog
关闭对话框
- 关闭时使用
BOOL DestroyWindow(HWND hWnd);
示例代码:
#include <windows.h>
#include "resource.h"HINSTANCE h_gInstance = 0;INT CALLBACK DlgProc(HWND hWndlg,UINT msgID,WPARAM wParam,LPARAM lParam){switch(msgID){case WM_SYSCOMMAND:if(wParam == SC_CLOSE)DestroyWindow(hWndlg);break;}return FALSE;
}void OnCommand(HWND hWnd,WPARAM wParam){switch(LOWORD(wParam)){case ID_UNMODEL:HWND hWndlg = CreateDialog(h_gInstance, (char*)IDD_DIALOG1, hWnd, DlgProc);ShowWindow(hWndlg, SW_SHOWNORMAL);break;}
}//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{switch(msgID){case WM_COMMAND:OnCommand(hWnd, wParam);break;case WM_DESTROY:PostQuitMessage(0);//可以使GetMessage函数返回0break;}return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{h_gInstance = hIns;//注册窗口类WNDCLASS wc = {0};wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.hCursor = NULL;wc.hIcon = NULL;wc.hInstance = hIns;wc.lpfnWndProc = WndProc;wc.lpszClassName = "Main";wc.lpszMenuName = (char*)IDR_MENU1;wc.style = CS_HREDRAW|CS_VREDRAW;RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核//在内存创建窗口HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);//显示窗口ShowWindow(hWnd,SW_SHOW);UpdateWindow(hWnd);//消息循环MSG nMsg = {0};while(GetMessage(&nMsg,NULL,0,0)){TranslateMessage(&nMsg);DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理}return 0;
}
Unit02静态库
01静态库特点
- 运行不存在
- 静态库源码被链接到调用程序中
- 目标程序的归档(就是程功能已经封装好直接来调用就行)
02C语言静态库
- C静态库的创建
- 创建一个静态库项目
- 添加库程序,源文件适应C文件
- C静态库的使用
- 库路径设置:可以使用
pragma
关键字设置 #pragma comment(lib,"../lib/clib.lib")
- 库路径设置:可以使用
![在这里插入图片描述](https://img-blog.csdnimg.cn/002a6bcdc7964dcaaf19f2d7ac1ed96a.png#pic_center
//通知链接器到哪抓源码
#pragma comment(lib, "../Debug/Clib.lib")int main(void){int sum, sub;sum = Clib_add(5,3);sub = Clib_sub(5,3);printf("sum=%d, sub=%d\n", sum, sub);getchar();return 0;
}
03C++语言静态库
- C++静态库的创建
- 创建一个静态库项目
- 添加程序库,源文件使用CPP文件
- C++静态库的使用
- 库路径设置:可以使用
pragma
关键字设置 #progma comment(lib, "../lib/cpplib.lib")
- 库路径设置:可以使用
#include <iostream>using namespace std;//添加函数声明
int CPPlib_add(int add1, int add2);
int CPPlib_sub(int sub1, int sub2);
//给连接器看的
#pragma comment(lib, "../Debug/CPPlib.lib")int main(){int sum = CPPlib_add(5, 4);int sub = CPPlib_sub(5, 4);cout << "sum=" << sum << ".sub=" << sub << endl;getchar();return 0;
}
- 使用C++调C语言的静态库
#include <iostream>using namespace std;//添加函数声明
int CPPlib_add(int add1, int add2);
int CPPlib_sub(int sub1, int sub2);
//给连接器看的
#pragma comment(lib, "../Debug/CPPlib.lib")//使用C语言的Clib.lib库函数,extern "C"防止c++编译器进行换名操作
extern "C" int Clib_add(int add1, int add2);
extern "C" int Clib_sub(int sub1, int sub2);
#pragma comment(lib, "../Debug/Clib.lib")int main(){int sum = CPPlib_add(5, 4);//?CPPlib_add@@YAHHH@Zint sub = CPPlib_sub(5, 4);//?CPPlib_sub@@YAHHH@Zcout << "sum=" << sum << ".sub=" << sub << endl;sum = Clib_add(5,3);//Clib_addsub = Clib_sub(5,3);//Clib_subcout << "sum=" << sum << ".sub=" << sub << endl;getchar();return 0;
}
Unit03动态库
01动态库的特点
- 动态库的特点
- 运行时独立存在
- 源码不会链接到执行程序
- 使用加载(使用动态库必须使动态库执行,就是让动态库进入内存)
- 与静态库相比较
- 由于静态库是将代码嵌入到使用程序中,多个程序使用时,会有多份代码,所以代码体积会增大。动态库的代码只需要一份,其他程序通过函数地址使用,所以代码体积小
- 静态库发生变化后,新的代码需要重新链接嵌入到执行程序中,动态库发生变化后如果库中的函数的定义(或地址)未变化,其他使用DLL的程序不需要重新链接。
02动态库创建
- 创建动态库项目
- 添加库程序
- 库程序导出:提供给使用者库中的函数信息(实际是导出的是动态库封装的函数的地址导出来,导出的地址在dll文件的文件头中)
- 1.声明导出:使用
_declspec(dllexport)
导出函数- 注意:动态库编译链接后,也会有
LIB
文件,是作为动态库函数映射使用,与静态库不完全相同
- 注意:动态库编译链接后,也会有
- 2.模块定义文件
.def
- 例如:
LIBRARY DLLFunc
//库 EXPORTS
//库导出表DLL_Mul @1
//导出的函数
- 例如:
- 1.声明导出:使用
//_declspec(dllexport)加上这个是为了导出动态库函数
_declspec(dllexport) int CPPdll_add(int add1, int add2){return add1 + add2;
}_declspec(dllexport) int CPPdll_sub(int sub1, int sub2){return sub1 + sub2;
}_declspec(dllexport) int CPPdll_mul(int mul1, int mul2){return mul1 + mul2;
}
03动态库的使用
隐式链接(操作系统负责动态库执行)
- 头文件和函数原型:可以在函数原型的声明前,增加
_declspec(dllimport)
- 导入动态库和
LIB
文件,#pragma comment(lib, "../Debug/CPPdll.lib")
- 在程序中使用函数
- 隐式链接的情况:dll文件可以存放在的路径:
- 与执行文件同一个目录下
(推荐使用这个路径下)
- 当前工作目录(就是当前的项目目录下)
Windows
目录(不建议放在系统目录下)Windows/System32
目录(不建议放在系统目录下)Windows/System
(不建议放在系统目录下)- 环境变量
PATH
指定目录(不建议放在系统路径下中,因为可以更改)
- 与执行文件同一个目录下
#include <iostream>using namespace std;
//声明函数
_declspec(dllimport) int CPPdll_add(int add1, int add2);
_declspec(dllimport) int CPPdll_sub(int sub1, int sub2);
_declspec(dllimport) int CPPdll_mul(int mul1, int mul2);//通知链接器到哪抓函数的 编号和dll文件名("CPPdll.dll")
#pragma comment(lib, "../Debug/CPPdll.lib")int main(){int sum = CPPdll_add(5,4);int sub = CPPdll_sub(5,4);int mul = CPPdll_mul(5,4);cout << "sum=" << sum << ",sub=" << sub << ",mul=" << mul << endl;system("pause");return 0;
}
显式链接(程序员自己负责使用动态库执行)
- 定义函数指针类型
typedef
- 加载动态库(就是让动态进内存)
HMODULE LoadLibrary(LPCTSTR lpFileName//动态库文件名或全路径
);//返回DLL的实例句柄(HINSTANCE)
- 获取函数
真实
地址
FARPROC GetProcAddress(HMODULE hModule,//DLL句柄LPCWSTR lpProcName//函数名称
); //成功返回函数地址
- 使用函数
- 卸载动态库
BOOL FreeLibrary(HMODULE hLibModule//DLL的实例句柄
);
#include <windows.h>
#include <iostream>using namespace std;typedef int(*ADD)(int m, int n);
typedef int(*SUB)(int m, int n);
typedef int(*MUL)(int m, int n);int main(){HINSTANCE hDll = LoadLibrary("CPPdll.dll");cout << "hDll:" << hDll << endl;//ADD myAdd = (ADD)GetProcAddress(hDll, "CPPdll_add");ADD myAdd = (ADD)GetProcAddress(hDll, "?CPPdll_add@@YAHHH@Z");cout << "myAdd:" << myAdd << endl;int sum = myAdd(5,4);cout << "sum=" << sum << endl;//SUB mySub = (SUB)GetProcAddress(hDll, "CPPdll_sub");SUB mySub = (SUB)GetProcAddress(hDll, "?CPPdll_sub@@YAHHH@Z");cout << "mySub:" << mySub << endl;int sub = mySub(5,4);cout << "sub=" << sub << endl;//MUL myMul = (MUL)GetProcAddress(hDll, "CPPdll_mul");MUL myMul = (MUL)GetProcAddress(hDll, "?CPPdll_mul@@YAHHH@Z");cout << "myMul:" << myMul << endl;int mul = myMul(5,4);cout << "mul=" << mul << endl;FreeLibrary(hDll);system("pause");return 0;
}
为了使用不换名的函数名,重名生成导出动态库文件
#include <windows.h>
#include <iostream>using namespace std;typedef int(*ADD)(int m, int n);
typedef int(*SUB)(int m, int n);
typedef int(*MUL)(int m, int n);int main(){HINSTANCE hDll = LoadLibrary("CPPdll.dll");cout << "hDll:" << hDll << endl;ADD myAdd = (ADD)GetProcAddress(hDll, "CPPdll_add");//ADD myAdd = (ADD)GetProcAddress(hDll, "?CPPdll_add@@YAHHH@Z");cout << "myAdd:" << myAdd << endl;int sum = myAdd(5,4);cout << "sum=" << sum << endl;SUB mySub = (SUB)GetProcAddress(hDll, "CPPdll_sub");//SUB mySub = (SUB)GetProcAddress(hDll, "?CPPdll_sub@@YAHHH@Z");cout << "mySub:" << mySub << endl;int sub = mySub(5,4);cout << "sub=" << sub << endl;//MUL myMul = (MUL)GetProcAddress(hDll, "CPPdll_mul");MUL myMul = (MUL)GetProcAddress(hDll, "?CPPdll_mul@@YAHHH@Z");cout << "myMul:" << myMul << endl;int mul = myMul(5,4);cout << "mul=" << mul << endl;FreeLibrary(hDll);system("pause");return 0;
}
04 动态库中封装类
- 在类名称前增加
_declspec(dllexport)
定义,例如:
class _declspec(dllexport) CMath{//...
};
- 通常使用预编译开关切换类的导入导出定义,例如:
#ifdef DLLCLASS_EXPORTS
#define EXT_CLASS_declspec(dllexport)//DLL
#else
#define EXT_CLASS_declspec(dllimport)//使用者
#endif
class EXT_CLASS CMath{//...
};
注意:封装类动态库一般只要声明导出,而不用定义文件导出,因为导出类真正是导出类中封装的函数相对地址
示例:创建封装类的动态库
#ifndef _DLLCLASS_H
#define _DLLCLASS_H#ifdef DLLCLASS_EXPORTS
#define EXT_CLASS _declspec(dllexport)
#else
#define EXT_CLASS _declspec(dllimport)
#endifclass EXT_CLASS CMath{public:int Add(int add1, int add2);int Sub(int sub1, int sub2);
};#endif //_DLLCLASS_H
#define DLLCLASS_EXPORTS#include "ClassDll.h"int CMath::Add(int add1, int add2){return add1 + add2;
}int CMath::Sub(int sub1, int sub2){return sub1 - sub2;
}
示例:调用封装好的动态库
#include <iostream>
#include "../ClassDll/ClassDll.h"#pragma comment(lib, "../Debug/ClassDll.lib")using namespace std;int main(){CMath math;int sum = math.Add(5, 6);int sub = math.Sub(5, 6);cout << "sum=" << sum << ",sub=" << sub << endl;return 0;
}
Windows内核开发相关推荐
- windows内核开发学习笔记十五:IRP结构
windows内核开发学习笔记十五:IRP结构 IRP(I/O Request Package)在windows内核中,有一种系统组件--IRP,即输入输出请求包.当上层应用程序需要访问底层输入输 ...
- windows内核开发学习笔记十八:IRP 处理的标准模式
windows内核开发学习笔记十八:IRP 处理的标准模式 在 Windows 内核中的请求基本上是通过 I/O Request Packet 完成的. I/O manager ---> Dis ...
- windows内核开发学习笔记十七:IRP 和 IO_STACK_LOCATION 的交互
windows内核开发学习笔记十七:IRP 和 IO_STACK_LOCATION 的交互 前面两篇学习笔记分别介绍了IRP和IO_STACK_LOCATION,整个设备栈来处理这个IRP,但是每个设 ...
- windows内核开发笔记七:内核开发OVERLAPPED结构体详解
windows内核开发笔记七:内核开发OVERLAPPED结构体详解 typedef struct _OVERLAPPED { DWORD Internal; DWORD InternalHi ...
- Windows内核开发之串口过滤
学习了几个月的内核编程,现在对Windows驱动开发又了更加深入的认识,特别是对IRP的分层处理逻辑有了深入认识. 总结起来就几句话: 当irp下来的时候,你要根据实际情况,进行处理 1> 无处 ...
- Windows内核开发调试环境配置详解
1. 下载和使用WDK 应用程序使用开发包SDK,类似的,内核编程使用"Windows Driver Kit",简称WDK.WDK已经自带所有需要的头文件.库.C/C++语言及汇编 ...
- Windows内核开发初步
环境配置并不复杂,只需要按照微软的要求装好VS2019和WDK,就可以在创建新项目中找到Driver.如果用的是Win11,可参考此文:驱动开发Windows11+VS2019环境配置 打开VS-&g ...
- windows内核开发学习笔记四十四:注册表存储结构-储巢
上一篇文章学习了注册表的逻辑结构,接下来我这篇文章来学习注册表的存储结构.注册表实际存储是由一组储巢构成,每个储巢包含了一个由键和值构成的层次结构.下面表是windows的各个储巢的注册表路径和文件路 ...
- Windows内核符号表学习总结
内核符号表 http://blog.csdn.net/vbsourcecode/article/details/8555796 在进行Windows Driver开发调试中,内核符号表是个问题.由于网 ...
最新文章
- keil5建立多文件的时候为什么总是出错
- 【微信小程序】 自定义导航栏(navigationStyle=custom)
- 机器学习实战(十)利用K-means算法对未标注数据分组
- 银联Apple Pay 总结
- Qt工作笔记-自定义模型【继承QAbstractTableModel】
- Spark Structured : HIve jdbc方式访问待下划线的表,找不到表的错误
- 机器人伪装成人类在 GitHub 上为开源项目修复 bug
- 服务器系统win12可以安装CAD,技术员教你解决win10系统安装CAD2012的教程介绍
- python aiml开发文档,带有Python的AIML文件
- 扫描仪怎样装无线网络服务器,怎么设置打印机IP地址和安装扫描仪。
- AI换脸骗过App,林俊杰和我们都怕
- matlab mat转bmp,mat格式转换
- 应用电路笔记(1)-三极管8550和8050应用
- 最小生成树Prim算法Java版
- 图像特征提取中的平移不变性、旋转不变性、尺度不变性
- python 操作word 替换字符串为图片_用python将.docx文件中的字符串替换为jpg
- SettingsProvider简单分析
- DNF2月18日早0点停机更新公告
- 协议 + socket import 和 form xx import *的区别 028
- keras搭建Unet实现图像分割