504 lines
7.9 KiB
C
504 lines
7.9 KiB
C
|
/*
|
||
|
* 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
|
||
|
*******************/
|
||
|
|
||
|
#pragma data_seg(DATA_SEG_READ_ONLY)
|
||
|
|
||
|
/* 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
|
||
|
}
|
||
|
};
|
||
|
|
||
|
#pragma data_seg()
|
||
|
|
||
|
|
||
|
/***************************** 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
|
||
|
|