dll注入c语言学习笔记
in 逆向工程 with 0 comment

dll注入c语言学习笔记

in 逆向工程 with 0 comment

1.预处理指令#pragma

一般格式
  其格式一般为:#pragma Para。其中Para 为参数,下面来看一些常用的参数。

message 参数
  Message 参数能够在编译信息输出窗口中输出相应的信息,这对于源代码信息的控制是非常重要的。其使用方法为:

  #pragma message(“消息文本”)

  当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。
code_seg
  另一个使用得比较多的pragma参数是code_seg。格式如:

  #pragma code_seg( ["section-name"[,"section-class"] ] )

  它能够设置程序中函数代码存放的代码段,当人们开发驱动程序的时候就会使用到它。

pragma once

  (比较常用)

  只要在头文件的最开始加入这条指令就能够保证头文件被编译一次,这条指令实际上在VC6中就已经有了,但是考虑到兼容性并没有太多的使用它。

  #pragma once是编译相关,就是说这个编译系统上能用,但在其他编译系统不一定可以,也就是说移植性差,不过基本上已经是每个编译器都有这个定义了。

  #ifndef,#define,#endif这个是C++语言相关,这是C++语言中的宏定义,通过宏定义避免文件多次编译。所以在所有支持C++语言的编译器上都是有效的,如果写的程序要跨平台,最好使用这种方式

pragma hdrstop

  #pragma hdrstop表示预编译头文件到此为止,后面的头文件不进行预编译。BCB可以预编译头文件以加快链接的速度,但如果所有头文件都进行预编译又可能占太多磁盘空间,所以使用这个选项排除一些头文件。

  有时单元之间有依赖关系,比如单元A依赖单元B,所以单元B要先于单元A编译。你可以用#pragma startup指定编译优先级,如果使用了#pragma package(smart_init) ,BCB就会根据优先级的大小先后编译。

pragma resource

  #pragma resource ".dfm"表示把.dfm文件中的资源加入工程。*.dfm中包括窗体外观的定义。

pragma warning

  #pragma warning( disable : 4507 34; once : 4385; error : 164 )

  等价于:

  #pragma warning(disable:4507 34) // 不显示4507和34号警告信息

  #pragma warning(once:4385) // 4385号警告信息仅报告一次

  #pragma warning(error:164) // 把164号警告信息作为一个错误。

  同时这个pragma warning 也支持如下格式:

  #pragma warning( push [ ,n ] )

  #pragma warning( pop )

  这里n代表一个警告等级(1---4)。

  #pragma warning( push )保存所有警告信息的现有的警告状态。

  #pragma warning( push, n)保存所有警告信息的现有的警告状态,并且把全局警告等级设定为n。

  #pragma warning( pop )向栈中弹出最后一个警告信息,

  </printcolor>

  在入栈和出栈之间所作的一切改动取消。例如:

  #pragma warning( push )

  #pragma warning( disable : 4705 )

  #pragma warning( disable : 4706 )

  #pragma warning( disable : 4707 )

  //.......

  #pragma warning( pop )

  在这段代码的最后,重新保存所有的警告信息(包括4705,4706和4707)。

pragma comment
  pragma comment(...)

  该指令将一个注释记录放入一个对象文件或可执行文件中。

  常用的lib关键字,可以帮人们连入一个库文件。

2.HMODULE

HINSTANCE表示实例句柄,HMODULE是模块句柄,实际上他们本质上都是VOID指针,是可以指向任何类型的指针。

线程概念

线程:线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。
多线程:多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。
C语言的开始设计,并未设计多线程的机制,由于随着软硬件的发展及需求的发展。后来C语言才开发了线程库以支持多线程的操作、应用。
主要基于Linux介绍C多线程。在编译C的多线程时候,一方面必须指定Linux C语言线程库多线程库pthread,才可以正确编译(例如:gcc test.c -o test -lpthread);另一方面要包含有关线程头文件#include <pthread.h>。

ThreadProc函数

基本内容
这个函数是一个应用程序定义的函数的占位符,作为一个线程的起始地址。在调用CreateThread函数时,指定该地址。LPTHREAD_START_ROUTINE类型定义了该回调函数的指针。 ThreadProc是一个应用程序定义的函数的名称的占位符。

DWORD WINAPI ThreadProc(LPVOID lpParameter);

参数

lpParameter

接收线程传递给函数使用的CreateThread函数lpParameter参数数据。

返回值

函数应该返回一个值,指出其成功或失败。

备注

一个进程可以通过调用GetExitCodeThread函数获取由CreateThread创建的线程的ThreadProc函数的返回值。

LPVOID

LPVOID是一个没有类型的指针,也就是说你可以将LPVOID类型的变量赋值给任意类型的指针

GetModuleFileName

GetModuleFileName是计算机应用中的一个函数,用以获取当前进程已加载模块文件的完整路径。

DWORD WINAPI GetModuleFileName(

_In_opt_  HMODULE hModule,

_Out_     LPTSTR lpFilename,

_In_      DWORD nSize

);。
返回数值
Long,如执行成功,返回复制到lpFileName的实际字符数量;零表示失败。使用GetLastError可以打印错误信息。

运用参数
hModule Long
一个模块的句柄。可以是一个DLL模块,或者是一个应用程序的实例句柄。如果该参数为NULL,该函数返回该应用程序全路径。

lpFileName String
指定一个字串缓冲区,要在其中容纳文件的用NULL字符中止的路径名,hModule模块就是从这个文件装载进来的。

nSize Long
装载到缓冲区lpFileName的最大字符数量。

strchr,wcschr 和strrchr, wcsrchr,_tcschr,_tcsrchr功能

(1)
char strchr( const char string, int c );
wchar_t wcschr( const wchar_t string, wchar_t c );
Find a character in a string.
查找一个字符串中首次出现的指定字符。
Return Value

Each of these functions returns a pointer to the first occurrence of c in string(address), or NULL if c is not found.

_tcschr是strchr或者wcschr,跟_UNICODE是否定义有关
(2)
char strrchr( const char string, int c);
char wcsrchr( const wchar_t string, int c );

Scan a string for the last occurrence of a character.

查找一个字符串中最后出现的指定字符。
Return Value

Each of these functions returns a pointer to the last occurrence of c in string(address), or NULL if c is not found.
找出字符串中最后一个出现查找字符的地址,然后将该字符出现的地址返回。

_tcsrchr这是strrchr或wcsrchr,同_UNICODE是否定义有关

URLDownloadToFile

Syntax:
HRESULT URLDownloadToFile(

LPUNKNOWN pCaller,
LPCTSTR szURL,
LPCTSTR szFileName,
DWORD dwReserved,
LPBINDSTATUSCALLBACK lpfnCB

);
Parameters:
pCallerPointer to the controlling IUnknown interface of the calling Microsoft ActiveX component (if the caller is an ActiveX component). //控件的接口,如果不是控件则为0.
szURL
Pointer to a string value containing the URL to be downloaded. Cannot be set to NULL
//要下载的url地址,不能为空.
szFileName
Pointer to a string value containing the name of the file to create for bits that come from the download.
//下载后保存的文件名.
dwReserved
Reserved. Must be set to 0.
//保留字段,必需为0
lpfnCB
Pointer to the caller's IBindStatusCallback interface. URLDownloadToFile calls this interface's IBindStatusCallback::OnProgress method on a connection activity, including the arrival of data. IBindStatusCallback::OnDataAvailable is never called.
//下载进度状态回调
Return Value
Returns one of the following values.
S_OK : The download started successfully.
E_OUTOFMEMORY: The buffer length is invalid, or there is insufficient memory to complete the operation.
INET_E_DOWNLOAD_FAILURE:The specified resource or callback interface was invalid.

DllMain

 系统是在什么时候调用DllMain函数的呢?静态链接时,或动态链接时调用LoadLibrary和FreeLibrary都会调用DllMain函数。DllMain的第二个参数fdwReason指明了系统调用Dll的原因,它可能是::

  DLL_PROCESS_ATTACH、

  DLL_PROCESS_DETACH、

  DLL_THREAD_ATTACH、

  DLL_THREAD_DETACH。

  以下从这四种情况来分析系统何时调用了DllMain。

DLL_PROCESS_ATTACH
  大家都知道,一个程序要调用Dll里的函数,首先要先把DLL文件映射到进程的地址空间。要把一个DLL文件映射到进程的地址空间,有两种方法:静态链接和动态链接的LoadLibrary或者LoadLibraryEx。

  当一个DLL文件被映射到进程的地址空间时,系统调用该DLL的DllMain函数,传递的fdwReason参数为DLL_PROCESS_ATTACH,这种调用只会发生在第一次映射时。如果同一个进程后来为已经映射进来的DLL再次调用LoadLibrary或者LoadLibraryEx,操作系统只会增加DLL的使用次数,它不会再用DLL_PROCESS_ATTACH调用DLL的DllMain函数。不同进程用LoadLibrary同一个DLL时,每个进程的第一次映射都会用DLL_PROCESS_ATTACH调用DLL的DllMain函数。

  可参考DllMainTest的DLL_PROCESS_ATTACH_Test函数。

DLL_PROCESS_DETACH
  当DLL被从进程的地址空间解除映射时,系统调用了它的DllMain,传递的fdwReason值是DLL_PROCESS_DETACH。当DLL处理该值时,它应该执行进程相关的清理工作。

  那么什么时候DLL被从进程的地址空间解除映射呢?两种情况:

  ◆FreeLibrary解除DLL映射(有几个LoadLibrary,就要有几个FreeLibrary)

  ◆进程结束而解除DLL映射,在进程结束前还没有解除DLL的映射,进程结束后会解除DLL映射。(如果进程的终结是因为调用了TerminateProcess,系统就不会用DLL_PROCESS_DETACH来调用DLL的DllMain函数。这就意味着DLL在进程结束前没有机会执行任何清理工作。)

  注意:当用DLL_PROCESS_ATTACH调用DLL的DllMain函数时,如果返回FALSE,说明没有初始化成功,系统仍会用DLL_PROCESS_DETACH调用DLL的DllMain函数。因此,必须确保清理那些没有成功初始化的东西。

  可参考DllMainTest的DLL_PROCESS_DETACH_Test函数。

DLL_THREAD_ATTACH
  当进程创建一线程时,系统查看当前映射到进程地址空间中的所有DLL文件映像,并用值DLL_THREAD_ATTACH调用DLL的DllMain函数。

  新创建的线程负责执行这次的DLL的DllMain函数,只有当所有的DLL都处理完这一通知后,系统才允许进程开始执行它的线程函数。

  注意跟DLL_PROCESS_ATTACH的区别,我们在前面说过,第n(n>=2)次以后地把DLL映像文件映射到进程的地址空间时,是不再用DLL_PROCESS_ATTACH调用DllMain的。而DLL_THREAD_ATTACH不同,进程中的每次建立线程,都会用值DLL_THREAD_ATTACH调用DllMain函数,哪怕是线程中建立线程也一样。

DLL_THREAD_DETACH
  如果线程调用了ExitThread来结束线程(线程函数返回时,系统也会自动调用ExitThread),系统查看当前映射到进程空间中的所有DLL文件映像,并用DLL_THREAD_DETACH来调用DllMain函数,通知所有的DLL去执行线程级的清理工作。

  注意:如果线程的结束是因为系统中的一个线程调用了TerminateThread,系统就不会用值DLL_THREAD_DETACH来调用所有DLL的DllMain函数。

OutputDebugString

The OutputDebugString function sends a string to the debugger for the current application.

VOID OutputDebugString(
LPCTSTR lpOutputString // pointer to string to be displayed
);

Parameters:

lpOutputString parameters Pointer to the null-terminated string to be displayed.

Return Values
This function does not return a value.

Remarks
If the application has no debugger, the system debugger displays the string.
If the application has no debugger and the system debugger is not active,
OutputDebugString does nothing.

STARTUPINFO

名称
STARTUPINFO

用途
指定新进程的主窗口特性

结构原型
  typedef struct _STARTUPINFO {

  DWORD cb;

  LPTSTR lpReserved;

  LPTSTR lpDesktop;

  LPTSTR lpTitle;

  DWORD dwX;

  DWORD dwY;

  DWORD dwXSize;

  DWORD dwYSize;

  DWORD dwXCountChars;

  DWORD dwYCountChars;

  DWORD dwFillAttribute;

  DWORD dwFlags;

  WORD wShowWindow;

  WORD cbReserved2;

  LPBYTE lpReserved2;

  HANDLE hStdInput;

  HANDLE hStdOutput;

  HANDLE hStdError;

  } STARTUPINFO, *LPSTARTUPINFO;

参数说明
  STARTUPINFO结构 该结构用于指定新进程的主窗口特性 

  DWORD cb; //包含STARTUPINFO结构中的字节数.如果Microsoft将来扩展该结构,它可用作版本控制手段.

  应用程序必须将cb初始化为sizeof(STARTUPINFO)

  PSTR lpReserved; //保留。必须初始化为N U L L

  PSTR lpDesktop; //用于标识启动应用程序所在的桌面的名字。如果该桌面存在,新进程便与指定的桌面相关联。

  如果桌面不存在,便创建一个带有默认属性的桌面,并使用为新进程指定的名字。

  如果lpDesktop是NULL(这是最常见的情况),那么该进程将与当前桌面相关联

  PSTR lpTitle; //用于设定控制台窗口的名称。如果l p Ti t l e 是N U L L ,则可执行文件的名字将用作窗口名

  DWORD dwX; //用于设定应用程序窗口在屏幕上应该放置的位置的x 和y 坐标(以像素为单位)。

  DWORD dwY; 只有当子进程用CW_USEDEFAULT作为CreateWindow的x参数来创建它的第一个重叠窗口时,

  才使用这两个坐标。若是创建控制台窗口的应用程序,这些成员用于指明控制台窗口的左上角

  DWORD dwXSize; //用于设定应用程序窗口的宽度和长度(以像素为单位)只有dwYsize

  DWORD dwYSize; 当子进程将C W _ U S E D E FA U LT 用作C r e a t e Wi n d o w 的

  n Wi d t h参数来创建它的第一个重叠窗口时,才使用这些值。

  若是创建控制台窗口的应用程序,这些成员将用于指明控制台窗口的宽度

  DWORD dwXCountChars; //用于设定子应用程序的控制台窗口的宽度和高度(以字符为单位)

  DWORD dwYCountChars;

  DWORD dwFillAttribute; //用于设定子应用程序的控制台窗口使用的文本和背景颜色

  DWORD dwFlags; //请参见下一段和表4 - 7 的说明

  WORD wShowWindow; //用于设定如果子应用程序初次调用的S h o w Wi n d o w 将S W _ S H O W D E FA U LT 作为

  n C m d S h o w 参数传递时,该应用程序的第一个重叠窗口应该如何出现。

  本成员可以是通常用于Show Wi n d o w 函数的任何一个S W _ *标识符

  WORD cbReserved2; //保留。必须被初始化为0

  PBYTE lpReserved2; //保留。必须被初始化为N U L L

  HANDLE hStdInput; //用于设定供控制台输入和输出用的缓存的句柄。

  按照默认设置,h S t d I n p u t 用于标识键盘缓存,

  h S t d O u t p u t 和h S t d E r r o r用于标识控制台窗口的缓存

  HANDLE hStdOutput;

  HANDLE hStdError;

  当Wi n d o w s 创建新进程时,它将使用该结构的有关成员。大多数应用程序将要求生成的应用程序仅仅使用默认值。至少应该将该结构中的所有成员初始化为零,然后将c b 成员设置为该结构的大小:

  STARTUPINFO si = { sizeof(si) };

  CreateProcess(...,&si,...);

  表4-7 dwFlags 使用标志及含义

  标志 含义

  STARTF_USESIZE // 使用d w X S i z e 和d w Y S i z e 成员

  STARTF_USESHOWWINDOW //使用w S h o w Wi n d o w 成员

  STARTF_USEPOSITION //使用d w X 和d w Y 成员

  STARTF_USECOUNTCHARS //使用d w X C o u n t C h a r s 和dwYCount Chars 成员

  STARTF_USEFILLATTRIBUTE //使用d w F i l l A t t r i b u t e 成员

  STARTF_USESTDHANDLES //使用h S t d I n p u t 、h S t d O u t p u t 和h S t d E r r o r 成员

  STARTF_RUN_FULLSCREEN //强制在x 8 6 计算机上运行的控制台应用程序以全屏幕方式启动运行

  另外还有两个标志,即STARTF_FORCEONFEEDBACK 和STARTF_+FORCEOFFF -EEDBACK ,当启动一个新进程时,它们可以用来控制鼠标的光标。由于Windows支持真正的多任务抢占式运行方式,因此可以启动一个应用程序,然后在进程初始化时,使用另一个程序。为了向用户提供直观的反馈信息,C r e a t e P r o c e s s 能够临时将系统的箭头光标改为一个新光标,即沙漏箭头光标:

  该光标表示可以等待出现某种情况,也可以继续使用系统。当启动另一个进程时,CreateProcess函数使你能够更好地控制光标。当设定STARTF_FORCEONFEEDBACK标志时,C r e a t e P r o c e s s 并不将光标改为沙漏。

  STARTF_FORCEONFEEDBACK可使CreateProcess能够监控新进程的初始化,并可根据结果来改变光标。当使用该标志来调用CreateProcess时,光标改为沙漏。过2 s 后,如果新进程没有调用G U I ,CreateProcess 将光标恢复为箭头。

  如果该进程在2 s 内调用了GUI ,CreateProcess将等待该应用程序显示一个窗口。这必须在进程调用G U I 后5 s内发生。如果没有显示窗口,CreateProcess就会恢复原来的光标。如果显示了一个窗口,CreateProcess将使沙漏光标继续保留5s 。如果某个时候该应用程序调用了G e t M e s s a g e 函数,指明它完成了初始化,那么C r e a t e P r o ce s s 就会立即恢复原来的光标,并且停止监控新进程。

  在结束这一节内容的介绍之前,我想讲一讲S TA RT U P I N F O 的w S h o w Wi n d o w成员。你将该成员初始化为传递给( w ) Wi n M a i n 的最后一个参数n C m d S h o w的值。该成员显示你想要传递给新进程的( w ) Wi n M a i n 函数的最后一个参数n C m d S h o w的值。它是可以传递给S h o w Wi n d o w 函数的标识符之一。通常,n C m d S h o w 的值既可以是S W SH O W N O R M A L ,也可以是SW SHOWMINNOACTIVE 。但是,它有时可以是S W _ S H O W D EFA U LT 。

  当在E x p l o r e r 中启动一个应用程序时,该应用程序的( w ) Wi n M a i n 函数被调用,而S W _ SH O W N O R M A L 则作为n C m d S h o w参数来传递。如果为该应用程序创建了一个快捷方式,可以使用快捷方式的属性页来告诉系统,应用程序的窗口最初应该如何显示。图4 - 3 显示了运行No t e p a d 的快捷方式的属性页。注意,使用R u n 选项的组合框,就能够设定如何显示N o t e p a d 的窗口。

  当使用E x p l o r e r 来启动该快捷方式时,E x p l o r e r 会正确地准备S TA RT U P I N FO 结构并调用C r e a t e P r o c e s s 。这时N o t e p a d 开始运行,并且为n C m d S h ow 参数将S W _ S H O W M I N N O A C T I V E传递给它的( w ) Wi n M a i n 函数。

  运用这样的方法,用户能够很容易地启动一个应用程序,其主窗口可以用正常状态、最小或最大状态进行显示。

  最后,应用程序可以调用下面的函数,以便获取由父进程初始化的S TA RT U P I N F O 结构的拷贝。子进程可以查看该结构,并根据该结构的成员的值来改变它的行为特性。

  VOID GetStartupInfo(LPSTARTUPINFO pStartupInfo);

  注意虽然Wi n d o w s 文档没有明确地说明,但是在调用G e t S t a r t I n f o 函数之前,必须像下面这样对该结构的c b 成员进行初始化:

  STARTUPINFO si = { sizeof(si) };

  GetStartupInfo(&si);

PROCESSINFORMATION结构

typedef struct_PROCESS_INFORMATION{

HANDLE hProcess;

HANDLE hThread;

DWORD dwProcessId;

DWORD dwThreadId;

}PROCESS_INFORMATION;

其中成员含义如下。

① hProcess:返回新进程的句柄。

② hThread:返回主线程的句柄。

③ dwProcessId:返回一个全局进程标识符。该标识符用于标识一个进程。从进程被

创建到终止,该值始终有效。

④ dwThreadId:返回一个全局线程标识符。该标识符用于标识一个线程。从线程被创

建到终止,该值始终有效。

_tcsrchr

char szFilePath[MAX_PATH]; //路径数组
GetModuleFileName(NULL, szFilePath, MAX_PATH); //获取应用程序完整路径 如: e:ba.exe
(_tcsrchr(szFilePath, _T('\')))[1] = 0; //去除最后一个后面的串,即: e:b\
用0截断字符串

_tcsstr:字符串1在字符串2中首次出现的位置,未出现返回NULL值;
_tcsrchr:字符1 在字符串2中首次出现的位置,未出现返回NULL值

_tcscpy_s

字符拷贝函数,使用的如果是UNICODE编码,则采用wcscpy_s()函数,如果是多字节编码,则采用strcpy_s()函数。

功能:字符串拷贝

后缀_s表示使用安全的字符串拷贝函数,防止缓冲区不够大而引起错误。

internetopen

概况:初始化一个应用程序,以使用WinINet函数。
参数
lpszAgent

指向一个 空结束的字符串,该字符串指定的应用程序或实体调用WinInet函数的名称。使用此名称作为用户代理的HTTP协议。

dwAccessType

指定访问类型,参数可以是下列值之一:

INTERNET_OPEN_TYPE_DIRECT

使用直接连接网络。

INTERNET_OPEN_TYPE_PRECONFIG

获取代理或直接从注册表中的配置,使用代理连接网络。

INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY

获取代理或直接从注册表中的配置,并防止启动Microsoft JScript或Internet设置(INS)文件的使用。

INTERNET_OPEN_TYPE_PROXY

通过代理的请求,除非代理旁路列表中提供的名称解析绕过代理,在这种情况下,该功能的使用。

lpszProxyName

指针指向一个空结束的字符串,该字符串指定的代理服务器的名称,不要使用空字符串;如果 未设置为 INTERNET_OPEN_TYPE_PROXY,则此参数应该设置为NULL。

lpszProxyBypass

指向一个空结束的字符串,该字符串指定的可选列表的主机名或IP地址。如果 未设置为INTERNET_OPEN_TYPE_PROXY的 ,参数省略则为NULL。

dwFlags

参数可以是下列值的组合:

INTERNET_FLAG_ASYNC

使异步请求处理的后裔从这个函数返回的句柄。

INTERNET_FLAG_FROM_CACHE

不进行网络请求,从缓存返回的所有实体,如果请求的项目不在缓存中,则返回一个合适的错误,如ERROR_FILE_NOT_FOUND。

INTERNET_FLAG_OFFLINE

不进行网络请求,从缓存返回的所有实体,如果请求的项目不在缓存中,则返回一个合适的错误,如ERROR_FILE_NOT_FOUND。

返回值
成功:返回一个有效的句柄,该句柄将由应用程序传递给接下来的WinINet函数。

失败:返回NULL。

备注:该函数是第一个由应用程序调用的 WinINet 函数。它告诉 Internet DLL 初始化内部数据结构并准备接收应用程序之后的其他调用。当应用程序结束使用 Internet 函数时,应调用 InternetCloseHandle 函数来释放与之相关的资源。

应用程序可以对该函数进行任意次数的调用,不过在一般情况下一次调用就已经足够了。如果要调用多次该函数,应用程序则有必要定义独立的函数实例的行为,诸如不同的代理服务器等。

InternetOpenUrl函数

通过一个完整的FTP,Gopher或HTTP网址打开一个资源。

HINTERNET InternetOpenUrl (__in HINTERNET hInternet
,__in LPCTSTR lpszUrl
,__in LPCTSTR lpszHeaders
,__in DWORD值dwHeadersLength
,__in的DWORD dwFlags
,__in DWORD_PTR dwContext
) ;
参数
hInternet
当前的 Internet 会话句柄。句柄必须由前期的 InternetOpen 调用返回。

lpszUrl
一 个空字符结束的字符串变量的指针,指定读取的网址。只有以ftp:, gopher:, http:, 或者 https: 开头的网址被支持。

lpszHeaders
一个空字符结束的字符串变量的指针,指定发送到HTTP服务器 的头信息。欲了解更多信息,请参阅HttpSendRequest 函 数里lpszHeaders 参数的说明。

dwHeadersLength
额外的头的大小,以TCHAR 为单位。如果这个参数是-1L并且lpszHeaders 不是NULL ,lpszHeaders 被 假设为零终止( ASCIIZ ),而长度被自动计算。

dwFlags
此参数 可为下列值之一。

数值 说明
INTERNET_FLAG_EXISTING_CONNECT

如果使用相同的必须属性创建会话,会尝试利用现有的InternetConnect对象。这只对FTP操作非常有用,因为 FTP是唯一在同一会话中执行多种操作的协议。WinINet API 为每个由InternetOpen 产生的HINTERNET 句 柄缓冲一个单独链接句柄。InternetOpenUrl 使用此标志的HTTP和FTP连接。

INTERNET_FLAG_HYPERLINK

当 决定何时从网络重载时,如果服务器没有返回 Expires time 和 LastModified,那么强制重载。

INTERNET_FLAG_IGNORE_CERT_CN_INVALID

停用检查从服务器对必须的主机名称返回的SSL/PCT-based证书。 WinINet函数使用简单的比较匹配主机名称和通配符的规则检查证书。

INTERNET_FLAG_IGNORE_CERT_DATE_INVALID

停 用检查的SSL/PCT-based的证书的适当的有效日期。

INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP

禁用检测这中特殊的重定向。当使用此标志, WinINet 透明允许从HTTPS到HTTP URL的重定向。

INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS

禁用检测这中特殊的重定向。当使用此标志, WinINet 透明的允许的HTTP到HTTPS URL的重定向。

INTERNET_FLAG_KEEP_CONNECTION

如果可能的话,为连接使用保活语义。这个标志要求微软网络( MSN ),NTLM和其他类型的身份验证。

INTERNET_FLAG_NEED_FILE

如果要创建的文件不能被缓存,创建临时文件。

INTERNET_FLAG_NO_AUTH

不试图自动验证。

INTERNET_FLAG_NO_AUTO_REDIRECT

不自动处理HttpSendRequest 中 的重定向。

INTERNET_FLAG_NO_CACHE_WRITE

不添加返回实体到缓存。

INTERNET_FLAG_NO_COOKIES

不会 自动添加的Cookie头到请求,并且不自动添加返回的cookie到cookie数据库。

INTERNET_FLAG_NO_UI

禁用 Cookie的对话框。

INTERNET_FLAG_PASSIVE

使用被动FTP语义。InternetOpenUrl 为FTP的文件和目录使用此标 志。

INTERNET_FLAG_PRAGMA_NOCACHE

即使代理中存在缓存副本,也强制要求由源服务器返回。

INTERNET_FLAG_RAW_DATA

检 索的Gopher目录信息时,传回的数据作为GOPHER_FIND_DATA 结 构,如果检索的FTP目录信息时,作为一个WIN32_FIND_DATA 结构。如果此标志没有指定,或者请求通过CERN代理创建, InternetOpenUrl 返 回的HTML版本的目录。

INTERNET_FLAG_RELOAD

从原服务器强制下载所要求的文件,对象,或目录列表,而不是从缓存下载。

INTERNET_FLAG_RESYNCHRONIZE

重新加载的HTTP资源,如果资源在最后一次下载后已被修改。所有FTP和Gopher资源将被重载。

INTERNET_FLAG_SECURE

使用安全传输语义。这次传输使用安全套字节层/专用通信技术(的SSL / PCT ),这只有在HTTP请求时有意义。

dwContext
一个 指向一个应用程序定义的值,将随着返回的句柄,一起传递给回调函数。

返回值
如果已成功建立 到FTP,Gopher,或HTTP URL的连接,返回一个有效的句柄,如果连接失败返回NULL。要检索特定的错误讯息,请GetLastError 。要确定为什么对服务器的访问被拒绝,请调用InternetGetLastResponseInfo 。

备注
先调用InternetCanonicalizeUrl , 如果正在使用的网址包含一个相对URL和一个空格分隔的基础URL。

这是一个通用的函数,可用于使用任何WinINet支持的协议检索数 据。这个函数在应用程序并不需要指定特定的协议,只需要相应的URL的数据时,特别有用。InternetOpenUrl 函数解析URL字 符串,建立连接到服务器,并准备下载的指定URL的数据。该应用程序可以用InternetReadFile (对文件)或InternetFindNextFile (对目录)来检索URL的数据。没有必要在InternetOpenUrl 前调用InternetConnect 。

InternetOpenUrl 在少于1024端口上禁用Gopher,除了70——标准的Gopher端口和105——通常用于 中央服务组织(民间组织)的名字搜索。

在使用完InternetOpenUrl 返回的HINTERNET 句 柄后,必须使用InternetCloseHandle 函 数关闭它。

InternetReadFile Function

从一个由InternetOpenUrl, FtpOpenFile, 或 HttpOpenRequest 函数打开的句柄中读取数据。

Syntax
C++
<span style="font-family: 新宋体; ">BOOL InternetReadFile(
__in HINTERNET hFile,
__out LPVOID lpBuffer,
__in DWORD dwNumberOfBytesToRead,
__out LPDWORD lpdwNumberOfBytesRead
);</span>

Parameters
hFile [in]
由InternetOpenUrl, FtpOpenFile, 或 HttpOpenRequest 函数返回的句柄.

lpBuffer [out]
缓冲器指针

dwNumberOfBytesToRead [in]
欲读数据的字节量。

lpdwNumberOfBytesRead [out]
接收读取字节量的变量。该函数在做任何工作或错误检查之前都设置该值为零

返回值
成功:返回TRUE,失败,返回FALSE

备注
该函数的操作非常类似于ReadFile函数。典型情况下,该函数从一个作为字节顺序流的HINTERNET句柄中返回数据。每次函数读取的数据量都由dwNumberOfBytesToRead参数指定,并且数据返回到lp
Buffer参数里。一个正常读取将持续到文件结束时为止。为了确保所有数据被接收,应用程序必须继续使用该函数直到函数返回TRUE且lpdwNumberOfBytesRead参数等于零值。此举在请求的数据被写入缓存中尤为重要,因为如不这样的话,缓存将不会正常的更新且下载的文件也将不会被允许写入到缓存中。注意:除了原始请求的命令设置为INTERNET_FLAG_NO_CACHE_WRITE标识的情况外,缓存操作都会自动进行。

当应用程序使用InternetOpenUrl函数获得一个句柄时,WinINet试图将所有的数据都变得如同文件下载一样。

WinINet试图每次向lpBuffer缓冲中写入一行HTML。如果应用程序的缓冲区太小以至于不能承载一行的HTML数据,错误代码ERROR_INSUFFICIENT_BUFFER 将发送给应用程序,通知它需要更大的缓冲区。同样,转换的行数也不一定和缓冲区的大小匹配,所以该函数可以返回比lpBuffer缓冲少的数据。接下来的读取工作将返回所有的HTML数据。应用程序必须再次检查搜有数据是否都被接收。

fwrite

size_t fwrite(const void buffer, size_t size, size_t count, FILE stream);

返回值:返回实际写入的数据块数目

(1)buffer:是一个指针,对fwrite来说,是要获取数据的地址;

(2)size:要写入内容的单字节数;

(3)count:要进行写入size字节的数据项的个数;

(4)stream:目标文件指针;

(5)返回实际写入的数据项个数count。

说明:写入到文件的哪里? 这个与文件的打开模式有关,如果是w+,则是从file pointer指向的地址开始写,替换掉之后的内容,文件的长度可以不变,stream的位置移动count个数;如果是a+,则从文件的末尾开始添加,文件长度加大。

fseek对此函数有作用,但是fwrite函数写到用户空间缓冲区,并未同步到文件中,所以修改后要将内存与文件同步可以用fflush(FILE *fp)函数同步。

WideCharToMultiByte

函数原型:

int WideCharToMultiByte(

UINTCodePage, //指定执行转换的代码页

DWORDdwFlags, //允许你进行额外的控制,它会影响使用了读音符号(比如重音)的字符

LPCWSTRlpWideCharStr, //指定要转换为宽字节字符串的缓冲区

intcchWideChar, //指定由参数lpWideCharStr指向的缓冲区的字符个数

LPSTRlpMultiByteStr, //指向接收被转换字符串的缓冲区

intcchMultiByte, //指定由参数lpMultiByteStr指向的缓冲区最大值

LPCSTRlpDefaultChar, //遇到一个不能转换的宽字符,函数便会使用pDefaultChar参数指向的字符

LPBOOLpfUsedDefaultChar//至少有一个字符不能转换为其多字节形式,函数就会把这个变量设为TRUE

);

参数:

CodePage:指定执行转换的代码页,这个参数可以为系统已安装或有效的任何代码页所给定的值。你也可以指定其为下面的任意一值:

CP_ACP:ANSI代码页;CP_MACCP:Macintosh代码页;CP_OEMCP:OEM代码页;

CP_SYMBOL:符号代码页(42);CP_THREAD_ACP:当前线程ANSI代码页;

CP_UTF7:使用UTF-7转换;CP_UTF8:使用UTF-8转换。

dwFlags[in] Specifies the handling of unmapped characters. The function performs more quickly when none of these flags is set. The following flag constants are defined.

Value Meaning
WC_NO_BEST_FIT_CHARS Windows 98/Me and Windows 2000/XP:Any Unicode characters that do not translate directly to multibyte equivalents are translated to the default character (seelpDefaultCharparameter). In other words, if translating from Unicode to multibyte and back to Unicode again does not yield the exact same Unicode character, the default character is used. This flag can be used by itself or in combination with the otherdwFlagoptions.
WC_COMPOSITECHECK Convert composite characters to precomposed characters.
WC_DISCARDNS Discard nonspacing characters during conversion.
WC_SEPCHARS Generate separate characters during conversion. This is the default conversion behavior.
WC_DEFAULTCHAR Replace exceptions with the default character during conversion.
When WC_COMPOSITECHECK is specified, the function converts composite characters to precomposed characters. A composite character consists of a base character and a nonspacing character, each having different character values. A precomposed character has a single character value for a base/nonspacing character combination. In the character , theeis the base character, and the accent grave mark is the nonspacing character.

When an application specifies WC_COMPOSITECHECK, it can use the last three flags in this list (WC_DISCARDNS, WC_SEPCHARS, and WC_DEFAULTCHAR) to customize the conversion to precomposed characters. These flags determine the function's behavior when there is no precomposed mapping for a base/nonspace character combination in a wide-character string. These last three flags can only be used if the WC_COMPOSITECHECK flag is set.

The function's default behavior is to generate separate characters (WC_SEPCHARS) for unmapped composite characters.

For the code pages in the following table,dwFlagsmust be zero, otherwise the function fails with ERROR_INVALID_FLAGS.

50220 502215022250225 50227 502295293654936 57002 through 57011 65000 (UTF7)65001 (UTF8)42 (Symbol)
相关变量
lpWideCharStr:指向将被转换的unicode字符串。

cchWideChar:指定由参数lpWideCharStr指向的缓冲区的字符个数。如果这个值为-1,字符串将被设定为以NULL为结束符的字符串,并且自动计算长度。

lpMultiByteStr:指向接收被转换字符串的缓冲区。

cchMultiByte:指定由参数lpMultiByteStr指向的缓冲区最大值(用字节来计量)。若此值为零,函数返回lpMultiByteStr指向的目标缓冲区所必需的字节数,在这种情况下,lpMultiByteStr参数通常为NULL。

lpDefaultChar和pfUsedDefaultChar:只有当WideCharToMultiByte函数遇到一个宽字节字符,而该字符在uCodePage参数标识的代码页中并没有它的表示法时,WideCharToMultiByte函数才使用这两个参数。如果宽字节字符不能被转换,该函数便使用lpDefaultChar参数指向的字符。如果该参数是NULL(这是大多数情况下的参数值),那么该函数使用系统的默认字符。该默认字符通常是个问号。这对于文件名来说是危险的,因为问号是个通配符。pfUsedDefaultChar参数指向一个布尔变量,如果Unicode字符串中至少有一个字符不能转换成等价多字节字符,那么函数就将该变量置为TRUE。如果所有字符均被成功地转换,那么该函数就将该变量置为FALSE。当函数返回以便检查宽字节字符串是否被成功地转换后,可以测试该变量。

返回值:如果函数运行成功,并且cchMultiByte不为零,返回值是由 lpMultiByteStr指向的缓冲区中写入的字节数;如果函数运行成功,并且cchMultiByte为零,返回值是接收到待转换字符串的缓冲区所必需的字节数。如果函数运行失败,返回值为零。若想获得更多错误信息,请调用GetLastError函数。

GlobalAlloc

说明
分配一个全局内存块
返回值
Long,返回全局内存句柄。零表示失败。会设置GetLastError
参数表
参数 类型及说明

wFlags Long,对分配的内存类型进行定义的常数标志,如下所示:

         GMEM_FIXED 分配一个固定内存块
         GMEM_MOVEABLE 分配一个可移动内存块
         GMEM_DISCARDABLE 分配一个可丢弃内存块
         GMEM_NOCOMPACT 堆在这个函数调用期间不进行累积
         GMEM_NODISCARD 函数调用期间不丢弃任何内存块
         GMEM_ZEROINIT 新分配的内存块全部初始化成零

dwBytes Long,要分配的字符数

globallock

调用GlobalAlloc函数分配一块内存,该函数会返回分配的内存句柄。调用GlobalLock函数锁定内存块,该函数接受一个内存句柄作为参数,然后返回一个指向被锁定的内存块的指针。您可以用该指针来读写内存。

说明
锁定内存中指定的内存块,并返回一个地址值,令其指向内存块的起始处。除非用 GlobalUnlock 函数将内存块解锁,否则地址会一直保持有效。

Windows 为每个内存对象都维持着一个锁定计数。对这个函数的每次调用都应有一个对应的 GlobalUnlock 调用返回值Long,如成功,返回内存块的地址;如出错,或者这是一个已被丢弃的“可丢弃”内存块,则返回零。会设置GetLastError参数表

参数类型
hMem Long,指定一个全局内存块的句柄

EnumWindows

函数功能:该函数枚举所有屏幕上的顶层窗口,办法是先将句柄传给每一个窗口,然后再传送给应用程序定义的回调函数。EnumThreadWindows函数继续到所有顶层窗口枚举完为止或回调函数返回FALSE为止

函数原型:BOOL EnumWindows(WNDENUMPROC lpEnumFunc,LPARAM lParam);

参数:

lpEnumFunc:指向一个应用程序定义的回调数指针,请参看EnumWindowsProc。

lPararm:指定一个传递给回调函数的应用程序定义值。

返回值:如果函数成功,返回值为非零;如果函数失败,返回值为零。若想获得更多错误信息,请调用GetLastError函数。

EnumWindowsProc

函数功能:该函数是一个与EnumWindows或 EnumDesktopWindows一起使用的应用程序定义的回调函数。它接收顶层窗口句柄。WNDENUMPROC定义一个指向这个回调函数的指针。EnumWindowsProc是应用程序定义函数名的位置标志符。

参数:

hwnd:顶层窗口句柄。

lParam:指定在EnumWindows或 EnumDesktopWindows中的应用程序定义值。

返回值:为继续列表,回调函数必须返回TRUE;若停止列表,它必须返回FALSE。

备注:应用程序必须通过传递给EnumWindows或 EnumDesktopWindows应用程序地址来注册这个回调函数。

GetWindowThreadProcessld

函数功能:该函数返回创建指定窗口线程的标识和创建窗口的进程的标识符,后一项是可选的。

函数原型;DWORD GetWindowThreadProcessld(HWND hwnd,LPDWORD lpdwProcessld);

参数:

hWnd:窗口句柄。

lpdwProcessld:接收进程标识的32位值的地址。如果这个参数不为NULL,GetWindwThreadProcessld将进程标识拷贝到这个32位值中,否则不拷贝。

返回值:返回值为创建窗口的线程标识。

atol

函数名: atol 功 能: 把字符串转换成长整型数 用 法: long atol(const char *nptr);
函数简介
函数说明: atol()会扫描参数nptr字符串,跳过前面的空格字符(就是忽略掉字符串左空格的意思),直到遇上数字或正负符号才开始做转换,而再遇到非数字或字符串结束时('0')才结束转换,并将结果返回。

返回值:返回转换后的长整型数。如果传入的字符串为空,或者字符串包含的内容非阿拉伯数字序列,则函数返回默认值0。

附加说明: atol()与使用strtol(nptr,(char**)NULL,10);结果相同。

getch():

所在头文件: conio.h

函数用途:从控制台读取一个字符,但不显示在屏幕上

函数原型:int getch(void)

返回值:读取的字符

例如:

char ch;或int ch;

_getch();或ch=_getch();

用_getch();会等待你按下任意键,再继续执行下面的语句;

用ch=_getch();会等待你按下 任意键之后,把该键 字符所对应的ASCII码赋给ch,再执行下面的语句。

KeyboardProc

键盘钩子处理函数:
  首先键盘钩子处理函数的函数名是可以自定义的 ,例如:MyKeyboardProc()

  函数原型:

  LRESULT CALLBACK KeyboardProc( int code,

  WPARAM wParam,

  LPARAM lParam

  );

参数:
  code:

  根据这个数值决定怎样处理消息

  如果 code 小于0,则 必须让KeyboardProc()函数返回CallNextHookEx()

  code可以是下列值:

  HC_ACTION:wParam和lParam包含按键消息

  HC_NOREMOVE:wParam和lParam包含按键消息,并且按键消息不能从消息队列中移除(一个被PeekMessage函数调用的请求,指定

  PM_NOREMOVE标志)

  wParam:

  按键的虚拟键值消息,例如:VK_F1

  lParam:

  32位内存,内容描述包括:指定扩展键值,扫描码,上下文,重复次数。

  0-15位:

  描述:按下键盘次数。

  16-23位

  指定扫描码. 依赖于OEM

  24位

  当24位为1时候:表示按键是扩展键

  当24位为0时候:表示按键是是数字键盘按键

  25-28位

  保留位

  29位

  上下文键:为1时: ALT按下,其他情况为0

  30位

  如果是按键按下后发送的消息,30位为1,如果是按键抬起后30位为1;

  31位

  指定转变状态:31位为0时候,按键正在被按下,为1时候,按键正在被释放

返回值:
  如果参数1:code小于0,则必须 返回CallNextHookEx(),也就是返回CallNextHookEx()的返回值

  如果参数1:code大于等于0,并且钩子处理函数没有处理消息,强烈建议您 返回CallNextHookEx()的返回值,否则当您安装WH_KEYBOARD钩子时

  ,钩子将不会得到通知,并返回错误结果。

  如果钩子处理的消息,您可以返回一个非0值,防止系统把消息传递给钩子链中的下一个钩子,或者把消息发送到目标窗口。

备注:
  安装键盘钩子需要把WH_KEYBOARD作为SetWindowsHookEx()的第一个参数,并且把键盘钩子处理函数的函数指针作为SetWindowsHookEx()的第2个参数.

留下jio印