SymGetModuleInfo64函数的一个问题
今天调用dbghelp.dll中的一个函数SymGetModuleInfo64来取得加载模块的信息,但是返回的结果发现常常是丢掉数据。比如本来加载的pdb文件在位置c:/测试/1.pdb上,但是返回的LoadedPdbName却是 c:/测试/1.p 。很奇怪。但是若是使用SymGetModuleInfoW64来调用(即SymGetModuleInfo64的Unicode版本)却没有这个问题。
通过更多的试验,确定问题出在SymGetModuleInfo64中计算字符长度的函数上,该将汉字和英文字符一样算作一个字节了。
为了证明这个推断,反编译了SymGetModuleInfo64发现调用过程如下:
SymGetModuleInfo64调用SymGetModuleInfoW64, 接着将返回的UNICODE字符调用SympConvertUnicodeModule64ToAnsiModule64进行转换,在SympConvertUnicodeModule64ToAnsiModule64中最终会调用dbghelp!wcs2ansi函数来将WChar字符串转换成Char字符串,下面是这个函数的反汇编代码,在这段代码里你会看到它是如何计算字符串占用的字节数的。
函数原型如下:
Bool WINAPI wcs2ansi(PWCHAR pwstr; PCHAR pstr;ULONG len);
dbghelp!wcs2ansi:
0303b4a0 8bff mov edi,edi
0303b4a2 55 push ebp
0303b4a3 8bec mov ebp,esp
0303b4a5 83ec18 sub esp,18h
0303b4a8 8b4508 mov eax,dword ptr [ebp+8]
0303b4ab 8945f4 mov dword ptr [ebp-0Ch],eax
0303b4ae 8b4df4 mov ecx,dword ptr [ebp-0Ch]
0303b4b1 83c102 add ecx,2
0303b4b4 894df0 mov dword ptr [ebp-10h],ecx
0303b4b7 8b55f4 mov edx,dword ptr [ebp-0Ch]
0303b4ba 668b02 mov ax,word ptr [edx]
0303b4bd 668945ee mov word ptr [ebp-12h],ax
0303b4c1 8345f402 add dword ptr [ebp-0Ch],2
0303b4c5 66837dee00 cmp word ptr [ebp-12h],0 //从源字符串找出为0的字。
0303b4ca 75eb jne dbghelp!wcs2ansi+0x17 (0303b4b7)
0303b4cc 8b4df4 mov ecx,dword ptr [ebp-0Ch]
0303b4cf 2b4df0 sub ecx,dword ptr [ebp-10h]
0303b4d2 d1f9 sar ecx,1 //将找出的长度除以2,得出字符串中需要的字节数。
0303b4d4 894de8 mov dword ptr [ebp-18h],ecx
0303b4d7 8b55e8 mov edx,dword ptr [ebp-18h]
0303b4da 8955f8 mov dword ptr [ebp-8],edx
0303b4dd 837df800 cmp dword ptr [ebp-8],0
0303b4e1 750d jne dbghelp!wcs2ansi+0x50 (0303b4f0)
0303b4e3 8b450c mov eax,dword ptr [ebp+0Ch]
0303b4e6 c60000 mov byte ptr [eax],0
0303b4e9 b801000000 mov eax,1
0303b4ee eb3a jmp dbghelp!wcs2ansi+0x8a (0303b52a)
0303b4f0 6a00 push 0
0303b4f2 6a00 push 0
0303b4f4 8b4d10 mov ecx,dword ptr [ebp+10h]
0303b4f7 51 push ecx
0303b4f8 8b550c mov edx,dword ptr [ebp+0Ch]
0303b4fb 52 push edx
0303b4fc 6aff push 0FFFFFFFFh
0303b4fe 8b4508 mov eax,dword ptr [ebp+8]
0303b501 50 push eax
0303b502 6820020000 push 220h
0303b507 6a00 push 0
0303b509 ff15fcf50e03 call dword ptr [dbghelp!_imp__WideCharToMultiByte (0
30ef5fc)]
0303b50f 8945fc mov dword ptr [ebp-4],eax
0303b512 837dfc00 cmp dword ptr [ebp-4],0
0303b516 7504 jne dbghelp!wcs2ansi+0x7c (0303b51c)
0303b518 33c0 xor eax,eax
0303b51a eb0e jmp dbghelp!wcs2ansi+0x8a (0303b52a)
0303b51c 8b4d0c mov ecx,dword ptr [ebp+0Ch]
0303b51f 034df8 add ecx,dword ptr [ebp-8]
0303b522 c60100 mov byte ptr [ecx],0 //在上面找出的长度处设置上NULL.
0303b525 b801000000 mov eax,1
0303b52a 8be5 mov esp,ebp
0303b52c 5d pop ebp
0303b52d c20c00 ret 0Ch