2016-12-03 7 views
0

Проблема заключается в запуске кода на старой машине, где запрошенная функция не существует. Для его проверки используются LoadLibrary и GetProcAddress, как показано в документе here, но GetProcAddress требует использования функций в TypeDef перед его использованием.
Например, возьмем эти два на, например, XP SP2 32 бит:ТипDef с указателем функции: Функция не существует

typedef BOOL (__stdcall *LPFN_Wow64RevertWow64FsRedirection) (PVOID OldValue); 
typedef BOOL (__stdcall *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); 
... 

... 
LPFN_Wow64RevertWow64FsRedirection wowRevert = NULL; 
LPFN_Wow64DisableWow64FsRedirection wowDisable = NULL; 
HINSTANCE hLib; 
if(GetProcAddresses(&hLib, "kernel32.dll", 2, &wowRevert,_ 
"Wow64RevertWow64FsRedirection", &wowDisable, Wow64DisableWow64FsRedirection")) 
{... 

код падает здесь с:

Процедура точки входа Wow64RevertWow64FsRedirection не может находиться в динамической библиотеки Kernel32. Dll

Это достаточно легко реализовать свой собственный пользовательский Wow64RevertWow64FsRedirection с не WinAPI определений типов, но как они могут быть заменены с базовым типом, когда функция экс ists в kernel32.dll?

+0

*, но GetProcAddress требует адрес функций * - Это не так. [GetProcAddress] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms683212%28v=vs.85%29.aspx) требуется только дескриптор модуля и строка. – PaulMcKenzie

+0

@Paul: Помогите мне здесь. Смотрел ваш [ответ] (http://forums.codeguru.com/showthread.php?247936-Problem-using-GetProcAddress) обратный путь: это все еще применяется? –

+0

Функция GetProcAddress возвращает указатель на функцию. Для вызова функции не требуется указатель на функцию (кроме указателя на имя строки). – PaulMcKenzie

ответ

1

У меня возникли проблемы с пониманием вашего вопроса. Функция Wow64RevertWow64FsRedirection, очевидно, не будет существовать в 32-разрядной операционной системе, поэтому она не будет существовать в 32-разрядной Windows XP. Поэтому попытка получить указатель на эту функцию с GetProcAddress не удастся. Вы получаете разумную ошибку, чтобы эта точка входа не была найдена. Если точка входа не найдена, функция не существует, и вы не должны пытаться ее вызвать.

Вы утверждаете, что можете реализовать свою собственную функцию Wow64RevertWow64FsRedirection, но у меня нет туманной идеи, почему вы хотели бы это сделать. Если операционная система поддерживает перенаправление файловой системы WOW64, она будет обеспечивать функцию Wow64RevertWow64FsRedirection. Если это не так, то это не обеспечивает функцию, но вам не нужна такая функция, потому что нет такой вещи, как перенаправление файловой системы WOW64. Вам не нужно включать, отключать или возвращать его.

Кажется, что вы делаете это намного сложнее, чем должно быть. Вам даже не нужно сначала проверять, является ли процесс 64-битным процессом. Вы можете просто попытаться найти точку входа в Wow64RevertWow64FsRedirection (или Wow64DisableWow64FsRedirection, если необходимо), вызвать ее, если она существует, или игнорировать сбой, если он не существует.

Это так просто, как:

BOOL RevertWOW64RedirectionIfNecessary(PVOID pOldValue) 
{ 
    typedef BOOL (WINAPI * fnWow64RevertWow64FsRedirection)(PVOID); 

    fnWow64RevertWow64FsRedirection pfn = 
     reinterpret_cast<fnWow64RevertWow64FsRedirection>(
      reinterpret_cast<void*>(
      GetProcAddress(GetModuleHandle(L"kernel32"), 
          "Wow64RevertWow64FsRedirection"))); 

    if (pfn) 
    { 
     // The function exists, so call it through the pointer we obtained. 
     return pfn(pOldValue); 
    } 
    else 
    { 
     // The function does not exist, so we can't call it. 
     // But we don't ever need to call it in such cases, 
     // so do nothing and feign success. 
     return TRUE; 
    } 
} 

Обратите внимание, что я звоню функцию GetModuleHandle, чтобы получить дескриптор модуля kernel32.dll (расширение .dll подразумевается). Я могу использовать здесь GetModuleHandle вместо LoadModule, так как знаю, что kernel32.dll всегда будет загружен в любой процесс приложения. И поскольку я использовал GetModuleHandle, мне также не нужно освобождать дескриптор модуля.

Я передаю полученную ручку функции GetProcAddress, а также строку, содержащую имя функции/процедуры, адрес которой должен быть восстановлен. Эта функция пытается получить адрес этой функции и возвращает ее, если она существует; в противном случае он терпит неудачу и возвращает NULL.

Я проверяю, вернул ли он верный указатель, и если это так, я вызываю функцию динамически через этот указатель. В противном случае он возвращает NULL, что означает, что функция недоступна, но в этом случае нам даже не нужно беспокоиться об этом, поэтому код просто становится не-op.

Что касается забавного литья, см. my answer here, что объясняет этот трюк.

+0

OUCH! В течение нескольких часов Google быстро наткнулся на [это] (http://stackoverflow.com/questions/25413612/wow64disablewow64fsredirection-on-32-bit-windows-xp). Но спасибо. Дело в том, что код разбился до того, как были выполнены какие-либо из операторов WOW64. Поэтому предполагалось, что это связано с тем, что «LPFN_ISWOW64PROCESS» - это единственное, что объявлено глобально, изначально. –

+0

Похоже, что метод в [Codeproject] (https://www.codeproject.com/Articles/1087/Loading-DLLs-made-easy?) Бесполезен, нет? –

+0

Он выглядит довольно переработанным для меня. Это может быть более полезно в случае, если вы не можете гарантировать загрузку модуля, который хотите загрузить. Это означало бы, что вы не можете использовать 'GetModuleHandle' и скорее должны называть' LoadLibrary'. Это подразумевает обращение к 'FreeLibrary'. Я использую ряд довольно сложных макросов оболочки, когда мне приходится делать обширную динамическую загрузку, главным образом потому, что она упрощает количество кода, который я должен писать, и уменьшает вероятность ошибок. Но это не нужно в простых сценариях, подобных этой. –