win32 message queue, multithreading, COM problem
Hello,
I am trying to get a simple program working that involves a console
application that spawns a thread; the thread will call an ATL COM object,
create a small dialog box and windows message queue, and loop until the user
presses the escape key. The COM object is created using STA model...I am
calling it from child thread only.
I do not understand what is wrong here. When I hit the escape key, the
program goes into an infinite loop starting at the cleanup of the thread
(CLEANUP02), runs past the ReleaseMutex call, and then resumes back at
CLEANUP02.
The COM object was from a codeproject application Systemtraydemo.
Here is my source code:
#ifndef _MT
#define _MT
#endif
#include <windows.h>
#include "stdio.h"
#include <iostream>
#include "process.h"
#define INITGUID
#include <objbase.h>
#include "SystemTrayDemo.h"
#include "resource.h"
// global flag
bool bDone = false;
// this function is called by a new thread
unsigned _stdcall InputThreadProc(LPVOID lpMutex)
{
HANDLE hMutex = (HANDLE) lpMutex;
// create the dialog window
HWND hWnd = ::CreateDialog(NULL,MAKEINTRESOURCE(IDD_DIALOG),NULL,NULL);
if ( hWnd!=NULL )
{
// show dialog
ShowWindow(hWnd,SW_SHOW);
}
else
{
printf("Failed to create dialog\n");
return -1;
}
// message loop to process user input
// Create Icon here
int count=0;
std::cout<<"main: Entry"<<std::endl;
IClassFactory *pCf;
IUnknown *pUnk;
IMyServer *pMyServer;
HRESULT hr;
std::cout<<"main: calling CoInitialize() \n"<<std::endl;
hr=CoInitialize(NULL);
if(FAILED(hr))
{
std::cout<<"main: CoInitialize Failed!\n"<<std::endl;
exit(-1);
}
std::cout<<"main: CoInitialize OK\n"<<std::endl;
std::cout<<"main: Calling CoGetClassObject\n"<<std::endl;
hr=CoGetClassObject(CLSID_MyServer,CLSCTX_INPROC_SERVER,NULL,IID_IClassFactory,(void**)&pCf);
if(FAILED(hr))
{
std::cout<<"main: CoGetClassObject Failed!\n"<<std::endl;
goto EXIT00;
}
std::cout<<"main: CoGetClassObject OK\n"<<std::endl;
std::cout<<"main: calling
pCf->CreateInstance(NULL,IID_IUnknown,...)"<<std::endl;
hr=pCf->CreateInstance(NULL,IID_IUnknown,(void**) &pUnk);
if(FAILED(hr))
{
std::cout<<"main: pCf->CreateInstance(NULL,IID_IUnknown,...)
Failed!\n"<<std::endl;
goto CLEANUP00;
}
std::cout<<"main: pCf->CreateInstance(NULL,IID_IUnknown,...)
OK"<<std::endl;
std::cout<<"main: calling
pUnk->QueryInterface(IID_IMyServer,...)"<<std::endl;
hr=pUnk->QueryInterface(IID_IMyServer,(void**) &pMyServer);
if(FAILED(hr))
{
std::cout<<"main: pUnk->QueryInterface(IID_IMyServer,...)
Failed!\n"<<std::endl;
goto CLEANUP01;
}
std::cout<<"main: pUnk->QueryInterface(IID_IMyServer,...)
OK\n"<<std::endl;
std::cout<<"main: Now Calling into the IMyServer
Interface\n"<<std::endl;
hr=pMyServer->Visible(VARIANT_TRUE);
if(FAILED(hr))
{
std::cout<<"main: pMyServer->Visible() Failed!\n"<<std::endl;
goto CLEANUP02;
}
hr=pMyServer->Animate(VARIANT_TRUE,200);
if(FAILED(hr))
{
std::cout<<"main: pMyServer->Animate() Failed!\n"<<std::endl;
goto CLEANUP02;
}
std::cout<<"main: pMyServer->Animate() OK!\n"<<std::endl;
MSG msg;
while(!bDone)
{
GetMessage(&msg, NULL, 0, 0);
if ( msg.message==WM_KEYUP )
{
int nVirtKey = (int) msg.wParam;
// if the user pressed the ESCAPE key, then
// print the text the user entered and quit
if ( nVirtKey==VK_ESCAPE )
{
DestroyWindow(hWnd);
bDone = true;
break;
}
}
// process message
TranslateMessage(&msg);
DispatchMessage(&msg);
}
CLEANUP02:
std::cout<<"main: calling IMyServer::Release"<<std::endl;
if(pMyServer){
pMyServer->Release();
pMyServer = NULL;
}
CLEANUP01:
std::cout<<"main: calling IUnknown::Release"<<std::endl;
if(pUnk){
pUnk->Release();
pUnk = NULL;
}
CLEANUP00:
std::cout<<"main: calling IClassFactory::Release"<<std::endl;
if(pCf){
pCf->Release();
pCf = NULL;
}
EXIT00:
CoUninitialize();
std::cout<<"main: We are done!"<<std::endl;
ReleaseMutex(hMutex);
}
int main(int argc, char* argv[])
{
HANDLE handle;
HANDLE hMutex;
unsigned uUnUsedThreadId;
hMutex = CreateMutex(NULL,FALSE,NULL);
if(hMutex==NULL)
{
printf("Primary Thread - error calling
CreateMutex().\n");
exit(0xFFFFFFFF);
}
// create a new thread to allow user input
handle = (HANDLE) _beginthreadex(NULL,0,InputThreadProc, (void*)
hMutex, 0, &uUnUsedThreadId);
if( (int) handle==-1)
{
printf("Failed to create thread");
return 0;
}
// wait for the new thread to finish
handle = (HANDLE) WaitForSingleObject(handle,INFINITE);
return 0;
}