/* * LOALLOC.C * * Setup, cleanup, and MAPI memory allocation for the low-level * MAPI utility library. */ #include "_apipch.h" #define LOALLOC_C #ifdef MAC #define PvGetInstanceGlobalsEx(_x) PvGetInstanceGlobalsMac(kInstMAPIU) #define ScSetInstanceGlobalsEx(_pinst, _x) ScSetInstanceGlobalsMac(_pinst, kInstMAPIU) //STDAPI HrCreateGuidNoNet(GUID FAR *pguid); #endif #ifndef STATIC #ifdef DEBUG #define STATIC #else #define STATIC static #endif #endif #ifdef OLD_STUFF #pragma SEGMENT(MAPI_Util) #endif // OLD_STUFF #if defined(WIN32) && !defined(MAC) const CHAR szMutexName[] = "MAPI_UIDGEN_MUTEX"; //STDAPI HrCreateGuidNoNet(GUID FAR *pguid); #endif typedef SCODE (GENMUIDFN)(MAPIUID *lpMuid); #if defined (WIN32) && !defined (MAC) extern CRITICAL_SECTION csMapiInit; #endif #ifndef MAC DefineInstList(lpInstUtil); #endif STDAPI_(SCODE) ScInitMapiUtil(ULONG ulFlags) { LPINSTUTIL pinst; SCODE sc = S_OK; HLH hlh; #ifdef WIN16 WORD wSS; HTASK hTask = GetCurrentTask(); _asm mov wSS, ss #endif // Cheesy parameter validation AssertSz(ulFlags == 0L, TEXT("ScInitMapiUtil: reserved flags used")); pinst = (LPINSTUTIL) PvGetInstanceGlobalsEx(lpInstUtil); #ifdef WIN16 { // Verify that the instance structure is valid because on Win16 the // stack segment could have been re-used by another task. When this // happens there is a good chance that PvGetInstanceGlobalsEx will // return a pinst belongs to the previous task. The memory for that // pinst may not be valid any more (because the system automatically // deallocates global memory when the task dies), or it may have been // allocated by some other task (in which case it is valid but isn't // a pinst anymore). Here we try our best to determine that the pinst // is indeed the one we were looking for. if ( pinst && ( IsBadWritePtr(pinst, sizeof(INSTUTIL)) || pinst->dwBeg != INSTUTIL_SIG_BEG || pinst->wSS != wSS || pinst->hTask != hTask || pinst->pvBeg != pinst || pinst->dwEnd != INSTUTIL_SIG_END)) { TraceSz("MAPI: ScInitMapiUtil: Rejecting orphaned instance globals"); (void) ScSetInstanceGlobalsEx(0, lpInstUtil); pinst = 0; } } #endif if (pinst) { if (pinst->cRef == 0) { Assert(pinst->cRefIdle == 0); Assert(pinst->hlhClient); } ++(pinst->cRef); return S_OK; } #if defined (WIN32) && !defined (MAC) EnterCriticalSection(&csMapiInit); #endif // Create local heap for MAPIAllocateBuffer to play in hlh = LH_Open(0); if (hlh == 0) { sc = MAPI_E_NOT_ENOUGH_MEMORY; goto ret; } LH_SetHeapName(hlh, TEXT("Client MAPIAllocator")); pinst = (LPINSTUTIL) LH_Alloc(hlh, sizeof(INSTUTIL)); if (!pinst) { LH_Close(hlh); sc = MAPI_E_NOT_ENOUGH_MEMORY; goto ret; } ZeroMemory((LPBYTE) pinst, sizeof(INSTUTIL)); #ifdef WIN16 pinst->dwBeg = INSTUTIL_SIG_BEG; pinst->wSS = wSS; pinst->hTask = hTask; pinst->pvBeg = pinst; pinst->dwEnd = INSTUTIL_SIG_END; #endif // Install the instance data sc = ScSetInstanceGlobalsEx(pinst, lpInstUtil); if (sc) { LH_Close(hlh); goto ret; } pinst->cRef = 1; pinst->hlhClient = hlh; ret: #if defined (WIN32) && !defined (MAC) LeaveCriticalSection(&csMapiInit); #endif DebugTraceSc(ScInitMapiUtil, sc); return sc; } STDAPI_(void) DeinitMapiUtil() { LPINSTUTIL pinst; pinst = (LPINSTUTIL) PvGetInstanceGlobalsEx(lpInstUtil); if (!pinst) return; Assert(pinst->cRef); if (--(pinst->cRef) == 0) { #if defined (WIN32) && !defined (MAC) EnterCriticalSection(&csMapiInit); #endif // Idle stuff must already have been cleaned up Assert(pinst->cRefIdle == 0); /* * !!! DO NOT CLOSE THE HEAP OR GET RID OF THE INST !!! * * Simple MAPI counts on being able to access and free buffers * right up until the DLL is unloaded from memory. Therefore we do * not explicitly close the heap; we count on the OS to make it * evaporate when the process exits. * Likewise, MAPIFreeBuffer needs the INSTUTIL to find the heap handle, * so we never deinstall the INSTUTIL. * * // Uninstall the globals. * (void) ScSetInstanceGlobalsEx(NULL, lpInstUtil); * * // Clean up the heap * hlh = pinst->hlhClient; * LH_Free(hlh, pinst); * * LH_Close(hlh); */ #if defined (WIN32) && !defined (MAC) LeaveCriticalSection(&csMapiInit); #endif } } HLH HlhUtilities(VOID) { LPINSTUTIL pinst = (LPINSTUTIL) PvGetInstanceGlobalsEx(lpInstUtil); return pinst ? pinst->hlhClient : (HLH) 0; } #ifdef NOTIFICATIONS #ifdef TABLES #if defined(WIN16) STDAPI_(SCODE) ScGenerateMuid (LPMAPIUID lpMuid) { return GetScode(CoCreateGuid((LPGUID)lpMuid)); } #endif // WIN16 #if (defined(WIN32) && !defined(MAC)) STDAPI_(SCODE) ScGenerateMuid (LPMAPIUID lpMuid) { HRESULT hr; // validate parameter AssertSz( !IsBadReadPtr( lpMuid, sizeof( MAPIUID ) ), "lpMuid fails address check" ); #ifdef OLD_STUFF // WAB won't use this... why bother bringing in RPC when we are local anyway? if (hMuidMutex == NULL) { RPC_STATUS rpc_s; rpc_s = UuidCreate((UUID __RPC_FAR *) lpMuid); if (rpc_s == RPC_S_OK) { hr = hrSuccess; goto err; } else { hMuidMutex = CreateMutex(NULL, FALSE, szMutexName); if (hMuidMutex == NULL) { TraceSz1("MAPIU: ScGenerateMuid: call to CreateMutex failed" " - error %08lX\n", GetLastError()); hr = ResultFromScode(MAPI_E_CALL_FAILED); goto err; } } } WaitForSingleObject(hMuidMutex, INFINITE); hr = HrCreateGuidNoNet((GUID FAR *) lpMuid); ReleaseMutex(hMuidMutex); #endif // OLD_STUFF //$ Note that we don't call CloseHandle on the mutex anywhere. If we're //$ really worried about this, we could call CloseHandle in the code that //$ WIN32 calls when the DLL is being unloaded. hr = CoCreateGuid((GUID *)lpMuid); err: DebugTraceResult(ScGenerateMuid, hr); return GetScode(hr); } #endif /* WIN32 - Mac*/ #ifdef MAC STDAPI_(SCODE) ScGenerateMuid (LPMAPIUID lpMuid) { HRESULT hr; // hr = HrCreateGuidNoNet((GUID FAR *) lpMuid); DebugTraceResult(ScGenerateMuid, hr); return GetScode(hr); } #endif // MAC #endif //#ifdef TABLES #endif //#ifdef NOTIFICATIONS