|
|
/*
* stub.c - Stub ADT module. */
/* Headers
**********/
#include "project.h"
#pragma hdrstop
#include "stub.h"
/* Macros
*********/
/* get a pointer to the stub type descriptor for a STUB */
#define GetStubTypeDescriptor(pcs) (&(Mrgcstd[pcs->st]))
/* Types
********/
/* stub functions */
typedef TWINRESULT (*UNLINKSTUBPROC)(PSTUB); typedef void (*DESTROYSTUBPROC)(PSTUB); typedef void (*LOCKSTUBPROC)(PSTUB); typedef void (*UNLOCKSTUBPROC)(PSTUB);
/* stub type descriptor */
typedef struct _stubtypedescriptor { UNLINKSTUBPROC UnlinkStub;
DESTROYSTUBPROC DestroyStub;
LOCKSTUBPROC LockStub;
UNLOCKSTUBPROC UnlockStub; } STUBTYPEDESCRIPTOR; DECLARE_STANDARD_TYPES(STUBTYPEDESCRIPTOR);
/* Module Prototypes
********************/
PRIVATE_CODE void LockSingleStub(PSTUB); PRIVATE_CODE void UnlockSingleStub(PSTUB);
#if defined(DEBUG) || defined(VSTF)
PRIVATE_CODE BOOL IsValidStubType(STUBTYPE);
#endif
#ifdef DEBUG
PRIVATE_CODE LPCTSTR GetStubName(PCSTUB);
#endif
/* Module Variables
*******************/
/* stub type descriptors */
/* Cast off compiler complaints about pointer argument mismatch. */
PRIVATE_DATA CONST STUBTYPEDESCRIPTOR Mrgcstd[] = { /* object twin STUB descriptor */
{ (UNLINKSTUBPROC)UnlinkObjectTwin, (DESTROYSTUBPROC)DestroyObjectTwin, LockSingleStub, UnlockSingleStub },
/* twin family STUB descriptor */
{ (UNLINKSTUBPROC)UnlinkTwinFamily, (DESTROYSTUBPROC)DestroyTwinFamily, LockSingleStub, UnlockSingleStub },
/* folder pair STUB descriptor */
{ (UNLINKSTUBPROC)UnlinkFolderPair, (DESTROYSTUBPROC)DestroyFolderPair, (LOCKSTUBPROC)LockFolderPair, (UNLOCKSTUBPROC)UnlockFolderPair } };
/***************************** Private Functions *****************************/
/*
** LockSingleStub() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PRIVATE_CODE void LockSingleStub(PSTUB ps) { ASSERT(IS_VALID_STRUCT_PTR(ps, CSTUB));
ASSERT(IsStubFlagClear(ps, STUB_FL_UNLINKED));
ASSERT(ps->ulcLock < ULONG_MAX); ps->ulcLock++;
return; }
/*
** UnlockSingleStub() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PRIVATE_CODE void UnlockSingleStub(PSTUB ps) { ASSERT(IS_VALID_STRUCT_PTR(ps, CSTUB));
if (EVAL(ps->ulcLock > 0)) { ps->ulcLock--;
if (! ps->ulcLock && IsStubFlagSet(ps, STUB_FL_UNLINKED)) DestroyStub(ps); }
return; }
#if defined(DEBUG) || defined(VSTF)
/*
** IsValidStubType() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PRIVATE_CODE BOOL IsValidStubType(STUBTYPE st) { BOOL bResult;
switch (st) { case ST_OBJECTTWIN: case ST_TWINFAMILY: case ST_FOLDERPAIR: bResult = TRUE; break;
default: bResult = FALSE; ERROR_OUT((TEXT("IsValidStubType(): Invalid STUB type %d."), st)); }
return(bResult); }
#endif
#ifdef DEBUG
/*
** GetStubName() ** ** ** ** Arguments: ** ** Returns: TWINRESULT ** ** Side Effects: none */ PRIVATE_CODE LPCTSTR GetStubName(PCSTUB pcs) { LPCTSTR pcszStubName;
ASSERT(IS_VALID_STRUCT_PTR(pcs, CSTUB));
switch (pcs->st) { case ST_OBJECTTWIN: pcszStubName = TEXT("object twin"); break;
case ST_TWINFAMILY: pcszStubName = TEXT("twin family"); break;
case ST_FOLDERPAIR: pcszStubName = TEXT("folder twin"); break;
default: ERROR_OUT((TEXT("GetStubName() called on unrecognized stub type %d."), pcs->st)); pcszStubName = TEXT("UNKNOWN"); break; }
ASSERT(IS_VALID_STRING_PTR(pcszStubName, CSTR));
return(pcszStubName); }
#endif
/****************************** Public Functions *****************************/
/*
** InitStub() ** ** Initializes a stub. ** ** Arguments: ps - pointer to stub to be initialized ** st - type of stub ** ** Returns: void ** ** Side Effects: none */ PUBLIC_CODE void InitStub(PSTUB ps, STUBTYPE st) { ASSERT(IS_VALID_WRITE_PTR(ps, STUB)); ASSERT(IsValidStubType(st));
ps->st = st; ps->ulcLock = 0; ps->dwFlags = 0;
ASSERT(IS_VALID_STRUCT_PTR(ps, CSTUB));
return; }
/*
** DestroyStub() ** ** Destroys a stub. ** ** Arguments: ps - pointer to stub to be destroyed ** ** Returns: TWINRESULT ** ** Side Effects: Depends upon stub type. */ PUBLIC_CODE TWINRESULT DestroyStub(PSTUB ps) { TWINRESULT tr; PCSTUBTYPEDESCRIPTOR pcstd;
ASSERT(IS_VALID_STRUCT_PTR(ps, CSTUB));
#ifdef DEBUG
if (IsStubFlagSet(ps, STUB_FL_UNLINKED) && ps->ulcLock > 0) WARNING_OUT((TEXT("DestroyStub() called on unlinked locked %s stub %#lx."), GetStubName(ps), ps));
#endif
pcstd = GetStubTypeDescriptor(ps);
/* Is the stub already unlinked? */
if (IsStubFlagSet(ps, STUB_FL_UNLINKED)) /* Yes. */ tr = TR_SUCCESS; else /* No. Unlink it. */ tr = (*(pcstd->UnlinkStub))(ps);
/* Is the stub still locked? */
if (tr == TR_SUCCESS && ! ps->ulcLock) /* No. Wipe it out. */ (*(pcstd->DestroyStub))(ps);
return(tr); }
/*
** LockStub() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE void LockStub(PSTUB ps) { ASSERT(IS_VALID_STRUCT_PTR(ps, CSTUB));
(*(GetStubTypeDescriptor(ps)->LockStub))(ps);
return; }
/*
** UnlockStub() ** ** Unlocks a stub. Carries out any pending deletion on the stub. ** ** Arguments: ps - pointer to stub to be unlocked ** ** Returns: void ** ** Side Effects: If the stub is unlinked and the lock count decreases to 0 ** after unlocking, the stub is deleted. */ PUBLIC_CODE void UnlockStub(PSTUB ps) { ASSERT(IS_VALID_STRUCT_PTR(ps, CSTUB));
(*(GetStubTypeDescriptor(ps)->UnlockStub))(ps);
return; }
/*
** GetStubFlags() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE DWORD GetStubFlags(PCSTUB pcs) { ASSERT(IS_VALID_STRUCT_PTR(pcs, CSTUB));
return(pcs->dwFlags); }
/*
** SetStubFlag() ** ** Sets given flag in a stub. Other flags in stub are not affected. ** ** Arguments: ps - pointer to stub whose flags are to be set ** ** Returns: void ** ** Side Effects: none */ PUBLIC_CODE void SetStubFlag(PSTUB ps, DWORD dwFlags) { ASSERT(IS_VALID_STRUCT_PTR(ps, CSTUB)); ASSERT(FLAGS_ARE_VALID(dwFlags, ALL_STUB_FLAGS));
SET_FLAG(ps->dwFlags, dwFlags);
return; }
/*
** ClearStubFlag() ** ** Clears given flag in a stub. Other flags in stub are not affected. ** ** Arguments: ps - pointer to stub whose flags are to be set ** ** Returns: void ** ** Side Effects: none */ PUBLIC_CODE void ClearStubFlag(PSTUB ps, DWORD dwFlags) { ASSERT(IS_VALID_STRUCT_PTR(ps, CSTUB)); ASSERT(FLAGS_ARE_VALID(dwFlags, ALL_STUB_FLAGS));
CLEAR_FLAG(ps->dwFlags, dwFlags);
return; }
/*
** IsStubFlagSet() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE BOOL IsStubFlagSet(PCSTUB pcs, DWORD dwFlags) { ASSERT(IS_VALID_STRUCT_PTR(pcs, CSTUB)); ASSERT(FLAGS_ARE_VALID(dwFlags, ALL_STUB_FLAGS));
return(IS_FLAG_SET(pcs->dwFlags, dwFlags)); }
/*
** IsStubFlagClear() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE BOOL IsStubFlagClear(PCSTUB pcs, DWORD dwFlags) { ASSERT(IS_VALID_STRUCT_PTR(pcs, CSTUB)); ASSERT(FLAGS_ARE_VALID(dwFlags, ALL_STUB_FLAGS));
return(IS_FLAG_CLEAR(pcs->dwFlags, dwFlags)); }
#ifdef VSTF
/*
** IsValidPCSTUB() ** ** ** ** Arguments: ** ** Returns: ** ** Side Effects: none */ PUBLIC_CODE BOOL IsValidPCSTUB(PCSTUB pcs) { BOOL bResult;
if (IS_VALID_READ_PTR(pcs, CSTUB) && IsValidStubType(pcs->st) && FLAGS_ARE_VALID(pcs->dwFlags, ALL_STUB_FLAGS)) bResult = TRUE; else bResult = FALSE;
return(bResult); }
#endif
|