Windows核心编程
文章平均质量分 77
china_jeffery
持续学习者;
擅长开发开源组件及相关工具;
长期致力于应用各种IT新技术提升生产效率和解决实际问题;
展开
-
Windows资源管理器图标覆盖优先级设定
我们在安装了TortoiseSVN或TortoiseGit后,会自动在资源管理器的文件夹和文件图标上显示覆盖图标(Icon Overlay),这样会比较方便的查看文件的状态。但有时候我们安装的其他软件,如Dropbox等,也会在资源管理器中显示覆盖图标,多个软件都显示时,会由于优先级问题导致覆盖图标不显示等问题。本文主要讲述如何调整软件覆盖图标的优先级。打开注册表:HKEY_LOCAL_MA...原创 2019-08-23 11:57:36 · 1554 阅读 · 0 评论 -
Windows批处理请求UAC管理员权限
@echo offcd /d "%~dp0"cacls.exe "%SystemDrive%\System Volume Information" >nul 2>nulif %errorlevel%==0 goto Adminif exist "%temp%\getadmin.vbs" del /f /q "%temp%\getadmin.vbs"echo Set Reque...原创 2019-08-05 17:35:36 · 1715 阅读 · 0 评论 -
Windows注册自定义URL协议
原理:在注册表HKEY_CLASSES_ROOT项下加入对应的子项,内容如下:Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\test]@="URL:test protocol""URL Protocol"=""[HKEY_CLASSES_ROOT\test\DefaultIcon]@="mytest.exe"[H...原创 2019-08-29 11:03:14 · 3517 阅读 · 0 评论 -
Windows注入与拦截(2) -- 使用注册表方式完成DLL注入
一. 如何做?如题,通过注册表的方式来实现DLL注入,我们只需要针对特定的注册表项进行修改即可,有一点需要注意的是:如果被注入的进程是64位进程,则注入的DLL也需要是64位的,同理,注入32位的进程也需要是32位的DLL。 另外,根据被注入进程的位数(32或64)不同,注册表的位置也不同。1.1 注入64位系统上的32位进程1) 将被注入的DLL名称填入到AppInit_DL...原创 2018-03-30 16:19:37 · 45799 阅读 · 1 评论 -
Windows内存体系(8) -- 内存管理API分层结构
从上图可以看到,虚拟内存机制(Virtual Memory)是windows内存体系的基础,无论你是使用堆,还是使用内存映射文件,它们的底层都是基于虚拟内存来实现的。从上往下,每一层的API在内部会依次调用下一层的API。下图中列举了每层API中经常使用的函数:CRT Memory Functions:malloc, free, new, deleteLocal, Global M...原创 2018-03-20 22:33:55 · 31828 阅读 · 0 评论 -
Windows内存体系(7) -- 堆
一、为什么要使用堆?应用程序虽然可以使用页面粒度的函数(如VirualAlloc)来分配一个最小为64KB的内存块,但是很多时候我们并不需要分配这么大的内存块,我们可能只想分配1K,2K的内存块,那么这个时候无论从内存的使用率,还是从性能的角度来看,再分配这么大的一个内存区域显然不是最优的了。为了满足这种需求,Windows提供了一个被称为“堆管理器”的组件,它负责管理大内存区域中的内存分...原创 2018-03-20 18:16:29 · 33606 阅读 · 1 评论 -
理解C/C++运行时库
一、什么是运行时库运行时库(Runtime library)通俗的说就是我们的程序运行的时候所依赖的库文件,在Windows平台这些库由微软提供,并且是以2种形式提供:静态库(lib)、动态库(lib+dll)。每个库还都提供debug、release 2个版本。C/C++运行时库从形式上来讲和我们自己开发的静态库、动态库没什么两样,只是它们由微软开发和维护,并提供了一些常用的功能支持(如...原创 2018-03-14 15:57:54 · 55139 阅读 · 3 评论 -
Windows内存体系(3) -- 虚拟内存使用实例
虚拟内存方面的API属于页面粒度API,通过这些API分配的内存的最小粒度是64KB。另外通过前面的《Windows内存体系(2) – 页交换文件》文章,我们可以知道,这些API分配(调拨)的内存区域最初都是位于“页交换文件”上面,当程序对该区域的某些“页面”(对虚拟内存的管理以页面为单位进行的)进行读写时,才会将这些页面交换到物理内存上面。从《Windows内存体系(1) – 虚拟地址空间》...原创 2018-03-20 15:17:03 · 31736 阅读 · 0 评论 -
Windows的消息机制
一、消息队列首先我们要明确一个观点:窗口是和线程相关联的,消息队列也是和线程相关联的,这个线程无论是主线程还是子线程。当一个线程被创建时,系统假定该线程不会被用于任何与用户界面相关的任务,所以不会为它分配相应的资源(如消息队列等),因为这样可以减少线程对系统资源的占用。但是,一旦这个线程调用一个与图形用户界面有关的函数(例如检查它的消息队列或建立一个窗口),系统就会为该线程分配一些额外...原创 2018-03-14 00:18:36 · 53018 阅读 · 0 评论 -
Windows注入与拦截(1) -- DLL注入的基本原理
一. DLL注入技术的用途从前面的《Windows内存体系》系列文章中我们可以知道,在Windows系统中,每个进程都有自己私有的地址空间。当我们用指针来引用内存的时候,指针的值表示的是进程自己的地址空间的一个虚拟的内存地址。进程不能通过指针来引用其他进程地址空间的内存。因此,如果一个进程有缺陷会导致其引用和覆盖随机地址处的内存,那么这个缺陷的影响就会不会扩散到其他的进程。独立的地址空间有...原创 2018-03-30 14:50:20 · 50077 阅读 · 2 评论 -
Windows注入与拦截(5)-- 实现对指定窗口控件的挂载
一. 挂载原理本文主要介绍如何通过DLL注入的方式来实现在指定的窗口控件上挂载自定义窗口。何谓挂载? 和舰载机挂载导弹类似,将我们自己的窗口挂到原有程序的窗口之上,可以实现对原有窗口功能的覆盖和扩展。结合本实例的代码,挂载的实现原理大致如下:通过远程线程的方式(其他方式也可以)将DLL注入到指定的进程(当然是被挂载窗口所属的进程)。在DllMain的DLL_PROCESS_A...原创 2018-04-08 18:12:25 · 36149 阅读 · 0 评论 -
Windows注入与拦截(3) -- 使用钩子方式完成DLL注入
一. 钩子技术介绍前面介绍了《 Windows注入与拦截(2) – 使用注册表方式完成DLL注入》,本文介绍使用钩子的方式将DLL注入到进程的地址空间中。Windows提供了3个API来让我们可以很方便使用钩子技术将DLL文件注入到进程之中:// 安装指定消息类型的钩子到钩子链中HHOOK SetWindowsHookEx(int idHook, HOOKPROC lpfn,...原创 2018-04-02 15:00:12 · 44409 阅读 · 1 评论 -
Windows注入与拦截(6) -- 从内存中加载DLL
Windows提供的API(LoadLibrary, LoadLibraryEx)只支持从文件系统上加载DLL文件,我们无法使用这些API从内存中加载DLL。但是有些时候,我们的确需要从内存中加载DLL,比如:对发布的文件数量有限制。我们可以将DLL打包到exe的资源中,程序运行时从调用LoadResource等API读取DLL文件到内存中,然后从内存中加载DLL。需要对DLL进行压缩...原创 2018-04-09 18:01:03 · 43904 阅读 · 10 评论 -
Windows注入与拦截(4) -- 使用远程线程方式完成DLL注入
一. 远程线程注入原理前面几篇文章介绍了《Windows注入与拦截(2) – 使用注册表方式完成DLL注入》,《Windows注入与拦截(3) – 使用钩子方式完成DLL注入》这2种注入方式。“注册表注入方式”由于不能精确指定需要注入的进程,而且只能注入到GUI程序中,灵活性较差;“钩子注入方式”虽然能够精确指定注入的线程,但只能针对特定类型的消息进行Hook,从而间接的实现注入,对于类似wi...原创 2018-04-02 18:00:43 · 41795 阅读 · 0 评论 -
Windows内存体系(10) -- 使用std::string跨MT模块传参
前面的《Windows内存体系(9) – 跨MT模块的内存相互释放的问题》文章解释了跨MT模块分配的内存相互释放为什么会崩溃的问题。一、问题描述这篇文章主要介绍我们在实际开发中经常遇到的一个问题:针对MT模块定义接口函数时,接口参数使用std::string类型,在程序运行时遇到"Debug Assertioni Failed"错误的问题。 上面的错误提示是debug_heap....原创 2018-03-28 12:11:51 · 43802 阅读 · 1 评论 -
Windows平台“路径”相关API汇总
#include <Shlwapi.h>#pragma comment(lib, "shlwapi.lib")路径截断与合并函数PathRemoveArgs 去除路径后面的参数PathRemoveBackslash 去除路径最后的反斜杠“\”PathAddBackslash 在路径最后加上反斜...原创 2018-07-27 09:39:13 · 917 阅读 · 0 评论 -
如何使软件适应高dpi显示环境
一、dpi介绍dpi是“Dots Per Inch”的缩写,表示每英寸的像素点个数,也就是像素点的密集度。dpi = 总像素点 / 总面积比如一个32寸的显示,但分辨率只有19201440,而一个24寸的显示器,分辨率却达到38402160,很明显后面这个显示器的每英寸的像素点的个数多,显示的画面更加细腻。所以:高分辨率不等于高dpi。苹果的视网膜屏幕的核心就是高dpi:屏幕面积小,却分...原创 2018-11-09 12:42:32 · 9484 阅读 · 0 评论 -
用户界面特权隔离
写这篇文章源于本人在开发过程中遇到向某个进程发送消息失败而起。一、用户界面特权隔离在早期的Windows操作系统中,在同一用户下运行的所有进程有着相同的安全等级,拥有相同的权限。例如,一个进程可以自由地发送一个Windows消息到另外一个进程的窗口。从Windows Vista开始,当然也包括Windows 7、Windows 10,对于某些Windows消息,这一方式再也行不通了。进程(...原创 2019-03-06 11:25:10 · 1852 阅读 · 0 评论 -
Windows Interlocked系列函数(2)
本文以InterlockedIncrement为例,来说明Windows Interlocked系列函数的实现原理。一、InterlockedIncrement反汇编代码如下C++代码:#include <windows.h>int main(){ LONG l = 1; LONG j = InterlockedIncrement(&l...原创 2018-03-06 16:58:53 · 48920 阅读 · 1 评论 -
Windows内存体系(4) -- 内存映射文件
“内存映射文件”可以将硬盘上的文件映射到虚拟地址空间,这样就不需要将所有东西都放入到页交换文件中,比如系统有许多程序同时运行时,如果将这些程序文件都加载到页交换文件中,页交换文件将会变得非常大。事实上,Windows也并没有将硬盘上的程序文件复制到页交换文件中,因为这样不仅会让页交换文件将会变得非常大,也会浪费很多时间,特别是可执行程序非常大的时候。当用户要求执行一个应用程序时,系统会打开该应...原创 2018-03-19 17:50:12 · 33581 阅读 · 1 评论 -
重定向命令行程序的I/O
一、 原理本文描述如何重定向命令行子进程的标准输入流、标准输出流、标准错误流。本文介绍的方式只对使用了标准输入、标准输出、标准错误流的命令行程序有用。创建子进程时,我们一般使用CreateProcess,而CreateProcess提供的LPSTARTUPINFO参数允许我们改变进程的标准输入输出句柄。CreateProcess函数定义如下:BOOL WINAPI CreatePr原创 2018-01-20 21:46:37 · 116955 阅读 · 1 评论 -
CONTAINING_RECORD宏的实现原理
在使用windows完成端口时,会使用到CONTAINING_RECORD宏,该宏的作用就是:根据结构体中的某成员的地址来推算出该结构体整体的地址,相当于一个万能公式。 下面代码的注释中,讲解了该宏的实现原理。#include #include int main(){ struct T { int a; int b;原创 2017-12-14 12:30:53 · 90464 阅读 · 0 评论 -
windows程序单实例
// pszUniqueName需要以Global\\开头,且需保证事件名在整个计算机上唯一,可以使用GUID // BOOL CheckSingleInstance(LPCTSTR pszUniqueName) { HANDLE hMutex = CreateEvent(NULL, TRUE, FALSE, pszUniqueName); DWOR原创 2017-12-13 10:26:22 · 89811 阅读 · 0 评论 -
OutputDebugString完美封装
C/C++开发中经常需要输出调试信息,我们一般使用OutputDebugString输出到DebugView或者调试器输出窗口。 OutputDebugString原型如下:void WINAPI OutputDebugString( LPCTSTR lpOutputString);它只支持一个字符串参数。 在实际使用中,一般都会将其封装,支持可变参数,方便调用。封装了2原创 2017-12-12 14:48:37 · 90190 阅读 · 2 评论 -
根据进程句柄获得可执行文件路径的几种方法
转载自: http://blog.csdn.net/hellokandy/article/details/52160077通过进程句柄,获得可执行文件的路径,主要有以下几种方法:第一种方法:也是最常用的方法,是通过GetModuleFileNameEx函数获得可执行文件的模块路径,这个函数从Windows NT 4.0开始到现在的Vista系统都能使用,向后兼容性比较好。转载 2017-11-28 10:15:16 · 130436 阅读 · 0 评论 -
Windows环境下“路径”处理
头文件#include 引用库文件#pragma comment(lib, "shlwapi.lib")路径截断与合并函数PathRemoveArgs 去除路径后面的参数PathRemoveBackslash 去除路径最后的反斜杠“\”PathAddBackslash原创 2017-11-08 22:27:35 · 84138 阅读 · 0 评论 -
Windows内核对象(1) -- 内核对象与句柄
一、什么是内核对象我们在windows开发中经常会遇到内核对象,如事件(Event),管道(Pipe),互斥量(Mutex),完成端口(IOCP),进程(Process),线程(Thread)等,他们都是内核对象。这些内核对象虽然通过不同的系统API来创建,但这些API都有一个共同特点,就是都需要传入SECURITY_ATTRIBUTES安全描述符结构体指针,并且返回句柄(HANDLE)。依据原创 2018-01-25 16:42:52 · 111503 阅读 · 1 评论 -
Windows内核对象(2) -- 内核对象跨进程访问
虽然内核对象位于独立于进程之外的内核区域,我们在开发中却只能通过调用Win32 API传入HANDLE参数来操作内核对象(如SetEvent等)。然而HANDLE句柄只对当前进程有效,离开了当前进程该句柄就无效了(具体原因参考:Windows内核对象(1) – 内核对象与句柄)。所以说,跨进程访问内核对象的关键在于我们怎么跨进程访问句柄HANDLE?下面介绍几种方法来实现跨进程共享内核对象。原创 2018-01-26 13:30:50 · 111521 阅读 · 0 评论 -
Windows环境下提升进程的权限
有时候我们需要对进程的权限进行提升,从而使进程能进行某种操作,如打开系统进程等等。 在Windows环境下,进程权限的种类定义如下(定义在winnt.h):#define SE_CREATE_TOKEN_NAME TEXT("SeCreateTokenPrivilege")#define SE_ASSIGNPRIMARYTOKEN_NAM原创 2018-01-26 15:54:37 · 113755 阅读 · 0 评论 -
Windows内核对象(3) -- DuplicateHandle实现文件占用
DuplicateHandle的用法参考:http://blog.csdn.net/china_jeffery/article/details/79171307实现的原理大致就是,通过DuplicateHandle拷贝文件句柄给另外一个进程(一般是系统进程),因为系统进程不会被关闭,所以达到了占用某个文件,不让其他进程删除、读取、写入等。因为需要拷贝文件句柄给系统进程,所以涉及到打开系统原创 2018-01-26 16:46:36 · 123833 阅读 · 1 评论 -
windows事件跨session访问
事件名前面加“Global\”的方法,只能实现跨session检测事件是否存在,但执行打开事件OpenEvent等操作会返回Access Denied的错误。解决方法是创建一个没有任何权限的事件(A NULL DACL):PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIP...原创 2017-11-24 22:37:38 · 85872 阅读 · 0 评论 -
Windows内存体系(5)-- 内存映射文件技术的使用
前面的《Windows内存体系(3) – 内存映射文件》文章,对内存映射文件技术的原理进行了介绍,本篇文章着重介绍该技术的使用场景。一、内存映射文件技术介绍常用的有Win32 API的CreateFile()、WriteFile()、ReadFile()和MFC提供的CFile类都可以实现文件的读写操作。一般来说,以上这些函数可以满足大多数场合的要求,但是对于某些特殊应用领域所...原创 2018-03-02 22:08:26 · 52978 阅读 · 1 评论 -
Windows内存体系(9) -- 跨MT模块的内存相互释放的问题
在阅读本文之前,需要先对MT和MD运行时库有所了解,参考:《理解C/C++运行时库》。另外建议先阅读《Windows内存体系》系列文章的前几篇文章,对“虚拟内存”,“堆”,“内存API体系结构”有所了解。《Windows核心编程 第五版》第19章 DLL基础(511页)中给出了一个建议:“当一个MT版本的模块如果提供一个内存分配函数的时候,它必须同时提供另一个用来释放内存的函数。”。说...原创 2018-03-22 17:21:52 · 49584 阅读 · 0 评论 -
Windows内存体系(1) -- 虚拟地址空间
一、实模式下内存分配机制在8086或者80186以前,要运行一个程序,操作系统会把这些程序全都装入内存,程序都是直接运行在物理内存上的,也就是说程序中访问的内存地址都是实际的物理内存地址。当计算机同时运行多个程序时,必须保证这些程序用到的内存总量要小于计算机实际物理内存的大小。例如某台计算机总的内存大小是128M ,现在同时运行两个程序 A和B ,A需占用内存10M , B需占用内存110...原创 2018-03-19 14:07:17 · 34325 阅读 · 7 评论 -
Windows Interlocked系列函数(1)
// 将Addend加上Value,相加的结果存储到Addend中,并且返回值也会返回该结果//LONG InterlockedAdd( LONG volatile* Addend, LONG Value);// 将Addend加上Increment,返回Addend加之前的值//LONG InterlockedExchangeAdd( LPLONG Addend...原创 2018-03-06 11:59:02 · 55891 阅读 · 0 评论 -
Windows内存体系(2) -- 页交换文件
一、页交换文件虚拟地址空间只是操作系统为进程“虚拟”出来的一块地址区域,并不代表任何实际的空间。而“页交换文件”却对应了实际的空间,这个空间一般是磁盘上名为“pagefile.sys”的文件。“页交换文件”的大小和位置可以在系统设置(系统属性 -> 高级 -> 性能 -> 设置 -> 高级 )中进行设置: 从微软的官方文档来看,“虚拟内存”等于“物理内存”+...原创 2018-03-19 15:59:18 · 34740 阅读 · 8 评论 -
Windows内存体系(6) -- 彻底理解内存对齐
一、内存为什么要对齐虽然所有的变量都是保存在特定地址的内存中,但最好还是按照内存对齐的要求来存储。这主要出于两个方面的原因考虑: 平台原因: 不是所有的硬件平台(特别是嵌入式系统中使用的低端处理器)都能访问任意地址上的任意数据,某些硬件平台只能访问对齐的地址,否则会出现硬件异常。 性能原因: 如果数据存放在未对齐的内存空间中,则处理器访问变量时需要进行两次内存访问才能完整读取该...原创 2017-12-24 23:40:51 · 94745 阅读 · 3 评论 -
Windows套接字I/O模型(5) -- 完成端口模型
一、写在前面前面介绍了套接字I/O的同步模型、WSAAsyncSelect模型、WSAEventSelect模型,套接字I/O还剩下2个模型没有介绍:重叠模型,完成端口模型。 如果程序对性能和并发要求不高,可以使用前面介绍的WSAEventSelect模型;如果对性能和并发有要求,可以使用本文介绍的完成端口模型。 因为完成端口模型是基于重叠模型的,且在易用性、可伸缩性等方面都高于重叠模型...原创 2017-12-15 17:38:55 · 91970 阅读 · 2 评论