327 lines
8.5 KiB
C++
327 lines
8.5 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// 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 <headers.cxx>
|
|
#pragma hdrstop
|
|
|
|
#include <ole2sp.h>
|
|
|
|
#include <olecoll.h>
|
|
#include <map_kv.h>
|
|
|
|
#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;
|
|
}
|
|
|