我手动注册一个WNDCLASS类,并创建一个窗口,为什么不输入hInstance,也成功?那hInstance参数有什么作用? 本帖最后由 xingguyuwang 于 2013-02-25 10:05:50 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 ATOM WINAPI RegisterClassA(__in const WNDCLASSA *lpWndClass){ WNDCLASSEXA wcex; wcex.cbSize = sizeof(WNDCLASSEX); // 30h memcpy(((char *)&wcex) + 4, lpWndClass, sizeof(WNDCLASS)); wcex.hIconSm = NULL; return RegisterClassExWOWA(&wcex, 0, 0, 0x100);}RegisterClassExWOW就不上图了,直接写出我逆的结果,大家要看码的话,直接把User32.dll拖到IDA看吧。代码:HINSTANCE _hmodUser = 0;ATOM WINAPI RegisterClassExWOWA(const WNDCLASSEXA *lpWndClassEx, int p2, int p3, int p4){ if(0 == HIWORD(p3)) { if(lpWndClassEx->cbClsExtra < 0 || lpWndClassEx->cbWndExtra < 0) { SetLastError(0x57); // ERROR_INVALID_PARAMETER return 0; } if(_hmodUser == lpWndClassEx->hInstance) { if(*(int *)(NtCurrentTeb() + 0x6D4) < 0x400) { SetLastError(0x57); return 0; } if(NULL == lpWndClassEx->hInstance) { lpWndClassEx->hInstance = GetModuleHandleA(NULL); } int ver; if(NULL == lpWndClassEx->hInstance) { ver = RtlGetExpWinVer(GetModuleHandleA(NULL)); } else { ver = RtlGetExpWinVer(lpWndClassEx->hInstance); } if(0x0F7FC0114 == lpWndClassEx->style) { if(ver > 0x30A) // Windows版本与样式不符 { SetLastError(0x57); return 0; } lpWndClassEx->style &= 0x803FEEB } if(lpWndClassEx->hbrBackground > 0x1F) // 小于0x1F的画刷没有Windows版本的限制,都支持 { if(0 == GdiValidateHandle(lpWndClassEx->hbrBackground)) // 无效的 { if(ver > 0x300) { SetLastError(0x57); return 0; } lpWndClassEx->hbrBackground = 0; } } int n; HMEMU hMem; if(InitClsMemuNameA(&hMem, lpWndClassEx->lpszMenuName, &n)) // 失败 { return 0; } p4 |= 2; WNDCLASSEXA wcex; memcpy(&wcex, lpWndClassEx, sizeof(WNDCLASSEXA)); if(ver > 0x30A) { p4 |= 0x80; } if(*(char *)(NtCurrentTeb() + 0x6E0) != 2) { if(GetAppCompatFlags2(0x9900) != 0x800000) { p4 &= 0xBFFFFFFF; } } if(int((p4 << 8) >> 24) != 1) { int x; if(NULL == ClassNameToVersion(lpWndClassEx->lpszClassName, &x, 0, 1)) { ver = 0; // 从 loc_77D1A552 开始下面的流程是根据临时指针变量是否为NULL来释放资源 if([ebp+var_138] == 0) // [ebp+var_138]在函数入口处确实被赋值为0 { RtlFreeHeap(NULL, 0, 0); } // ... return ver; } else { // 调用NtUserRegisterClassExWOW // NtUserRegisterClassExWOW进入系统调用,调用号11E8h } } } else { // lpWndClassEx->hInstance有值 } } else { }}NtUserRegisterClassExWOW部分比较简单是直接进行系统调用看样子,如果instance为NULL。这个函数自己会取一个instance. 下面代码应该是你所说的。能不能输入别的应用程序的hInstance? if(NULL == lpWndClassEx->hInstance) { lpWndClassEx->hInstance = GetModuleHandleA(NULL); } dll中调用CFileDialog的DoModal不能显示 请问如何删除listbox里选中的一项。以及如何删队listbox中值为"XXX"的一项 怎么样实现右键菜单图标的添加 如何理解消息映射函数和类提供的虚拟函数区别 各位在线大哥,如何重启正在运行的本次程序 +++ 200分! 诚心请教原始套接字处于混杂模式(嗅探)的几个小问题 !! 来者有分 ! 关于消息的问题 求救!图像处理 需要定时更新CStatic上的Text,怎么解决闪烁问题。 下面的几个函数又什么区别? mfc单文档ScrollView基类滚动滚动条以后怎么重绘窗口?? 怎么判断编辑框处于获得焦点状态
{
WNDCLASSEXA wcex;
wcex.cbSize = sizeof(WNDCLASSEX); // 30h
memcpy(((char *)&wcex) + 4, lpWndClass, sizeof(WNDCLASS));
wcex.hIconSm = NULL;
return RegisterClassExWOWA(&wcex, 0, 0, 0x100);
}
RegisterClassExWOW就不上图了,直接写出我逆的结果,大家要看码的话,直接把User32.dll拖到IDA看吧。代码:
HINSTANCE _hmodUser = 0;
ATOM WINAPI RegisterClassExWOWA(const WNDCLASSEXA *lpWndClassEx, int p2, int p3, int p4)
{
if(0 == HIWORD(p3))
{
if(lpWndClassEx->cbClsExtra < 0 || lpWndClassEx->cbWndExtra < 0)
{
SetLastError(0x57); // ERROR_INVALID_PARAMETER
return 0;
}
if(_hmodUser == lpWndClassEx->hInstance)
{
if(*(int *)(NtCurrentTeb() + 0x6D4) < 0x400)
{
SetLastError(0x57);
return 0;
}
if(NULL == lpWndClassEx->hInstance)
{
lpWndClassEx->hInstance = GetModuleHandleA(NULL);
} int ver;
if(NULL == lpWndClassEx->hInstance)
{
ver = RtlGetExpWinVer(GetModuleHandleA(NULL));
}
else
{
ver = RtlGetExpWinVer(lpWndClassEx->hInstance);
}
if(0x0F7FC0114 == lpWndClassEx->style)
{
if(ver > 0x30A) // Windows版本与样式不符
{
SetLastError(0x57);
return 0;
}
lpWndClassEx->style &= 0x803FEEB
} if(lpWndClassEx->hbrBackground > 0x1F) // 小于0x1F的画刷没有Windows版本的限制,都支持
{
if(0 == GdiValidateHandle(lpWndClassEx->hbrBackground)) // 无效的
{
if(ver > 0x300)
{
SetLastError(0x57);
return 0;
}
lpWndClassEx->hbrBackground = 0;
}
} int n;
HMEMU hMem;
if(InitClsMemuNameA(&hMem, lpWndClassEx->lpszMenuName, &n)) // 失败
{
return 0;
} p4 |= 2;
WNDCLASSEXA wcex;
memcpy(&wcex, lpWndClassEx, sizeof(WNDCLASSEXA));
if(ver > 0x30A)
{
p4 |= 0x80;
}
if(*(char *)(NtCurrentTeb() + 0x6E0) != 2)
{
if(GetAppCompatFlags2(0x9900) != 0x800000)
{
p4 &= 0xBFFFFFFF;
}
}
if(int((p4 << 8) >> 24) != 1)
{
int x;
if(NULL == ClassNameToVersion(lpWndClassEx->lpszClassName, &x, 0, 1))
{
ver = 0;
// 从 loc_77D1A552 开始下面的流程是根据临时指针变量是否为NULL来释放资源
if([ebp+var_138] == 0) // [ebp+var_138]在函数入口处确实被赋值为0
{
RtlFreeHeap(NULL, 0, 0);
}
// ...
return ver;
}
else
{
// 调用NtUserRegisterClassExWOW
// NtUserRegisterClassExWOW进入系统调用,调用号11E8h
}
}
}
else
{
// lpWndClassEx->hInstance有值
}
}
else
{ }
}
NtUserRegisterClassExWOW部分比较简单是直接进行系统调用看样子,如果instance为NULL。这个函数自己会取一个instance.
能不能输入别的应用程序的hInstance? if(NULL == lpWndClassEx->hInstance)
{
lpWndClassEx->hInstance = GetModuleHandleA(NULL);
}