系列文章目录
[笔记]Windows核心编程《一》错误处理、字符编码
[笔记]Windows核心编程《二》内核对象
[笔记]Windows核心编程《三》进程
[笔记]Windows核心编程《四》作业
[笔记]快乐的LInux命令行《五》什么是shell
[笔记]Windows核心编程《五》线程基础
[笔记]Windows核心编程《六》线程调度、优先级和关联性
[笔记]Windows核心编程《七》用户模式下的线程同步
[笔记]Windows核心编程《八》用内核对象进行线程同步
[笔记]Windows核心编程《九》同步设备I/O和异步设备I/O
[笔记]Windows核心编程《十一》Windows线程池
[笔记]Windows核心编程《十二》纤程
[笔记]Windows核心编程《十三》windows内存体系结构
[笔记]Windows核心编程《十四》探索虚拟内存
[笔记]Windows核心编程《十五》在应用程序中使用虚拟内存
[笔记]Windows核心编程《十六》线程栈
[笔记]Windows核心编程《十七》内存映射文件
[笔记]Windows核心编程《十八》堆栈
[笔记]Windows核心编程《十九》DLL基础
[笔记]Windows核心编程《二十》DLL的高级操作技术
[笔记]Windows核心编程《二十一》线程本地存储器TLS
[笔记]Windows核心编程《二十二》注入DLL和拦截API
[笔记]Windows核心编程《二十三》结构化异常处理
文章目录
系列文章目录
前言
一、错误处理
1.1 strerror(errno)
1.2 _set_errno(0)
1.3 GetLastError
1.4 FormatMessage()
1.5 LocalLock/LocalFree
二、Windows函数常见返回值的意义
三、字符和字符串处理
3.1字符编码
3.1.1 ASCII字符集(多字节字符集)
3.1.2 UNICODE字符集
a.字符编码
3.1.3 常见关于字符编码的宏
3.1.4字符串处理
a.字符串函数
3.1.5 代码实战
四、代码页
总结
小技巧
前言
windows核心编程
一、错误处理
1.1 strerror(errno)
string.h
解析全局errno变量的含义 转成字符串
1.2 _set_errno(0)
string.h
字面意思 设置全局错误码
1.3 GetLastError
windows.h
GetLastError() 获取错误码
1.4 FormatMessage()
windows.h
将GetLastError获得的错误码转化为字符串信息
从系统中获取错误码 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, 0, NULL, str, 200, NULL); 从模块中获取错误码 HMOUDLE hMoudle = LoadLibrary(L"user32.dll"); FormatMessage( FORMAT_MESSAGE_FROM_MODULE | FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_ALLOCATE_BUFFER, hModule, 0, NULL, str, 200, NULL); // FORMAT_MESSAGE_ALLOCATE_BUFFER 自动分配内存
1.5 LocalLock/LocalFree
锁定本地内存与销毁内存,一般用于函数自动分配的内存。
二、Windows函数常见返回值的意义
VOID:这个函数不可能失败!
BOOL:FALSE失败;TRUE成功。
HANDLE:失败返回NULL,否则返回非零句柄。如果有特殊说明,则可能为特殊值例如:INVALID_HANDLE_VALUE。
PVOID:返回一个内存地址,失败为NULL
LONG/DWORD:应该根据SDK说明来确定函数状况。
三、字符和字符串处理
3.1字符编码
3.1.1 ASCII字符集(多字节字符集)
ASCII 字符集在 0x00 - 0x7F 范围内定义字符。 还有许多其他字符集(主要是欧洲字符集),它们在 0x00 - 0x7F
范围内定义与 ASCII 字符集相同的字符,还在 0x80 - 0xFF. 范围内定义扩展字符集。 (SBCS) 的8位单字节字符集足以表示 ASCII 字符集以及许多欧洲语言的字符集,这一点非常好。
但是,一些非欧洲字符集(如日本汉字)包含的字符数多于单字节编码方案可表示的字符数,因此需要多字节字符集 (MBCS) 编码。
多字节字符集可以包含单字节和双字节字符。
多字节字符字符串可以包含单字节字符和双字节字符的组合。
两字节多字节字符具有一个前导字节和一个尾字节。
在特定的多字节字符集中,前导字节位于某个范围内,尾字节也是如此。
当这些范围重叠时,可能需要计算上下文,以确定给定的字节是用作前导字节还是尾字节。
3.1.2 UNICODE字符集
UNICODE字符,什么是UNICODE字符,为什么要有UNICODE字符??
a.字符编码
UTF-8:
一个字节一个字符,有些字符是2个字节,有的字符是3个字节,还有的字符是4个字节。
UTF-16
大部分字符都是2个字节,一般UNICODE就是指utf-16,
Windows的Unicode编码一般指utf-16,然后Java的String一般也是Utf-16编码。
UTF-32
所有字符都是4个字节。一般非Windows平台。
3.1.3 常见关于字符编码的宏
TEXT()
_T()
TCHAR 字符类型
UNICODE 判断是否UNICODE编码的宏
WIN32 表示跨平台时使用,如果一个工程使用了windows api,那么它在引入windows api相关的头文件后,必须预定义WIN32以启用WIN32API
_WIN64 表示编译时使用,同_WIN32,只不过此编译选项编出来的代码只能在 64位机器上运行。
_WIN32 表示编译时使用,用来指定编译器的编译结果可以在哪种架构上运行,如果是_WIN32,则既可以在 x86上 又可以在 x64上运行,此外还可以在ARM32和ARM64上运行,简言之,编出来的代码可以同时在 32位机器和64位机器上运行。
3.1.4字符串处理
a.字符串函数
1. 包含宽字符和窄字符处理
例如_tcslen(),
定义多字节宏 _MBCS 则使用strlen()
定义Unicode宏_UNICODE 则使用wcslen()
2.StringSafe.h包含安全字符串处理
我们编程的时候,尽量使用安全字符串,
strcpy(dst,src)->strcpy_s(dst,srcLen,src)
而StringSafe.h中包含不少可以安全处理字符串的函数
HRESULT StringCchCat( __inout LPTSTR pszDest, __in size_t cchDest, __in LPCTSTR pszSrc ); pszDest:目标字符串; cchDest:目标字符串内存大小; pszSrc: 源字符串。 这是一个字符串拷贝函数,在strsafe.h中。 HRESULT StringCchPrintf( __out LPTSTR pszDest, __in size_t cchDest,//目标内存大小 __in LPCTSTR pszFormat, __in ... ); 这个函数和printf函数用法类似,只是将字符写入了pszDest内存块中,而不是屏幕上!
Windows.h中 字符串比较函数
int CompareString( __in LCID Locale, __in DWORD dwCmpFlags, __in LPCTSTR lpString1, __in int cchCount1, __in LPCTSTR lpString2, __in int cchCount2 ); int CompareStringOrdinal( __in LPCWSTR lpString1, __in int cchCount1, __in LPCWSTR lpString2, __in int cchCount2, __in BOOL bIgnoreCase ); 第二个和语言无关,速度更快!!!建议使用!!!
3.ASCII 和 UNICODE 之间的字符转换
int MultiByteToWideChar( __in UINT CodePage, __in DWORD dwFlags, __in LPCSTR lpMultiByteStr, __in int cbMultiByte, __out LPWSTR lpWideCharStr, __in int cchWideChar ); int WideCharToMultiByte( __in UINT CodePage, __in DWORD dwFlags, __in LPCWSTR lpWideCharStr, __in int cchWideChar, __out LPSTR lpMultiByteStr, __in int cbMultiByte, __in LPCSTR lpDefaultChar, __out LPBOOL lpUsedDefaultChar ); BOOL IsTextUnicode( __in const VOID *lpv, __in int iSize, __inout LPINT lpiResult );
3.1.5 代码实战
1.vs下使用printf/wsprintf 打印中文的宽字符%S和窄字符%s
#include <stdio.h> #include <locale.h> #include <stdlib.h> #include <string.h> void main() { setlocale(LC_ALL, ""); wchar_t wszName[] = L"WCHAR中文TEST"; char szName[] = "CHAR汉语测试TEST"; printf("szWchar = %S, length = %d\n", wszName, wcslen(wszName)); printf("szChar = %s, length = %d\n", szName, strlen(szName)); wprintf(L"wprintf szWchar = %s\n", wszName); wprintf(L"wprintf szChar = %S\n", szName); }
2.使用StringCchPrintf/StringCchCat/StringCchCopy
char mem[1000] = {0}; StringCchPrintf(mem, 1000, "%d,%s", 10, "helloworld"); StringCchCat(mem, 1000, "你好");//追加 StringCchCopy(mem, 1000, "您好");//拷贝
3.使用CompareString/CompareStringOriginal
TCHAR szBuffer[10] = { TEXT('A'),TEXT('A'),TEXT('A'),TEXT('A'),TEXT('A'), TEXT('A'),TEXT('A'),TEXT('A'),TEXT('B'),'\0' }; LCID local = GetThreadLocale(); //int result = CompareString(local/*LOCALE_SYSTEM_DEFAULT*/, NORM_IGNORECASE, szBuffer, _countof(szBuffer), TEXT("AAAAAAAAA"), 10); int result = CompareStringOrdinal(L"AAAAAAAAB", 10, L"AAAAAAAAA", 10, TRUE); switch (result) { case 0: cout << "Error" << endl; break; case CSTR_LESS_THAN: cout << "Str1 《 Str2" << endl; break; case CSTR_GREATER_THAN: cout << "Str1 》 Str2" << endl; break; case CSTR_EQUAL: cout << "Str1 = Str2" << endl; break; default: cout << "Don't goto there" << endl; break; }
4.使用IsTextUnicode判断
if (IsTextUnicode(L"abc", 4, NULL)) { printf("is unicode"); } else { printf("is ascii code"); }
5.多字节和UNICODE转换
void main2() { char sBuf[25] = { 0 }; strcpy_s(sBuf,25, "我最棒"); //获取输入缓存大小 int sBufSize = strlen(sBuf); //获取输出缓存大小 //VC++ 默认使用ANSI,故取第一个参数为CP_ACP DWORD dBufSize = MultiByteToWideChar(CP_ACP, 0, sBuf, sBufSize, NULL, 0); printf("需要wchar_t%u个\n", dBufSize); wchar_t* dBuf = new wchar_t[dBufSize]; wmemset(dBuf, 0, dBufSize); //进行转换 int nRet = MultiByteToWideChar(CP_ACP, 0, sBuf, sBufSize, dBuf, dBufSize); if (nRet <= 0) { cout << "转换失败" << endl; DWORD dwErr = GetLastError(); switch (dwErr) { case ERROR_INSUFFICIENT_BUFFER: printf("ERROR_INSUFFICIENT_BUFFER\n"); break; case ERROR_INVALID_FLAGS: printf("ERROR_INVALID_FLAGS\n"); break; case ERROR_INVALID_PARAMETER: printf("ERROR_INVALID_PARAMETER\n"); break; case ERROR_NO_UNICODE_TRANSLATION: printf("ERROR_NO_UNICODE_TRANSLATION\n"); break; } } else { cout << "转换成功" << endl; cout << dBuf; } delete(dBuf); } void main(){ //从宽字符串转换窄字符串 wchar_t sBuf[25] = { 0 }; wcscpy_s(sBuf,100, L"我最棒"); //获取转换所需的目标缓存大小 DWORD dBufSize = WideCharToMultiByte(CP_OEMCP, 0, sBuf, -1, NULL, 0, NULL, FALSE); //分配目标缓存 char* dBuf = new char[dBufSize]; memset(dBuf, 0, dBufSize); //转换 int nRet = WideCharToMultiByte(CP_OEMCP, 0, sBuf, -1, dBuf, dBufSize, NULL, FALSE); if (nRet <= 0) { printf("转换失败\n"); } else { printf("转换成功\nAfter Convert: %s\n", dBuf); } delete[]dBuf; }
四、代码页
代码页通常和软件本地化 多语言支持有关。
https://www.cnblogs.com/benbenalin/p/6911781.html
https://www.cnblogs.com/benbenalin/p/6907907.html
https://www.cnblogs.com/benbenalin/p/6915513.html
总结
小技巧
1.vs
选中函数 按下f1 可进入msdn网页 函数具体详情
2.vs
F5运行,Cirl+F5 无调试运行,F7编译,
3.工具栏-》错误查找 工具可以查找错误码对应的错误含义