Click here to Skip to main content
15,893,564 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 
Here is a moments to be done left
operator= and constructor uses Convert without checking the result of conversion. I'd prefer to set a result flag rather than throwing an exception. Another moment is, ::UuidFromString() cannot convert regedit-style GUIDs (i.e. with braces:"{x-x-xx}"). It seems author solved it in Convert(BSTR bstrGuid, GUID& guid) method by cutting braces out but only here and not in any another place.
Here is my variant. You are free to change #define's THROW_INVALID* and CHECK_VALID* to change behavior in case of using an object in invalid state.
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

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);
	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 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(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

#define THROW_INVALID_OBJECT_USED throw CString("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;
}

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)
{
    CHECK_VALID_THIS;
	return !::memcmp(&m_guid, &g, sizeof(GUID));
}

bool CGuid::operator==(const CGuid& g)
{
    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 CComBSTR()
{ 
    CHECK_VALID_THIS;
	CComBSTR bstrGuid;
	Convert(m_guid, bstrGuid);
	return bstrGuid; 
}

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

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

bool CGuid::operator!=(const CGuid& g)
{
    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(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(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(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 Convert((LPCTSTR)csGuid.Mid(1, csGuid.GetLength()-2), guid);
	}
	else
	{
		return Convert((LPCTSTR)csGuid, guid);
	}
}

bool CGuid::Convert(LPCTSTR lpszGuid, GUID& guid)
{
	ATLASSERT(lpszGuid);
    RPC_STATUS rpc_status = ::UuidFromString((RPC_WSTR)(LPCWSTR)CStringW(lpszGuid), &guid);
	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
Dilukhin29-Dec-13 23:21
Dilukhin29-Dec-13 23:21 
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.