滴水逆向——Win32_杂项
1、什么是Win32 API?有哪些?在哪里?
主要是存放在 C : \WINDOWS\system32 下面所有的dll
2、非常重要的几个DLL
Kernel32.dll:最核心的功能模块,比如管理内存、进程和线程相关的函数等.
User32.dll : 是Windows用户界面相关应用程序接口, 如创建窗口和发送消息等.
GDI32.dll : 全称是Graphical Device Interface(图形设备接口), 包含用于画图和显示文本的函数
比如要显示一个程序窗口,就调用了其中的函数来画这个窗口
3、Win32 API中的宽字符和多字节字符
Windows是使用C语言开发的,Win32 API同时支持宽字符与多字节字符.
(1) 字符类型(2) 字符串指针
char CHAR PSTR(LPSTR) 指向多字节字符串
wchar_t WCHAR PWSTR(LPWSTR) 指向宽字符串
宏 TCHAR 宏 PTSTR(LPTSTR)
字符数组赋值
CHAR cha[] = "中国";
WCHAR chw[] = L"中国";
TCHAR cht[] = TEXT("中国");
为字符串指针赋值:
PSTR pszChar = "china"; //多字节字符
PWSTR pszWChar = L"china"; //宽字符
PTSTR pszTChar = TEXT("china"); //如果项目是ASCII的 相当于"china" UNICODE 相当于L"china"
4、各种版本的MessageBox
MessageBoxA(0, "内容多字节", "标题", MB_OK);
MessageBoxW(0, L"内容宽字节", L"标题", MB_OK);
MessageBox(0, TEXT("根据项目字符集决定"), TEXT("标题"), MB_OK);
Windows提供的API 凡是需要传递字符串参数的函数,都会提供两个版本和一个宏.
MessageBox的第一个参数通常是一个窗口句柄。
第二个参数是将要在信息框里出现的文本字符。
第三个参数是将要在标题栏上显示的文本字符串。一般来说,并不需要把所有字符串都打包到TEXT宏代码里面,之所以这样做是因为这样再把程序转化为Unicode时会方便很多。
第四个参数是以MB_打头的一些常量的组合。
5、Windows程序入口
int CALLBACK WinMain(
_In_ HINSTANCE hInstance,
_In_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow
)
WinMain的第一个参数叫“实例句柄”。在Windows程序中,句柄无非就是一个数值,程序用他来标识某些东西在早期Windows程序中,当多路并发运行同一个程序时,就需要为那个程序创建多个实例。同一个程序的所有实例都共享代码以及只读存储(即菜单或对话框模板之类的资源)。一个程序可以通过查看hPrevInstance参数从而知道是否有它的其他实例正在运行。
在32位Windows中,这一概念已不再采用。因此WinMain的第二个参数通常总是NULL。
WinMain的第三个参数是用来运行程序的命令行。有些Windows程序在启动时用它来把文件装入内存。
WinMain的第四个参数用来指示程序最初如何显示:或正常显示,或最大化,或最小化。
6、打印
Win32程序不像普通的控制台程序,它的打印信息不会出现在dos窗口,可以使用 OutputDebugStringF函数出现在输出窗口。对 OutputDebugStringF做些改动,就可以使打印信息在debug版本中调试,而不出现在正式的release版本中。
头文件中:
void __cdecl OutputDebugStringF(const char *format, ...);
#ifdef _DEBUG
#define DbgPrintf OutputDebugStringF
#else
#define DbgPrintf
#endif
源文件中:
void __cdecl OutputDebugStringF(const char *format, ...)
{
va_list vlArgs;
char *strBuffer = (char*)GlobalAlloc(GPTR, 4096);
va_start(vlArgs, format);
_vsnprintf(strBuffer, 4096 - 1, format, vlArgs);
va_end(vlArgs);
strcat(strBuffer, "\n");
OutputDebugStringA(strBuffer);
GlobalFree(strBuffer);
return;
}
7、错误处理
DWORD GetLastError(VOID);
GetLastError返回的值通过在api函数中调用SetLastError或SetLastErrorEx设置。函数并无必要设置上一次错误信息,所以即使一次GetLastError调用返回的是零值,也不能担保函数已成功执行。只有在函数调用返回一个错误结果时,这个函数指出的错误结果才是有效的。通常,只有在函数返回一个错误结果,而且已知函数会设置GetLastError变量的前提下,才应访问GetLastError;这时能保证获得有效的结果。