343 lines
7.3 KiB
C
343 lines
7.3 KiB
C
|
/****************************************************************************
|
||
|
*
|
||
|
* $Archive: S:/STURGEON/SRC/CALLCONT/VCS/Hangman.c_v $
|
||
|
*
|
||
|
* INTEL Corporation Prorietary Information
|
||
|
*
|
||
|
* This listing is supplied under the terms of a license agreement
|
||
|
* with INTEL Corporation and may not be copied nor disclosed except
|
||
|
* in accordance with the terms of that agreement.
|
||
|
*
|
||
|
* Copyright (c) 1993-1994 Intel Corporation.
|
||
|
*
|
||
|
* $Revision: 1.16 $
|
||
|
* $Date: 22 Jan 1997 14:55:52 $
|
||
|
* $Author: MANDREWS $
|
||
|
*
|
||
|
* Deliverable:
|
||
|
*
|
||
|
* Abstract:
|
||
|
*
|
||
|
*
|
||
|
* Notes:
|
||
|
*
|
||
|
***************************************************************************/
|
||
|
|
||
|
#pragma warning ( disable : 4115 4201 4214 )
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
#include <windows.h>
|
||
|
#pragma warning ( default : 4115 4201 4214 )
|
||
|
#include "apierror.h"
|
||
|
#include "incommon.h"
|
||
|
#include "callcont.h"
|
||
|
#include "q931.h"
|
||
|
#include "ccmain.h"
|
||
|
#include "ccutils.h"
|
||
|
#include "hangman.h"
|
||
|
|
||
|
|
||
|
static BOOL bHangupInited = FALSE;
|
||
|
|
||
|
static struct {
|
||
|
PHANGUP pHead;
|
||
|
LOCK Lock;
|
||
|
} HangupTable;
|
||
|
|
||
|
static struct {
|
||
|
HHANGUP hHangup;
|
||
|
LOCK Lock;
|
||
|
} HangupHandle;
|
||
|
|
||
|
|
||
|
HRESULT InitHangupManager()
|
||
|
{
|
||
|
ASSERT(bHangupInited == FALSE);
|
||
|
|
||
|
HangupTable.pHead = NULL;
|
||
|
InitializeLock(&HangupTable.Lock);
|
||
|
|
||
|
HangupHandle.hHangup = CC_INVALID_HANDLE + 1;
|
||
|
InitializeLock(&HangupHandle.Lock);
|
||
|
|
||
|
bHangupInited = TRUE;
|
||
|
return CC_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
HRESULT DeInitHangupManager()
|
||
|
{
|
||
|
PHANGUP pHangup;
|
||
|
PHANGUP pNextHangup;
|
||
|
|
||
|
if (bHangupInited == FALSE)
|
||
|
return CC_OK;
|
||
|
|
||
|
pHangup = HangupTable.pHead;
|
||
|
while (pHangup != NULL) {
|
||
|
AcquireLock(&pHangup->Lock);
|
||
|
pNextHangup = pHangup->pNextInTable;
|
||
|
FreeHangup(pHangup);
|
||
|
pHangup = pNextHangup;
|
||
|
}
|
||
|
|
||
|
DeleteLock(&HangupHandle.Lock);
|
||
|
DeleteLock(&HangupTable.Lock);
|
||
|
bHangupInited = FALSE;
|
||
|
return CC_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
HRESULT _AddHangupToTable( PHANGUP pHangup)
|
||
|
{
|
||
|
ASSERT(pHangup != NULL);
|
||
|
ASSERT(pHangup->hHangup != CC_INVALID_HANDLE);
|
||
|
ASSERT(pHangup->bInTable == FALSE);
|
||
|
|
||
|
AcquireLock(&HangupTable.Lock);
|
||
|
|
||
|
pHangup->pNextInTable = HangupTable.pHead;
|
||
|
pHangup->pPrevInTable = NULL;
|
||
|
if (HangupTable.pHead != NULL)
|
||
|
HangupTable.pHead->pPrevInTable = pHangup;
|
||
|
HangupTable.pHead = pHangup;
|
||
|
|
||
|
pHangup->bInTable = TRUE;
|
||
|
|
||
|
RelinquishLock(&HangupTable.Lock);
|
||
|
return CC_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
HRESULT _RemoveHangupFromTable( PHANGUP pHangup)
|
||
|
{
|
||
|
HHANGUP hHangup;
|
||
|
BOOL bTimedOut;
|
||
|
|
||
|
ASSERT(pHangup != NULL);
|
||
|
ASSERT(pHangup->bInTable == TRUE);
|
||
|
|
||
|
// Caller must have a lock on the hangup object;
|
||
|
// in order to avoid deadlock, we must:
|
||
|
// 1. unlock the hangup object,
|
||
|
// 2. lock the HangupTable,
|
||
|
// 3. locate the hangup object in the HangupTable (note that
|
||
|
// after step 2, the hangup object may be deleted from the
|
||
|
// HangupTable by another thread),
|
||
|
// 4. lock the hangup object (someone else may have the lock)
|
||
|
// 5. remove the hangup object from the HangupTable,
|
||
|
// 6. unlock the HangupTable
|
||
|
//
|
||
|
// The caller can now safely unlock and destroy the hangup object,
|
||
|
// since no other thread will be able to find the object (its been
|
||
|
// removed from the HangupTable), and therefore no other thread will
|
||
|
// be able to lock it.
|
||
|
|
||
|
// Save the hangup handle; its the only way to look up
|
||
|
// the hangup object in the HangupTable. Note that we
|
||
|
// can't use pHangup to find the hangup object, since
|
||
|
// pHangup may be free'd up, and another hangup object
|
||
|
// allocated at the same address
|
||
|
hHangup = pHangup->hHangup;
|
||
|
|
||
|
// step 1
|
||
|
RelinquishLock(&pHangup->Lock);
|
||
|
|
||
|
step2:
|
||
|
// step 2
|
||
|
AcquireLock(&HangupTable.Lock);
|
||
|
|
||
|
// step 3
|
||
|
pHangup = HangupTable.pHead;
|
||
|
while ((pHangup != NULL) && (pHangup->hHangup != hHangup))
|
||
|
pHangup = pHangup->pNextInTable;
|
||
|
|
||
|
if (pHangup != NULL) {
|
||
|
// step 4
|
||
|
AcquireTimedLock(&pHangup->Lock,10,&bTimedOut);
|
||
|
if (bTimedOut) {
|
||
|
RelinquishLock(&HangupTable.Lock);
|
||
|
Sleep(0);
|
||
|
goto step2;
|
||
|
}
|
||
|
// step 5
|
||
|
if (pHangup->pPrevInTable == NULL)
|
||
|
HangupTable.pHead = pHangup->pNextInTable;
|
||
|
else
|
||
|
pHangup->pPrevInTable->pNextInTable = pHangup->pNextInTable;
|
||
|
|
||
|
if (pHangup->pNextInTable != NULL)
|
||
|
pHangup->pNextInTable->pPrevInTable = pHangup->pPrevInTable;
|
||
|
|
||
|
pHangup->pNextInTable = NULL;
|
||
|
pHangup->pPrevInTable = NULL;
|
||
|
pHangup->bInTable = FALSE;
|
||
|
}
|
||
|
|
||
|
// step 6
|
||
|
RelinquishLock(&HangupTable.Lock);
|
||
|
|
||
|
if (pHangup == NULL)
|
||
|
return CC_BAD_PARAM;
|
||
|
else
|
||
|
return CC_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
HRESULT _MakeHangupHandle( PHHANGUP phHangup)
|
||
|
{
|
||
|
AcquireLock(&HangupHandle.Lock);
|
||
|
*phHangup = HangupHandle.hHangup++;
|
||
|
RelinquishLock(&HangupHandle.Lock);
|
||
|
return CC_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
HRESULT AllocAndLockHangup( PHHANGUP phHangup,
|
||
|
CC_HCONFERENCE hConference,
|
||
|
DWORD dwUserToken,
|
||
|
PPHANGUP ppHangup)
|
||
|
{
|
||
|
HRESULT status;
|
||
|
|
||
|
ASSERT(bHangupInited == TRUE);
|
||
|
|
||
|
// all parameters should have been validated by the caller
|
||
|
ASSERT(phHangup != NULL);
|
||
|
ASSERT(hConference != CC_INVALID_HANDLE);
|
||
|
ASSERT(ppHangup != NULL);
|
||
|
|
||
|
// set phHangup now, in case we encounter an error
|
||
|
*phHangup = CC_INVALID_HANDLE;
|
||
|
|
||
|
*ppHangup = (PHANGUP)Malloc(sizeof(HANGUP));
|
||
|
if (*ppHangup == NULL)
|
||
|
return CC_NO_MEMORY;
|
||
|
|
||
|
(*ppHangup)->bInTable = FALSE;
|
||
|
status = _MakeHangupHandle(&(*ppHangup)->hHangup);
|
||
|
if (status != CC_OK) {
|
||
|
Free(*ppHangup);
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
(*ppHangup)->hConference = hConference;
|
||
|
(*ppHangup)->wNumCalls = 0;
|
||
|
(*ppHangup)->dwUserToken = dwUserToken;
|
||
|
(*ppHangup)->pNextInTable = NULL;
|
||
|
(*ppHangup)->pPrevInTable = NULL;
|
||
|
|
||
|
InitializeLock(&(*ppHangup)->Lock);
|
||
|
AcquireLock(&(*ppHangup)->Lock);
|
||
|
|
||
|
*phHangup = (*ppHangup)->hHangup;
|
||
|
|
||
|
// add the Hangup to the Hangup table
|
||
|
status = _AddHangupToTable(*ppHangup);
|
||
|
if (status != CC_OK)
|
||
|
FreeHangup(*ppHangup);
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// Caller must have a lock on the Hangup object
|
||
|
HRESULT FreeHangup( PHANGUP pHangup)
|
||
|
{
|
||
|
HHANGUP hHangup;
|
||
|
|
||
|
ASSERT(pHangup != NULL);
|
||
|
|
||
|
// caller must have a lock on the Hangup object,
|
||
|
// so there's no need to re-lock it
|
||
|
|
||
|
hHangup = pHangup->hHangup;
|
||
|
|
||
|
if (pHangup->bInTable == TRUE)
|
||
|
if (_RemoveHangupFromTable(pHangup) == CC_BAD_PARAM)
|
||
|
// the Hangup object was deleted by another thread,
|
||
|
// so just return CC_OK
|
||
|
return CC_OK;
|
||
|
|
||
|
// Since the hangup object has been removed from the HangupTable,
|
||
|
// no other thread will be able to find the hangup object and obtain
|
||
|
// a lock, so its safe to unlock the hangup object and delete it here
|
||
|
RelinquishLock(&pHangup->Lock);
|
||
|
DeleteLock(&pHangup->Lock);
|
||
|
Free(pHangup);
|
||
|
return CC_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
HRESULT LockHangup( HHANGUP hHangup,
|
||
|
PPHANGUP ppHangup)
|
||
|
{
|
||
|
BOOL bTimedOut;
|
||
|
|
||
|
ASSERT(hHangup != CC_INVALID_HANDLE);
|
||
|
ASSERT(ppHangup != NULL);
|
||
|
|
||
|
step1:
|
||
|
AcquireLock(&HangupTable.Lock);
|
||
|
|
||
|
*ppHangup = HangupTable.pHead;
|
||
|
while ((*ppHangup != NULL) && ((*ppHangup)->hHangup != hHangup))
|
||
|
*ppHangup = (*ppHangup)->pNextInTable;
|
||
|
|
||
|
if (*ppHangup != NULL) {
|
||
|
AcquireTimedLock(&(*ppHangup)->Lock,10,&bTimedOut);
|
||
|
if (bTimedOut) {
|
||
|
RelinquishLock(&HangupTable.Lock);
|
||
|
Sleep(0);
|
||
|
goto step1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RelinquishLock(&HangupTable.Lock);
|
||
|
|
||
|
if (*ppHangup == NULL)
|
||
|
return CC_BAD_PARAM;
|
||
|
else
|
||
|
return CC_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
HRESULT ValidateHangup( HHANGUP hHangup)
|
||
|
{
|
||
|
PHANGUP pHangup;
|
||
|
|
||
|
ASSERT(hHangup != CC_INVALID_HANDLE);
|
||
|
|
||
|
AcquireLock(&HangupTable.Lock);
|
||
|
|
||
|
pHangup = HangupTable.pHead;
|
||
|
while ((pHangup != NULL) && (pHangup->hHangup != hHangup))
|
||
|
pHangup = pHangup->pNextInTable;
|
||
|
|
||
|
RelinquishLock(&HangupTable.Lock);
|
||
|
|
||
|
if (pHangup == NULL)
|
||
|
return CC_BAD_PARAM;
|
||
|
else
|
||
|
return CC_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
HRESULT UnlockHangup( PHANGUP pHangup)
|
||
|
{
|
||
|
ASSERT(pHangup != NULL);
|
||
|
|
||
|
RelinquishLock(&pHangup->Lock);
|
||
|
return CC_OK;
|
||
|
}
|