NT4/private/windows/rover/filesync/core/stub.c
2020-09-30 17:12:29 +02:00

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