This is a possibility but I haven't created any connections to this but the local lock to prevent it from leaving since it was started manually.
I find it weird that this only happens on NT 4.0 machines (all with SP6) and not on any W2000 machines. I should be able to break it down to the simplest possible by the time I leave tonight (I have class for most of the day)
On start up of the COM server I lock it using the code in cbInterface. This is the only code (along with the init code below) that has executed at the time of exit as I haven't launched the client yet.
I deleted the headers and haven't tried this code yet but otherwise this is the code that is running at the time of the problem.
#define MAX_THREADS 30
/// Structure for flagging a section as critical for this process
CRITICAL_SECTION cs;
int exitThreads = 0;
int hThrdPool = 0;
char exitThread = 0;
int hMonSelect = 0;
CAServerObjHandle hGlobeObj = 0;
int __stdcall WinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
int runServer = 0;
char errBuf [500] = {0};
if (InitCVIRTE (hInstance, 0, 0) == 0)
return -1; // Out of memory
// ActiveX server initialization
if (FAILED (CaSrvrBenchInterfaceInit (
hInstance, lpszCmdLine, &runServer,
errBuf, sizeof(errBuf))))
return -1; // Server initialization error.
if (runServer){
InitializeCriticalSection( &cs );
hFocusSt = LoadPanel (0, "Mirror.uir", PNL_FOC);
hAzElSt = LoadPanel (0, "Mirror.uir", PNL_AZEL);
hSrcSlctSt = LoadPanel (0, "Mirror.uir", PNL_SRC);
hTargetWhl = LoadPanel (0, "TgtFltr.uir", PNL_TGT);
hIRSrc = LoadPanel (0, "IRVisSrc.uir", PNL_IR);
hVisSrc = LoadPanel (0, "IRVisSrc.uir", PNL_VIS);
hChopper = LoadPanel (0, "ChopperGUI.uir", PNL_CHP);
hAzElDraw = LoadPanel (0, "MirrorMtn.uir", PNL_AEDRAW);
hAzElMtn = LoadPanel (0, "MirrorMtn.uir", PNL_AEMTN);
hMonSelect = LoadPanel (0, "CtlSelect.uir", PNL_MON);
hVac = LoadPanel (0, "Vac.uir", PNL_VAC);
CmtNewThreadPool (MAX_THREADS, &hThrdPool);
DisplayPanel(hMonSelect);
RunUserInterface (); // Process messages
// Flag the threads to exit and let them do it
exitThreads = 1;
ProcessSystemEvents ();
ProcessSystemEvents ();
// We need to monitor this and check how long it is taking
CmtGetThreadPoolAttribute (hThrdPool, ATTR_TP_NUM_ACTIVE_THREADS, &qtyRunning);
CmtDiscardThreadPool (hThrdPool);
DiscardPanel (hVac);
DiscardPanel (hAzElMtn);
DiscardPanel (hAzElDraw);
DiscardPanel (hChopper);
DiscardPanel (hVisSrc);
DiscardPanel (hIRSrc);
DiscardPanel (hTargetWhl);
DiscardPanel (hSrcSlctSt);
DiscardPanel (hAzElSt);
DiscardPanel (hFocusSt);
}
// ActiveX server cleanup
CaSrvrBenchInterfaceUninit (hInstance);
return 0;
}
/******************************************************************************/
/* ActiveX Server Callback Function */
/* */
/* Events: */
/* 1) CA_SERVER_EVENT_MODULE_EXIT */
/* */
/******************************************************************************/
int CVIFUNC cbServer (int event)
{
HRESULT retVal = S_OK;
return retVal;
}
/******************************************************************************/
/* ActiveX Object Callback Function(s) */
/* */
/* Events: */
/* 1) CA_SERVER_EVENT_OBJECT_CREATE */
/* 2) CA_SERVER_EVENT_OBJECT_DESTROY */
/* */
/******************************************************************************/
HRESULT CVIFUNC cbInterface (
CAServerObjHandle objHandle, const CLSID *pClsid,
int event, void *callbackData)
{
HRESULT retVal = S_OK;
if(event == CA_SERVER_EVENT_OBJECT_CREATE){
hGlobeObj = objHandle;
CA_ServerLockActiveObject (hGlobeObj);
ProcessSystemEvents ();
}
return retVal;
}