//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1993. // // File: ETASK.CXX (16 bit target) // // Contents: ETask management code, taken from 16-bit COMPOBJ.CPP // // Functions: // // History: 08-Mar-94 BobDay Copied parts from \\ole\slm\...\compobj.cpp // 01-Feb-95 JohannP modified/simplified // //-------------------------------------------------------------------------- #include #pragma hdrstop #include #include #include #include "comlocal.hxx" #include "map_htsk.h" #include "etask.hxx" #include "call32.hxx" #include "apilist.hxx" // NOTE: NEAR forces this variable to be in the default data segment; without // NEAR, the ambient model of the class CMapHandleEtask, which is FAR, // causes the variable to be in a far_data segment. // // For WIN32/NT this table is in instance data, the table contains exactly one // entry // HTASK v_hTaskCache = NULL; Etask NEAR v_etaskCache; // quick check that the etask is valid (e.g., pointers are valid) INTERNAL_(BOOL) IsValidEtask(HTASK hTask, Etask FAR& etask) { Win(Assert(GetCurrentProcess() == hTask)); thkDebugOut((DEB_DLLS16, "IsValidEtask (%X) pMalloc(%p)\n", hTask, etask.m_pMalloc)); #ifdef _CHICAGO_ if ( etask.m_pMalloc != NULL && !IsValidInterface(etask.m_pMalloc)) #else if (!IsValidInterface(etask.m_pMalloc)) #endif { thkDebugOut((DEB_DLLS16, "IsValidEtask (%X) FALSE\n", hTask)); return FALSE; } // FUTURE: verify that stack segment is the same // FUTURE: verify that hInst/hMod are the same thkDebugOut((DEB_DLLS16, "IsValidEtask (%X) TRUE\n", hTask)); return TRUE; } // if task map empty, clear globals in case lib doesn't get unloaded INTERNAL_(void) CheckIfMapEmpty(void) { // if no more entries, clear v_pMallocShared; this ensures we clear the // variable if the app holds onto this pointer erroneously. if (v_mapToEtask.IsEmpty()) { v_pMallocShared = NULL; } } //+--------------------------------------------------------------------------- // // Method: LookupEtask // // Synopsis: get etask for current task (and also return hTask); // does not create if none // // Arguments: [hTask] -- // [etask] -- // // Returns: // // History: Ole16 created for CompObj 16 bit for Ole2 // 2-03-95 JohannP (Johann Posch) modified/simplified // // Notes: // //---------------------------------------------------------------------------- STDAPI_(BOOL) LookupEtask(HTASK FAR& hTask, Etask FAR& etask) { hTask = GetCurrentProcess(); thkDebugOut((DEB_DLLS16, "LookupEtask on Process (%X) \n", hTask)); if (hTask == v_hTaskCache) { thkDebugOut((DEB_DLLS16, "LookupEtask found in cache (%X) \n", hTask)); etask = v_etaskCache; goto CheckEtask; } if (!v_mapToEtask.Lookup(hTask, etask)) { thkDebugOut((DEB_DLLS16, "LookupEtask faild on lookup (%X) \n", hTask)); return FALSE; } else { thkDebugOut((DEB_DLLS16, "LookupEtask found in lookup (%X) \n", hTask)); } // found etask; make this the current cache v_hTaskCache = hTask; v_etaskCache = etask; CheckEtask: if (IsValidEtask(hTask, etask)) { return TRUE; } else { // task got reused; kill cache and entry in map v_hTaskCache = NULL; v_mapToEtask.RemoveKey(hTask); CheckIfMapEmpty(); thkAssert(0 && "LookupEtask - failed (invalid Etask)"); return FALSE; } } //+--------------------------------------------------------------------------- // // Method: SetEtask // // Synopsis: set etask for task given (must be current task); return FALSE // if OOM (only first time; all other times should return TRUE). // // Arguments: [hTask] -- // [etask] -- // // Returns: // // History: Ole16 created for CompObj 16 bit for Ole2 // 02-03-95 JohannP (Johann Posch) modified/simplified // // Notes: // //---------------------------------------------------------------------------- STDAPI_(BOOL) SetEtask(HTASK hTask, Etask FAR& etask) { Win(Assert(GetCurrentProcess() == hTask)); if (!v_mapToEtask.SetAt(hTask, etask)) return FALSE; Assert(IsValidEtask(hTask, etask)); // map set; make this the current cache v_hTaskCache = hTask; v_etaskCache = etask; return TRUE; } //+--------------------------------------------------------------------------- // // Method: ReleaseEtask // // Synopsis: release all fields in the etask; do all the task memory // (except the task allocator) first; then all the shared // memory (except the shared allocator); then the shared // allocator and finally the task allocator. // Also removes key if htask is given. // // Arguments: [htask] -- // [etask] -- // // Returns: // // History: Ole16 created for CompObj 16 bit for Ole2 // 2-03-95 JohannP (Johann Posch) modified/simplified // // Notes: Called by daytona and chicago. // //---------------------------------------------------------------------------- void ReleaseEtask(HTASK htask, Etask FAR& etask) { thkDebugOut((DEB_DLLS16, "ReleaseEtask on Process (%X) \n", htask)); Assert(etask.m_inits == 1); Assert(etask.m_oleinits == 0); Assert(etask.m_reserved == 0); // Release any state that may have been set if (etask.m_punkState != NULL && IsValidInterface(etask.m_punkState)) { etask.m_punkState->Release(); #ifdef _CHICAGO_ if (!LookupEtask(htask, etask)) return; #endif } // first delete all task memory items delete etask.m_pDlls; // task memory delete etask.m_pMapToServerCO; // task memory delete etask.m_pMapToHandlerCO; // task memory delete etask.m_pArraySH; // task memory Assert(etask.m_pCThrd == NULL); // task memory; must be gone by now // remove key now that all task memory that will be freed is freed #ifdef _CHICAGO_ // Note: just null this out // Key is removed later in RemoveEtask called etask.m_pDlls = 0; etask.m_pMapToServerCO = 0; etask.m_pMapToHandlerCO = 0; etask.m_pArraySH = 0; etask.m_pCThrd = 0; #else if (htask != NULL) { v_mapToEtask.RemoveKey(htask); } // if no more entries, remove last remaining memory; this prevents // problems if the dll is not unloaded for some reason before being // used again. if (v_mapToEtask.IsEmpty()) v_mapToEtask.RemoveAll(); #endif // now remove all shared memory (doesn't need access to task pMalloc) #ifdef NOTYET if (etask.m_pMallocSBlock != NULL) etask.m_pMallocSBlock->Release(); // in shared memory if (etask.m_pMallocPrivate != NULL) etask.m_pMallocPrivate->Release(); // in shared memory #endif #ifndef _CHICAGO_ Assert(etask.m_pMallocShared != NULL); if (etask.m_pMallocShared->Release() == 0) { // in shared memory // last use of the shared allocator; set global to null v_pMallocShared = NULL; Assert(v_mapToEtask.IsEmpty()); } CheckIfMapEmpty(); #endif // finally, release the task memory Assert(etask.m_pMalloc != NULL); etask.m_pMalloc->Release(); // in task memory etask.m_pMalloc = NULL; thkDebugOut((DEB_DLLS16, "ReleaseEtask (%X) pMalloc(%p)\n", htask, etask.m_pMalloc)); #if defined(_CHICAGO_) // Note: update the etask now. Will be deleted on // DllEntryPoint when refcount is zero by Remove Etask. SetEtask(htask,etask); #endif // invalidate cache v_hTaskCache = NULL; thkDebugOut((DEB_DLLS16, "ReleaseEtask done on (%X) \n", htask)); } //+--------------------------------------------------------------------------- // // Function: RemoveEtask // // Synopsis: Releases the shares allocator and removes // the etask from the global list // // Arguments: [hTask] -- htask // [etask] -- etask // // Returns: // // History: 2-03-95 JohannP (Johann Posch) Created // // Notes: Called only by Chicago. // //---------------------------------------------------------------------------- STDAPI_(BOOL) RemoveEtask(HTASK FAR& hTask, Etask FAR& etask) { hTask = GetCurrentProcess(); thkDebugOut((DEB_DLLS16, "RemoveEtask on Process (%X) \n", hTask)); if (hTask == v_hTaskCache) { v_hTaskCache = NULL; } v_mapToEtask.RemoveKey(hTask); if (v_mapToEtask.IsEmpty()) v_mapToEtask.RemoveAll(); thkAssert(etask.m_pMallocShared != NULL); if(etask.m_pMallocShared->Release() == 0) { // in shared memory // last use of the shared allocator; set global to null v_pMallocShared = NULL; thkDebugOut((DEB_DLLS16, "RemoveEtask Set v_pMallocShared to NULL (%X) \n", hTask)); Assert(v_mapToEtask.IsEmpty()); } CheckIfMapEmpty(); thkDebugOut((DEB_DLLS16, "RemoveEtask done (%X) \n", hTask)); return TRUE; }