Archive

Posts Tagged ‘COM’

How to create a GUID programmatically?

Do the following…

GUID guId = { 0 };
CoCreateGuid( &guId );
// or
UUID uid = { 0 };
UuidCreate( &uid );

For converting to string use…

PUCHAR pChar = 0;

// Convert to string
UuidToString( &uid, &pChar );
MessageBox( NULL, (char*)pChar, NULL, MB_OK );

//Don't forget to free allocated string
RpcStringFree( &pChar );
Advertisements

Freeing unused libraries while using COM!

It’s a good practice to free unused COM dlls if it’s not used anymore. So is there a function call which does this?

Yes, it’s called CoFreeUnusedLibraries or CoFreeUnusedLibrariesEx!

Are the libraries immediately removed from the internal COM dll list, no there is a time delay of 10 minutes for MTAs and neutral apartment models, this is to avoid multi threaded race conditions but there is no delay for STAs.

To avoid a ten minute delay call CoFreeUnusedLibrariesEx with the delay parameter set to some reasonable value, but avoid values of zero allowing a dll to do cleanup stuff. MSDN says there will be problems if delay is set to zero.

Internally COM maintains a list of COM dlls loaded for a process, and when CoFreeUnusedLibraries is called this dll is moved to “candidate-for-removal” list as per MSDN. So just in case if the dll get’s used again while in this list, it’s moved back to the active list of COM libraries of loaded for a process.

CoFreeUnusedLibrariesEx/CoFreeUnusedLibraries calls DllCanUnloadNow to figure out whether a COM dll is ready to be unloaded, if it’s ready then it returns S_OK else S_FALSE.

Useful macros for working with VARIANT!

VARIANT is a COM data type desgined to hold different kinds types of values. VARIANT structure contains a member vt of type VARTYPE. This vt determines the type of data that a VARIANT object will hold!

For eg:

VARIANT vtVarUINT;
vtVarUINT.vt = VT_UI4;
vtVarUINT.ulVal = 123;

So every vt type has a corresponding value member, and sometimes it’s hard to correctly map between these types as there are more than 40 types from what I see!

So that’s why we have macros to help us maintain this mapping correctly, above code can be re-written as follows…

VARIANT vtVarUINT;
vtVarUINT.vt = VT_UI4;
// No need to worry here about <em>ulVal</em>, it will be done for use by this macro
V_UI4( &vtVarUINT ) = 123;

Well this was assigning, how about using this on the RHS side, it’s easy…

// No need to worry about which value type to pick from the big structure, correctly
// mapped for us by this macro.
const UINT uBlah = V_UI4( &vtVarUINT );

VT_UI4 is one among many macros provided in oleauto.h. I am pasting the rest here for your reference sake!

V_UI1(X)
V_UI1REF(X)
V_I2(X)
V_I2REF(X)
V_I4(X)
V_I4REF(X)
V_R4(X)
V_R4REF(X)
V_R8(X)
V_R8REF(X)
V_I1(X)
V_I1REF(X)
V_UI2(X)
V_UI2REF(X)
V_UI4(X)
V_UI4REF(X)
V_INT(X)
V_INTREF(X)
V_UINT(X)
V_UINTREF(X)
V_CY(X)
V_CYREF(X)
V_DATE(X)
V_DATEREF(X)
V_BSTR(X)
V_BSTRREF(X)
V_DISPATCH(X)
V_DISPATCHREF(X
V_ERROR(X)
V_ERRORREF(X)
V_BOOL(X)
V_BOOLREF(X)
V_UNKNOWN(X)
V_UNKNOWNREF(X)
V_VARIANTREF(X)
V_ARRAY(X)
V_ARRAYREF(X)
V_BYREF(X)
V_DECIMAL(X)
V_DECIMALREF(X)
Categories: Windows API Tags: , , , ,

Dynamically determining the base class of a class using templates

November 27, 2007 Leave a comment

Well nearly dynamically! When working on the ATL COM framework I came across a piece of framework code which makes a template parameter as the base class of a class which looked quite useful to me.

Here is a demo…

template<class BaseClass = CWnd> class SomeWnd : public BaseClass
{
    public:
      LRESULT WindowProc(UINT uMessage, WPARAM wParam, LPARAM lParam );
};    

template</class><class BaseClass>
LRESULT SomeWnd<baseclass>::WindowProc( UINT uMessage, WPARAM wParam, LPARAM lParam )
{
    //... Do some additional processing here ...
    return BaseClass::WindowProc( uMessage, wParam, lParam );
}   

class MyDialog : public SomeWnd<cdialog>
{
};     

class MyFrame : public SomeWnd<cframewnd>
{
};   

class MyCustomWindow : public SomeWnd<> // Use default template param
{
};

Now you may ask why I needed this, well I had to write some code in the WindowProc of a window class, but the base differed from implementation to implementation, so I adapted this idea from the ATL COM framework.

Since WindowProc is found in all CWnd derived window classes and at the same time I also needed to call the correct the default base implementation too, so this helped.

How to resolve a shortcut!

September 12, 2007 Leave a comment

Ever wondered how to resolve a shortcut! There is a hidden helper function if you are using MFC, it’s called AfxResolveShortcut. I customized it a bit, so that we can use it independently without MFC, and here is the finished product. 😉

BOOL ResolveShortcut( HWND hWnd_i,
                      LPCTSTR lpctszFileIn_i,
                      LPTSTR  lptszFileOut_o,
                      const int nPathLength_i )
{
    // Object for resolving link
    IShellLink* psl = NULL;
    *lptszFileOut_o = 0;   // assume failure            

    if (!hWnd_i)
        return FALSE;            

    SHFILEINFO info;
    if (( SHGetFileInfo(lpctszFileIn_i,
                        0,
                        &info,
                        sizeof(info),
                        SHGFI_ATTRIBUTES) == 0) || !(info.dwAttributes & SFGAO_LINK))
    {
        return FALSE;
    }            

    CoInitialize( 0 );            

    // Create instance
    HRESULT hCreateRes = CoCreateInstance( CLSID_ShellLink,
                                           0,
                                           CLSCTX_INPROC_SERVER,
                                           IID_IShellLink,
                                           reinterpret_cast<lpvoid *>( &psl ));
    if ( FAILED( hCreateRes ) || psl == NULL )
    {
        return FALSE;
    }            

    IPersistFile *ppf = NULL;
    if (SUCCEEDED(psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf)))
    {
        USES_CONVERSION; // T2COLE needs this
        if ( ppf != NULL && SUCCEEDED( ppf->Load( T2COLE( lpctszFileIn_i ), STGM_READ)) )
        {
            /* Resolve the link, this may post UI to find the link */
            if ( SUCCEEDED(psl->Resolve( hWnd_i,
                 			    SLR_ANY_MATCH)))
            {
                psl->GetPath(lptszFileOut_o, nPathLength_i, NULL, 0);
                ppf->Release();
                psl->Release();
                CoUninitialize();
                return TRUE;
            }
        }           

        if (ppf != NULL)
            ppf->Release();
    }           

    psl->Release();
    CoUninitialize();
    return FALSE;           

}// End ResolveShortcut           

//Lets test the above code...
int main()
{
  TCHAR chBuffer[MAX_PATH] = { 0 };
  ResolveShortcut( hSomeWindow,
                   _T( "C:\\shortcut to msdev.lnk" ), // Make sure the shortcut is there
                   chBuffer,
                   MAX_PATH );
  MessageBox( hSomeWindow, chBuffer, _T( "Hurray shortcut resolved" ), MB_OK | MB_ICONINFORMATION );
  return 0;
}// End main

Easy way to display Gif’s, Ico’s, JPEG’s and BMP’s on your window

July 16, 2007 2 comments

Here is a function that does this! You only have to call this function with an image file, (gif, jpeg, jpg, bmp, ico) and a window handle onto which picture is to be painted. This is originally from MSDN but I modified it slightly to make it into one function… 😉

// This function loads a file into an IStream.
void LoadPictureFile( LPCTSTR szFile, HWND hWnd )
{
  LPPICTURE gpPicture = 0;
  // open file
  HANDLE hFile = CreateFile(szFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
  _ASSERTE(INVALID_HANDLE_VALUE != hFile);

  // get file size
  DWORD dwFileSize = GetFileSize(hFile, NULL);
  _ASSERTE(-1 != dwFileSize);

  LPVOID pvData = NULL;
  // alloc memory based on file size
  HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);
  _ASSERTE(NULL != hGlobal);

  pvData = GlobalLock(hGlobal);
  _ASSERTE(NULL != pvData);

  DWORD dwBytesRead = 0;
  // read file and store in global memory
  BOOL bRead = ReadFile(hFile, pvData, dwFileSize, &dwBytesRead, NULL);
  _ASSERTE(FALSE != bRead);
  GlobalUnlock(hGlobal);
  CloseHandle(hFile);

  LPSTREAM pstm = NULL;
  // create IStream* from global memory
  HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pstm);
  _ASSERTE(SUCCEEDED(hr) && pstm);

  // Create IPicture from image file
  if (gpPicture)
    gpPicture->Release();
  hr = ::OleLoadPicture(pstm, dwFileSize, FALSE, IID_IPicture, (LPVOID *)&gpPicture);
  _ASSERTE(SUCCEEDED(hr) && gpPicture); 
  pstm->Release();  

  /** Painting part added to make it into one function **/ 

  // Retrieve dc
  HDC hdc = GetDC( hWnd );
  long hmWidth = 0;
  long hmHeight = 0;
  gpPicture->get_Width(&hmWidth);
  gpPicture->get_Height(&hmHeight); 

  // convert himetric to pixels
  int nWidth = MulDiv(hmWidth, GetDeviceCaps(hdc, LOGPIXELSX), HIMETRIC_INCH);
  int nHeight = MulDiv(hmHeight, GetDeviceCaps(hdc, LOGPIXELSY), HIMETRIC_INCH);
  RECT rc;
  GetClientRect(hWnd, &rc); 

  // display picture using IPicture::Render
  gpPicture->Render(hdc, 0, 0, nWidth, nHeight, 0, hmHeight, hmWidth, -hmHeight, &rc);
  ReleaseDC( hWnd, hdc );
  gpPicture->Release(); 

  /** End Painting Part **/
}// End LoadPictureFile

It’s not a good idea to put painting stuff in one function, since painted image will get erased when window is moved or resized.  Ideally painting stuff should be in the WM_PAINT handler, so I leave that part to you.

%d bloggers like this: