/*========================================================================== * * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved. * * File: Handles.cpp * Content: Handle manager * * History: * Date By Reason * ==== == ====== * 08/19/99 mjn Created * 03/23/00 mjn Revised to ensure 64-bit compliance * 03/24/00 mjn Added H_Enum * 07/09/00 rmt Added signature bytes * 08/05/00 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles. * 08/31/00 rmt Whistler Prefix Bug 171826 * ***************************************************************************/ #include "dnlobbyi.h" #define INC_SERIAL_COUNT(a) if (++((a)->dwSerial) == 0) ((a)->dwSerial)++ #define INDEX_MASK 0x000fffff #define SERIAL_MASK 0xfff00000 #define SERIAL_SHIFT 20 #define GET_INDEX(h) (h & INDEX_MASK) #define GET_SERIAL(h) ((h & SERIAL_MASK) >> SERIAL_SHIFT) #define MAKE_HANDLE(i,s) ((i & INDEX_MASK) | ((s << SERIAL_SHIFT) & SERIAL_MASK)) #define VERIFY_HANDLE(p,h) (((h & INDEX_MASK) < (p)->dwNumHandles) && ((p)->HandleArray[(h & INDEX_MASK)].dwSerial) && ((h & SERIAL_MASK) == ((p)->HandleArray[(h & INDEX_MASK)].dwSerial << SERIAL_SHIFT))) #undef DPF_MODNAME #define DPF_MODNAME "H_Grow" HRESULT H_Grow(HANDLESTRUCT *const phs, const DWORD dwIncSize) { HRESULT hResultCode = S_OK; DWORD dw; DPFX(DPFPREP, 9,"Parameters: phs [0x%p], dwIncSize [%ld]",phs,dwIncSize); if (dwIncSize == 0) { DPFERR("Must grow handles by at least 1"); return(E_INVALIDARG); } // Grab CS DNEnterCriticalSection(&phs->dncs); if (phs->HandleArray == NULL || phs->dwNumHandles == 0) { if ((phs->HandleArray = static_cast(DNMalloc((dwIncSize + phs->dwNumHandles) * sizeof(HANDLEELEMENT)))) == NULL) { DPFERR("Could not create handle array"); hResultCode = E_OUTOFMEMORY; goto EXIT_H_Grow; } } else { if ((phs->HandleArray = static_cast(DNRealloc(phs->HandleArray,(dwIncSize + phs->dwNumHandles) * sizeof(HANDLEELEMENT)))) == NULL) { DPFERR("Could not grow handle array"); hResultCode = E_OUTOFMEMORY; goto EXIT_H_Grow; } } // Update Handle Structure phs->dwFirstFreeHandle = phs->dwNumHandles; phs->dwLastFreeHandle = phs->dwNumHandles + dwIncSize - 1; phs->dwNumFreeHandles = dwIncSize; phs->dwNumHandles += dwIncSize; // Setup free Handle Elements for (dw = 0 ; dw < dwIncSize - 1 ; dw++) { phs->HandleArray[phs->dwFirstFreeHandle + dw].dwSerial = 0; phs->HandleArray[phs->dwFirstFreeHandle + dw].Entry.dwIndex = phs->dwFirstFreeHandle + dw + 1; } phs->HandleArray[phs->dwFirstFreeHandle + dw].dwSerial = 0; phs->HandleArray[phs->dwFirstFreeHandle + dw].Entry.pvData = NULL; EXIT_H_Grow: // Release CS DNLeaveCriticalSection(&phs->dncs); DPFX(DPFPREP, 9,"Returning: [0x%lx]",hResultCode); return(hResultCode); } #undef DPF_MODNAME #define DPF_MODNAME "H_Initialize" HRESULT H_Initialize(HANDLESTRUCT *const phs, const DWORD dwInitialNum) { HRESULT hResultCode = S_OK; DPFX(DPFPREP, 9,"Parameters: phs [0x%p], dwInitialNum [%ld]",phs,dwInitialNum); if (dwInitialNum == 0) { DPFERR("Must initialize handles with at least 1"); return(E_INVALIDARG); } if (!DNInitializeCriticalSection(&phs->dncs)) { DPFERR("DNInitializeCriticalSection() failed"); return(E_OUTOFMEMORY); } // Lock DNEnterCriticalSection(&phs->dncs); phs->dwSignature = DPLSIGNATURE_HANDLESTRUCT; phs->HandleArray = NULL; phs->dwNumHandles = 0; phs->dwNumFreeHandles = 0; phs->dwFirstFreeHandle = 0; phs->dwLastFreeHandle = 0; phs->dwSerial = 1; if ((hResultCode = H_Grow(phs,dwInitialNum)) != S_OK) { DPFERR("H_Grow() failed"); goto EXIT_H_Initialize; } EXIT_H_Initialize: // Unlock DNLeaveCriticalSection(&phs->dncs); DPFX(DPFPREP, 9,"Returning: [0x%lx]",hResultCode); return(hResultCode); } #undef DPF_MODNAME #define DPF_MODNAME "H_Terminate" void H_Terminate(HANDLESTRUCT *const phs) { DPFX(DPFPREP, 9,"Parameters: phs [0x%p]",phs); if (phs->HandleArray != NULL) DNFree(phs->HandleArray); phs->dwNumHandles = 0; phs->dwSignature = DPLSIGNATURE_HANDLESTRUCT_FREE; DNDeleteCriticalSection(&phs->dncs); DPFX(DPFPREP, 9,"Returning"); } #undef DPF_MODNAME #define DPF_MODNAME "H_Create" HRESULT H_Create(HANDLESTRUCT *const phs, void *const pvData, DWORD *const pHandle) { DWORD dwIndex; HRESULT hResultCode = S_OK; DPFX(DPFPREP, 9,"Parameters: phs [0x%p], pvData [0x%p], pHandle [0x%p]",phs,pvData,pHandle); if (pHandle == NULL) { DPFERR("Invalid handle pointer"); return(E_INVALIDARG); } // Lock DNEnterCriticalSection(&phs->dncs); // If there are no free handles, double the handle array if (phs->dwNumFreeHandles == 0) { if ((hResultCode = H_Grow(phs,phs->dwNumHandles)) != S_OK) // Double the size { DPFERR("H_Grow() failed"); goto EXIT_H_Create; } } // Update internal handle pointers dwIndex = phs->dwFirstFreeHandle; phs->dwFirstFreeHandle = phs->HandleArray[dwIndex].Entry.dwIndex; phs->dwNumFreeHandles--; do { // Update handle information INC_SERIAL_COUNT(phs); phs->HandleArray[dwIndex].dwSerial = phs->dwSerial; phs->HandleArray[dwIndex].Entry.pvData = pvData; // Create user's handle *pHandle = MAKE_HANDLE(dwIndex,phs->dwSerial); } while (*pHandle == 0); // Don't want 0 handle DPFX(DPFPREP, 9,"Returning: *pHandle = [0x%lx]",*pHandle); EXIT_H_Create: // Unlock DNLeaveCriticalSection(&phs->dncs); DPFX(DPFPREP, 9,"Returning: [0x%lx]",hResultCode); return(hResultCode); } #undef DPF_MODNAME #define DPF_MODNAME "H_Destroy" HRESULT H_Destroy(HANDLESTRUCT *const phs, const DWORD handle) { DWORD dwIndex; DWORD dwSerial; HRESULT hResultCode = S_OK; DPFX(DPFPREP, 9,"Parameters: phs [0x%p], handle [0x%lx]",phs,handle); // Lock DNEnterCriticalSection(&phs->dncs); // Ensure valid handle supplied if (!VERIFY_HANDLE(phs,handle)) { DPFERR("Invalid handle"); hResultCode = E_INVALIDARG; goto EXIT_H_Destroy; } dwIndex = GET_INDEX(handle); dwSerial = GET_SERIAL(handle); // Add handle to end of free list if (phs->dwNumFreeHandles == 0) // Only free handle { phs->dwFirstFreeHandle = phs->dwLastFreeHandle = dwIndex; } else // Other handles, so add to end of list { phs->HandleArray[phs->dwLastFreeHandle].Entry.dwIndex = dwIndex; phs->dwLastFreeHandle = dwIndex; } // Clear out returned handle phs->HandleArray[dwIndex].dwSerial = 0; phs->HandleArray[dwIndex].Entry.pvData = NULL; // Update handle structure INC_SERIAL_COUNT(phs); phs->dwNumFreeHandles++; EXIT_H_Destroy: // Unlock DNLeaveCriticalSection(&phs->dncs); DPFX(DPFPREP, 9,"Returning: [0x%lx]",hResultCode); return(hResultCode); } #undef DPF_MODNAME #define DPF_MODNAME "H_Retrieve" HRESULT H_Retrieve(HANDLESTRUCT *const phs, const DWORD handle, void **const ppvData) { DWORD dwIndex; DWORD dwSerial; HRESULT hResultCode = S_OK; DPFX(DPFPREP, 9,"Parameters: phs [0x%p], handle [0x%lx], ppvData [0x%p]",phs,handle,ppvData); // Lock DNEnterCriticalSection(&phs->dncs); // Ensure valid handle supplied if (!VERIFY_HANDLE(phs,handle)) { DPFERR("Invalid handle"); hResultCode = DPNERR_INVALIDHANDLE; goto EXIT_H_Retrieve; } if (ppvData == NULL) { DPFERR("Invalid data return pointer"); hResultCode = DPNERR_INVALIDHANDLE; goto EXIT_H_Retrieve; } dwIndex = GET_INDEX(handle); dwSerial = GET_SERIAL(handle); *ppvData = phs->HandleArray[GET_INDEX(handle)].Entry.pvData; DPFX(DPFPREP, 9,"Returning: *ppvData = [0x%p]",*ppvData); EXIT_H_Retrieve: // Unlock DNLeaveCriticalSection(&phs->dncs); DPFX(DPFPREP, 9,"Returning: [0x%lx]",hResultCode); return(hResultCode); } #undef DPF_MODNAME #define DPF_MODNAME "H_Enum" HRESULT H_Enum(HANDLESTRUCT *const phs, DWORD *const pdwNumHandles, DWORD *const rgHandles) { HRESULT hResultCode; DWORD dw; DWORD dwNumHandles; DWORD *pHandle; DPFX(DPFPREP, 3,"Parameters: phs [0x%p], pdwNumHandles [0x%p], rgHandles [0x%p]", phs,pdwNumHandles,rgHandles); DNASSERT(phs != NULL); DNASSERT(pdwNumHandles != NULL); DNASSERT(rgHandles != NULL || *pdwNumHandles == 0); hResultCode = S_OK; dwNumHandles = 0; DNEnterCriticalSection(&phs->dncs); for (dw = 0 ; dw < phs->dwNumHandles ; dw++) { if (phs->HandleArray[dw].dwSerial != NULL) { DPFX(DPFPREP, 5,"Found handle data at [%ld]",dw); dwNumHandles++; } } if (dwNumHandles) { if( rgHandles == NULL ) { DPFX(DPFPREP, 1, "Buffer too small!" ); *pdwNumHandles = dwNumHandles; DNLeaveCriticalSection(&phs->dncs); return E_POINTER; } if (dwNumHandles <= *pdwNumHandles) { pHandle = rgHandles; for (dw = 0 ; dw < phs->dwNumHandles ; dw++) { if (phs->HandleArray[dw].dwSerial != NULL) { *pHandle++ = MAKE_HANDLE(dw,phs->HandleArray[dw].dwSerial); } } } else { hResultCode = E_POINTER; } } *pdwNumHandles = dwNumHandles; DNLeaveCriticalSection(&phs->dncs); DPFX(DPFPREP, 3,"Returning: [0x%lx]",hResultCode); return(hResultCode); }