You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
421 lines
11 KiB
421 lines
11 KiB
/*++
|
|
|
|
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
|
|
|