Print a GUID variable

I have a GUID variable and I want to write inside a text file its value. GUID definition is:

typedef struct _GUID {          // size is 16
    DWORD Data1;
    WORD   Data2;
    WORD   Data3;
    BYTE  Data4[8];
} GUID;

But I want to write its value like:

CA04046D-0000-0000-0000-504944564944

I observed that:

  • Data1 holds the decimal value for CA04046D
  • Data2 holds the decimal value for 0
  • Data3 holds the decimal value for next 0

But what about the others?

I have to interpret myself this values in order to get that output or is there a more direct method to print such a variable?


Solution 1:

Sometimes its useful to roll your own. I liked fdioff's answer but its not quite right. There are 11 elements of different sizes.

printf("Guid = {%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}", 
  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]);

Output: "Guid = {44332211-1234-ABCD-EFEF-001122334455}"

Refer to Guiddef.h for the GUID layout.

Same, as a method:

void printf_guid(GUID guid) {
    printf("Guid = {%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}", 
      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]);
}

you can also pass a CLSID to this method.

Solution 2:

Use the StringFromCLSID function to convert it to a string

e.g.:

GUID guid;
CoCreateGuid(&guid);

OLECHAR* guidString;
StringFromCLSID(guid, &guidString);

// use guidString...

// ensure memory is freed
::CoTaskMemFree(guidString);

Also see the MSDN definition of a GUID for a description of data4, which is an array containing the last 8 bytes of the GUID

Solution 3:

In case you prefer C++ way

std::ostream& operator<<(std::ostream& os, REFGUID guid){

    os << std::uppercase;
    os.width(8);
    os << std::hex << guid.Data1 << '-';

    os.width(4);
    os << std::hex << guid.Data2 << '-';

    os.width(4);
    os << std::hex << guid.Data3 << '-';

    os.width(2);
    os << std::hex
        << static_cast<short>(guid.Data4[0])
        << static_cast<short>(guid.Data4[1])
        << '-'
        << static_cast<short>(guid.Data4[2])
        << static_cast<short>(guid.Data4[3])
        << static_cast<short>(guid.Data4[4])
        << static_cast<short>(guid.Data4[5])
        << static_cast<short>(guid.Data4[6])
        << static_cast<short>(guid.Data4[7]);
    os << std::nouppercase;
    return os;
}

Usage:

static const GUID guid = 
{ 0xf54f83c5, 0x9724, 0x41ba, { 0xbb, 0xdb, 0x69, 0x26, 0xf7, 0xbd, 0x68, 0x13 } };

std::cout << guid << std::endl;

Output:

F54F83C5-9724-41BA-BBDB-6926F7BD6813

Solution 4:

In case when your code uses ATL/MFC you also could use CComBSTR::CComBSTR(REFGUID guid) from atlbase.h:

GUID guid = ...;
const CComBSTR guidBstr(guid);  // Converts from binary GUID to BSTR
const CString guidStr(guidBstr); // Converts from BSTR to appropriate string, ANSI or Wide

It will make conversion & memory cleanup automatically.