Sep 032014
 

Issue

Recently had a customer who was facing this issue. His code looked as follows (assuming COM’s initialized) which apparently is trying to setup an ActiveX control…

HWND hWnd = CreateWindow(_T(ATLAXWIN_CLASS),
_T(“SysMon”),
WS_CHILD,
0, 10, 100, 200,
hwndParent,
NULL,
hInstance,
NULL);

As soon as above code executes the application crashes.

image

Why loading ActiveX failed?

Callstack for the crash looks as follows…

ConsoleApplication1.exe!ATL::CComPolyObject<ATL::CAxHostWindow>::CComPolyObject<ATL::CAxHostWindow>
ConsoleApplication1.exe!ATL::CComCreator<ATL::CComPolyObject<ATL::CAxHostWindow> >::CreateInstance
ConsoleApplication1.exe!AtlAxCreateControlLicEx
ConsoleApplication1.exe!AtlAxCreateControlLic
ConsoleApplication1.exe!ATL::AtlAxWindowProc
user32.dll!UserCallWinProcCheckWow
user32.dll!DispatchClientMessage
user32.dll!__fnINLPCREATESTRUCT
ntdll.dll!KiUserCallbackDispatch    Unknown
user32.dll!ZwUserCreateWindowEx    Unknown
user32.dll!VerNtUserCreateWindowEx
user32.dll!CreateWindowInternal
user32.dll!CreateWindowExW
ConsoleApplication1.exe!wmain
ConsoleApplication1.exe!__tmainCRTStartup
ConsoleApplication1.exe!wmainCRTStartup
kernel32.dll!BaseThreadInitThunk
ntdll.dll!RtlUserThreadStart

 

Autos debug window showed following…

image

Resolution

The highlighted elements gave ample hint. This is a console application with no ATL boilerplate code generated by project wizard for this project. Ideally ATL requires a global CComModule instance to initialize itself. This is how the CComModule constructor looks like…

CComModule()
{
// Should have only one instance of a class
// derived from CComModule in a project.
ATLASSERT(_pModule == NULL);
<span style="background-color: #ffff00;">_pModule = this;</span>
#if !defined(_ATL_NATIVE_INITIALIZATION)
#pragma warning(push)  // disable 4483
#pragma warning(disable:4483)
using namespace __identifier("<AtlImplementationDetails>");
#pragma warning(pop)  // disable 4483
ATLASSERT(ComModuleInitialized == false);
// If ComModuleHelper.Module == NULL it mean that DllMain has not been called, so we assume CComModule lives in
// an exe and not in a dll
if (ComModuleHelper.Module != NULL)
{
ATLASSERT(ComModuleHelper.Module == this);
_DllMain(ComModuleHelper.Instance, DLL_PROCESS_ATTACH, NULL, ComModuleHelper.ObjectMap, ComModuleHelper.LibraryId);
}
ComModuleInitialized = true;
#endif
}

This function further initializes _pModule instance to point to this global instance of ours eventually. So after we declare CComModule global instance this is how _pAtlModule (it points to our  global instance) will look after instantiation of our global CComModule…

image

Crash resolved.

Mar 172011
 

Recently a customer of mine faced this issue. So he had an ActiveX control and when displaying the ActiveX control in browser a string is displayed right in the middle of the control: “ATL 9.0”.

So this issue happens because you didn’t override CComControlBase::OnDraw  function. The default code for CComControlBase::OnDraw looks like the following…

HRESULT CComControlBase::YourClassName::OnDraw(_In_ ATL_DRAWINFO& di)
{
  ::SetTextAlign(di.hdcDraw, TA_CENTER|TA_BASELINE);
  LPCTSTR pszText = _T("ATL ") _T(_ATL_VER_RBLD); // "ATL 9.0"
  ::TextOut(di.hdcDraw,
            di.prcBounds->left + (di.prcBounds->right - di.prcBounds->left) / 2,
            di.prcBounds->top + (di.prcBounds->bottom - di.prcBounds->top) / 2,
            pszText,
            lstrlen(pszText)); 
   return S_OK;
}

MSDN documentation for CComControlBase::OnDraw function confirms this behavior. Quote…

The wizard’s default OnDraw draws a rectangle with the label “ATL 8.0”.

The solution for this is to override CComControlBase::OnDraw function in your derived class and provide your own drawing or just return S_OK.

Jul 142009
 

Recently a user asked this question in forums, I was quite able to answer his query. So thought this might be useful to you guys too. 🙂

So the basic difference is that CComPtr is an ATL class is used with using ATL COM implementations while _com_ptr_t is one of the few COM support classes to support non ATL COM development. The definitions of these COM support classes go along with the tlb files and probably that’s why they are called as COM support classes. Also their definition can be found in comdef.h too. The other classes similar to _com_ptr_t are …

  1. _bstr_t
  2. _com_error
  3. _com_ptr_t
  4. _variant_t

So what are COM support classes? These are special lightweight classes that wraps basic useful COM functionality so that ideas like COM smart pointer typedefs over raw COM inteface classes works just by using tlb file. An example on how _com_ptr_t is used…

_COM_SMARTPTR_TYPEDEF(IMyInterface, __uuidof(IMyInterface));

This above line declares _com_ptr_t specialization IMyInterfacePtr.

The library to link to for using COM support classes is comsuppw.lib.

Oct 252008
 

Why?

Well debugging exe is quite easy, but ever wondered how to debug a dll. Well why? Simple, you write a dll and you wanna debug a bug just like you would do with an executable.

Can you give us some examples?

Well so what is a dll? I think of it as a parasite because just like a parasite it’s dependent on an executable to get it running. Some examples follow…

  1. A good example to think of will be rundll32.exe. Ever thought about that name “rundll32.exe”, it just means “run a 32 bit dll using this exe”, so how does this achieve this, remember the command line that we pass to it, i.e. name of the dll followed by a procedure name exported from our dll.
  2. Another example to think of is regsvr32.exe, does the same stuff i.e. registers a COM dll but this time with a difference, we don’t have to give a procedure name. Because COM programming protocol defines mandatory functions to be exported from a COM dll and regsvr32.exe knows exactly which function to call based on the command line switches passed in.
  3. Another example that comes to mind is the windows surrogate process “dllhost.exe”, I’ve heard people say that it’s a virus ;). Naah it’s a COM surrogate process which helps in hosting a COM dll to make the dll behave like a process hence providing the flexibility to behave like an executabable and at the same time like a dll, vice versa is not possible. Well it can at times be hosting a malicious dll too. It’s quite rare though.

What has this got to do with debugging a DLL?

The reason why I’ve given above examples is to help you understand that a DLL cannot run by itself, it needs a host process to help it run.

Exactly! same for debugging it needs a process to get it running so that execution reaches our breakpoint that we’ve set. Aha! so there must be some option to tell the debugger about the host process. Oh yeah, goto Project settings->Debugging->Executable for Debug Session. Select any process which is using your dll.

Think that you are writing a window’s shell extension, which are dlls, think on how to debug them. So for this case your target process will be explorer.exe. So you will specify explorer.exe as your process. Or imagine writing an activex control, so for this case the target process will be an activex test container.

This is a shot from VC6, it’s quite similar in VC7, VC8 and VC9, instead of tabs there you have a tree menu holding the “Debugging” item right at the top of the tree.

Well now just press F5 and see what happens, you will see your target process running and just try doing a button or menu click that could invoke the function in which you’ve set a breakpoint.  If you are writing a shell extension for e.g. extending shell context menu, then you would right click on a file in the explorer window.

Also note that if your active project is a ‘dll project’ then you’ll get prompted to enter a target process name to get the dll hosted as soon as you press F5. So no need to go to project properties.

Hope this helps you?

Jul 022008
 

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 );
May 042008
 

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.

Sep 122007
 

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

Jul 162007
 

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.