/*++ Copyright (c) 1990-1995 Microsoft Corporation Module Name: handle.c Abstract: This module contains all function which deal with handle table for the common UI Author: 30-Jan-1996 Tue 16:28:56 created -by- Daniel Chou (danielc) [Environment:] NT Windows - Common Printer Driver UI DLL [Notes:] Revision History: --*/ #include "precomp.h" #pragma hdrstop #define DBG_CPSUIFILENAME DbgHandle #define DBG_CPSUI_HTABLE 0x00000001 #define DBG_FINDHANDLE 0x00000002 #define DBG_ADD_DATA 0x00000004 #define DBG_HANDLE_DESTROY 0x00000008 #define DBG_GET_HPSPINFO 0x00000010 #define DBG_SEM 0x00000020 DEFINE_DBGVAR(0); HANDLE hCPSUIMutex = NULL; CPSUIHANDLETABLE CPSUIHandleTable = { NULL, 0, 0, 0, 0 }; extern DWORD TlsIndex; BOOL LOCK_CPSUI_HANDLETABLE( VOID ) /*++ Routine Description: This function get the lock the object Arguments: VOID Return Value: BOOL Author: 27-Mar-1996 Wed 11:27:26 created -by- Daniel Chou (danielc) Revision History: --*/ { BOOL Ok = FALSE; if (hCPSUIMutex) { WORD Idx; switch (WaitForSingleObject(hCPSUIMutex, MAX_SEM_WAIT)) { case WAIT_OBJECT_0: // // Signaled, and own it now // if (!CPSUIHandleTable.cWait++) { CPSUIHandleTable.ThreadID = GetCurrentThreadId(); } Idx = TLSVALUE_2_IDX(TlsGetValue(TlsIndex)); TlsSetValue(TlsIndex, ULongToPtr(MK_TLSVALUE(CPSUIHandleTable.cWait, Idx))); CPSUIDBG(DBG_SEM, ("LOCK_CPSUI_HANDLETABLE: ThreadID=%ld, cWait=%ld", GetCurrentThreadId(), CPSUIHandleTable.cWait)); Ok = TRUE; break; case WAIT_ABANDONED: CPSUIERR(("LockCPSUIObject()= WAIT_ABANDONED")); break; case WAIT_TIMEOUT: CPSUIERR(("LockCPSUIObject()= WAIT_TIMEOUT")); break; default: CPSUIERR(("LockCPSUIObject()= UNKNOWN")); break; } } return(Ok); } BOOL UNLOCK_CPSUI_HANDLETABLE( VOID ) /*++ Routine Description: Arguments: Return Value: Author: 27-Mar-1996 Wed 11:39:37 created -by- Daniel Chou (danielc) Revision History: --*/ { BOOL Ok = FALSE; if (hCPSUIMutex) { DWORD ThreadID = GetCurrentThreadId(); WORD Idx; CPSUIDBG(DBG_SEM, ("UNLOCK_CPSUI_HANDLETABLE: ThreadID=%ld, cWait=%ld", ThreadID, CPSUIHandleTable.cWait)); if (ThreadID == CPSUIHandleTable.ThreadID) { if (CPSUIHandleTable.cWait) { if (--CPSUIHandleTable.cWait == 0) { CPSUIHandleTable.ThreadID = NO_THREADID; } Idx = TLSVALUE_2_IDX(TlsGetValue(TlsIndex)); TlsSetValue(TlsIndex, ULongToPtr(MK_TLSVALUE(CPSUIHandleTable.cWait, Idx))); ReleaseMutex(hCPSUIMutex); Ok = TRUE; } else { CPSUIERR(("The Thread ID does not match=%ld", CPSUIHandleTable.ThreadID)); } } else { CPSUIERR(("The ThreadID=%ld does not own the mutex", ThreadID)); } } return(Ok); } PCPSUIPAGE HANDLETABLE_GetCPSUIPage( HANDLE hTable ) /*++ Routine Description: This function take a handle table and return the pData assoicated with it, the pData must already added by HANDLETABLE_AddCPSUIPage() Arguments: Return Value: pCPSUIPage, NULL if FAILED Author: 28-Dec-1995 Thu 17:05:11 created -by- Daniel Chou (danielc) Revision History: --*/ { PDATATABLE pDataTable; PCPSUIPAGE pFoundPage = NULL; PCPSUIPAGE pCPSUIPage; WORD Idx; LOCK_CPSUI_HANDLETABLE(); if ((hTable) && (pDataTable = CPSUIHandleTable.pDataTable) && (HANDLE_2_PREFIX(hTable) == HANDLE_TABLE_PREFIX) && ((Idx = HANDLE_2_IDX(hTable)) < CPSUIHandleTable.MaxCount) && (pCPSUIPage = pDataTable[Idx].pCPSUIPage)) { if (pCPSUIPage->ID != CPSUIPAGE_ID) { CPSUIERR(("HANDLETABLE_FindpCPSUIPage(%08lx), pCPSUIPage=%08lx INVALID Internal ID", hTable, pCPSUIPage)); } else if (pCPSUIPage->hCPSUIPage != hTable) { CPSUIERR(("HANDLETABLE_FIndpCPSUIPage(%08lx), pCPSUIPagePage=%08lx, HANDLE not matched", hTable, pCPSUIPage)); } else { pCPSUIPage->cLock++; pFoundPage = pCPSUIPage; } } UNLOCK_CPSUI_HANDLETABLE(); return(pFoundPage); } DWORD HANDLETABLE_LockCPSUIPage( PCPSUIPAGE pCPSUIPage ) /*++ Routine Description: This function decrement the cLock for the Page currently in USE Arguments: pCPSUIPage - Pointer to the CPSUIPAGE Return Value: BOOL, true if decrment successfully Author: 05-Apr-1996 Fri 16:41:46 created -by- Daniel Chou (danielc) Revision History: --*/ { DWORD cLock = 0; if (pCPSUIPage) { LOCK_CPSUI_HANDLETABLE(); cLock = ++(pCPSUIPage->cLock); UNLOCK_CPSUI_HANDLETABLE(); } return(cLock); } BOOL HANDLETABLE_UnGetCPSUIPage( PCPSUIPAGE pCPSUIPage ) /*++ Routine Description: This function decrement the cLock for the Page currently in USE Arguments: pCPSUIPage - Pointer to the CPSUIPAGE Return Value: BOOL, true if decrment successfully Author: 05-Apr-1996 Fri 16:41:46 created -by- Daniel Chou (danielc) Revision History: --*/ { BOOL Ok; if (pCPSUIPage) { LOCK_CPSUI_HANDLETABLE(); if (Ok = (BOOL)pCPSUIPage->cLock) { --(pCPSUIPage->cLock); } else { CPSUIERR(("HANDLETABLE_UnlockpCPSUIPage(%08lx), cLock is ZERO", pCPSUIPage)); } UNLOCK_CPSUI_HANDLETABLE(); } else { Ok = FALSE; } return(Ok); } BOOL HANDLETABLE_IsChildPage( PCPSUIPAGE pChildPage, PCPSUIPAGE pParentPage ) /*++ Routine Description: This function check if pChildPage is one of the pParentPage's child or its decedent child Arguments: pChildPage - Pointer to the CPSUIPAGE for child pParentPage - Pointer to the CPSUIPAGE for parent to be checked Return Value: TRUE, if this is child, otherwise FALSE Author: 08-Apr-1996 Mon 12:52:51 created -by- Daniel Chou (danielc) Revision History: --*/ { BOOL Ok = FALSE; LOCK_CPSUI_HANDLETABLE(); if (pChildPage) { while (pChildPage->pParent) { if (pChildPage->pParent == pParentPage) { Ok = TRUE; break; } else { pChildPage = pChildPage->pParent; } } } UNLOCK_CPSUI_HANDLETABLE(); return(Ok); } PCPSUIPAGE HANDLETABLE_GetRootPage( PCPSUIPAGE pCPSUIPage ) /*++ Routine Description: This function find the root page for pCPSUIPage Arguments: pCPSUIPage - Pointer to the CPSUIPAGE who's root page to be searched Return Value: PCPSUIPAGE - Pointer to root page, NULL if failed Author: 08-Apr-1996 Mon 12:49:42 created -by- Daniel Chou (danielc) Revision History: --*/ { PCPSUIPAGE pPage; PCPSUIPAGE pRootPage = NULL; LOCK_CPSUI_HANDLETABLE(); pPage = pCPSUIPage; // // If we need to search for the root page, then try it now // while ((pPage) && (pPage->pParent)) { pPage = pPage->pParent; } if ((pPage) && (pPage->Flags & CPF_ROOT)) { pPage->cLock++; pRootPage = pPage; } else { CPSUIERR(("HANDLETABLE_FindpRootPage(%08lx): No ROOT Page found", pCPSUIPage)); } UNLOCK_CPSUI_HANDLETABLE(); return(pRootPage); } HANDLE HANDLETABLE_AddCPSUIPage( PCPSUIPAGE pCPSUIPage ) /*++ Routine Description: This function add pData to the handle table, if new Arguments: pCPSUIPage - Pointer to the CPSUIPAGE to be add to the handle table Return Value: HANDLE, if NULL then it failed, the handle already exists Author: 28-Dec-1995 Thu 16:03:25 created -by- Daniel Chou (danielc) Revision History: --*/ { HANDLE hTable; PDATATABLE pDataTable; LOCK_CPSUI_HANDLETABLE(); if ((!CPSUIHandleTable.pDataTable) || (CPSUIHandleTable.CurCount >= CPSUIHandleTable.MaxCount)) { if (!CPSUIHandleTable.pDataTable) { CPSUIHandleTable.CurCount = CPSUIHandleTable.MaxCount = 0; } CPSUIDBG(DBG_ADD_DATA, ("HANDLETABLE_AddCPSUIPage(%08lx): Table reach LIMIT, Expanded=%ld->%ld", CPSUIHandleTable.pDataTable, CPSUIHandleTable.CurCount, CPSUIHandleTable.CurCount + DATATABLE_BLK_COUNT)); // // Reallocate Table // if ((CPSUIHandleTable.MaxCount <= DATATABLE_MAX_COUNT) && (pDataTable = LocalAlloc(LPTR, (CPSUIHandleTable.MaxCount + DATATABLE_BLK_COUNT) * sizeof(DATATABLE)))) { if (CPSUIHandleTable.pDataTable) { CopyMemory(pDataTable, CPSUIHandleTable.pDataTable, CPSUIHandleTable.MaxCount * sizeof(DATATABLE)); LocalFree((HLOCAL)CPSUIHandleTable.pDataTable); } CPSUIHandleTable.pDataTable = pDataTable; CPSUIHandleTable.MaxCount += DATATABLE_BLK_COUNT; } else { CPSUIERR(("HANDLETABLE_AddCPSUIPage(): Expand TABLE failed")); } } hTable = NULL; if (pDataTable = CPSUIHandleTable.pDataTable) { WORD Idx; for (Idx = 0; Idx < CPSUIHandleTable.MaxCount; Idx++, pDataTable++) { if (!pDataTable->pCPSUIPage) { hTable = WORD_2_HANDLE(Idx); pDataTable->pCPSUIPage = pCPSUIPage; pCPSUIPage->cLock = 1; CPSUIHandleTable.CurCount++; CPSUIDBG(DBG_ADD_DATA, ("HANDLETABLE_AddCPSUIPage(%08lx): Idx=%ld, Cur=%ld, Max=%ld", pCPSUIPage, Idx, CPSUIHandleTable.CurCount, CPSUIHandleTable.MaxCount)); break; } else if (pDataTable->pCPSUIPage == pCPSUIPage) { CPSUIERR(("HANDLETABLE_AddCPSUIPage(%08lx): pCPSUIPage exists, Idx=%ld", pCPSUIPage, Idx)); } } } if (!hTable) { CPSUIERR(("HANDLETABLE_AddCPSUIPage(%08lx:%ld) Cannot find empty entry", CPSUIHandleTable.pDataTable, CPSUIHandleTable.MaxCount)); } UNLOCK_CPSUI_HANDLETABLE(); return(hTable); } BOOL HANDLETABLE_DeleteHandle( HANDLE hTable ) /*++ Routine Description: This function delete a handle from the handle table Arguments: hTable - Handle to the handle table to be deleted Return Value: BOOL Author: 28-Dec-1995 Thu 17:42:42 created -by- Daniel Chou (danielc) Revision History: --*/ { PDATATABLE pDataTable; PCPSUIPAGE pCPSUIPage; WORD Idx; BOOL Ok = FALSE; LOCK_CPSUI_HANDLETABLE(); if ((pDataTable = CPSUIHandleTable.pDataTable) && (HANDLE_2_PREFIX(hTable) == HANDLE_TABLE_PREFIX) && (CPSUIHandleTable.CurCount) && ((Idx = HANDLE_2_IDX(hTable)) < CPSUIHandleTable.MaxCount) && (pCPSUIPage = (pDataTable += Idx)->pCPSUIPage)) { if (pCPSUIPage->cLock) { CPSUIERR(("HANDLETABLE_DeleteHandle(%08lx), pCPSUIPage=%08lx, cLock=%ld", hTable, pCPSUIPage, pCPSUIPage->cLock)); } else { // check to release the activation context (if any) if (pCPSUIPage->hActCtx && pCPSUIPage->hActCtx != INVALID_HANDLE_VALUE) { ReleaseActCtx(pCPSUIPage->hActCtx); pCPSUIPage->hActCtx = INVALID_HANDLE_VALUE; } pDataTable->pCPSUIPage = NULL; Ok = TRUE; // // Reduce current count and free the memory // CPSUIHandleTable.CurCount--; LocalFree((HLOCAL)pCPSUIPage); } } else { CPSUIERR(("HANDLETABLE_DeleteHandle(%08lx) not found, Idx=%ld, pDataTable=%08lx", hTable, Idx, pDataTable)); } UNLOCK_CPSUI_HANDLETABLE(); return(Ok); } BOOL HANDLETABLE_Create( VOID ) /*++ Routine Description: Arguments: Return Value: Author: 28-Dec-1995 Thu 16:46:27 created -by- Daniel Chou (danielc) Revision History: --*/ { CPSUIHandleTable.pDataTable = NULL; CPSUIHandleTable.MaxCount = CPSUIHandleTable.CurCount = 0; CPSUIHandleTable.ThreadID = NO_THREADID; CPSUIHandleTable.cWait = 0; if (hCPSUIMutex = CreateMutex(NULL, FALSE, NULL)) { CPSUIDBG(DBG_CPSUI_HTABLE, ("CREATE: CreateMutex=%08lx", hCPSUIMutex)); return(TRUE); } else { CPSUIERR(("CreateMutex() FAILED, Exit")); return(FALSE); } } VOID HANDLETABLE_Destroy( VOID ) /*++ Routine Description: Arguments: Return Value: Author: 28-Dec-1995 Thu 16:48:32 created -by- Daniel Chou (danielc) Revision History: --*/ { PDATATABLE pDataTable; WORD Idx; LOCK_CPSUI_HANDLETABLE(); if (hCPSUIMutex) { if (pDataTable = CPSUIHandleTable.pDataTable) { for (Idx = 0; Idx < CPSUIHandleTable.MaxCount; Idx++, pDataTable++) { if (pDataTable->pCPSUIPage) { CPSUIERR(("HANDLETABLE_Destroy: Idx=%ld, pPage=%08lx, cLock=%ld is not delete yet", Idx, pDataTable->pCPSUIPage, pDataTable->pCPSUIPage->cLock)); LocalFree((HLOCAL)pDataTable->pCPSUIPage); pDataTable->pCPSUIPage = NULL; if (CPSUIHandleTable.CurCount) { --(CPSUIHandleTable.CurCount); } else { CPSUIERR(("HANDLETABLE_Destroy(): Unmatched CurCount")); } } } LocalFree((HLOCAL)CPSUIHandleTable.pDataTable); CPSUIHandleTable.pDataTable = NULL; CPSUIHandleTable.MaxCount = CPSUIHandleTable.CurCount = 0; } } UNLOCK_CPSUI_HANDLETABLE(); CloseHandle(hCPSUIMutex); }