我知道我可以正确使用WinApi函数,DsGetDcName如下所示:
DOMAIN_CONTROLLER_INFO* dcInfo = nullptr;
unsigned long res = ::DsGetDcName(nullptr,
nullptr,
nullptr,
nullptr,
0, &dcInfo);
Run Code Online (Sandbox Code Playgroud)
我知道,这是不自然的,但我想理解为什么一个人也不能这样写:
void* dcInfo = nullptr;
unsigned long res = ::DsGetDcName(nullptr,
nullptr,
nullptr,
nullptr,
0, (DOMAIN_CONTROLLER_INFO**) dcInfo);
if (res)
{
wchar_t* name;
name = static_cast<DOMAIN_CONTROLLER_INFO*> (dcInfo)->DomainControllerName;
}
Run Code Online (Sandbox Code Playgroud)
第二个版本void*用作指针类型,这就是我在运行它时(在调用时)获得访问冲突的原因::DsGetDcName.但我不明白为什么会这样?在指定void*而dcInfo不是类型时,是否与内存对齐的方式有关DOMAIN_CONTROLLER_INFO* dcInfo?
解
我发现了问题,我实际上可以使用复杂的不安全的void*版本,我只是没有将正确的指针地址传递给该函数.这里是:
void* dcInfo = nullptr;
unsigned long res = ::DsGetDcName(nullptr,
nullptr,
nullptr,
nullptr,
0, (DOMAIN_CONTROLLER_INFO**) &dcInfo);
Run Code Online (Sandbox Code Playgroud)
请注意,我通过(DOMAIN_CONTROLLER_INFO**) &dcInfo而不是(DOMAIN_CONTROLLER_INFO**) dcInfo.之前我只是因为我告诉编译器我知道我在做什么但是传递给函数一个指针值而不是所需指针的地址(是的,那个指针值是nullptr):-))
这是使用正确版本(版本1)的另一个原因.在第二种情况下,缺点是你必须再次强制转换结果如下:
wchar_t* name;
name = static_cast<DOMAIN_CONTROLLER_INFO*>(dcInfo)->DomainControllerName; // Get DC
Run Code Online (Sandbox Code Playgroud)
您需要查看大会。两个可用的选项(#2 和#3)都使用 LEA 指令。这会将数据结构的地址加载到 EAX 中,在本例中 EAX 为空。失败的示例加载该地址的值为空的值。如您所知,您不能取消引用 null。
// #1 - Fails
::DsGetDcName(nullptr, nullptr, nullptr, nullptr, 0, (DOMAIN_CONTROLLER_INFO**)void_ptr);
01101A63 mov esi,esp
01101A65 mov eax,dword ptr [void_ptr]
01101A68 push eax
01101A69 push 0
01101A6B push 0
01101A6D push 0
01101A6F push 0
01101A71 push 0
01101A73 call dword ptr [__imp__DsGetDcNameW@24 (1108350h)]
01101A79 cmp esi,esp
01101A7B call @ILT+310(__RTC_CheckEsp) (110113Bh)
// #2 - Works
::DsGetDcName(nullptr, nullptr, nullptr, nullptr, 0, (DOMAIN_CONTROLLER_INFO**)&void_ptr);
00EE1A63 mov esi,esp
00EE1A65 lea eax,[void_ptr]
00EE1A68 push eax
00EE1A69 push 0
00EE1A6B push 0
00EE1A6D push 0
00EE1A6F push 0
00EE1A71 push 0
00EE1A73 call dword ptr [__imp__DsGetDcNameW@24 (0EE8350h)]
00EE1A79 cmp esi,esp
00EE1A7B call @ILT+310(__RTC_CheckEsp) (0EE113Bh)
// #3 - Works
::DsGetDcName(nullptr, nullptr, nullptr, nullptr, 0, &dc_ptr);
013D1A5C mov esi,esp
013D1A5E lea eax,[dc_ptr]
013D1A61 push eax
013D1A62 push 0
013D1A64 push 0
013D1A66 push 0
013D1A68 push 0
013D1A6A push 0
013D1A6C call dword ptr [__imp__DsGetDcNameW@24 (13D8350h)]
013D1A72 cmp esi,esp
013D1A74 call @ILT+310(__RTC_CheckEsp) (13D113Bh)
Run Code Online (Sandbox Code Playgroud)