|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
handle.c
Abstract:
This module contains the handle table mgmt routines.
Author:
Wesley Witt (wesw) 12-Nov-1996
Revision History:
--*/
#include "faxsvc.h"
#pragma hdrstop
LIST_ENTRY g_HandleTableListHead; CFaxCriticalSection g_CsHandleTable;
void FreeServiceContextHandles( void ) { PLIST_ENTRY Next; PHANDLE_ENTRY pHandleEntry;
Next = g_HandleTableListHead.Flink; while ((ULONG_PTR)Next != (ULONG_PTR)&g_HandleTableListHead) { pHandleEntry = CONTAINING_RECORD( Next, HANDLE_ENTRY, ListEntry ); Next = pHandleEntry->ListEntry.Flink; CloseFaxHandle (pHandleEntry); } return; }
static PHANDLE_ENTRY CreateNewHandle( handle_t hBinding, FaxHandleType Type, DWORD dwClientAPIVersion, // Used for connection handles
PLINE_INFO LineInfo, // Used for port handles
DWORD Flags // Used for port handles
) { PHANDLE_ENTRY pHandleEntry;
pHandleEntry = (PHANDLE_ENTRY) MemAlloc( sizeof(HANDLE_ENTRY) ); if (!pHandleEntry) { return NULL; } ZeroMemory (pHandleEntry, sizeof(HANDLE_ENTRY));
pHandleEntry->hBinding = hBinding; pHandleEntry->Type = Type; pHandleEntry->dwClientAPIVersion = dwClientAPIVersion; pHandleEntry->LineInfo = LineInfo; pHandleEntry->Flags = Flags; pHandleEntry->bReleased = FALSE; pHandleEntry->hFile = INVALID_HANDLE_VALUE;
EnterCriticalSection( &g_CsHandleTable ); InsertTailList( &g_HandleTableListHead, &pHandleEntry->ListEntry ); LeaveCriticalSection( &g_CsHandleTable ); return pHandleEntry; }
PHANDLE_ENTRY CreateNewConnectionHandle( handle_t hBinding, DWORD dwClientAPIVersion ) { return CreateNewHandle( hBinding, FHT_SERVICE, dwClientAPIVersion, NULL, // Unused
0 // Unused
); }
PHANDLE_ENTRY CreateNewPortHandle( handle_t hBinding, PLINE_INFO LineInfo, DWORD Flags ) { return CreateNewHandle( hBinding, FHT_PORT, 0, // Unused
LineInfo, Flags ); }
PHANDLE_ENTRY CreateNewMsgEnumHandle( handle_t hBinding, HANDLE hFileFind, LPCWSTR lpcwstrFirstFileName, FAX_ENUM_MESSAGE_FOLDER Folder ) /*++
Routine name : CreateNewMsgEnumHandle
Routine description:
Creates a new context handle for messages enumeration
Author:
Eran Yariv (EranY), Dec, 1999
Arguments:
hBinding [in] - RPC Binding handle hFileFind [in] - Find file handle lpcwstrFirstFileName [in] - Name of first file found Folder [in] - Archive folder type of find file search
Return Value:
Returns a pointer to a newly created handle
--*/ { DEBUG_FUNCTION_NAME(TEXT("CreateNewMsgEnumHandle"));
Assert (INVALID_HANDLE_VALUE != hFileFind); if (MAX_PATH <= lstrlen (lpcwstrFirstFileName)) { DebugPrintEx( DEBUG_ERR, TEXT("String passed is too long (%s)"), lpcwstrFirstFileName); ASSERT_FALSE; return NULL; }
PHANDLE_ENTRY pHandle = CreateNewHandle (hBinding, FHT_MSGENUM, FindClientAPIVersion(hBinding), // Client API version
NULL, // Unused
0); // Unused
if (!pHandle) { DebugPrintEx( DEBUG_ERR, TEXT("CreateNewHandle failed")); return NULL; } //
// Store find file handle and first file in the new context
//
pHandle->hFile = hFileFind; wcsncpy (pHandle->wstrFileName, lpcwstrFirstFileName, ARR_SIZE(pHandle->wstrFileName)-1); pHandle->Folder = Folder; return pHandle; } // CreateNewMsgEnumHandle
PHANDLE_ENTRY CreateNewCopyHandle( handle_t hBinding, HANDLE hFile, BOOL bCopyToServer, LPCWSTR lpcwstrFileName, PJOB_QUEUE pJobQueue ) /*++
Routine name : CreateNewCopyHandle
Routine description:
Creates a new context handle for RPC copy
Author:
Eran Yariv (EranY), Dec, 1999
Arguments:
hBinding [in] - RPC Binding handle hFileFind [in] - File handle bCopyToServer [in] - Copy direction lpcwstrFileName [in] - Name of file generated on the server (in use for rundown purposes only if bCopyToServer is TRUE) pJobQueue [in] - Pointer to the job queue containing thr preview file (in use for rundown purposes only if bCopyToServer is FALSE)
Return Value:
Returns a pointer to a newly created handle
--*/ { DEBUG_FUNCTION_NAME(TEXT("CreateNewCopyHandle"));
Assert (INVALID_HANDLE_VALUE != hFile); PHANDLE_ENTRY pHandle = CreateNewHandle (hBinding, FHT_COPY, 0, // Unused
NULL, // Unused
0); // Unused
if (!pHandle) { DebugPrintEx( DEBUG_ERR, TEXT("CreateNewHandle failed")); return NULL; } //
// Store file handle and direction in the new context
//
pHandle->hFile = hFile; pHandle->bCopyToServer = bCopyToServer; pHandle->bError = FALSE; if (bCopyToServer) { //
// If this is a copy operation to the server, we keep the name of the file
// created in the server's queue so that in the rundown operation we can delete this file.
//
Assert (lstrlen (lpcwstrFileName) < MAX_PATH); //wstrFileName is MAX_PATH size
wcsncpy (pHandle->wstrFileName, lpcwstrFileName, ARR_SIZE(pHandle->wstrFileName)-1); } else { pHandle->pJobQueue = pJobQueue; } return pHandle; } // CreateNewCopyHandle
VOID CloseFaxHandle( PHANDLE_ENTRY pHandleEntry ) { //
// note that the HandleEntry may be a context handle,
// which may be NULL in some cases. Do nothing if
// this is the case
//
DEBUG_FUNCTION_NAME(TEXT("CloseFaxHandle")); Assert (pHandleEntry);
EnterCriticalSection( &g_CsHandleTable ); RemoveEntryList( &pHandleEntry->ListEntry ); if ((pHandleEntry->Type == FHT_SERVICE) && !(pHandleEntry->bReleased)) { SafeDecIdleCounter (&g_dwConnectionCount); } else if (pHandleEntry->Type == FHT_MSGENUM) { if (!FindClose (pHandleEntry->hFile)) { DebugPrintEx( DEBUG_ERR, TEXT("FindClose returned error code %ld"), GetLastError()); } } else if (pHandleEntry->Type == FHT_COPY) { if (!CloseHandle (pHandleEntry->hFile)) { DebugPrintEx( DEBUG_ERR, TEXT("CloseHandle returned error code %ld"), GetLastError()); } if (pHandleEntry->bError && pHandleEntry->bCopyToServer) { //
// We found an error while copying to the server.
// Remove temporary file created in the server's queue
//
if (!DeleteFile (pHandleEntry->wstrFileName)) { DWORD dwRes = GetLastError (); DebugPrintEx( DEBUG_ERR, TEXT("DeleteFile (%s) returned error code %ld"), pHandleEntry->wstrFileName, dwRes); } } if (FALSE == pHandleEntry->bCopyToServer) { if (pHandleEntry->pJobQueue) { //
// Decrease ref count only for queued jobs
//
EnterCriticalSection (&g_CsQueue); DecreaseJobRefCount (pHandleEntry->pJobQueue, TRUE, TRUE, TRUE); LeaveCriticalSection (&g_CsQueue); } } } MemFree( pHandleEntry ); LeaveCriticalSection( &g_CsHandleTable ); }
BOOL IsPortOpenedForModify( PLINE_INFO LineInfo ) { PLIST_ENTRY Next; PHANDLE_ENTRY HandleEntry;
EnterCriticalSection( &g_CsHandleTable );
Next = g_HandleTableListHead.Flink; if (Next == NULL) { LeaveCriticalSection( &g_CsHandleTable ); return FALSE; }
while ((ULONG_PTR)Next != (ULONG_PTR)&g_HandleTableListHead) {
HandleEntry = CONTAINING_RECORD( Next, HANDLE_ENTRY, ListEntry ); if (HandleEntry->Type == FHT_PORT && (HandleEntry->Flags & PORT_OPEN_MODIFY) && HandleEntry->LineInfo == LineInfo) { LeaveCriticalSection( &g_CsHandleTable ); return TRUE; }
Next = HandleEntry->ListEntry.Flink; }
LeaveCriticalSection( &g_CsHandleTable );
return FALSE; }
DWORD FindClientAPIVersion ( handle_t hFaxHandle ) /*++
Routine name : FindClientAPIVersion
Routine description:
Finds the API version of a connected client by its RPC binding handle
Author:
Eran Yariv (EranY), Mar, 2001
Arguments:
hFaxHandle [in] - RPC binding handle
Return Value:
Client API version
--*/ { PLIST_ENTRY pNext; DEBUG_FUNCTION_NAME(TEXT("FindClientAPIVersion"));
EnterCriticalSection (&g_CsHandleTable);
pNext = g_HandleTableListHead.Flink; if (pNext == NULL) { ASSERT_FALSE; DebugPrintEx( DEBUG_ERR, TEXT("g_CsHandleTable is corrupted")); LeaveCriticalSection (&g_CsHandleTable); return FAX_API_VERSION_0; }
while ((ULONG_PTR)pNext != (ULONG_PTR)&g_HandleTableListHead) { PHANDLE_ENTRY pHandleEntry = CONTAINING_RECORD(pNext, HANDLE_ENTRY, ListEntry); if ( ((FHT_SERVICE == pHandleEntry->Type) || (FHT_MSGENUM == pHandleEntry->Type) ) && (pHandleEntry->hBinding == hFaxHandle) ) { DWORD dwRes = pHandleEntry->dwClientAPIVersion; LeaveCriticalSection (&g_CsHandleTable); return dwRes; } pNext = pHandleEntry->ListEntry.Flink; }
LeaveCriticalSection (&g_CsHandleTable); DebugPrintEx( DEBUG_ERR, TEXT("No matching client entry for binding handle %08p"), hFaxHandle); return FAX_API_VERSION_0; } // FindClientAPIVersion
|