Using GUIDFromString requries including Shell32.dl

2019-07-20 03:04发布

问题:

I am attempting to use the WinAPI function GUIDFromString() but it requires some finagling to include it in my project.

According to the msdn documentation:

This function is not declared in a header or exported by name from a .dll file. It must be loaded from Shell32.dll as ordinal 703 for GUIDFromStringA and ordinal 704 for GUIDFromStringW.

It can also be accessed from Shlwapi.dll as ordinal 269 for GUIDFromStringA and ordinal 270 for GUIDFromStringW.

I have never loaded a DLL before so I am not sure what I should do and I am unsure if loading the DLL is enough, do I also have to include an 'ordinal' with the number 703? Would anyone be able to provide any advice on what I need to do to use this function and even an example?

My attempt below does not work(I am using VC++ 2010 Express):

#pragma comment(lib, "shell32.lib") // if I am including the dll do I need to include the lib aswell?

// I've heard that the dll location differs across versions of windows
// Does anyone know of a Cross-Windows-Version way to include Shell32.dll no matter where it is? Maybe use a keyword like "%SYSTEM%/Shell32.dll"
HINSTANCE shell32DLL = LoadLibary("C:/System/Shell32.dll"); 

// Now do I include 'Ordinal 703' as described in msdn? And how do I do that?

回答1:

If you read the documentation for GUIDFromString(), it says:

GUIDFromString is available through Windows XP with Service Pack 2 (SP2) or Windows Vista. It might be altered or unavailable in subsequent versions. Applications should use CLSIDFromString or IIDFromString in place of this function.

CLSIDFromString() and IIDFromString() are both exported by name from Ole32.dll, so you can use them like you would any other DLL function.

With that said, if you still want to use GUIDFromString() then use LoadLibrary() to load shell32.dll and then use GetProcAddress() to access the function. MSDN documentation demonstrates how to do that. To load a function by ordinal, you can use the MAKEINTRESOURCE() macro when calling GetProcAddress().

So, for example:

// MAKEINTRESOURCE() returns an LPTSTR, but GetProcAddress()
// expects LPSTR even in UNICODE, so using MAKEINTRESOURCEA()...
#ifdef UNICODE
#define MAKEINTRESOURCEA_T(a, u) MAKEINTRESOURCEA(u)
#else
#define MAKEINTRESOURCEA_T(a, u) MAKEINTRESOURCEA(a)
#endif

BOOL myGUIDFromString(LPCTSTR psz, LPGUID pguid)
{
    BOOL bRet = FALSE;

    typedef BOOL (WINAPI *LPFN_GUIDFromString)(LPCTSTR, LPGUID);
    LPFN_GUIDFromString pGUIDFromString = NULL;

    HINSTANCE hInst = LoadLibrary(TEXT("shell32.dll"));
    if (hInst)
    {
        pGUIDFromString = (LPFN_GUIDFromString) GetProcAddress(hInst, MAKEINTRESOURCEA_T(703, 704));
        if (pGUIDFromString)
            bRet = pGUIDFromString(psz, pguid);
        FreeLibrary(hInst);
    }

    if (!pGUIDFromString)
    {
        hInst = LoadLibrary(TEXT("Shlwapi.dll"));
        if (hInst)
        {
            pGUIDFromString = (LPFN_GUIDFromString) GetProcAddress(hInst, MAKEINTRESOURCEA_T(269, 270));
            if (pGUIDFromString)
                bRet = pGUIDFromString(psz, pguid);
            FreeLibrary(hInst);
        }
    }

    return bRet;
}


回答2:

This gives your an error "syntax error '('":

typedef BOOL WINAPI (*LPFN_GUIDFromString)(LPCTSTR, LPGUID);

The proper version is:

typedef BOOL (WINAPI *LPFN_GUIDFromString)(LPCTSTR, LPGUID);


回答3:

Save the following lines as SHLWAPIX.DEF:

LIBRARY SHLWAPI
VERSION 6.0
EXPORTS
 GUIDFromStringA @269
 GUIDFromStringW @270

Save the following lines as SHLWAPIX.C:

// https://msdn.microsoft.com/en-us/library/bb776431.aspx

__declspec(dllexport)
int __stdcall GUIDFromStringA(void *_1, void *_2)
{ return 0; }

__declspec(dllexport)
int __stdcall GUIDFromStringW(void *_1, void *_2)
{ return 0; }

Run CL.EXE /LD /Zl SHLWAPIX.C /link /DEF:SHLWAPIX.DEF /NOENTRY to create the import library SHLWAPIX.LIB, then delete SHLWAPIX.OBJ, SHLWAPIX.EXP and SHLWAPIX.DLL

Save the following lines as SHLWAPIX.H:

#pragma once
#pragma comment(linker, "/DEFAULTLIB:SHLWAPIX.LIB")

__declspec(dllimport)
BOOL WINAPI GUIDFromStringA(LPCSTR psz, LPGUID pguid);

__declspec(dllimport)
BOOL WINAPI GUIDFromStringW(LPCWSTR psz, LPGUID pguid);

Finally save the following lines as SHLWAPIX.C:

#pragma comment(lib, "SHLWAPIX.LIB")
#pragma comment(lib, "USER32.LIB")

#pragma comment(linker, "/ENTRY:wWinMainCRTStartup")
#pragma comment(linker, "/SUBSYSTEM:WINDOWS,5.0")
#pragma comment(linker, "/VERSION:1.0")

#define STRICT
#define UNICODE
#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include "shlwapix.h"

VOID wWinMainCRTStartup()
{
    GUID guid = {0};
    WCHAR szBuffer[1025] = L"";

    if (GUIDFromStringA("{00112233-4455-6677-8899-AABBCCDDEEFF}", &guid))
        if (wsprintf(szBuffer, L"GUID = {%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",`
                     guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]) > 0)
            MessageBox((HWND) NULL, szBuffer, L"GUIDFromStringA()", MB_OK);

    if (GUIDFromStringW(L"{FFEEDDCC-BBAA-9988-7766-554433221100}", &guid))
        if (wsprintf(szBuffer, L"GUID = {%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
                     guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]) > 0)
            MessageBox((HWND) NULL, szBuffer, L"GUIDFromStringW()", MB_OK);
}

Finally run CL.EXE /GS- SHLWAPIX.C to create SHLWAPIX.EXE, then run the latter.



标签: c++ winapi dll