- ccomthread_src.zip
- LegacyCOMObject1
- Shared
- SimpleCOMObject1
- SimpleCOMObject2
- Test Programs
- VBTest
- VCTests
- DemonstrateDefaultSTA
- VCTest01
- main.cpp
- SimpleCOMObject2.tlh
- SimpleCOMObject2.tli
- VCTest01.dsp
- VCTest01.dsw
- VCTest02
- main.cpp
- SimpleCOMObject2.tlh
- SimpleCOMObject2.tli
- VCTest02.dsp
- VCTest02.dsw
- DemonstrateExeServerSTA
- Client
- VCTest01
- Implementation
- ExeServerImpl
- Interface
- ExeServerInterfaces
- DemonstrateLegacySTA
- VCTest01
- LegacyCOMObject1.tlh
- LegacyCOMObject1.tli
- main.cpp
- VCTest01.dsp
- VCTest01.dsw
- VCTest02
- DemonstrateNoMessageLoop
- VCTest01
- main.cpp
- SimpleCOMObject2.tlh
- SimpleCOMObject2.tli
- VCTest01.dsp
- VCTest01.dsw
- DemonstrateSTA
- VCTest01
- main.cpp
- SimpleCOMObject2.tlh
- SimpleCOMObject2.tli
- VCTest01.dsp
- VCTest01.dsw
|
// ComThread.h : Declaration of the CComThread
#ifndef __CCOMTHREAD_H_
#define __CCOMTHREAD_H_
#include <windows.h>
#include <vector>
using namespace std;
typedef vector<LPSTREAM> ISTREAM_VECTOR;
typedef vector<LPUNKNOWN> IUNKNOWN_VECTOR;
class CComThread
{
public :
enum Flags
{
FLAG_START_SUSPENDED = 0x00000001
};
CComThread() :
m_hThread(NULL),
m_lpStartAddress(NULL),
m_lpParam(NULL),
m_Flags((Flags)0),
m_dwThreadId(0)
{
InitializeCriticalSection(&m_csStreamVectorAccess);
}
~CComThread()
{
if (m_hThread)
{
CloseHandle (m_hThread);
m_hThread = NULL;
}
ClearVectorStream();
ClearVectorUnknown();
DeleteCriticalSection(&m_csStreamVectorAccess);
}
void SetStartAddress (LPTHREAD_START_ROUTINE lpStartAddress)
{
m_lpStartAddress = lpStartAddress;
}
void SetThreadParam (void* lpParam)
{
m_lpParam = lpParam;
}
void* GetThreadParam()
{
return m_lpParam;
}
void SetFlags (Flags FlagsSet)
{
m_Flags = FlagsSet;
}
long ThreadStart()
{
long lRet = 0;
if (m_hThread)
{
CloseHandle(m_hThread);
m_hThread = NULL;
}
m_hThread = (HANDLE)CreateThread
(
(LPSECURITY_ATTRIBUTES)NULL, // SD
(SIZE_T)0, // initial stack size
(LPTHREAD_START_ROUTINE)(CComThreadStartFunction), // thread function
(LPVOID)this, // thread argument
(DWORD)((m_Flags & FLAG_START_SUSPENDED) ? CREATE_SUSPENDED : 0), // creation option
(LPDWORD)&m_dwThreadId // thread identifier
);
return lRet;
}
long ThreadSuspend()
{
long lRet = 0;
if (m_hThread)
{
lRet = (long)SuspendThread(m_hThread);
}
return lRet;
}
long ThreadResume()
{
long lRet = 0;
lRet = (long)ResumeThread(m_hThread);
return lRet;
}
long WaitThreadStop()
{
HANDLE dwChangeHandles[1];
BOOL bContinueLoop = TRUE;
DWORD dwWaitStatus = 0;
long lRet = 0;
dwChangeHandles[0] = m_hThread;
// Msg Loop while waiting for thread to exit.
while (bContinueLoop)
{
// Wait for notification.
dwWaitStatus = ::MsgWaitForMultipleObjectsEx
(
(DWORD)1, // number of handles in array
dwChangeHandles, // object-handle array
(DWORD)INFINITE, // time-out interval
(DWORD)(QS_ALLINPUT | QS_ALLPOSTMESSAGE), // input-event type
(DWORD)(MWMO_INPUTAVAILABLE) // wait options
);
switch (dwWaitStatus)
{
// First wait (thread exit) object has been signalled.
case WAIT_OBJECT_0 :
{
// Flag to indicate stop loop.
bContinueLoop = FALSE;
break;
}
// Windows message has arrived.
case WAIT_OBJECT_0 + 1:
{
MSG msg;
// Dispatch all windows messages in queue.
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage (&msg);
DispatchMessage(&msg);
}
break;
}
default:
{
break;
}
}
}
return lRet;
}
long WaitThreadStop2()
{
long lRet = 0;
WaitForSingleObject(m_hThread, INFINITE);
return lRet;
}
long ClearVectorStream()
{
long lRet = 0;
EnterCriticalSection(&m_csStreamVectorAccess);
// No need to Release() IStream pointers in m_vectorStream.
// They have all been Release()'d previously when we called
// CoGetInterfaceAndReleaseStream().
m_vectorStream.clear();
LeaveCriticalSection(&m_csStreamVectorAccess);
return lRet;
}
long ClearVectorUnknown()
{
IUNKNOWN_VECTOR::iterator theIterator;
int iIndex = 0;
long lRet = 0;
for (theIterator = m_vectorUnknown.begin(); theIterator != m_vectorUnknown.end(); theIterator++)
{
IUnknown* pIUnknown = (*theIterator);
if (pIUnknown)
{
pIUnknown -> Release();
pIUnknown = NULL;
}
}
m_vectorUnknown.clear();
return lRet;
}
// Note that AddUnknownPointer() must be called outside the thread.
long AddUnknownPointer(LPUNKNOWN& lpUnknown)
{
IStream* pIStreamTemp = NULL;
HRESULT hrTemp = S_OK;
long lRet = 0;
EnterCriticalSection(&m_csStreamVectorAccess);
if (lpUnknown)
{
// Create stream for marshaling lpUnknown to thread.
hrTemp = ::CoMarshalInterThreadInterfaceInStream
(
IID_IUnknown, // interface ID to marshal
lpUnknown, // ptr to interface to marshal
&pIStreamTemp // output variable
);
// Place stream in member variable where COM thread will look for it.
// No need to call Release() on pStream. They will be Release()'d
// when we later call CoGetInterfaceAndReleaseStream().
if (pIStreamTemp)
{
m_vectorStream.push_back(pIStreamTemp);
}
}
LeaveCriticalSection(&m_csStreamVectorAccess);
return lRet;
}
// Note that UnMarshallInterfaces() must only be called in the thread (managed by this object).
long UnMarshallInterfaces ()
{
ISTREAM_VECTOR::iterator theIterator;
int iIndex = 0;
HRESULT hrTemp = S_OK;
long lRet = 0;
EnterCriticalSection(&m_csStreamVectorAccess);
// Unmarshal interface pointers
for (theIterator = m_vectorStream.begin(); theIterator != m_vectorStream.end(); theIterator++)
{
IUnknown* pIUnknownTemp = NULL;
IStream* pIStreamTemp = NULL;
// Get stream pointer from array where owner has placed it.
pIStreamTemp = (*theIterator);
if (pIStreamTemp)
{
// Use stream pointer to create IUnknown that we can call from this thread.
hrTemp = ::CoGetInterfaceAndReleaseStream
(
pIStreamTemp, // stream containing marshaling info
IID_IUnknown, // interface desired
(void**)&pIUnknownTemp // output variable
);
// Note that at this time, pIStreamTemp will be Release()'d and will no longer
// be valid.
// Put resulting IUnknown in IUnknown pointers vector.
if (pIUnknownTemp)
{
m_vectorUnknown.push_back(pIUnknownTemp);
pIUnknownTemp -> AddRef(); // Since we have added pIUnknownTemp into a collection, we have an additional reference to it.
}
}
}
// Once all the streams in the stream vector has been unmarshalled,
// we no longer need the streams vector (the streams have been Release()'d
// anyway and so are no longer valid).
ClearVectorStream();
LeaveCriticalSection(&m_csStreamVectorAccess);
return lRet;
}
IUNKNOWN_VECTOR& GetUnknownVector()
{
return m_vectorUnknown;
}
operator IUNKNOWN_VECTOR&()
{
return GetUnknownVector();
}
protected :
static DWORD WINAPI CComThreadStartFunction(LPVOID lpThreadParameter)
{
CComThread* pCComThread = (CComThread*)lpThreadParameter;
DWORD dwRet = 0;
CoInitialize(NULL);
// At this point in time, the thread managed by CComThread has just started.
// We take this opportunity to unmarshall the interfaces stored in m_mapStream.
pCComThread -> UnMarshallInterfaces();
dwRet = (pCComThread -> m_lpStartAddress)(/*pCComThread -> m_lpParam*/ pCComThread);
// Once user thread has completed, we clear the Stream and IUnknown vectors.
pCComThread -> ClearVectorStream();
pCComThread -> ClearVectorUnknown();
CoUninitialize();
return dwRet;
}
protected :
HANDLE m_hThread;
LPTHREAD_START_ROUTINE m_lpStartAddress;
void* m_lpParam;
Flags m_Flags;
DWORD m_dwThreadId;
CRITICAL_SECTION m_csStreamVectorAccess;
ISTREAM_VECTOR m_vectorStream;
IUNKNOWN_VECTOR m_vectorUnknown;
};
DWORD ThreadMsgWaitForSingleObject (HANDLE hHandle, DWORD dwMilliseconds);
#endif // __CCOMTHREAD_H_
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
Lim Bio Liong is a Specialist at a leading Software House in Singapore.
Bio has been in software development for over 10 years. He specialises in C/C++ programming and Windows software development.
Bio has also done device-driver development and enjoys low-level programming. Bio has recently picked up C# programming and has been researching in this area.