Click here to Skip to main content
15,893,190 members
Articles / Desktop Programming / WTL
Article

A light wrapper class for GUID

Rate me:
Please Sign up or sign in to vote.
4.22/5 (20 votes)
6 Oct 2005CPOL 64.9K   641   39   10
A CGuid class for manipulating the GUID structure.

Introduction

If you are programmer who strongly use COM/DCOM technology and its base structure GUID, you know how (and I now :-) often you are using this structure in API (CLSIDFrom...) calls and converting it from/to string, and what about MFC templates CMap<>, CList<>... So, for these reasons, some weeks ago I decided to write a wrapper class CGuid with some helper methods. With this class, you can easily convert GUID structures to CString or BSTRs and vice versa or create new GUIDs.

Source Code

// Guid.h: interface for the CGuid class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_GUID_H__BBBFB961_9EC0_4414_8B69_067CDD2FFB85__INCLUDED_)
#define AFX_GUID_H__BBBFB961_9EC0_4414_8B69_067CDD2FFB85__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CGuid 
{
public:
    CGuid();
    CGuid(BSTR guid);
    CGuid(const CString& csGuid);
    CGuid(LPCTSTR lpszGuid);
    CGuid(const CGuid& g);
    CGuid(const GUID& g);
    virtual ~CGuid();
    
    CGuid& operator=(const GUID& g);
    CGuid& operator=(const CGuid& g);
    CGuid& operator=(BSTR g);
    CGuid& operator=(const CComBSTR& g);
    CGuid& operator=(const CString& g);
    CGuid& operator=(LPCTSTR g);
    bool operator==(const GUID& g);
    bool operator==(const CGuid& g);
    bool operator!=(const GUID& g);
    bool operator!=(const CGuid& g);
    operator GUID&();
    operator GUID*();
    operator CComBSTR();
    operator CString();
    bool operator<(const CGuid& g1) const;
    bool operator>(const CGuid& g1) const;
    long HasKey(){ return HashKey(*this); };
    BOOL ProgID(CString& csProgID);
    BOOL ProgID(CComBSTR& bstrProgID);

    static bool Create(GUID& guid);
    static bool Create(CComBSTR& guid);
    static bool Convert(GUID& guid, CComBSTR& bstrGuid);
    static bool Convert(GUID& guid, CString& csGuid);
    static bool Convert(BSTR bstrGuid, GUID& guid);
    static bool Convert(const CComBSTR& bstrGuid, GUID& guid);
    static bool Convert(const CString& bstrGuid, GUID& guid);
    static bool Convert(LPCTSTR lpszGuid, GUID& guid);
    
    static long HashKey(GUID& guid);

protected:
    GUID m_guid;
    void copy(const CGuid& g); 
    void copy(const GUID& g);
};
#endif // !defined(AFX_GUID_H__BBBFB961_9EC0_4414_8B69_067CDD2FFB85__INCLUDED_)

// Guid.cpp: implementation of the CGuid class.
//
///////////////////////////////////////////////////
#include "stdafx.h"
#include "Guid.h"
///////////////////////////////////////////////////
// Construction/Destruction
///////////////////////////////////////////////////
#pragma comment(lib, "rpcrt4.lib")
#define GUID_STRING_LEN 40

CGuid::CGuid()
{
    m_guid = GUID_NULL;
}
CGuid::CGuid(BSTR guid)
{
    operator=(guid);
}
CGuid::CGuid(const CString& csGuid)
{
    operator=(csGuid);
}
CGuid::CGuid(LPCTSTR lpszGuid)
{
    operator=(lpszGuid);
}
CGuid::~CGuid()
{
}
CGuid::CGuid(const CGuid& g)
{
    m_guid = g.m_guid; 
}
CGuid::CGuid(const GUID& g)
{
    m_guid = g;
}
bool CGuid::operator==(const GUID& g)
{
    return !::memcmp(&m_guid, &g, sizeof(GUID));
}
bool CGuid::operator==(const CGuid& g)
{ 
    return operator==(g.m_guid);
}
CGuid::operator GUID&()
{ 
    return m_guid;
}
CGuid::operator GUID*()
{ 
    return &m_guid; 
}
CGuid::operator CComBSTR()
{ 
    CComBSTR bstrGuid;
    Convert(m_guid, bstrGuid);
    return bstrGuid; 
}
CGuid::operator CString()
{ 
    CString csGuid;
    Convert(m_guid, csGuid);
    return csGuid; 
}
bool CGuid::operator!=(const GUID& g)
{
    return ::memcmp(&m_guid, &g, sizeof(GUID)) != 0;
}
bool CGuid::operator!=(const CGuid& g)
{
    return operator!=(g.m_guid);
}
CGuid& CGuid::operator=(const GUID& g)
{
    if( ::memcmp(&m_guid, &g, sizeof(GUID)) != 0 )
    {
        copy(g);
    }
    return *this;
}
CGuid& CGuid::operator=(const CComBSTR& g)
{
    ATLASSERT(g.m_str);
    Convert(g, m_guid);
    return *this;
}
CGuid& CGuid::operator=(BSTR g)
{
    ATLASSERT(g);
    Convert(g, m_guid);
    return *this;
}
CGuid& CGuid::operator=(LPCTSTR g)
{
    ATLASSERT(g);
    Convert(g, m_guid);
    return *this;
}
CGuid& CGuid::operator=(const CString& g)
{
    Convert(g, m_guid);
    return *this;
}
CGuid& CGuid::operator=(const CGuid& g)
{
    if(this != &g )
    {
    copy(g.m_guid);
    }

    return *this;
}
inline void CGuid::copy(const CGuid& g)
{
    copy(g.m_guid);
}
inline void CGuid::copy(const GUID& g)
{
    ::memcpy(&m_guid, (void*)&g, sizeof(GUID));
}
bool CGuid::operator<(const CGuid& g1) const
{
    RPC_STATUS status;
    return ::UuidCompare(const_cast<GUID*>(&m_guid), 
           const_cast<GUID*>(&g1.m_guid), &status)==-1;
}
bool CGuid::operator>(const CGuid& g1) const
{
    return !this->operator<(g1) && ::memcmp(&g1.m_guid, 
                                &m_guid, sizeof(GUID));
}
bool CGuid::Convert(GUID& guid, CComBSTR& bstrGuid)
{
    OLECHAR szGuid[GUID_STRING_LEN]={0};
    int nCount = ::StringFromGUID2(guid, szGuid, GUID_STRING_LEN);
    bstrGuid = szGuid;
    
    return nCount !=0;
}
bool CGuid::Convert(GUID& guid, CString& csGuid)
{
    OLECHAR szGuid[GUID_STRING_LEN]={0};
    int nCount = ::StringFromGUID2(guid, szGuid, GUID_STRING_LEN);
    csGuid = szGuid;
    
    return nCount !=0;
}
bool CGuid::Convert(const CComBSTR& bstrGuid, GUID& guid)
{ 
    return Convert(bstrGuid.m_str, guid);
}
bool CGuid::Convert(BSTR bstrGuid, GUID& guid)
{
    if( bstrGuid == NULL )
    {
    return false;
    }
    
    UINT nLen = ::SysStringLen(bstrGuid);
    if( nLen < GUID_STRING_LEN - 4 )
    {
        return false;
    }
    CString csguid=bstrGuid;
    if( csguid.GetAt(0) == TCHAR('{') )
    {
        ATLASSERT(csguid.Find(TCHAR('}'))!=-1);
        return Convert(csguid.Mid(1, 
               csguid.GetLength()-2), guid);
    }
    else
    {
        return Convert(csguid, guid);
    }
}
bool CGuid::Convert(const CString& csGuid, GUID& guid)
{
    if( csGuid.GetLength() < GUID_STRING_LEN - 4 )
    {
        return false;
    }
    return Convert((LPCTSTR)csGuid, guid);
}
bool CGuid::Convert(LPCTSTR lpszGuid, GUID& guid)
{
    ATLASSERT(lpszGuid);
    return ::UuidFromString((unsigned char*)lpszGuid, 
                                  &guid) == RPC_S_OK;
}
bool CGuid::Create(CComBSTR& bstrGuid)
{
    GUID guid;
    if( Create(guid) )
    {
        return Convert(guid, bstrGuid);
    }
    return false;
}
bool CGuid::Create(GUID& guid)
{
    return ::UuidCreate(&guid) == RPC_S_OK;
}
long CGuid::HashKey(GUID& guid)
{
    RPC_STATUS status=RPC_S_OK;
    return ::UuidHash(&guid, &status);
}
BOOL CGuid::ProgID(CString& csProgID)
{
    CComBSTR bstrTmp;
    BOOL bRet = ProgID(bstrTmp);
    csProgID = bstrTmp;
    return bRet;
}

BOOL CGuid::ProgID(CComBSTR& bstrProgID)
{
    BOOL bRet=FALSE;
    if( *this == GUID_NULL )
    {
        return bRet;
    }
    LPOLESTR psz = NULL;
    if( ::ProgIDFromCLSID(m_guid, &psz) == S_OK )
    {
        bstrProgID=psz;
        ::CoTaskMemFree(psz);
        psz=NULL;
        bRet=TRUE;
    }
    return bRet;
}

As you can see, the only dependence is on the Rpcrt4.lib library. I have tested this class in WTL 7.5.

So enjoy.

History

  • 07 Oct 2005 - additional constructors and methods added, code improvements.
  • 21 Sep 2005 - initial version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
CEO bring-it-together s.r.o.
Slovakia Slovakia
Jozef Božek is currently a software engineer at bring-it-together s.r.o. in area of large scale infomation systems and mobile applications development.
He has been developing in C++ nearly full time since 2000, in Java since 2004 and in Objective-C since 2009. He is programming using Java EE SDK, iOS SDK, COM/DCOM, MFC, ATL, STL and so on Smile | :)

Comments and Discussions

 
SuggestionGreat, but can't be used as-is Pin
Dilukhin1-Dec-13 21:57
Dilukhin1-Dec-13 21:57 
GeneralRe: Great, but can't be used as-is Pin
Dilukhin29-Dec-13 23:21
Dilukhin29-Dec-13 23:21 
Update. Some more bugs fixed. Now it works good in our project
C++
// Guid.h: interface for the CGuid class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_GUID_H__BBBFB961_9EC0_4414_8B69_067CDD2FFB85__INCLUDED_)
#define AFX_GUID_H__BBBFB961_9EC0_4414_8B69_067CDD2FFB85__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <stdexcept>
struct EGuidException : public std::runtime_error
{
    EGuidException(const std::string& mess)
        :
    std::runtime_error(mess)
    {
    }
};

class CGuid
{
protected:
    bool m_bValid;
public:
    CGuid();
    CGuid(BSTR guid);
    CGuid(const CString& csGuid);
    CGuid(LPCTSTR lpszGuid);
    CGuid(const CGuid& g);
    CGuid(const GUID& g);
    virtual ~CGuid();

    CGuid& operator=(const GUID& g);
    CGuid& operator=(const CGuid& g);
    CGuid& operator=(BSTR g);
    CGuid& operator=(const CComBSTR& g);
    CGuid& operator=(const CString& g);
    CGuid& operator=(LPCTSTR g);

    bool operator==(const GUID& g) const;
    bool operator==(const CGuid& g) const;

    bool operator!=(const GUID& g) const;
    bool operator!=(const CGuid& g) const;

    operator GUID&();
    operator GUID*();
    operator const GUID&() const;
    operator const GUID*() const;
    operator CComBSTR() const;
    operator CString() const;

    bool operator<(const CGuid& g1) const;
    bool operator>(const CGuid& g1) const;

    long HashKey(){ return HashKey(*this); };
    bool IsValid() const{ return m_bValid; }

    BOOL ProgID(CString& csProgID);
    BOOL ProgID(CComBSTR& bstrProgID);

    static bool Create(GUID& guid);
    static bool Create(CComBSTR& guid);

    static bool Convert(const GUID& guid, CComBSTR& bstrGuid);
    static bool Convert(const GUID& guid, CString& csGuid);

    static bool Convert(BSTR bstrGuid, GUID& guid);
    static bool Convert(const CComBSTR& bstrGuid, GUID& guid);
    static bool Convert(const CString& bstrGuid, GUID& guid);

    static long HashKey(GUID& guid);


protected:
    GUID m_guid;
    void copy(const CGuid& g);	
    void copy(const GUID& g);
    static bool ConvertImpl(LPCTSTR lpszGuid, GUID& guid);
};

#endif // !defined(AFX_GUID_H__BBBFB961_9EC0_4414_8B69_067CDD2FFB85__INCLUDED_)


// Guid.cpp: implementation of the CGuid class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Guid.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

#pragma comment(lib, "rpcrt4.lib")

#define GUID_STRING_LEN	40

#define THROW_INVALID_OBJECT_USED throw EGuidException("Invalid GUID object used")
#define CHECK_VALID_THIS if(!this->IsValid()) THROW_INVALID_OBJECT_USED
#define CHECK_VALID(g) if(!(g).IsValid()) THROW_INVALID_OBJECT_USED
#define CHECK_VALID_BOTH(g) if(!this->IsValid() || !(g).IsValid()) THROW_INVALID_OBJECT_USED

CGuid::CGuid()
{
    m_guid = GUID_NULL;
    m_bValid=true;
}

CGuid::CGuid(BSTR guid)
{
    operator=(guid);
}

CGuid::CGuid(const CString& csGuid)
{
    operator=(csGuid);
    CHECK_VALID_THIS;
}

CGuid::CGuid(LPCTSTR lpszGuid)
{
    operator=(lpszGuid);
    CHECK_VALID_THIS;
}

CGuid::~CGuid()
{

}

CGuid::CGuid(const CGuid& g)
{
    m_guid = g.m_guid;
    m_bValid=g.m_bValid;
    //CHECK_VALID_THIS;
}

CGuid::CGuid(const GUID& g)
{
    m_guid = g;
    m_bValid=true;
    //CHECK_VALID_THIS;
}

bool CGuid::operator==(const GUID& g) const
{
    CHECK_VALID_THIS;
    return !::memcmp(&m_guid, &g, sizeof(GUID));
}

bool CGuid::operator==(const CGuid& g) const
{
    CHECK_VALID_BOTH(g);
    return operator==(g.m_guid);
}

CGuid::operator GUID&()
{ 
    CHECK_VALID_THIS;
    return m_guid; 
}

CGuid::operator GUID*()
{ 
    CHECK_VALID_THIS;
    return &m_guid; 
}

CGuid::operator const GUID&() const
{ 
    CHECK_VALID_THIS;
    return m_guid; 
}

CGuid::operator const GUID*() const
{ 
    CHECK_VALID_THIS;
    return &m_guid; 
}

CGuid::operator CComBSTR() const
{ 
    CHECK_VALID_THIS;
    CComBSTR bstrGuid;
    Convert(m_guid, bstrGuid);
    return bstrGuid; 
}

CGuid::operator CString() const
{ 
    CHECK_VALID_THIS;
    CString csGuid;
    Convert(m_guid, csGuid);
    return csGuid; 
}

bool CGuid::operator!=(const GUID& g) const
{
    CHECK_VALID_THIS;
    return ::memcmp(&m_guid, &g, sizeof(GUID)) != 0;
}

bool CGuid::operator!=(const CGuid& g) const
{
    CHECK_VALID_BOTH(g);
    return operator!=(g.m_guid);
}

CGuid& CGuid::operator=(const GUID& g)
{
    if( ::memcmp(&m_guid, &g, sizeof(GUID)) != 0 )
    {
        copy(g);
        m_bValid = true;
    }
    else
        m_bValid = false;

    return *this;
}

CGuid& CGuid::operator=(const CComBSTR& g)
{
    ATLASSERT(g.m_str);
    m_bValid = Convert(g, m_guid);
    return *this;
}

CGuid& CGuid::operator=(BSTR g)
{
    ATLASSERT(g);
    m_bValid = Convert(g, m_guid);
    return *this;
}

CGuid& CGuid::operator=(LPCTSTR g)
{
    ATLASSERT(g);
    m_bValid = Convert(CString(g), m_guid);
    return *this;
}

CGuid& CGuid::operator=(const CString& g)
{
    m_bValid = Convert(g, m_guid);
    return *this;
}

CGuid& CGuid::operator=(const CGuid& g)
{
    if(this != &g )
    {
        copy(g.m_guid);
    }

    return *this;
}

inline void CGuid::copy(const CGuid& g)
{
    CHECK_VALID(g);
    copy(g.m_guid);
}

inline void CGuid::copy(const GUID& g)
{
    ::memcpy(&m_guid, (void*)&g, sizeof(GUID));
}

bool CGuid::operator<(const CGuid& g1) const
{
    CHECK_VALID_BOTH(g1);
    RPC_STATUS status;
    return ::UuidCompare(const_cast<GUID*>(&m_guid), const_cast<GUID*>(&g1.m_guid), &status)==-1;
}

bool CGuid::operator>(const CGuid& g1) const
{
    CHECK_VALID_BOTH(g1);
    return !this->operator<(g1) && ::memcmp(&g1.m_guid, &m_guid, sizeof(GUID));
}

bool CGuid::Convert(const GUID& guid, CComBSTR& bstrGuid)
{
    OLECHAR szGuid[GUID_STRING_LEN]={0};
    int nCount = ::StringFromGUID2(guid, szGuid, GUID_STRING_LEN);
    bstrGuid = szGuid;

    return nCount !=0;
}

bool CGuid::Convert(const GUID& guid, CString& csGuid)
{
    OLECHAR szGuid[GUID_STRING_LEN]={0};
    int nCount = ::StringFromGUID2(guid, szGuid, GUID_STRING_LEN);
    csGuid = szGuid;

    return nCount !=0;
}

bool CGuid::Convert(const CComBSTR& bstrGuid, GUID& guid)
{	
    return Convert(CString(bstrGuid), guid);
}

bool CGuid::Convert(BSTR bstrGuid, GUID& guid)
{
    if( bstrGuid == NULL )
    {
        return false;
    }

    return Convert(CString(bstrGuid), guid);
}

bool CGuid::Convert(const CString& csGuid, GUID& guid)
{
    if( csGuid.GetLength() < GUID_STRING_LEN - 4 )
    {
        return false;
    }
    CStringW cstringw;

    if( csGuid.GetAt(0) == TCHAR('{') )
    {
        ATLASSERT(csGuid.Find(TCHAR('}'))!=-1);
        return ConvertImpl((LPCTSTR)csGuid.Mid(1, csGuid.GetLength()-2), guid);
    }
    else
    {
        return ConvertImpl((LPCTSTR)csGuid, guid);
    }
}

bool CGuid::ConvertImpl(LPCTSTR lpszGuid, GUID& guid)
{
    ATLASSERT(lpszGuid);
#ifdef _UNICODE
    RPC_STATUS rpc_status = ::UuidFromString((RPC_WSTR)lpszGuid, &guid);
#else
    RPC_STATUS rpc_status = ::UuidFromString((RPC_CSTR)lpszGuid, &guid);
#endif
    ASSERT(RPC_S_INVALID_STRING_UUID!=rpc_status);
    return rpc_status == RPC_S_OK;
}

bool CGuid::Create(CComBSTR& bstrGuid)
{
    GUID guid;
    if( Create(guid) )
    {
        return Convert(guid, bstrGuid);
    }

    return false;
}

bool CGuid::Create(GUID& guid)
{
    return ::UuidCreate(&guid) == RPC_S_OK;
}

long CGuid::HashKey(GUID& guid)
{
    RPC_STATUS status=RPC_S_OK;
    return ::UuidHash(&guid, &status);
}

BOOL CGuid::ProgID(CString& csProgID)
{
    CComBSTR bstrTmp;
    BOOL bRet = ProgID(bstrTmp);
    csProgID = bstrTmp;
    return bRet;
}

BOOL CGuid::ProgID(CComBSTR& bstrProgID)
{
    CHECK_VALID_THIS;
    BOOL bRet=FALSE;
    if( *this == GUID_NULL )
    {
        return bRet;
    }

    LPOLESTR psz = NULL;
    if( ::ProgIDFromCLSID(m_guid, &psz) == S_OK )
    {
        bstrProgID=psz;
        ::CoTaskMemFree(psz);
        psz=NULL;
        bRet=TRUE;
    }
    return bRet;
}

GeneralRe: Great, but can't be used as-is Pin
memo-57-Mar-14 0:47
memo-57-Mar-14 0:47 
GeneralMy vote of 5 Pin
John Patrick Francis8-Jul-11 9:51
John Patrick Francis8-Jul-11 9:51 
GeneralVery Useful Class [modified] Pin
rahul.kulshreshtha11-Dec-10 18:48
rahul.kulshreshtha11-Dec-10 18:48 
GeneralGood wrapper class Pin
Todd Chen16-Sep-09 17:54
Todd Chen16-Sep-09 17:54 
Generalconst operators Pin
tmcgarr17-Oct-07 15:42
tmcgarr17-Oct-07 15:42 
GeneralNice Work Pin
dr3´28-Mar-07 23:09
dr3´28-Mar-07 23:09 
GeneralNice Work Pin
dr3´28-Mar-07 23:09
dr3´28-Mar-07 23:09 
GeneralSmall remark Pin
zero2zero200127-Aug-06 22:55
zero2zero200127-Aug-06 22:55 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.