Leaked source code of windows server 2003
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.
 
 
 
 
 
 

6280 lines
142 KiB

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
CShadow.c
Abstract:
This file implements the "cshadow" interface that is used by the redir and ioctls.
The cshadow interface hides the actual implementation of the csc database from the
users of the database.
There are three persistant database types exposed
1) The database of shares
2) The filesystem hierarchy under any particular share
3) The priority queue / Master File Table
Operations for set and get are provided on the 1) and 2). 3) Is allwed to be
enumerated. The priority queue is enumerated by the usermode agent to a) fill partially
filled files and b) keep the space used within the specified constraints
Author:
Shishir Pardikar [Shishirp] 01-jan-1995
Revision History:
Joe Linn [JoeLinn] 23-jan-97 Ported for use on NT
--*/
#include "precomp.h"
#pragma hdrstop
#pragma code_seg("PAGE")
#ifndef CSC_RECORDMANAGER_WINNT
#define WIN32_APIS
#include "record.h"
#include "cshadow.h"
#endif //ifndef CSC_RECORDMANAGER_WINNT
#include "string.h"
#include "stdlib.h"
#include "vxdwraps.h"
// Defines and Typedefs -------------------------------------------------------------------
#undef RxDbgTrace
#define RxDbgTrace(a,b,__d__) {qweee __d__;}
#ifdef DEBUG
//cshadow dbgprint interface
#define CShadowKdPrint(__bit,__x) {\
if (((CSHADOW_KDP_##__bit)==0) || FlagOn(CShadowKdPrintVector,(CSHADOW_KDP_##__bit))) {\
KdPrint (__x);\
}\
}
#define CSHADOW_KDP_ALWAYS 0x00000000
#define CSHADOW_KDP_BADERRORS 0x00000001
#define CSHADOW_KDP_CREATESHADOWHI 0x00000002
#define CSHADOW_KDP_CREATESHADOWLO 0x00000004
#define CSHADOW_KDP_DELETESHADOWBAD 0x00000008
#define CSHADOW_KDP_DELETESHADOWHI 0x00000010
#define CSHADOW_KDP_DELETESHADOWLO 0x00000020
#define CSHADOW_KDP_RENAMESHADOWHI 0x00000040
#define CSHADOW_KDP_RENAMESHADOWLO 0x00000080
#define CSHADOW_KDP_GETSHADOWHI 0x00000100
#define CSHADOW_KDP_GETSHADOWLO 0x00000200
#define CSHADOW_KDP_SETSHADOWINFOHI 0x00000400
#define CSHADOW_KDP_SETSHADOWINFOLO 0x00000800
#define CSHADOW_KDP_READSHADOWINFOHI 0x00001000
#define CSHADOW_KDP_READSHADOWINFOLO 0x00002000
#define CSHADOW_KDP_COPYLOCAL 0x00004000
#define CSHADOW_KDP_COPYFILE 0x00008000
#define CSHADOW_KDP_FINDCREATESHARE 0x80000000
#define CSHADOW_KDP_MISC 0x00010000
#define CSHADOW_KDP_STOREDATA 0x00020000
#define CSHADOW_KDP_GOOD_DEFAULT (CSHADOW_KDP_BADERRORS \
| CSHADOW_KDP_CREATESHADOWHI \
| CSHADOW_KDP_DELETESHADOWHI \
| CSHADOW_KDP_RENAMESHADOWHI \
| CSHADOW_KDP_GETSHADOWHI \
| CSHADOW_KDP_SETSHADOWINFOHI \
| CSHADOW_KDP_FINDCREATESHARE \
| 0)
#define IF_HSHADOW_SPECIAL(___hshadow) if((___hshadow)==hShadowSpecial_x)
#define SET_HSHADOW_SPECIAL(___hshadow) {hShadowSpecial_x = (___hshadow);}
ULONG CShadowKdPrintVector = CSHADOW_KDP_BADERRORS;
//ULONG CShadowKdPrintVector = CSHADOW_KDP_GOOD_DEFAULT;
ULONG CShadowKdPrintVectorDef = CSHADOW_KDP_GOOD_DEFAULT;
#else
#define CShadowKdPrint(__bit,__x) {NOTHING;}
#define IF_HSHADOW_SPECIAL(___hshadow) if(FALSE)
#define SET_HSHADOW_SPECIAL(___hshadow) {NOTHING;}
#endif
// ReadShadowInfo action flags
#define RSI_COMPARE 0x0001
#define RSI_GET 0x0002
#define RSI_SET 0x0004
#define mIsDir(lpF32) (((LPFIND32)(lpF32))->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
#define ENTERCRIT_SHADOW {if (semShadow)\
Wait_Semaphore(semShadow, BLOCK_SVC_INTS);}
#define LEAVECRIT_SHADOW {if (semShadow)\
Signal_Semaphore(semShadow);}
#define InuseGlobalFRExt() (vfInuseFRExt)
#define UseGlobalFilerecExt() {Assert(!vfInuseFRExt);vfInuseFRExt = TRUE;memset(&vsFRExt, 0, sizeof(FILERECEXT));}
#define UnUseGlobalFilerecExt() (vfInuseFRExt = FALSE)
#pragma intrinsic (memcmp, memcpy, memset, strcat, strcmp, strcpy, strlen)
// Global data ----------------------------------------------------------------------------
USHORT vwzRegDelimiters[] = L";, ";
USHORT *vrgwExclusionListDef[] =
{
L"*.SLM",
L"*.MDB",
L"*.LDB",
L"*.MDW",
L"*.MDE",
L"*.PST",
L"*.DB?"
};
USHORT **vlplpExclusionList = vrgwExclusionListDef;
ULONG vcntExclusionListEntries = (sizeof(vrgwExclusionListDef)/sizeof(USHORT *));
USHORT *vrgwBandwidthConservationListDef[] =
{
L"*.EXE",
L"*.DLL",
L"*.SYS",
L"*.COM",
L"*.HLP",
L"*.CPL",
L"*.INF"
};
USHORT **vlplpBandwidthConservationList = vrgwBandwidthConservationListDef;
ULONG vcntBandwidthConservationListEntries = (sizeof(vrgwBandwidthConservationListDef)/sizeof(USHORT *));
USHORT vtzExcludedCharsList[] = L":*?";
ULONG hShadowSpecial_x = -1;
VMM_SEMAPHORE semShadow=0; // To serialize Shadow database accesses
ULONG hShadowCritOwner=0;
#ifdef DEBUG
BOOL vfInShadowCrit = FALSE;
extern BOOL vfStopHandleCaching;
#endif
char vszShadowVolume[] = "SHADOW";
USHORT vwszFileSystemName[] = L"FAT";
FILERECEXT vsFRExt;
BOOL vfInuseFRExt = FALSE;
LPVOID lpdbShadow = NULL;
// vdwSparseStaleDetecionCount is a tick counter used to keep track of how many stale or sparse
// file inodes were encountered by the cshadow interface during all APIs that produce
// sparse or stale files, such as CreateShadowInternal, SetShadowinfoEx and ReadShadowInfo
// The agent continues to loop through the PQ till he finds that he has looped through
// the entire PQ and hasn't encountered a single sparse or stale file at which point he
// goes in a mode where he starts to check whether any inodes have been newly sparsed
// or gone stale. If none are, then he doesn't enumerate the queue, else he goes to
// the earlier state.
// ACHTUNG: It is to be noted that a sparse or a stale entry may get counted multiple times.
// As an example, when a shadow is created the count is bumped once, then if it's
// pin data is changed it is bumped up, similarly when it is moved in the priority Q
// it is again changed because SetPriorityHSHADOW goes through SetShadowInfoEx
DWORD vdwSparseStaleDetecionCount=0;
DWORD vdwManualFileDetectionCount=0;
// vdwCSCNameSpaceVersion is bumped up everytime a create,rename or delete is performed on
// the local database. This is useful for quickly checking cache-coherency. When a full
// UNC name is cached, the version# of the database is obtained before caching. When using the
// cached UNC name, the version # is queried. If it has changed, the cache is thrown away.
// The version is at a very coarse granularity. It would be nice to have a finer control
DWORD vdwCSCNameSpaceVersion=0;
DWORD vdwPQVersion=0;
AssertData
AssertError
// a callback function that someone can set and be called when a directory delete succeeds
// this is useful only for ioctls doing finds on a directory, at the moment
// If there is a more general need for callbacks, we will extend this to be a list etc.
LPDELETECALLBACK lpDeleteCBForIoctl = NULL;
// status of the database. Used mostly for encryption state
ULONG vulDatabaseStatus=0;
// Local function prototypes -----------------------------------------------------------
int PRIVATE ReadShadowInfo(HSHADOW, HSHADOW, LPFIND32, ULONG far *, LPOTHERINFO, LPVOID, LPDWORD, ULONG);
int CopyFilerecToOtherInfo(LPFILERECEXT lpFR, LPOTHERINFO lpOI);
int CopyOtherInfoToFilerec(LPOTHERINFO lpOI, LPFILERECEXT lpFR);
int CreateShadowInternal(HSHADOW, LPFIND32, ULONG, LPOTHERINFO, LPHSHADOW);
int CopySharerecToFindInfo(LPSHAREREC, LPFIND32);
int CopyOtherInfoToSharerec(LPOTHERINFO, LPSHAREREC);
int CopyPQToOtherInfo(LPPRIQREC, LPOTHERINFO);
int CopyOtherInfoToPQ(LPOTHERINFO, LPPRIQREC);
int CopySharerecToShadowInfo(LPSHAREREC lpSR, LPSHADOWINFO lpSI);
int RenameDirFileHSHADOW(HSHADOW, HSHADOW, HSHARE, HSHADOW, HSHADOW, ULONG, LPOTHERINFO, ULONG, LPFILERECEXT, LPFIND32, LPVOID, LPDWORD);
int RenameFileHSHADOW(HSHADOW, HSHADOW, HSHADOW, HSHADOW, ULONG, LPOTHERINFO, ULONG, LPFILERECEXT, LPFIND32, LPVOID, LPDWORD);
int DestroyShareInternal(LPSHAREREC);
//prototypes added to make it compile on NT
int PUBLIC SetPriorityHSHADOW(
HSHADOW hDir,
HSHADOW hShadow,
ULONG ulRefPri,
ULONG ulIHPri
);
int CopySharerecToOtherInfo(LPSHAREREC lpSR, LPOTHERINFO lpOI);
int MetaMatchShare(
HSHADOW hDir,
LPFIND32 lpFind32,
ULONG *lpuCookie,
LPHSHADOW lphShadow,
ULONG *lpuStatus,
LPOTHERINFO lpOI,
METAMATCHPROC lpfnMMP,
LPVOID lpData
);
int MetaMatchDir( HSHADOW hDir,
LPFIND32 lpFind32,
ULONG *lpuCookie,
LPHSHADOW lphShadow,
ULONG *lpuStatus,
LPOTHERINFO lpOI,
METAMATCHPROC lpfnMMP,
LPVOID lpData
);
int
DeleteShadowInternal( //
HSHADOW hDir,
HSHADOW hShadow,
BOOL fForce
);
int
CShadowFindFilerecFromInode(
LPVOID lpdbID,
HSHADOW hDir,
HSHADOW hShadow,
LPPRIQREC lpPQ,
LPFILERECEXT lpFRUse
);
BOOL
CopySecurityContextToBuffer(
LPRECORDMANAGER_SECURITY_CONTEXT lpSecurityContext,
LPVOID lpSecurityBlob,
LPDWORD lpdwBlobSize
);
BOOL
CopyBufferToSecurityContext(
LPVOID lpSecurityBlob,
LPDWORD lpdwBlobSize,
LPRECORDMANAGER_SECURITY_CONTEXT lpSecurityContext
);
int CopyFindInfoToSharerec(
LPFIND32 lpFind32,
LPSHAREREC lpSR
);
#ifdef DEBUG
int
ValidatePri(
LPFILERECEXT lpFR
);
#endif
VOID
AdjustSparseStaleDetectionCount(
ULONG hShare,
LPFILERECEXT lpFRUse
);
VOID FreeLists(
VOID
);
VOID
CscNotifyAgentOfFullCacheIfRequired(
VOID);
//
// From cscapi.h
//
#define FLAG_CSC_SHARE_STATUS_MANUAL_REINT 0x0000
#define FLAG_CSC_SHARE_STATUS_AUTO_REINT 0x0040
#define FLAG_CSC_SHARE_STATUS_VDO 0x0080
#define FLAG_CSC_SHARE_STATUS_NO_CACHING 0x00c0
#define FLAG_CSC_SHARE_STATUS_CACHING_MASK 0x00c0
// Functions -------------------------------------------------------------------------------
BOOL FExistsShadowDB(
LPSTR lpszLocation
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
return (FExistsRecDB(lpszLocation));
}
int OpenShadowDB(
LPSTR lpszLocation,
LPSTR lpszUserName,
DWORD dwDefDataSizeHigh,
DWORD dwDefDataSizeLow,
DWORD dwClusterSize,
BOOL fReinit,
BOOL *lpfReinited
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
DWORD Status;
BOOL fEncrypt;
if (!semShadow)
{
CShadowKdPrint(ALWAYS,("OpenShadowDB:Shadow Semaphore doesn't exist, bailing out \r\n"));
SetLastErrorLocal(ERROR_SERVICE_NOT_ACTIVE);
return -1;
}
Status = CscInitializeSecurityDescriptor();
if (Status != ERROR_SUCCESS) {
CShadowKdPrint(BADERRORS,("Failed to initialize Security descriptor Status=%x\n",Status));
return -1;
}
if (!(lpdbShadow = OpenRecDB(lpszLocation, lpszUserName, dwDefDataSizeHigh, dwDefDataSizeLow, dwClusterSize, fReinit, lpfReinited, &vulDatabaseStatus)))
{
return -1;
}
Status = CscInitializeSecurity(lpdbShadow);
if (Status != ERROR_SUCCESS)
{
CloseShadowDB();
CscUninitializeSecurityDescriptor();
CShadowKdPrint(BADERRORS,("OpenShadowDB %s at %s for %s with size %ld %lx \n",
"couldn't Initialize Security %lx",
lpszLocation, lpszUserName, dwDefDataSizeLow,Status));
return -1;
}
fEncrypt = -1;
if(mDatabasePartiallyEncrypted(vulDatabaseStatus))
{
fEncrypt = TRUE;
}
else if (mDatabasePartiallyUnencrypted(vulDatabaseStatus))
{
fEncrypt = FALSE;
}
// do the best we can
if (fEncrypt != -1)
{
if(EncryptDecryptDB(lpdbShadow, fEncrypt))
{
if (fEncrypt)
{
vulDatabaseStatus = ((vulDatabaseStatus & ~FLAG_DATABASESTATUS_ENCRYPTION_MASK) | FLAG_DATABASESTATUS_ENCRYPTED);
}
else
{
vulDatabaseStatus = ((vulDatabaseStatus & ~FLAG_DATABASESTATUS_ENCRYPTION_MASK) | FLAG_DATABASESTATUS_UNENCRYPTED);
}
SetDatabaseStatus(vulDatabaseStatus, FLAG_DATABASESTATUS_ENCRYPTION_MASK);
}
}
// CSCInitLists();
return 1;
}
int CloseShadowDB(
VOID
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
if (!lpdbShadow)
{
return -1;
}
if(!CloseRecDB(lpdbShadow))
{
return -1;
}
CscUninitializeSecurityDescriptor();
FreeLists();
lpdbShadow = NULL;
Assert(semShadow != 0);
return (1);
}
//on NT, we allocate this statically
#ifdef CSC_RECORDMANAGER_WINNT
FAST_MUTEX Nt5CscShadowMutex;
#endif
BOOL
InitializeShadowCritStructures (
void
)
{
#ifndef CSC_RECORDMANAGER_WINNT
semShadow = Create_Semaphore(1);
#else
semShadow = &Nt5CscShadowMutex;
ExInitializeFastMutex(semShadow);
#endif
return (semShadow != 0);
}
VOID
CleanupShadowCritStructures(
VOID
)
{
// Assert(semShadow);
#ifndef CSC_RECORDMANAGER_WINNT
Destroy_Semaphore(semShadow);
#else
semShadow = NULL;
#endif
}
#ifdef DEBUG
WINNT_DOIT(
PSZ ShadowCritAcquireFile;
ULONG ShadowCritAcquireLine;
BOOLEAN ShadowCritDbgPrintEnable = FALSE; //TRUE;
)
#endif
#ifndef CSC_RECORDMANAGER_WINNT
int EnterShadowCrit( void)
#else
int __EnterShadowCrit(ENTERLEAVESHADOWCRIT_SIGNATURE)
#endif
{
#ifdef CSC_RECORDMANAGER_WINNT
if(!MRxSmbIsCscEnabled) {
SetLastErrorLocal(ERROR_SERVICE_NOT_ACTIVE);
DbgPrint("CSC not enabled, not asserting for semShadow\n");
return(1);
}
#endif
Assert(semShadow != NULL);
ENTERCRIT_SHADOW;
hShadowCritOwner = GetCurThreadHandle();
#ifdef DEBUG
++vfInShadowCrit;
WINNT_DOIT(
ShadowCritAcquireFile = FileName;
ShadowCritAcquireLine = LineNumber;
if (ShadowCritDbgPrintEnable) {
DbgPrint("ACQUIRESHADOWCRIT at %s %u\n",FileName,LineNumber);
}
)
#endif
return 1;
}
#ifndef CSC_RECORDMANAGER_WINNT
int LeaveShadowCrit( void)
#else
int __LeaveShadowCrit(ENTERLEAVESHADOWCRIT_SIGNATURE)
#endif
{
#ifdef CSC_RECORDMANAGER_WINNT
if(!MRxSmbIsCscEnabled) {
DbgPrint("CSC not enabled, not asserting for vfInShadowCrit\n");
SetLastErrorLocal(ERROR_SERVICE_NOT_ACTIVE);
return(1);
}
#endif
Assert(vfInShadowCrit != 0);
#ifdef DEBUG
--vfInShadowCrit;
WINNT_DOIT(
ShadowCritAcquireLine *= -1;
if (ShadowCritDbgPrintEnable) {
DbgPrint("RELEASESHADOWCRIT at %s %u\n",FileName,LineNumber);
}
)
#endif
hShadowCritOwner = 0;
LEAVECRIT_SHADOW;
return 1;
}
int LeaveShadowCritIfThisThreadOwnsIt(
void
)
{
if (hShadowCritOwner == GetCurThreadHandle())
{
LeaveShadowCrit();
}
return 1;
}
int SetList(
USHORT *lpList,
DWORD cbBufferSize,
int typeList
)
/*++
Routine Description:
This routine sets various lists that the CSHADOW interface provides. The known lists include
the exclusion list and the bandwidth conservation list.
The exclusion list contains wildcarded file extensions that should not be cached automatically.
The bandwidth conservation list is the list of file types for which opens should be
done locally if possible.
Parameters:
lpList A list of wide character strings terminated by a NULL string
typeList CSHADOW_LIST_TYPE_EXCLUDE or CSHADOW_LIST_TYPE_CONSERVE_BW
Return Value:
Notes:
--*/
{
DWORD dwCount=0;
USHORT **lplpListArray = NULL, *lpuT;
int iRet = -1;
BOOL fUpdateList = FALSE;
if (cbBufferSize)
{
CShadowKdPrint(MISC, (" %ws\r\n", lpList));
#if 0
if (typeList == CSHADOW_LIST_TYPE_EXCLUDE)
{
DbgPrint("ExclusionList: %ws\n", lpList);
}
if (typeList == CSHADOW_LIST_TYPE_CONSERVE_BW)
{
DbgPrint("BW: %ws\n", lpList);
}
#endif
if (CreateStringArrayFromDelimitedList(lpList, vwzRegDelimiters, NULL, &dwCount))
{
if (dwCount)
{
lplpListArray = (LPWSTR *)AllocMem(dwCount * sizeof(USHORT *) + cbBufferSize);
if (lplpListArray)
{
lpuT = (USHORT *)((LPBYTE)lplpListArray + dwCount * sizeof(USHORT *));
// copy it while uppercasing
memcpy(lpuT, lpList, cbBufferSize);
UniToUpper(lpuT, lpuT, cbBufferSize);
if (CreateStringArrayFromDelimitedList( lpuT,
vwzRegDelimiters,
lplpListArray,
&dwCount))
{
fUpdateList = TRUE;
}
}
}
else
{
Assert(lplpListArray == NULL);
fUpdateList = TRUE;
}
if (fUpdateList)
{
switch (typeList)
{
case CSHADOW_LIST_TYPE_EXCLUDE:
if(vlplpExclusionList != vrgwExclusionListDef)
{
if (vlplpExclusionList)
{
FreeMem(vlplpExclusionList);
}
}
vlplpExclusionList = lplpListArray;
vcntExclusionListEntries = dwCount;
iRet = 0;
break;
case CSHADOW_LIST_TYPE_CONSERVE_BW:
if(vlplpBandwidthConservationList != vrgwBandwidthConservationListDef)
{
if (vlplpBandwidthConservationList)
{
FreeMem(vlplpBandwidthConservationList);
}
}
vlplpBandwidthConservationList = lplpListArray;
vcntBandwidthConservationListEntries = dwCount;
iRet = 0;
break;
default:
break;
}
}
}
}
if (iRet == -1)
{
if (lplpListArray)
{
FreeMem(lplpListArray);
}
}
return (iRet);
}
VOID FreeLists(
VOID
)
/*++
Routine Description:
Free the user associated lists and set them back to the default
Parameters:
None
Return Value:
None
Notes:
Called while shutting down the database
--*/
{
if(vlplpExclusionList != vrgwExclusionListDef)
{
if (vlplpExclusionList)
{
FreeMem(vlplpExclusionList);
vlplpExclusionList = NULL;
}
vlplpExclusionList = vrgwExclusionListDef;
vcntExclusionListEntries = (sizeof(vrgwExclusionListDef)/sizeof(USHORT *));
}
if(vlplpBandwidthConservationList != vrgwBandwidthConservationListDef)
{
if (vlplpBandwidthConservationList)
{
FreeMem(vlplpBandwidthConservationList);
vlplpBandwidthConservationList = NULL;
}
vcntBandwidthConservationListEntries = 0;
}
}
int BeginInodeTransactionHSHADOW(
VOID
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
This routine ensures that an inode is not reused while this is happening. It is used by various APIs so that while they
are travesring a hierarchy, they don't end up pointing somewhere else if they refer to an inode.
--*/
{
if (!lpdbShadow)
{
SetLastErrorLocal(ERROR_SERVICE_NOT_ACTIVE);
return -1;
}
BeginInodeTransaction();
return 1;
}
int EndInodeTransactionHSHADOW(
VOID
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
The converse of BeginInodeTransaction. The timespan betwen the two is supposed to be very short (20 sec).
--*/
{
if (!lpdbShadow)
{
SetLastErrorLocal(ERROR_SERVICE_NOT_ACTIVE);
return -1;
}
EndInodeTransaction();
return 1;
}
HSHADOW HAllocShadowID( HSHADOW hDir,
BOOL fFile
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
HSHADOW hShadow;
Assert(vfInShadowCrit != 0);
hShadow = UlAllocInode(lpdbShadow, hDir, fFile);
return (hShadow);
}
int FreeShadowID( HSHADOW hShadow
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
return(FreeInode(lpdbShadow, hShadow));
}
int GetShadowSpaceInfo(
LPSHADOWSTORE lpShSt
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
SHAREHEADER sSH;
if (ReadShareHeader(lpdbShadow, &sSH) < SRET_OK)
return SRET_ERROR;
lpShSt->sMax = sSH.sMax;
lpShSt->sCur = sSH.sCur;
lpShSt->uFlags= sSH.uFlags;
return SRET_OK;
}
int SetMaxShadowSpace(
long nFileSizeHigh,
long nFileSizeLow
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
SHAREHEADER sSH;
if (ReadShareHeader(lpdbShadow, &sSH) < SRET_OK)
return SRET_ERROR;
Win32ToDosFileSize(nFileSizeHigh, nFileSizeLow, &(sSH.sMax.ulSize));
if (WriteShareHeader(lpdbShadow, &sSH) < SRET_OK)
return SRET_ERROR;
return SRET_OK;
}
int AdjustShadowSpace(
long nFileSizeHighOld,
long nFileSizeLowOld,
long nFileSizeHighNew,
long nFileSizeLowNew,
BOOL fFile
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
DWORD dwFileSizeNew, dwFileSizeOld;
STOREDATA sSD;
int iRet = 0;
memset(&sSD, 0, sizeof(STOREDATA));
dwFileSizeNew = RealFileSize(nFileSizeLowNew);
dwFileSizeOld = RealFileSize(nFileSizeLowOld);
if (dwFileSizeNew > dwFileSizeOld)
{
sSD.ulSize = dwFileSizeNew - dwFileSizeOld;
iRet = AddStoreData(lpdbShadow, &sSD);
}
else if (dwFileSizeNew < dwFileSizeOld)
{
sSD.ulSize = dwFileSizeOld - dwFileSizeNew;
iRet = SubtractStoreData(lpdbShadow, &sSD);
}
return (iRet);
}
int AllocShadowSpace(
long nFileSizeHigh,
long nFileSizeLow,
BOOL fFile
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
STOREDATA sSD;
memset(&sSD, 0, sizeof(STOREDATA));
sSD.ulSize = RealFileSize(nFileSizeLow);
AddStoreData(lpdbShadow, &sSD);
return (0);
}
int FreeShadowSpace(
long nFileSizeHigh,
long nFileSizeLow,
BOOL fFile
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
STOREDATA sSD;
memset(&sSD, 0, sizeof(STOREDATA));
sSD.ulSize = RealFileSize(nFileSizeLow);
SubtractStoreData(lpdbShadow, &sSD);
return (0);
}
int
SetDatabaseStatus(
ULONG ulStatus,
ULONG uMask
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
SHAREHEADER sSH;
if (ReadShareHeader(lpdbShadow, &sSH) < SRET_OK)
return SRET_ERROR;
sSH.uFlags &= ~uMask;
sSH.uFlags |= ulStatus;
if (WriteShareHeader(lpdbShadow, &sSH) < SRET_OK)
return SRET_ERROR;
vulDatabaseStatus = sSH.uFlags;
return SRET_OK;
}
int
GetDatabaseInfo(
SHAREHEADER *psSH
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
if (ReadShareHeader(lpdbShadow, psSH) < SRET_OK)
return SRET_ERROR;
return SRET_OK;
}
int GetLocalNameHSHADOW( HSHADOW hShadow,
LPBYTE lpName,
int cbSize,
BOOL fExternal
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
LPSTR lpszName, lpT;
int iRet = SRET_ERROR;
lpT = lpszName = FormNameString(lpdbShadow, hShadow);
if (!lpszName)
{
return (SRET_ERROR);
}
if (fExternal)
{
#ifdef CSC_RECORDMANAGER_WINNT
lpT = lpszName + (sizeof(NT_DB_PREFIX)-1);
#endif
}
// bad interface, caller can't know what the problem was; needed to send in a pointer to cbSize
if (strlen(lpT) < ((ULONG)cbSize))
{
strcpy(lpName, lpT);
iRet = SRET_OK;
}
FreeNameString(lpszName);
return iRet;
}
int GetWideCharLocalNameHSHADOW(
HSHADOW hShadow,
USHORT *lpBuffer,
LPDWORD lpdwSize,
BOOL fExternal
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
LPSTR lpszName, lpT;
int iRet = SRET_ERROR;
DWORD dwRequiredSize;
lpT = lpszName = FormNameString(lpdbShadow, hShadow);
if (!lpszName)
{
return (SRET_ERROR);
}
if (fExternal)
{
#ifdef CSC_RECORDMANAGER_WINNT
lpT = lpszName + (sizeof(NT_DB_PREFIX)-1);
#endif
}
dwRequiredSize = (strlen(lpT)+1)*sizeof(USHORT);
// bad interface, caller can't know what the problem was; needed to send in a pointer to cbSize
if ( dwRequiredSize <= *lpdwSize)
{
BCSToUni(lpBuffer, lpT, dwRequiredSize/sizeof(USHORT), BCS_WANSI);
iRet = SRET_OK;
}
else
{
SetLastErrorLocal(ERROR_MORE_DATA);
*lpdwSize = dwRequiredSize;
}
FreeNameString(lpszName);
return iRet;
}
int CreateFileHSHADOW(
HSHADOW hShadow
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
CSCHFILE hf;
LPSTR lpszName;
int iRet = SRET_ERROR;
ULONG ulAttrib = 0;
lpszName = FormNameString(lpdbShadow, hShadow);
if (!lpszName)
{
return (SRET_ERROR);
}
// Nuke it if it exists, this is a very strict semantics
if(DeleteFileLocal(lpszName, ATTRIB_DEL_ANY) < SRET_OK)
{
if((GetLastErrorLocal() !=ERROR_FILE_NOT_FOUND) &&
(GetLastErrorLocal() !=ERROR_PATH_NOT_FOUND))
{
FreeNameString(lpszName);
return (SRET_ERROR);
}
}
ulAttrib = ((IsLeaf(hShadow) && mDatabaseEncryptionEnabled(vulDatabaseStatus))? FILE_ATTRIBUTE_ENCRYPTED:0);
if ((hf = R0OpenFileEx(ACCESS_READWRITE, ACTION_CREATEALWAYS, ulAttrib, lpszName, FALSE)))
{
CloseFileLocal(hf);
iRet = SRET_OK;
}
FreeNameString(lpszName);
return iRet;
}
#if defined(BITCOPY)
int OpenFileHSHADOWAndCscBmp(
HSHADOW hShadow,
USHORT usOpenFlags,
UCHAR bAction,
CSCHFILE far *lphf,
BOOL fOpenCscBmp,
DWORD filesize, // if !fOpenCscBmp this field is ignored
LPCSC_BITMAP * lplpbitmap
)
#else
int OpenFileHSHADOW(
HSHADOW hShadow,
USHORT usOpenFlags,
UCHAR bAction,
CSCHFILE far *lphf
)
#endif // defined(BITCOPY)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
LPSTR lpszName = NULL;
int iRet = SRET_ERROR;
ULONG ulAttrib = 0;
*lphf = NULL;
lpszName = FormNameString(lpdbShadow, hShadow);
if (!lpszName)
return (SRET_ERROR);
if (!(bAction & (ACTION_NEXISTS_CREATE|ACTION_CREATEALWAYS))) {
*lphf = OpenFileLocal(lpszName);
if (*lphf != NULL) {
#if defined(BITCOPY)
if (fOpenCscBmp)
CscBmpRead(lplpbitmap, lpszName, filesize);
#endif // defined(BITCOPY)
iRet = SRET_OK;
}
} else {
// Nuke it if it exists, this is a very strict semantics
if (DeleteFileLocal(lpszName, ATTRIB_DEL_ANY) < SRET_OK) {
if ((GetLastErrorLocal() != ERROR_FILE_NOT_FOUND) &&
(GetLastErrorLocal() != ERROR_PATH_NOT_FOUND)) {
iRet = SRET_ERROR;
goto Cleanup;
}
}
ulAttrib = 0;
if (IsLeaf(hShadow) && mDatabaseEncryptionEnabled(vulDatabaseStatus))
ulAttrib = FILE_ATTRIBUTE_ENCRYPTED;
*lphf = R0OpenFileEx(
ACCESS_READWRITE,
ACTION_CREATEALWAYS,
ulAttrib,
lpszName,
FALSE);
if (*lphf != NULL) {
#if defined(BITCOPY)
if (fOpenCscBmp)
CscBmpRead(lplpbitmap, lpszName, 0);
#endif // defined(BITCOPY)
iRet = SRET_OK;
}
}
Cleanup:
if (lpszName != NULL)
FreeNameString(lpszName);
return iRet;
}
#if defined(BITCOPY)
int
OpenCscBmp(
HSHADOW hShadow,
LPCSC_BITMAP *lplpbitmap)
{
LPSTR strmName = NULL;
int iRet = SRET_ERROR;
ULONG fileSizeLow;
ULONG fileSizeHigh;
strmName = FormAppendNameString(lpdbShadow, hShadow, CscBmpAltStrmName);
if (strmName == NULL)
return (SRET_ERROR);
if (GetSizeHSHADOW(hShadow, &fileSizeHigh, &fileSizeLow) < SRET_OK)
fileSizeLow = 0; // Set the bitmap size to 0 so it can expand later on
if (CscBmpRead(lplpbitmap, strmName, fileSizeLow) == 1)
iRet = SRET_OK;
FreeNameString(strmName);
return iRet;
}
#endif // defined(BITCOPY)
int GetSizeHSHADOW( HSHADOW hShadow,
ULONG *lpnFileSizeHigh,
ULONG *lpnFileSizeLow
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
ULONG uSize;
if (GetInodeFileSize(lpdbShadow, hShadow, &uSize) < SRET_OK)
return SRET_ERROR;
DosToWin32FileSize(uSize, lpnFileSizeHigh, lpnFileSizeLow);
return (0);
}
int GetDosTypeSizeHSHADOW( HSHADOW hShadow,
ULONG *lpFileSize
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
if (GetInodeFileSize(lpdbShadow, hShadow, lpFileSize) < SRET_OK)
return SRET_ERROR;
return (0);
}
BOOL PUBLIC
ExcludeFromCreateShadow(
USHORT *lpuName,
ULONG len,
BOOL fCheckFileTypeExclusionList
)
/*++
Routine Description:
Parameters:
lpuName File name
len size
fCheckFileTypeExclusionList if !FALSE, check exclusion list as well as the metacharacter rules
if FALSE check only the character exclusion rules
Return Value:
Notes:
--*/
{
ULONG i;
USHORT *lpuT1;
BOOL fRet = FALSE;
if (!len || (len> MAX_PATH))
{
return TRUE;
}
UseGlobalFilerecExt();
lpuT1 = (USHORT *)&vsFRExt;
memcpy(lpuT1, lpuName, len * sizeof(USHORT));
lpuT1[len] = 0;
if (!wstrpbrk(lpuT1, vtzExcludedCharsList))
{
//
if (fCheckFileTypeExclusionList)
{
for (i=0; i< vcntExclusionListEntries; ++i)
{
if(IFSMgr_MetaMatch(vlplpExclusionList[i], lpuT1, UFLG_NT|UFLG_META))
{
fRet = TRUE;
break;
}
}
}
}
else
{
fRet = TRUE; // exclude
}
UnUseGlobalFilerecExt();
return fRet;
}
BOOL PUBLIC
CheckForBandwidthConservation(
USHORT *lpuName,
ULONG len
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
ULONG i;
USHORT *lpuT1;
BOOL fRet = FALSE;
if (!len || (len> MAX_PATH))
{
return FALSE;
}
UseGlobalFilerecExt();
lpuT1 = (USHORT *)&vsFRExt;
memcpy(lpuT1, lpuName, len * sizeof(USHORT));
lpuT1[len] = 0;
for (i=0; i< vcntBandwidthConservationListEntries; ++i)
{
if(IFSMgr_MetaMatch(vlplpBandwidthConservationList[i], lpuT1, UFLG_NT|UFLG_META))
{
fRet = TRUE;
break;
}
}
UnUseGlobalFilerecExt();
return fRet;
}
int PUBLIC // ret
CreateShadow( //
HSHADOW hDir,
LPFIND32 lpFind32,
ULONG uFlags,
LPHSHADOW lphNew,
BOOL *lpfCreated
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
ULONG uStatus;
int iRet = SRET_ERROR;
Assert(vfInShadowCrit != 0);
if (lpfCreated)
{
*lpfCreated = FALSE;
}
mClearBits(uFlags, SHADOW_NOT_FSOBJ);
if (GetShadow(hDir, lpFind32->cFileName, lphNew, NULL, &uStatus, NULL)>=SRET_OK)
{
if (*lphNew)
{
CShadowKdPrint(ALWAYS,("CreateShadow: already exists for %ws\r\n", lpFind32->cFileName));
if (mNotFsobj(uStatus))
{
iRet = SRET_ERROR;
}
else
{
iRet = SetShadowInfo(hDir, *lphNew, lpFind32, uFlags, SHADOW_FLAGS_ASSIGN);
}
}
else
{
iRet = CreateShadowInternal(hDir, lpFind32, uFlags, NULL, lphNew);
if ((iRet >= SRET_OK) && lpfCreated)
{
*lpfCreated = TRUE;
}
}
}
return (iRet);
}
int PUBLIC // ret
CreateShadowInternal(
HSHADOW hDir,
LPFIND32 lpFind32,
ULONG uFlags,
LPOTHERINFO lpOI,
LPHSHADOW lphNew
)
/*++
Routine Description:
Routine that creates database entries for all names other than the root of a share
HCreateShareObj deals with createing the share entry where the root of the share gets created
Parameters:
hDir Directory inode in which to create the entry
lpFind32 WIN32_FIND_DATA info to be kept in the database
uFlags status flags (SHADOW_XXXX in csc\inc\shdcom.h) to be assigned to this entry
lpOI all the rest of the metadata needed for managing the entry. May be NULL
lphNew out parameter, returns the inode that was created if successful
Return Value:
Notes:
--*/
{
PRIQREC sPQ;
int iRet = SRET_ERROR;
LPFILERECEXT lpFR = NULL, lpFRUse;
HSHADOW hNew=0, hAncestor=0;
HSHARE hShare=0;
ULONG ulRefPri=MAX_PRI, ulrecDirEntry=INVALID_REC, ulHintPri=0, ulHintFlags=0;
STOREDATA sSD;
Assert(vfInShadowCrit != 0);
if (!(!hDir || IsDirInode(hDir)))
return SRET_ERROR;
BEGIN_TIMING(CreateShadowInternal);
if (InuseGlobalFRExt())
{
if (!(lpFR = (LPFILERECEXT)AllocMem(sizeof(FILERECEXT))))
goto bailout;
lpFRUse = lpFR;
}
else
{
UseGlobalFilerecExt();
lpFRUse = &vsFRExt;
}
memset(lpFRUse, 0, sizeof(FILERECEXT));
// Don't do anything for server yet
if (hDir)
{
*lphNew = hNew = UlAllocInode(lpdbShadow, hDir, IsFile(lpFind32->dwFileAttributes));
if (!hNew)
{
CShadowKdPrint(BADERRORS,("Error creating shadow Inode\r\n"));
goto bailout;
}
if (IsFile(lpFind32->dwFileAttributes))
{
if (lpFind32->nFileSizeHigh)
{
SetLastErrorLocal(ERROR_ONLY_IF_CONNECTED);
goto bailout;
}
if(CreateFileHSHADOW(hNew) == SRET_ERROR)
{
CShadowKdPrint(BADERRORS,("Error creating shadow data for %x \r\n", hNew));
goto bailout;
}
// start file priorities with max
ulRefPri=MAX_PRI;
}
else
{
if(CreateDirInode(lpdbShadow, 0, hDir, hNew) < 0)
{
CShadowKdPrint(BADERRORS,("Error creating shadow data for %x \r\n", hNew));
goto bailout;
}
// start directory priorities with MIN_PRI, this is to optimize
// later moving
// A better solution might be to change createshadow to take refpri and pincount
// as parameters
ulRefPri=MIN_PRI;
}
CopyFindInfoToFilerec(lpFind32, lpFRUse, CPFR_INITREC|CPFR_COPYNAME);
//RxDbgTrace(0,Dbg,("CreateShadowInternal3 %s %s\n",
// lpFRUse->sFR.rgcName, lpFRUse->sFR.rg83Name));
lpFRUse->sFR.uchRefPri = (UCHAR)ulRefPri;
lpFRUse->sFR.uchHintPri = (UCHAR)ulHintPri;
lpFRUse->sFR.uchHintFlags = (UCHAR)ulHintFlags;
// overwite filerec with any info that the user gave
if (lpOI)
{
CShadowKdPrint(CREATESHADOWHI,("ulHintPri=%x ulHintFlags=%x\r\n",lpOI->ulHintPri, lpOI->ulHintFlags));
CopyOtherInfoToFilerec(lpOI, lpFRUse);
}
lpFRUse->sFR.ftOrgTime = lpFRUse->sFR.ftLastWriteTime;
CShadowKdPrint(CREATESHADOWHI,("CreateShadow: %x for %ws: loctLo=%x loctHi=%x \r\n",
hNew,
lpFRUse->sFR.rgwName,
lpFRUse->sFR.ftOrgTime.dwLowDateTime,
lpFRUse->sFR.ftOrgTime.dwHighDateTime));
lpFRUse->sFR.ulidShadow = hNew;
lpFRUse->sFR.uStatus = (USHORT)uFlags;
lpFRUse->sFR.ulLastRefreshTime = (ULONG)IFSMgr_Get_NetTime();
// if this entry is being created offline, then it doesn't have any original inode
if (uFlags & SHADOW_LOCALLY_CREATED)
{
lpFRUse->sFR.ulidShadowOrg = 0;
}
else
{
lpFRUse->sFR.ulidShadowOrg = hNew;
}
#ifdef DEBUG
ValidatePri(lpFRUse);
#endif
if(!(ulrecDirEntry = AddFileRecordFR(lpdbShadow, hDir, lpFRUse)))
{
// could be legit failure if we are running out of disk space
CShadowKdPrint(CREATESHADOWHI,("Failed AddFileRecordFR for %x, %ws\r\n",
hNew,
lpFRUse->sFR.rgwName));
goto bailout;
}
Assert(ulrecDirEntry != INVALID_REC);
if(FindAncestorsFromInode(lpdbShadow, hDir, &hAncestor, &hShare) < 0)
{
CShadowKdPrint(CREATESHADOWHI,("Failed to find ancestor for %x, %ws\r\n",
hNew,
lpFRUse->sFR.rgwName));
goto bailout;
}
// mark the inode as locally created or not
// NB, this flag has meaning only for the inode
// We use this information during reintegration of
// renames and deletes
if (uFlags & SHADOW_LOCALLY_CREATED)
{
uFlags |= SHADOW_LOCAL_INODE;
}
else
{
uFlags &= ~SHADOW_LOCAL_INODE;
}
if (AddPriQRecord( lpdbShadow,
hShare,
hDir,
hNew,
uFlags,
(ULONG)(lpFRUse->sFR.uchRefPri),
(ULONG)(lpFRUse->sFR.uchIHPri),
(ULONG)(lpFRUse->sFR.uchHintPri),
(ULONG)(lpFRUse->sFR.uchHintFlags),
ulrecDirEntry) < 0)
{
CShadowKdPrint(CREATESHADOWHI,("Failed to AddPriQRecord for %x, %ws\r\n",
hNew,
lpFRUse->sFR.rgwName));
Assert(FALSE);
goto bailout;
}
// The check below was is a holdover from our now-defunct hints scheme
if (!mNotFsobj(lpFRUse->sFR.uStatus))
{
memset(&sSD, 0, sizeof(STOREDATA));
CShadowKdPrint(CREATESHADOWHI,("uchHintPri=%x uchHintFlags=%x\r\n",lpFRUse->sFR.uchHintPri, lpFRUse->sFR.uchHintFlags));
if ((!(lpFind32->dwFileAttributes &
(FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE))))
{
sSD.ucntFiles++;
// if there is a initial pin count or special pinflags are set
// then this files data should not be considered for space accounting
sSD.ulSize = (lpFRUse->sFR.uchHintPri || mPinFlags(lpFRUse->sFR.uchHintFlags))?0:RealFileSize(lpFRUse->sFR.ulFileSize);
}
else
{
sSD.ucntDirs++;
}
if (sSD.ulSize)
{
CShadowKdPrint(STOREDATA,("CreateShadowInternal: Adding %d for hDir=%x Name=%ws\r\n", sSD.ulSize, hDir, lpFind32->cFileName));
}
else
{
if ((!(lpFind32->dwFileAttributes &
(FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE)))
&& RealFileSize(lpFRUse->sFR.ulFileSize)
)
{
Assert((lpFRUse->sFR.uchHintPri || mPinFlags(lpFRUse->sFR.uchHintFlags)));
}
}
AddStoreData(lpdbShadow, &sSD);
AdjustSparseStaleDetectionCount(hShare, lpFRUse);
}
vdwCSCNameSpaceVersion++;
vdwPQVersion++;
iRet = SRET_OK;
}
bailout:
if (iRet==SRET_ERROR)
{
if (hNew)
{
FreeInode(lpdbShadow, hNew);
}
}
if (lpFR)
FreeMem(lpFR);
else
UnUseGlobalFilerecExt();
END_TIMING(CreateShadowInternal);
return iRet;
}
int
DeleteShadow(
HSHADOW hDir,
HSHADOW hShadow
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
return DeleteShadowInternal(hDir, hShadow, FALSE); // try a gentle delete
}
ULONG DelShadowInternalEntries = 0;
#define JOE_DECL_CURRENT_PROGRESS CscProgressDelShdwI
JOE_DECL_PROGRESS();
int
DeleteShadowInternal( //
HSHADOW hDir,
HSHADOW hShadow,
BOOL fForce
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
STOREDATA sSD;
int iRet= SRET_ERROR;
PRIQREC sPQ;
LPFILERECEXT lpFR = NULL, lpFRUse;
Assert(vfInShadowCrit != 0);
DelShadowInternalEntries++;
JOE_INIT_PROGRESS(DelShadowInternalEntries,&hDir);
if (InuseGlobalFRExt())
{
if (!(lpFR = (LPFILERECEXT)AllocMem(sizeof(FILERECEXT))))
goto bailout;
lpFRUse = lpFR;
}
else
{
UseGlobalFilerecExt();
lpFRUse = &vsFRExt;
}
if (!hDir)
{
if(FindSharerecFromInode(lpdbShadow, hShadow, (LPSHAREREC)lpFRUse))
{
if (fForce || !HasDescendents(lpdbShadow, 0, ((LPSHAREREC)lpFRUse)->ulidShadow))
{
iRet = DestroyShareInternal((LPSHAREREC)lpFRUse);
}
}
}
else
{
int iRetInner;
//ASSERT(hShadow!=0);
JOE_PROGRESS(2);
if (!fForce && // not being forced
!FInodeIsFile(lpdbShadow, hDir, hShadow) && // and it is a dir
HasDescendents(lpdbShadow, hDir, hShadow)) // and has descendents
{
JOE_PROGRESS(3);
CShadowKdPrint(DELETESHADOWBAD,("DeleteShadow: Trying to delete a directory with descendents \r\n"));
SetLastErrorLocal(ERROR_DIR_NOT_EMPTY);
goto bailout;
}
JOE_PROGRESS(4);
if(FindPriQRecord(lpdbShadow, hDir, hShadow, &sPQ)<=0)
{
JOE_PROGRESS(5);
CShadowKdPrint(DELETESHADOWBAD,("DeleteShadow: Trying to delete a noexistent inode %x \r\n", hShadow));
SetLastErrorLocal(ERROR_FILE_NOT_FOUND);
goto bailout;
}
Assert(hShadow == sPQ.ulidShadow);
DeleteFromHandleCache(hShadow);
iRetInner = DeleteInodeFile(lpdbShadow, hShadow);
if(iRetInner<0){
if (GetLastErrorLocal() != ERROR_FILE_NOT_FOUND)
{
CShadowKdPrint(DELETESHADOWBAD,("DeleteShadow: delete stent inode %x \r\n", hShadow));
goto bailout;
}
}
JOE_PROGRESS(6);
if(DeleteFileRecFromInode(lpdbShadow, hDir, hShadow, sPQ.ulrecDirEntry, lpFRUse) == 0L)
{
JOE_PROGRESS(7);
CShadowKdPrint(DELETESHADOWBAD,("DeleteShadow:DeleteFileRecord failed \r\n"));
goto bailout;
}
JOE_PROGRESS(8);
Assert(hShadow == lpFRUse->sFR.ulidShadow);
JOE_PROGRESS(11);
// No error checking is done on the following call as they
// are benign errors.
iRetInner = DeletePriQRecord(lpdbShadow, hDir, hShadow, &sPQ);
if(iRetInner>=0){
JOE_PROGRESS(12);
CShadowKdPrint(DELETESHADOWBAD,("DeleteShadow priq %d\n", iRetInner));
}
JOE_PROGRESS(13);
memset((LPVOID)&sSD, 0, sizeof(STOREDATA));
// Let us deal with only file records for now
if (!mNotFsobj(lpFRUse->sFR.uStatus))
{
if(IsFile(lpFRUse->sFR.dwFileAttrib))
{
sSD.ucntFiles++;
// subtract store data only if it was accounted for in the first place
sSD.ulSize = (lpFRUse->sFR.uchHintPri || mPinFlags(lpFRUse->sFR.uchHintFlags))
? 0 : RealFileSize(lpFRUse->sFR.ulFileSize);
}
else
{
sSD.ucntDirs++;
}
if (sSD.ulSize)
{
CShadowKdPrint(STOREDATA,("DeleteShadowInternal:Deleting storedata for hDir=%x Name=%ws\r\n", hDir, lpFRUse->sFR.rgwName));
}
SubtractStoreData(lpdbShadow, &sSD);
}
if (!FInodeIsFile(lpdbShadow, hDir, hShadow) && lpDeleteCBForIoctl)
{
(*lpDeleteCBForIoctl)(hDir, hShadow);
}
// we don't care if this fails because then the worst
// that can happen is that this inode will be permanenetly lost.
// Checkdisk utility should recover this.
JOE_PROGRESS(14);
FreeInode(lpdbShadow, hShadow);
// Yes we did delete a shadow
iRet = SRET_OK;
vdwCSCNameSpaceVersion++;
vdwPQVersion++;
}
bailout:
JOE_PROGRESS(20);
#if 0 //this insert has errors.........
#if VERBOSE > 2
if (iRet==SRET_OK)
CShadowKdPrint(DELETESHADOWHI,("DeleteShadow: deleted shadow %x for %s\r\n", lpFRUse->sFR.ulidShadow, lpName));
else
CShadowKdPrint(DELETESHADOWHI,("DeleteShadow: error deleting shadow for %s\r\n", lpName));
#endif //VERBOSE > 2
#endif //if 0 for errors
if (lpFR)
FreeMem(lpFR);
else
UnUseGlobalFilerecExt();
JOE_PROGRESS(21);
return (iRet);
}
int TruncateDataHSHADOW(
HSHADOW hDir,
HSHADOW hShadow
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
ULONG uSize=0;
// long nFileSizeHigh, nFileSizeLow;
Assert(vfInShadowCrit != 0);
Assert(!hDir || IsDirInode(hDir));
if (FInodeIsFile(lpdbShadow, hDir, hShadow))
{
// GetInodeFileSize(lpdbShadow, hShadow, &uSize);
// DosToWin32FileSize(uSize, &nFileSizeHigh, &nFileSizeLow);
if (TruncateInodeFile(lpdbShadow, hShadow) < SRET_OK)
return SRET_ERROR;
// FreeShadowSpace(nFileSizeHigh, nFileSizeLow, IsLeaf(hShadow));
}
else
{
if (!HasDescendents(lpdbShadow, hDir, hShadow))
{
CreateDirInode(lpdbShadow, 0, hDir, hShadow);
}
else
{
SetLastErrorLocal(ERROR_ACCESS_DENIED);
return SRET_ERROR;
}
}
return(SRET_OK);
}
int PUBLIC
RenameShadow(
HSHADOW hDirFrom,
HSHADOW hShadowFrom,
HSHADOW hDirTo,
LPFIND32 lpFind32To,
ULONG uShadowStatusTo,
LPOTHERINFO lpOI,
ULONG uRenameFlags,
LPHSHADOW lphShadowTo
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
return (RenameShadowEx(hDirFrom, hShadowFrom, 0, hDirTo, lpFind32To, uShadowStatusTo, lpOI, uRenameFlags, NULL, NULL, lphShadowTo));
}
int PUBLIC
RenameShadowEx(
HSHADOW hDirFrom,
HSHADOW hShadowFrom,
HSHARE hShareTo,
HSHADOW hDirTo,
LPFIND32 lpFind32To,
ULONG uShadowStatusTo,
LPOTHERINFO lpOI,
ULONG uRenameFlags,
LPVOID lpSecurityBlobTo,
LPDWORD lpdwBlobSizeTo,
LPHSHADOW lphShadowTo
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int iRet = SRET_ERROR;
HSHADOW hShadowTo;
LPFILERECEXT lpFR = NULL, lpFRUse;
BOOL fFile = FInodeIsFile(lpdbShadow, hDirFrom, hShadowFrom);
Assert(vfInShadowCrit != 0);
Assert(!hDirFrom || IsDirInode(hDirFrom));
Assert(!hDirTo || IsDirInode(hDirTo));
if (InuseGlobalFRExt())
{
if (!(lpFR = (LPFILERECEXT)AllocMem(sizeof(FILERECEXT))))
goto bailout;
lpFRUse = lpFR;
}
else
{
UseGlobalFilerecExt();
lpFRUse = &vsFRExt;
}
// If we are keeping the renamer, we are going to have to create
// a new inode and an empty directory/file
if (mQueryBits(uRenameFlags, RNMFLGS_MARK_SOURCE_DELETED))
{
// Allocate an INODE for the new shadow
if (!(hShadowTo = UlAllocInode(lpdbShadow, hDirFrom, IsLeaf(hShadowFrom))))
{
goto bailout;
}
Assert(IsLeaf(hShadowFrom) == IsLeaf(hShadowTo));
if (!IsLeaf(hShadowTo))
{
if(CreateDirInode(lpdbShadow, 0, hDirFrom, hShadowTo) < 0)
goto bailout;
}
else
{
if(CreateFileHSHADOW(hShadowTo) < 0)
{
goto bailout;
}
}
}
else
{
hShadowTo = 0;
}
iRet = RenameDirFileHSHADOW(hDirFrom, hShadowFrom, hShareTo, hDirTo, hShadowTo, uShadowStatusTo, lpOI, uRenameFlags, lpFRUse, lpFind32To, lpSecurityBlobTo, lpdwBlobSizeTo);
if (lphShadowTo)
{
*lphShadowTo = (hShadowTo)?hShadowTo:hShadowFrom;
}
bailout:
if (lpFR)
FreeMem(lpFR);
else
UnUseGlobalFilerecExt();
return (iRet);
}
int RenameDirFileHSHADOW(
HSHADOW hDirFrom,
HSHADOW hShadowFrom,
HSHADOW hShareTo,
HSHADOW hDirTo,
HSHADOW hShadowTo,
ULONG uShadowStatusTo,
LPOTHERINFO lpOI,
ULONG uRenameFlags,
LPFILERECEXT lpFRUse,
LPFIND32 lpFind32To,
LPVOID lpSecurityBlobTo,
LPDWORD lpdwBlobSizeTo
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
FILEHEADER sFH;
PRIQREC sPQ;
int count, iRet = SRET_ERROR;
LPFILERECEXT lpFRDir = NULL;
ULONG ulrecDirEntryTo, ulrecDirEntryFrom;
BOOL fWasPinned=FALSE, fIsPinned=FALSE;
Assert(lpFind32To);
if(FindPriQRecord(lpdbShadow, hDirFrom, hShadowFrom, &sPQ)<=0)
{
// Assert(FALSE);
goto bailout;
}
ulrecDirEntryFrom = sPQ.ulrecDirEntry;
if(CShadowFindFilerecFromInode(lpdbShadow, hDirFrom, hShadowFrom, &sPQ, lpFRUse)<=0)
{
// Assert(FALSE);
goto bailout;
}
Assert(sPQ.ulidShadow == lpFRUse->sFR.ulidShadow);
fWasPinned = ((lpFRUse->sFR.uchHintPri || mPinFlags(lpFRUse->sFR.uchHintFlags)) != 0);
if (mQueryBits(uRenameFlags, RNMFLGS_MARK_SOURCE_DELETED))
{
lpFRDir = (LPFILERECEXT)AllocMem(sizeof(FILERECEXT));
if (!lpFRDir)
{
Assert(FALSE);
goto bailout;
}
}
if (lpFRDir)
{
Assert (mQueryBits(uRenameFlags, RNMFLGS_MARK_SOURCE_DELETED));
// Save it's contents
*lpFRDir = *lpFRUse;
}
// Change the name of hShadowFrom to the new name
CopyNamesToFilerec(lpFind32To, lpFRUse);
if (lpOI)
{
CopyOtherInfoToFilerec(lpOI, lpFRUse);
CopyOtherInfoToPQ(lpOI, &sPQ);
}
fIsPinned = ((lpFRUse->sFR.uchHintPri || mPinFlags(lpFRUse->sFR.uchHintFlags)) != 0);
// And it's status as requested by the caller
lpFRUse->sFR.uStatus = (USHORT)uShadowStatusTo;
if (uRenameFlags & RNMFLGS_USE_FIND32_TIMESTAMPS)
{
lpFRUse->sFR.ftLastWriteTime = lpFind32To->ftLastWriteTime;
lpFRUse->sFR.ftOrgTime = lpFind32To->ftLastAccessTime;
}
// Both SAVE and RETAIN should never be ON
Assert(mQueryBits(uRenameFlags, (RNMFLGS_SAVE_ALIAS|RNMFLGS_RETAIN_ALIAS))
!=(RNMFLGS_SAVE_ALIAS|RNMFLGS_RETAIN_ALIAS));
if (mQueryBits(uRenameFlags, RNMFLGS_SAVE_ALIAS))
{
Assert(!mQueryBits(uRenameFlags, RNMFLGS_RETAIN_ALIAS));
Assert(hShadowTo != 0);
lpFRUse->sFR.ulidShadowOrg = hShadowTo;
}
else if (!mQueryBits(uRenameFlags, RNMFLGS_RETAIN_ALIAS))
{
lpFRUse->sFR.ulidShadowOrg = 0;
}
// update the security context
CopyBufferToSecurityContext(lpSecurityBlobTo, lpdwBlobSizeTo, &(lpFRUse->sFR.Security));
// Write the record. Now hDirFrom is the renamee
if ((ulrecDirEntryTo = AddFileRecordFR(lpdbShadow, hDirTo, lpFRUse)) <=0)
{
// this could happen if there is no disk space
goto bailout;
}
// if this going across shares, fix up the PQ entry with the right share
if (hShareTo)
{
sPQ.ulidShare = hShareTo;
}
sPQ.ulidDir = hDirTo;
sPQ.ulrecDirEntry = ulrecDirEntryTo;
sPQ.uStatus = ((USHORT)uShadowStatusTo | (sPQ.uStatus & SHADOW_LOCAL_INODE));
if (UpdatePriQRecord(lpdbShadow, hDirTo, hShadowFrom, &sPQ)< 0)
{
Assert(FALSE);
goto bailout;
}
// by this time a hShadowFrom has been associated with the new name
// and is also pointing back to hDirTo
// We still have a filerec entry which associates hShadowFrom with
// the old name and we need to take care of it
if (mQueryBits(uRenameFlags, RNMFLGS_MARK_SOURCE_DELETED))
{
// we are running in disconnected mode
// need to keep the old name
Assert(hShadowTo != 0);
lpFRDir->sFR.uStatus = SHADOW_DELETED;
lpFRDir->sFR.ulidShadow = hShadowTo;
// update filerecord without doing any compares
if(UpdateFileRecFromInodeEx(lpdbShadow, hDirFrom, hShadowFrom, ulrecDirEntryFrom, lpFRDir, FALSE)<=0)
{
Assert(FALSE);
goto bailout;
}
if(AddPriQRecord(lpdbShadow, sPQ.ulidShare, hDirFrom, hShadowTo, SHADOW_DELETED
, (ULONG)(sPQ.uchRefPri), (ULONG)(sPQ.uchIHPri)
, (ULONG)(sPQ.uchHintPri), (ULONG)(sPQ.uchHintFlags), ulrecDirEntryFrom)<=0)
{
Assert(FALSE);
goto bailout;
}
}
else
{
if(DeleteFileRecFromInode(lpdbShadow, hDirFrom, hShadowFrom, ulrecDirEntryFrom, lpFRUse) <= 0L)
{
Assert(FALSE);
goto bailout;
}
}
if (IsLeaf(hShadowFrom) && (fWasPinned != fIsPinned))
{
CShadowKdPrint(STOREDATA,("RenameDirFileHSHADOW: hDirFrom=%x hShadowFrom=%x hDirTo=%x To=%ws\r\n", hDirFrom, hShadowFrom, hDirTo, lpFind32To->cFileName));
CShadowKdPrint(STOREDATA,("RenameDirFileHSHADOW: WasPinned=%d IsPinned=%d\r\n", fWasPinned, fIsPinned));
AdjustShadowSpace( 0,
(fWasPinned)?0:RealFileSize(lpFRUse->sFR.ulFileSize), // if it was pinned it's old size was zero for space computation
// else it was the actual size
0,
(fWasPinned)?RealFileSize(lpFRUse->sFR.ulFileSize):0, // if it was pinned it's new size should be zero for space computation
// else it should be the actual size
TRUE);
}
iRet = SRET_OK;
vdwCSCNameSpaceVersion++;
bailout:
if (lpFRDir)
{
FreeMem(lpFRDir);
}
return (iRet);
}
int PUBLIC // ret
GetShadow( //
HSHADOW hDir,
USHORT *lpName,
LPHSHADOW lphShadow,
LPFIND32 lpFind32,
ULONG far *lpuShadowStatus,
LPOTHERINFO lpOI
) //
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
return (GetShadowEx(hDir, lpName, lphShadow, lpFind32, lpuShadowStatus, lpOI, NULL, NULL));
}
int PUBLIC // ret
GetShadowEx( //
HSHADOW hDir,
USHORT *lpName,
LPHSHADOW lphShadow,
LPFIND32 lpFind32,
ULONG far *lpuShadowStatus,
LPOTHERINFO lpOI,
LPVOID lpSecurityBlob,
LPDWORD lpdwBlobSize
) //
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int iRet=SRET_ERROR;
LPFILERECEXT lpFR = NULL, lpFRUse;
Assert(vfInShadowCrit != 0);
if(!(!hDir || IsDirInode(hDir)))
{
return iRet;
}
BEGIN_TIMING(GetShadow);
if (InuseGlobalFRExt())
{
if (!(lpFR = (LPFILERECEXT)AllocMem(sizeof(FILERECEXT))))
goto bailout;
lpFRUse = lpFR;
}
else
{
UseGlobalFilerecExt();
lpFRUse = &vsFRExt;
}
*lphShadow = 0L;
*lpuShadowStatus = 0;
if (!hDir)
{
// We are looking for the root
if(FindShareRecord(lpdbShadow, lpName, (LPSHAREREC)lpFRUse))
{
*lphShadow = ((LPSHAREREC)lpFRUse)->ulidShadow;
*lpuShadowStatus = (ULONG)(((LPSHAREREC)lpFRUse)->uStatus);
if (lpFind32)
{
CopySharerecToFindInfo(((LPSHAREREC)lpFRUse), lpFind32);
}
if (lpOI)
{
CopySharerecToOtherInfo((LPSHAREREC)lpFRUse, lpOI);
}
CopySecurityContextToBuffer(
&((LPSHAREREC)lpFRUse)->sShareSecurity,
lpSecurityBlob,
lpdwBlobSize);
}
}
else
{
if (FindFileRecord(lpdbShadow, hDir, lpName, lpFRUse))
{
*lphShadow = lpFRUse->sFR.ulidShadow;
if (lpFind32)
{
CopyFilerecToFindInfo(lpFRUse, lpFind32);
}
*lpuShadowStatus = lpFRUse->sFR.uStatus;
CopySecurityContextToBuffer(&(lpFRUse->sFR.Security), lpSecurityBlob, lpdwBlobSize);
}
if (lpOI)
{
CopyFilerecToOtherInfo(lpFRUse, lpOI);
}
}
iRet = SRET_OK;
if (*lphShadow)
{
CShadowKdPrint(GETSHADOWHI,("GetShadow: %0lX is the shadow for %ws \r\n", *lphShadow, lpName));
if (0) { //keep this in case we need it again.........
if ((lpName[0]==L'm') && (lpName[1]==L'f') && (lpName[2]==0)) {
DbgPrint("Found mf!!!!\n");
SET_HSHADOW_SPECIAL(*lphShadow);
}
}
}
else
{
CShadowKdPrint(GETSHADOWHI,("GetShadow: No shadow for %ws \r\n", lpName));
}
bailout:
if (lpFR)
FreeMem(lpFR);
else
UnUseGlobalFilerecExt();
END_TIMING(GetShadow);
return iRet;
}
int PUBLIC // ret
ChkStatusHSHADOW( //
HSHADOW hDir,
HSHADOW hShadow,
LPFIND32 lpFind32,
ULONG far *lpuStatus
) //
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int iRet;
iRet = ReadShadowInfo(hDir, hShadow, lpFind32, lpuStatus, NULL, NULL, NULL, RSI_COMPARE);
return(iRet);
}
int PUBLIC // ret
ChkUpdtStatusHSHADOW( //
HSHADOW hDir,
HSHADOW hShadow,
LPFIND32 lpFind32,
ULONG far *lpuStatus
) //
{
int iRet;
iRet = ReadShadowInfo(hDir, hShadow, lpFind32, lpuStatus, NULL, NULL, NULL, RSI_COMPARE|RSI_SET);
return(iRet);
}
int PUBLIC GetShadowInfo
(
HSHADOW hDir,
HSHADOW hShadow,
LPFIND32 lpFind32,
ULONG far *lpuStatus,
LPOTHERINFO lpOI
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int iRet=SRET_ERROR;
SHAREREC sSR;
BEGIN_TIMING(GetShadowInfo);
iRet = ReadShadowInfo(hDir, hShadow, lpFind32, lpuStatus, lpOI, NULL, NULL, RSI_GET);
END_TIMING(GetShadowInfo);
return(iRet);
}
int PUBLIC GetShadowInfoEx
(
HSHADOW hDir,
HSHADOW hShadow,
LPFIND32 lpFind32,
ULONG far *lpuStatus,
LPOTHERINFO lpOI,
LPVOID lpSecurityBlob,
LPDWORD lpdwBlobSize
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int iRet=SRET_ERROR;
SHAREREC sSR;
BEGIN_TIMING(GetShadowInfo);
iRet = ReadShadowInfo(hDir, hShadow, lpFind32, lpuStatus, lpOI, lpSecurityBlob, lpdwBlobSize, RSI_GET);
END_TIMING(GetShadowInfo);
return(iRet);
}
int PUBLIC // ret
SetShadowInfo( //
HSHADOW hDir,
HSHADOW hShadow,
LPFIND32 lpFind32,
ULONG uFlags,
ULONG uOp
) //
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
return (SetShadowInfoEx(hDir, hShadow, lpFind32, uFlags, uOp, NULL, NULL, NULL));
}
int PUBLIC // ret
SetShadowInfoEx( //
HSHADOW hDir,
HSHADOW hShadow,
LPFIND32 lpFind32,
ULONG uFlags,
ULONG uOp,
LPOTHERINFO lpOI,
LPVOID lpSecurityBlob,
LPDWORD lpdwBlobSize
) //
/*++
Routine Description:
This routine is the central routine that modifies the database entry for a particular inode
Parameters:
Return Value:
Notes:
--*/
{
int iRet = SRET_ERROR;
LPFILERECEXT lpFR = NULL, lpFRUse;
PRIQREC sPQ;
ULONG uOldSize = 0, uNewSize=0, ulOldHintPri=0, ulOldHintFlags = 0, ulOldRefPri, ulOldFlags;
BOOL fRefPriChange = FALSE;
Assert(vfInShadowCrit != 0);
if(!(!hDir || IsDirInode(hDir)))
{
return iRet;
}
BEGIN_TIMING(SetShadowInfoInternal);
if (lpFind32)
{
if(!( (IsLeaf(hShadow) && IsFile(lpFind32->dwFileAttributes)) ||
(!IsLeaf(hShadow) && !IsFile(lpFind32->dwFileAttributes))))
{
return SRET_ERROR;
}
}
if (InuseGlobalFRExt())
{
if (!(lpFR = (LPFILERECEXT)AllocMem(sizeof(FILERECEXT))))
goto bailout;
lpFRUse = lpFR;
}
else
{
UseGlobalFilerecExt();
lpFRUse = &vsFRExt;
}
if (!hDir)
{
// We are looking for the root
if(FindSharerecFromInode(lpdbShadow, hShadow, (LPSHAREREC)lpFRUse))
{
if (lpFind32)
{
CopyFindInfoToSharerec(lpFind32, (LPSHAREREC)lpFRUse);
}
if (lpOI)
{
CopyOtherInfoToSharerec(lpOI, (LPSHAREREC)lpFRUse);
}
CopyBufferToSecurityContext( lpSecurityBlob,
lpdwBlobSize,
&(((LPSHAREREC)lpFRUse)->sRootSecurity));
if (mAndShadowFlags(uOp))
{
((LPSHAREREC)lpFRUse)->usRootStatus &= (USHORT)uFlags;
}
else if (mOrShadowFlags(uOp))
{
((LPSHAREREC)lpFRUse)->usRootStatus |= (USHORT)uFlags;
}
else
{
((LPSHAREREC)lpFRUse)->usRootStatus = (USHORT)uFlags;
}
iRet = SetShareRecord(lpdbShadow, ((LPSHAREREC)lpFRUse)->ulShare, (LPSHAREREC)lpFRUse);
}
}
else
{
IF_HSHADOW_SPECIAL(hShadow) {
//ASSERT(!"SpecialShadow in setshadinfo");
}
if(FindPriQRecord(lpdbShadow, hDir, hShadow, &sPQ) < 0)
{
goto bailout;
}
Assert((sPQ.ulidDir == hDir) && (sPQ.ulidShadow == hShadow));
if (CShadowFindFilerecFromInode(lpdbShadow, hDir, hShadow, &sPQ, lpFRUse)> 0)
{
Assert(lpFRUse->sFR.ulidShadow == hShadow);
uOldSize = uNewSize = lpFRUse->sFR.ulFileSize;
ulOldFlags = lpFRUse->sFR.usStatus;
if (lpFind32)
{
uNewSize = (ULONG)(lpFind32->nFileSizeLow);
CopyFindInfoToFilerec(lpFind32, lpFRUse, (mChange83Name(uOp))?CPFR_COPYNAME:0);
if (!mDontUpdateOrgTime(uOp))
{
lpFRUse->sFR.ftOrgTime = lpFRUse->sFR.ftLastWriteTime;
}
}
if (mAndShadowFlags(uOp))
{
lpFRUse->sFR.uStatus &= (USHORT)uFlags;
}
else if (mOrShadowFlags(uOp))
{
lpFRUse->sFR.uStatus |= (USHORT)uFlags;
}
else
{
lpFRUse->sFR.uStatus = (USHORT)uFlags;
}
if (mShadowNeedReint(ulOldFlags) && !mShadowNeedReint(lpFRUse->sFR.usStatus))
{
if(DeleteStream(lpdbShadow, hShadow, CscBmpAltStrmName) < SRET_OK)
{
DbgPrint("DeleteStream failed with %x /n", GetLastErrorLocal());
goto bailout;
}
}
if (lpOI)
{
// save some key old info before copying the new info
ulOldHintPri = lpFRUse->sFR.uchHintPri;
ulOldHintFlags = lpFRUse->sFR.uchHintFlags;
ulOldRefPri = lpFRUse->sFR.uchRefPri;
CopyOtherInfoToFilerec(lpOI, lpFRUse);
CopyOtherInfoToPQ(lpOI, &sPQ);
if (IsFile(lpFRUse->sFR.dwFileAttrib))
{
if ((!ulOldHintPri && !mPinFlags(ulOldHintFlags)) && // was unpinned
(lpFRUse->sFR.uchHintPri || mPinFlags(lpFRUse->sFR.uchHintFlags))) //is getting pinned
{
// If it went from unpinned to pinned
// make the new size 0
uNewSize = 0;
}
else if ((ulOldHintPri || mPinFlags(ulOldHintFlags)) && // was pinned
(!lpFRUse->sFR.uchHintPri && !mPinFlags(lpFRUse->sFR.uchHintFlags))) //is getting unpinned
{
// If it went from pinned to unpinned
// we must add the new size
uOldSize = 0;
}
}
if(mForceRelink(uOp) || ((ulOldRefPri != (ULONG)(sPQ.uchRefPri))
)
)
{
fRefPriChange = TRUE;
}
}
else
{
// if this is a pinned entry, we need to not have any space adjustment
if(lpFRUse->sFR.uchHintPri || mPinFlags(lpFRUse->sFR.uchHintFlags))
{
uOldSize = uNewSize;
}
}
if (IsFile(lpFRUse->sFR.dwFileAttrib))
{
Assert(lpFRUse->sFR.uchRefPri == MAX_PRI);
}
else
{
Assert(sPQ.uchRefPri == MIN_PRI);
Assert(lpFRUse->sFR.uchRefPri == MIN_PRI);
}
CShadowKdPrint(SETSHADOWINFOHI,("SetShadowInfo: %x %x: loctLo=%x loctHi=%x \r\n",
hDir,hShadow,
lpFRUse->sFR.ftOrgTime.dwLowDateTime,
lpFRUse->sFR.ftOrgTime.dwHighDateTime));
CopyBufferToSecurityContext(lpSecurityBlob, lpdwBlobSize, &(lpFRUse->sFR.Security));
#ifdef DEBUG
ValidatePri(lpFRUse);
#endif
if ((ulOldFlags & SHADOW_SPARSE) && !(lpFRUse->sFR.usStatus & SHADOW_SPARSE))
{
CShadowKdPrint(SETSHADOWINFOHI,("SetShadowInfo: File Unsparsed\n"));
}
if (mSetLastRefreshTime(uOp) || ((ulOldFlags & SHADOW_STALE) && !(lpFRUse->sFR.usStatus & SHADOW_STALE)))
{
lpFRUse->sFR.ulLastRefreshTime = (ULONG)IFSMgr_Get_NetTime();
}
if (UpdateFileRecFromInode(lpdbShadow, hDir, hShadow, sPQ.ulrecDirEntry, lpFRUse) < SRET_OK)
{
Assert(FALSE);
goto bailout;
}
if (mShadowNeedReint(ulOldFlags) && !mShadowNeedReint(lpFRUse->sFR.usStatus))
{
sPQ.usStatus = lpFRUse->sFR.uStatus;
// Assert(!(sPQ.usStatus & SHADOW_LOCAL_INODE));
lpFRUse->sFR.ulidShadowOrg = lpFRUse->sFR.ulidShadow;
}
else
{
sPQ.usStatus = ((USHORT)(lpFRUse->sFR.uStatus) | (sPQ.usStatus & SHADOW_LOCAL_INODE));
}
if (fRefPriChange)
{
// update the record with and relinking it in the queue
if (UpdatePriQRecordAndRelink(lpdbShadow, hDir, hShadow, &sPQ) < SRET_OK)
{
Assert(FALSE);
goto bailout;
}
}
else
{
// update the record without relinking
if (UpdatePriQRecord(lpdbShadow, hDir, hShadow, &sPQ) < SRET_OK)
{
Assert(FALSE);
goto bailout;
}
}
// we do space accounting only for files
// If the file went from pinned to upinned and viceversa
if (IsFile(lpFRUse->sFR.dwFileAttrib) && (uOldSize != uNewSize))
{
CShadowKdPrint(STOREDATA,("SetShadowInfo: Size changed for hDir=%x Name=%ws\r\n", hDir, lpFRUse->sFR.rgwName));
AdjustShadowSpace(0, uOldSize, 0, uNewSize, TRUE);
}
AdjustSparseStaleDetectionCount(0, lpFRUse);
iRet = SRET_OK;
}
}
bailout:
if (lpFR)
FreeMem(lpFR);
else
UnUseGlobalFilerecExt();
END_TIMING(SetShadowInfoInternal);
return iRet;
}
int PRIVATE ReadShadowInfo(
HSHADOW hDir,
HSHADOW hShadow,
LPFIND32 lpFind32,
ULONG far *lpuStatus,
LPOTHERINFO lpOI,
LPVOID lpSecurityBlob,
LPDWORD lpdwBlobSize,
ULONG uFlags
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
BOOL fStale = FALSE;
int iRet = SRET_ERROR;
LPFILERECEXT lpFR = NULL, lpFRUse;
PRIQREC sPQ;
Assert(vfInShadowCrit != 0);
if(!(!hDir || IsDirInode(hDir)))
{
return iRet;
}
if (InuseGlobalFRExt())
{
if (!(lpFR = (LPFILERECEXT)AllocMem(sizeof(FILERECEXT))))
goto bailout;
lpFRUse = lpFR;
}
else
{
UseGlobalFilerecExt();
lpFRUse = &vsFRExt;
}
Assert((uFlags & (RSI_GET|RSI_SET)) != (RSI_GET|RSI_SET));
if (!hDir)
{
if(FindSharerecFromInode(lpdbShadow, hShadow, (LPSHAREREC)lpFRUse))
{
if (lpuStatus != NULL) {
*lpuStatus = (ULONG)(((LPSHAREREC)lpFRUse)->usRootStatus);
}
if (lpFind32)
{
CopySharerecToFindInfo((LPSHAREREC)lpFRUse, lpFind32);
}
if (lpOI)
{
CopySharerecToOtherInfo((LPSHAREREC)lpFRUse, lpOI);
}
CopySecurityContextToBuffer(
&(((LPSHAREREC)lpFRUse)->sShareSecurity),
lpSecurityBlob,
lpdwBlobSize);
iRet = SRET_OK;
}
goto bailout;
}
Assert(hDir);
if(FindPriQRecord(lpdbShadow, hDir, hShadow, &sPQ) < 0)
goto bailout;
if(!CShadowFindFilerecFromInode(lpdbShadow, hDir, hShadow, &sPQ, lpFRUse))
{
CShadowKdPrint(ALWAYS,("ReadShadowInfo: !!! no filerec for pq entry Inode=%x, deleting PQ entry\r\n",
hShadow));
goto bailout;
}
CopySecurityContextToBuffer(&(lpFRUse->sFR.Security), lpSecurityBlob, lpdwBlobSize);
if (lpFind32)
{
if (uFlags & RSI_COMPARE)
{
// ACHTUNG!! we compare last write times. It is possible that
// somebody might have changed the filetime on the server to
// be something earlier than what we had when we shadowed the file
// for the first time. We detect this case here and say that the file
// is stale
#ifdef CSC_RECORDMANAGER_WINNT
fStale = ((CompareTimes(lpFind32->ftLastWriteTime, lpFRUse->sFR.ftOrgTime) != 0)||
(lpFind32->nFileSizeLow !=lpFRUse->sFR.ulFileSize));
#else
fStale = (CompareTimesAtDosTimePrecision(lpFind32->ftLastWriteTime, lpFRUse->sFR.ftOrgTime) != 0);
#endif
// If remote time > local time, copy the file
if ((!fStale && (lpFRUse->sFR.uStatus & SHADOW_STALE))||
(fStale && !(lpFRUse->sFR.uStatus & SHADOW_STALE)))
{
CShadowKdPrint(READSHADOWINFOHI,("ReadShadowInfo: %x: remtLo=%x remtHi=%x, \r\n locTLo=%x, locTHi=%x \r\n"
,hShadow, lpFind32->ftLastWriteTime.dwLowDateTime, lpFind32->ftLastWriteTime.dwHighDateTime
, lpFRUse->sFR.ftOrgTime.dwLowDateTime, lpFRUse->sFR.ftOrgTime.dwHighDateTime));
// Toggle the staleness bit
lpFRUse->sFR.uStatus ^= SHADOW_STALE;
sPQ.usStatus = (USHORT)(lpFRUse->sFR.uStatus) | (sPQ.usStatus & SHADOW_LOCAL_INODE);
if (uFlags & RSI_SET)
{
if (UpdateFileRecFromInode(lpdbShadow, hDir, hShadow, sPQ.ulrecDirEntry, lpFRUse) < SRET_OK)
{
Assert(FALSE);
goto bailout;
}
if (UpdatePriQRecord(lpdbShadow, hDir, hShadow, &sPQ) < SRET_OK)
{
// Toggle the staleness bit
lpFRUse->sFR.uStatus ^= SHADOW_STALE;
//try to undo the change
if (UpdateFileRecFromInode(lpdbShadow, hDir, hShadow, sPQ.ulrecDirEntry, lpFRUse) < SRET_OK)
{
Assert(FALSE);
}
goto bailout;
}
AdjustSparseStaleDetectionCount(0, lpFRUse);
}
iRet = 1;
}
else
{
iRet = 0;
}
}
else
{
iRet = 0;
}
if (uFlags & RSI_GET)
{
CopyFilerecToFindInfo(lpFRUse, lpFind32);
Assert((IsLeaf(hShadow) && IsFile(lpFind32->dwFileAttributes)) ||
(!IsLeaf(hShadow) && !IsFile(lpFind32->dwFileAttributes)));
}
}
else
{
iRet = 0;
}
if (lpOI)
{
CopyFilerecToOtherInfo(lpFRUse, lpOI);
}
if (lpuStatus != NULL) {
*lpuStatus = lpFRUse->sFR.uStatus;
}
bailout:
if (lpFR)
{
FreeMem(lpFR);
}
else
{
UnUseGlobalFilerecExt();
}
return iRet;
}
HSHARE PUBLIC // ret
HCreateShareObj( //
USHORT *lpShare,
LPSHADOWINFO lpSI
) //
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
ULONG ulidShare=0;
HSHADOW hRoot=0;
SHAREREC sSR;
Assert(vfInShadowCrit != 0);
memset(lpSI, 0, sizeof(SHADOWINFO));
if(!InitShareRec(&sSR, lpShare,0))
{
return 0;
}
if (!(ulidShare = AllocShareRecord(lpdbShadow, lpShare)))
return 0;
if(!(hRoot = UlAllocInode(lpdbShadow, 0L, FALSE)))
return 0;
// Let us create an empty root
if(CreateDirInode(lpdbShadow, ulidShare, 0L, hRoot) < 0L)
{
CShadowKdPrint(BADERRORS,("Error in creating root \r\n"));
return 0L;
}
if (AddPriQRecord(lpdbShadow, ulidShare, 0, hRoot, SHADOW_SPARSE, 0, 0, 0, 0, ulidShare) < 0)
{
CShadowKdPrint(BADERRORS,("Error in inserting root in the priorityQ\r\n"));
return 0L;
}
sSR.ulShare = ulidShare;
sSR.ulidShadow = hRoot;
sSR.uStatus = 0;
sSR.usRootStatus = SHADOW_SPARSE;
sSR.dwFileAttrib = FILE_ATTRIBUTE_DIRECTORY;
if (sSR.ftLastWriteTime.dwLowDateTime == 0 && sSR.ftLastWriteTime.dwHighDateTime == 0) {
KeQuerySystemTime(((PLARGE_INTEGER)(&sSR.ftLastWriteTime)));
if (sSR.ftOrgTime.dwLowDateTime == 0 && sSR.ftOrgTime.dwHighDateTime == 0)
sSR.ftOrgTime = sSR.ftLastWriteTime;
}
// there needs to be a way for passing in ftLastWriteTime, which we would
// stamp as the ftOrgTime. We don't use the ORG time right now, but we might want to
// in future
// All entities have been individually created. Let us tie them up
// in the database
ulidShare = AddShareRecord(lpdbShadow, &sSR);
if (ulidShare)
{
CopySharerecToShadowInfo(&sSR, lpSI);
vdwCSCNameSpaceVersion++;
vdwPQVersion++;
}
return ((HSHARE)ulidShare);
}
int PUBLIC // ret
DestroyHSHARE( //
HSHARE hShare
) //
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
SHAREREC sSR;
int iRet = SRET_ERROR;
Assert(vfInShadowCrit != 0);
if(FindSharerecFromShare(lpdbShadow, hShare, &sSR))
{
if (DestroyShareInternal(&sSR) >= 0)
iRet = SRET_OK;
}
return (iRet);
}
int DestroyShareInternal( LPSHAREREC lpSR
)
{
PRIQREC sPQ;
int iRet = -1;
if (!mNotFsobj(lpSR->uStatus))
{
if(DeletePriQRecord(lpdbShadow, 0, lpSR->ulidShadow, &sPQ) >= 0)
{
if (DeleteShareRecord(lpdbShadow, lpSR->ulShare))
{
FreeInode(lpdbShadow, lpSR->ulidShadow);
DeleteInodeFile(lpdbShadow, lpSR->ulidShadow);
iRet = 1;
vdwCSCNameSpaceVersion++;
vdwPQVersion++;
}
else
{
CShadowKdPrint(BADERRORS, ("Failed to delete record for share=%x\r\n", lpSR->ulShare));
}
}
}
return (iRet);
}
int PUBLIC // ret
GetShareFromPath( //
USHORT *lpShare,
LPSHADOWINFO lpSI
) //
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
SHAREREC sSR;
Assert(vfInShadowCrit != 0);
memset(lpSI, 0, sizeof(SHADOWINFO));
if(FindShareRecord(lpdbShadow, lpShare, &sSR))
{
CopySharerecToShadowInfo(&sSR, lpSI);
}
return SRET_OK;
}
int PUBLIC // ret
GetShareFromPathEx( //
USHORT *lpShare,
LPSHADOWINFO lpSI,
LPVOID lpSecurityBlob,
LPDWORD lpdwBlobSize
) //
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
SHAREREC sSR;
memset(lpSI, 0, sizeof(SHADOWINFO));
Assert(vfInShadowCrit != 0);
if(FindShareRecord(lpdbShadow, lpShare, &sSR))
{
CopySharerecToShadowInfo(&sSR, lpSI);
CopySecurityContextToBuffer(&(sSR.sShareSecurity), lpSecurityBlob, lpdwBlobSize);
}
return SRET_OK;
}
int PUBLIC // ret
GetShareInfo( //
HSHARE hShare,
LPSHAREINFOW lpShareInfo,
LPSHADOWINFO lpSI
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
return (GetShareInfoEx(hShare, lpShareInfo, lpSI, NULL, NULL));
}
int PUBLIC
GetShareInfoEx(
HSHARE hShare,
LPSHAREINFOW lpShareInfo,
LPSHADOWINFO lpSI,
LPVOID lpSecurityBlob,
LPDWORD lpdwBlobSize
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
SHAREREC sSR;
Assert(vfInShadowCrit != 0);
if (!hShare)
{
SetLastErrorLocal(ERROR_INVALID_PARAMETER);
return SRET_ERROR;
}
if (GetShareRecord(lpdbShadow, hShare, &sSR) < SRET_OK)
{
return SRET_ERROR;
}
if (lpShareInfo)
{
lpShareInfo->hShare = hShare;
memset(lpShareInfo->rgSharePath, 0, sizeof(lpShareInfo->rgSharePath));
memcpy(lpShareInfo->rgSharePath, sSR.rgPath, wstrlen(sSR.rgPath)*sizeof(USHORT));
memcpy(lpShareInfo->rgFileSystem, vwszFileSystemName, wstrlen(vwszFileSystemName)*sizeof(USHORT));
lpShareInfo->usCaps = FS_CASE_IS_PRESERVED|FS_VOL_SUPPORTS_LONG_NAMES;
lpShareInfo->usState = RESSTAT_OK;
}
if (lpSI)
{
CopySharerecToShadowInfo(&sSR, lpSI);
}
CopySecurityContextToBuffer(&(sSR.sShareSecurity), lpSecurityBlob, lpdwBlobSize);
return (SRET_OK);
}
int
SetShareStatus( HSHARE hShare,
ULONG uStatus,
ULONG uOp
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
return (SetShareStatusEx(hShare, uStatus, uOp, NULL, NULL));
}
int
SetShareStatusEx(
HSHARE hShare,
ULONG uStatus,
ULONG uOp,
LPVOID lpSecurityBlob,
LPDWORD lpdwBlobSize
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
SHAREREC sSR;
Assert(vfInShadowCrit != 0);
if (!hShare)
{
SetLastErrorLocal(ERROR_INVALID_PARAMETER);
return SRET_ERROR;
}
if (GetShareRecord(lpdbShadow, hShare, &sSR) < SRET_OK)
{
return SRET_ERROR;
}
if (mAndShadowFlags(uOp))
{
sSR.uStatus &= (USHORT)uStatus;
}
else if (mOrShadowFlags(uOp))
{
sSR.uStatus |= (USHORT)uStatus;
}
else
{
sSR.uStatus = (USHORT)uStatus;
}
CopyBufferToSecurityContext(lpSecurityBlob, lpdwBlobSize, &(sSR.sShareSecurity));
return (SetShareRecord(lpdbShadow, hShare, &sSR));
}
int PUBLIC // ret
GetAncestorsHSHADOW( //
HSHADOW hName,
LPHSHADOW lphDir,
LPHSHARE lphShare
) //
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
return (FindAncestorsFromInode(lpdbShadow, hName, lphDir, lphShare));
}
int PUBLIC SetPriorityHSHADOW(
HSHADOW hDir,
HSHADOW hShadow,
ULONG ulRefPri,
ULONG ulIHPri
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
OTHERINFO sOI;
ULONG uOp = SHADOW_FLAGS_OR;
Assert(vfInShadowCrit != 0);
ulIHPri;
InitOtherInfo(&sOI);
// we make sure that if the new priority being set is MAX_PRI, then this
// inode does get to the top of the PQ even if it's current priority is
// MAX_PRI.
if (ulRefPri == MAX_PRI)
{
uOp |= SHADOW_FLAGS_FORCE_RELINK;
}
sOI.ulRefPri = ulRefPri;
sOI.ulIHPri = 0;
if(SetShadowInfoEx(hDir, hShadow, NULL, 0, uOp, &sOI, NULL, NULL))
return (SRET_ERROR);
return (SRET_OK);
}
int PUBLIC GetPriorityHSHADOW(
HSHADOW hDir,
HSHADOW hShadow,
ULONG *lpulRefPri,
ULONG *lpulIHPri
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
PRIQREC sPQ;
Assert(vfInShadowCrit != 0);
if((FindPriQRecord(lpdbShadow, hDir, hShadow, &sPQ) < 0)||mNotFsobj(sPQ.usStatus))
return SRET_ERROR;
if (lpulRefPri)
{
*lpulRefPri = (ULONG)(sPQ.uchRefPri);
}
if (lpulIHPri)
{
*lpulIHPri = (ULONG)(sPQ.uchIHPri);
}
return (SRET_OK);
}
int PUBLIC
ChangePriEntryStatusHSHADOW(
HSHADOW hDir,
HSHADOW hShadow,
ULONG uStatus,
ULONG uOp,
BOOL fChangeRefPri,
LPOTHERINFO lpOI
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
PRIQREC sPQ;
int iRet;
#ifdef DEBUG
ULONG ulRefPri;
#endif
Assert(vfInShadowCrit != 0);
Assert(!hDir || IsDirInode(hDir));
BEGIN_TIMING(ChangePriEntryStatusHSHADOW);
if(FindPriQRecord(lpdbShadow, hDir, hShadow, &sPQ) < 0)
return SRET_ERROR;
#ifdef DEBUG
ulRefPri = (ULONG)(sPQ.uchRefPri);
#endif
if (uOp==SHADOW_FLAGS_AND)
{
sPQ.usStatus &= (USHORT)uStatus;
}
else if (uOp==SHADOW_FLAGS_OR)
{
sPQ.usStatus |= (USHORT)uStatus;
}
else
{
sPQ.usStatus = (USHORT)uStatus;
}
if (lpOI)
{
CopyOtherInfoToPQ(lpOI, &sPQ);
}
if (!fChangeRefPri)
{
Assert(ulRefPri == (ULONG)(sPQ.uchRefPri));
iRet = UpdatePriQRecord(lpdbShadow, hDir, hShadow, &sPQ);
}
else
{
iRet = UpdatePriQRecordAndRelink(lpdbShadow, hDir, hShadow, &sPQ);
vdwPQVersion++;
}
END_TIMING(ChangePriEntryStatusHSHADOW);
return (iRet);
}
CSC_ENUMCOOKIE PUBLIC // ret
HBeginPQEnum( //
VOID) // no params
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
Assert(vfInShadowCrit != 0);
return ((CSC_ENUMCOOKIE)BeginSeqReadPQ(lpdbShadow));
}
int PUBLIC EndPQEnum(
CSC_ENUMCOOKIE hPQEnum
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
Assert(vfInShadowCrit != 0);
return(EndSeqReadQ((CSCHFILE)hPQEnum));
}
int PUBLIC // ret
PrevPriSHADOW(
LPPQPARAMS lpPQ
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
QREC sQrec;
int iRet=-1;
Assert(vfInShadowCrit != 0);
sQrec.uchType = 0;
if (lpPQ->uPos)
{
sQrec.ulrecPrev = lpPQ->uPos;
iRet = SeqReadQ(lpPQ->uEnumCookie, &sQrec, &sQrec, Q_GETPREV);
}
else
{
iRet=SeqReadQ(lpPQ->uEnumCookie, &sQrec, &sQrec, Q_GETLAST);
}
if (iRet>=0)
{
// it is possible, that as the agent is traversing the PQ,
// the next inode he is trying to read may have already been
// deleted. In such a case, just fail, so he will start all
// over in due course
if(sQrec.uchType == REC_DATA)
{
lpPQ->hShare = sQrec.ulidShare;
lpPQ->hDir = sQrec.ulidDir;
lpPQ->hShadow = sQrec.ulidShadow;
lpPQ->ulStatus = sQrec.usStatus;
if (FInodeIsFile(lpdbShadow, sQrec.ulidDir, sQrec.ulidShadow))
{
lpPQ->ulStatus |= SHADOW_IS_FILE;
}
lpPQ->ulRefPri = (ULONG)(sQrec.uchRefPri);
lpPQ->ulHintPri = (ULONG)(sQrec.uchHintPri);
lpPQ->ulHintFlags = (ULONG)(sQrec.uchHintFlags);
lpPQ->uPos = sQrec.ulrecPrev;
lpPQ->dwPQVersion = vdwPQVersion;
}
else
{
lpPQ->hShadow = 0;
iRet = -1;
}
}
return (iRet);
}
int PUBLIC // ret
NextPriSHADOW(
LPPQPARAMS lpPQ
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
QREC sQrec;
int iRet=-1;
Assert(vfInShadowCrit != 0);
sQrec.uchType = 0;
if (lpPQ->uPos)
{
sQrec.ulrecNext = lpPQ->uPos;
iRet = SeqReadQ(lpPQ->uEnumCookie, &sQrec, &sQrec, Q_GETNEXT);
}
else
{
iRet = SeqReadQ(lpPQ->uEnumCookie, &sQrec, &sQrec, Q_GETFIRST);
}
if (iRet >=0)
{
// it is possible, that as the agent is traversing the PQ,
// the next inode he is trying to read may have already been
// deleted. In such a case, just fail, so he will start all
// over in due course
if(sQrec.uchType == REC_DATA)
{
lpPQ->hShare = sQrec.ulidShare;
lpPQ->hDir = sQrec.ulidDir;
lpPQ->hShadow = sQrec.ulidShadow;
lpPQ->ulStatus = (sQrec.usStatus);
if (FInodeIsFile(lpdbShadow, sQrec.ulidDir, sQrec.ulidShadow))
{
lpPQ->ulStatus |= SHADOW_IS_FILE;
}
lpPQ->ulRefPri = (ULONG)(sQrec.uchRefPri);
lpPQ->ulHintPri = (ULONG)(sQrec.uchHintPri);
lpPQ->ulHintFlags = (ULONG)(sQrec.uchHintFlags);
lpPQ->uPos = sQrec.ulrecNext;
lpPQ->dwPQVersion = vdwPQVersion;
}
else
{
lpPQ->hShadow = 0;
iRet = -1;
}
}
return (iRet);
}
int GetRenameAliasHSHADOW( HSHADOW hShadow,
HSHADOW hDir,
LPHSHADOW lphDirFrom,
LPHSHADOW lphShadowFrom
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int iRet = SRET_ERROR;
LPFILERECEXT lpFR = NULL, lpFRUse;
PRIQREC sPQ;
if (InuseGlobalFRExt())
{
if (!(lpFR = (LPFILERECEXT)AllocMem(sizeof(FILERECEXT))))
goto bailout;
lpFRUse = lpFR;
}
else
{
UseGlobalFilerecExt();
lpFRUse = &vsFRExt;
}
*lphShadowFrom = *lphDirFrom = 0;
if(FindPriQRecord(lpdbShadow, hDir, hShadow, &sPQ) < 0)
{
goto bailout;
}
if(!CShadowFindFilerecFromInode(lpdbShadow, hDir, hShadow, &sPQ, lpFRUse))
goto bailout;
Assert(lpFRUse->sFR.ulidShadow == sPQ.ulidShadow);
*lphShadowFrom = lpFRUse->sFR.ulidShadowOrg;
if (*lphShadowFrom)
{
FindAncestorsFromInode(lpdbShadow, *lphShadowFrom, lphDirFrom, NULL);
}
iRet = SRET_OK;
bailout:
if (lpFR)
FreeMem(lpFR);
else
UnUseGlobalFilerecExt();
return iRet;
}
int
CopyHSHADOW(
HSHADOW hDir,
HSHADOW hShadow,
LPSTR lpszDestinationFile,
ULONG ulAttrib
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
return (CopyFileLocal(lpdbShadow, hShadow, lpszDestinationFile, ulAttrib));
}
int RenameDataHSHADOW(
ULONG ulidFrom,
ULONG ulidTo
)
{
return (RenameInode(lpdbShadow, ulidFrom, ulidTo));
}
int MetaMatchInit(
ULONG *lpuCookie
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
*lpuCookie = 1;
return(0);
}
int MetaMatch(
HSHADOW hDir,
LPFIND32 lpFind32,
ULONG *lpuCookie,
LPHSHADOW lphShadow,
ULONG *lpuStatus,
LPOTHERINFO lpOI,
METAMATCHPROC lpfnMMP,
LPVOID lpData
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int iRet;
Assert(vfInShadowCrit != 0);
if (hDir)
iRet = MetaMatchDir(hDir, lpFind32, lpuCookie, lphShadow, lpuStatus, lpOI, lpfnMMP, lpData);
else
iRet = MetaMatchShare(hDir, lpFind32, lpuCookie, lphShadow, lpuStatus, lpOI, lpfnMMP, lpData);
return (iRet);
}
int MetaMatchShare(
HSHADOW hDir,
LPFIND32 lpFind32,
ULONG *lpuCookie,
LPHSHADOW lphShadow,
ULONG *lpuStatus,
LPOTHERINFO lpOI,
METAMATCHPROC lpfnMMP,
LPVOID lpData
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int iRet = -1, iFound=-1;
GENERICHEADER sGH;
CSCHFILE hf = NULL;
ULONG uSize, ulrecPosFound = 0;
OTHERINFO sOI;
SHAREREC sSR;
BOOL fCached;
if (!(hf = OpenInodeFileAndCacheHandle(lpdbShadow, ULID_SHARE, ACCESS_READWRITE, &fCached)))
{
goto bailout;
}
if(ReadHeader(hf, &sGH, sizeof(FILEHEADER)) < 0)
{
goto bailout;
}
for (;*lpuCookie <=sGH.ulRecords;)
{
iRet = ReadRecord(hf, &sGH, *lpuCookie, (LPGENERICREC)&sSR);
if (iRet < 0)
goto bailout;
// bump the record pointer
*lpuCookie += iRet;
if (sSR.uchType != REC_DATA)
continue;
CopySharerecToFindInfo(&sSR, lpFind32);
CopySharerecToOtherInfo(&sSR, &sOI);
if (lpOI)
{
*lpOI = sOI;
}
*lpuStatus = (ULONG)(sSR.usStatus);
*lphShadow = sSR.ulidShadow;
iFound = (*lpfnMMP)(lpFind32, hDir, *lphShadow, *lpuStatus, &sOI, lpData);
if (iFound==MM_RET_FOUND_CONTINUE)
{
ulrecPosFound = *lpuCookie - iRet;
}
else if (iFound <= MM_RET_FOUND_BREAK)
{
break;
}
}
if (ulrecPosFound || (iFound==MM_RET_FOUND_BREAK))
{
if (ulrecPosFound)
{
ReadRecord(hf, &sGH, ulrecPosFound, (LPGENERICREC)&sSR);
CopySharerecToFindInfo(&sSR, lpFind32);
*lpuStatus = (ULONG)(sSR.usStatus);
*lphShadow = sSR.ulidShadow;
if (lpOI)
{
CopySharerecToOtherInfo(&sSR, lpOI);
}
}
}
else
{
*lpuStatus = *lphShadow = 0;
}
iRet = SRET_OK;
bailout:
if (hf && !fCached)
{
Assert(vfStopHandleCaching);
CloseFileLocal(hf);
}
else
{
Assert(!hf || !vfStopHandleCaching);
}
return (iRet);
}
int MetaMatchDir(
HSHADOW hDir,
LPFIND32 lpFind32,
ULONG *lpuCookie,
LPHSHADOW lphShadow,
ULONG *lpuStatus,
LPOTHERINFO lpOI,
METAMATCHPROC lpfnMMP,
LPVOID lpData
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int iRet = SRET_ERROR, iFound=-1;
GENERICHEADER sGH;
CSCHFILE hf = NULL;
ULONG uSize, ulrecPosFound = 0;
OTHERINFO sOI;
LPFILERECEXT lpFR = NULL, lpFRUse;
BOOL fCached;
PRIQREC sPQ;
if (InuseGlobalFRExt())
{
if (!(lpFR = (LPFILERECEXT)AllocMem(sizeof(FILERECEXT))))
goto bailout;
lpFRUse = lpFR;
}
else
{
UseGlobalFilerecExt();
lpFRUse = &vsFRExt;
}
if (FInodeIsFile(lpdbShadow, 0, hDir))
{
SetLastErrorLocal(ERROR_INVALID_PARAMETER);
goto bailout;
}
if (!(hf = OpenInodeFileAndCacheHandle(lpdbShadow, hDir, ACCESS_READWRITE, &fCached)))
{
DWORD dwError;
dwError = GetLastErrorLocal();
if(FindPriQRecordInternal(lpdbShadow, hDir, &sPQ) < 0)
{
SetLastErrorLocal(ERROR_INVALID_PARAMETER);
}
else
{
SetCSCDatabaseErrorFlags(CSC_DATABASE_ERROR_MISSING_INODE);
SetLastErrorLocal(dwError);
}
goto bailout;
}
if(ReadHeader(hf, &sGH, sizeof(FILEHEADER)) < 0)
{
goto bailout;
}
for (;*lpuCookie <=sGH.ulRecords;)
{
iRet = ReadRecord(hf, &sGH, *lpuCookie, (LPGENERICREC)lpFRUse);
if (iRet < 0)
{
goto bailout;
}
// bump the record pointer
*lpuCookie += iRet;
if (lpFRUse->sFR.uchType != REC_DATA)
{
continue;
}
CopyFilerecToFindInfo(lpFRUse, lpFind32);
*lphShadow = lpFRUse->sFR.ulidShadow;
CopyFilerecToOtherInfo(lpFRUse, &sOI);
if (lpOI)
{
*lpOI = sOI;
}
*lpuStatus = (ULONG)(lpFRUse->sFR.uStatus);
iFound = (*lpfnMMP)(lpFind32, hDir, *lphShadow, *lpuStatus, &sOI, lpData);
if (iFound==MM_RET_FOUND_CONTINUE)
{
ulrecPosFound = *lpuCookie - iRet;
}
else if (iFound <= MM_RET_FOUND_BREAK)
{
break;
}
}
if (ulrecPosFound || (iFound==MM_RET_FOUND_BREAK))
{
if (ulrecPosFound)
{
ReadRecord(hf, &sGH, ulrecPosFound, (LPGENERICREC)lpFRUse);
CopyFilerecToFindInfo(lpFRUse, lpFind32);
*lpuStatus = (ULONG)(lpFRUse->sFR.uStatus);
*lphShadow = lpFRUse->sFR.ulidShadow;
if (lpOI)
{
CopyFilerecToOtherInfo(lpFRUse, lpOI);
}
}
}
else
{
*lpuStatus = *lphShadow = 0;
}
iRet = SRET_OK;
bailout:
if (hf && !fCached)
{
Assert(vfStopHandleCaching);
CloseFileLocal(hf);
}
else
{
Assert(!hf || !vfStopHandleCaching);
}
if (lpFR)
{
FreeMem(lpFR);
}
else
{
UnUseGlobalFilerecExt();
}
return (iRet);
}
int CreateHint(
HSHADOW hShadow,
LPFIND32 lpFind32,
ULONG ulHintFlags,
ULONG ulHintPri,
LPHSHADOW lphHint
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int iRet=SRET_ERROR;
OTHERINFO sOI;
ULONG uStatus;
// This must be either a wildcard hint, or else it can't be without an Fsobj
if ((GetShadow(hShadow, lpFind32->cFileName, lphHint, lpFind32, &uStatus, &sOI)>=SRET_OK)
&& (*lphHint))
{
Assert((FHasWildcard(lpFind32->cFileName, MAX_PATH) || !mNotFsobj(uStatus)));
if ((sOI.ulHintPri < MAX_HINT_PRI) &&
(ulHintPri < MAX_HINT_PRI)
)
{
sOI.ulHintPri += ulHintPri;
if (sOI.ulHintPri <= MAX_HINT_PRI)
{
sOI.ulHintFlags = ulHintFlags;
mClearBits(sOI.ulHintFlags, HINT_WILDCARD);
iRet = SetShadowInfoEx(hShadow, *lphHint, lpFind32, 0, SHADOW_FLAGS_OR, &sOI, NULL, NULL);
if (iRet>=SRET_OK)
{
iRet = SRET_OBJECT_HINT;
}
}
}
}
else
{
if (FHasWildcard(lpFind32->cFileName, MAX_PATH) && (ulHintPri <= MAX_HINT_PRI))
{
InitOtherInfo(&sOI);
sOI.ulHintFlags = ulHintFlags;
sOI.ulHintPri = ulHintPri;
// Tell him that we are creating a file shadow
lpFind32->dwFileAttributes = FILE_ATTRIBUTE_ARCHIVE;
iRet = CreateShadowInternal(hShadow, lpFind32, SHADOW_NOT_FSOBJ, &sOI, lphHint);
if (iRet>=SRET_OK)
{
iRet = SRET_WILDCARD_HINT;
}
}
}
return (iRet);
}
int DeleteHint(
HSHADOW hShadow,
USHORT *lpuHintName,
BOOL fClearAll
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
ULONG uStatus;
HSHADOW hChild;
int iRet=SRET_ERROR;
OTHERINFO sOI;
if (GetShadow(hShadow, lpuHintName, &hChild, NULL, &uStatus, &sOI)>=SRET_OK)
{
// Nuke if there is no filesystem object with it
if (mNotFsobj(uStatus))
{
iRet = DeleteShadowInternal(hShadow, hChild, TRUE);
if (iRet>=SRET_OK)
{
iRet = SRET_WILDCARD_HINT;
}
}
else
{
BOOL fDoit = TRUE;
if (fClearAll)
{
sOI.ulHintPri = 0;
sOI.ulHintFlags = 0;
}
else
{
if (sOI.ulHintPri > 0)
{
--sOI.ulHintPri;
}
else
{
fDoit = FALSE;
}
}
if (fDoit)
{
iRet = SetShadowInfoEx( hShadow,
hChild,
NULL,
uStatus,
SHADOW_FLAGS_ASSIGN,
&sOI,
NULL,
NULL
);
if (iRet>=SRET_OK)
{
iRet = SRET_OBJECT_HINT;
}
}
}
}
return (iRet);
}
int CreateGlobalHint(
USHORT *lpuName,
ULONG ulHintFlags,
ULONG ulHintPri
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int iRet = SRET_ERROR;
SHAREREC sSR;
ULONG ulidShare, ulT;
#if 0
if (FindShareRecord(lpdbShadow, lpuName, &sSR))
{
if ((sSR.uchHintPri < MAX_HINT_PRI) &&
(ulHintPri < MAX_HINT_PRI)
)
{
ulT = (ULONG)sSR.uchHintPri + ulHintPri;
if (ulT <= MAX_HINT_PRI)
{
// Setting a hint on the root of the server
sSR.uchHintFlags = (UCHAR)(ulHintFlags);
sSR.uchHintPri = (UCHAR)(ulT);
mClearBits(sSR.uchHintFlags, HINT_WILDCARD);
Assert(FHasWildcard(lpuName, MAX_PATH) || !mNotFsobj(sSR.uStatus));
if(SetShareRecord(lpdbShadow, sSR.ulShare, &sSR) > 0)
{
iRet = SRET_OBJECT_HINT;
}
}
}
}
else
{
if (FHasWildcard(lpuName, MAX_SERVER_SHARE))
{
if (ulidShare = AllocShareRecord(lpdbShadow, lpuName))
{
//InitShareRec(lpuName, &sSR);
InitShareRec(&sSR, lpuName, 0);
sSR.ulShare = ulidShare;
sSR.ulidShadow = 0xffffffff; // Just to fool FindOpenHSHADOW
sSR.uchHintFlags = (UCHAR)ulHintFlags;
sSR.uchHintPri = (UCHAR)ulHintPri;
mSetBits(sSR.uStatus, SHADOW_NOT_FSOBJ);
if(AddShareRecord(lpdbShadow, &sSR) > 0)
{
iRet = SRET_WILDCARD_HINT;
}
}
}
}
#endif
return (iRet);
}
int DeleteGlobalHint(
USHORT *lpuName,
BOOL fClearAll
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int iRet = SRET_ERROR;
SHAREREC sSR;
#if 0
if (FindShareRecord(lpdbShadow, lpuName, &sSR))
{
if (mNotFsobj(sSR.uStatus))
{
iRet = DeleteShareRecord(lpdbShadow, sSR.ulShare);
}
else
{
if (fClearAll)
{
sSR.uchHintPri = sSR.uchHintFlags = 0;
}
else
{
if (sSR.uchHintPri > 0)
{
--sSR.uchHintPri;
}
}
if(SetShareRecord(lpdbShadow, sSR.ulShare, &sSR) > 0)
{
iRet = SRET_OK;
}
}
}
#endif
return (iRet);
}
int CopyFilerecToOtherInfo(
LPFILERECEXT lpFR,
LPOTHERINFO lpOI
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
lpOI->ulRefPri = (ULONG)(lpFR->sFR.uchRefPri);
lpOI->ulIHPri = (ULONG)(lpFR->sFR.uchIHPri);
lpOI->ulHintFlags = (ULONG)(lpFR->sFR.uchHintFlags);
lpOI->ulHintPri = (ULONG)(lpFR->sFR.uchHintPri);
lpOI->ftOrgTime = lpFR->sFR.ftOrgTime;
lpOI->ftLastRefreshTime = IFSMgr_NetToWin32Time(lpFR->sFR.ulLastRefreshTime);
return(0);
}
int CopyOtherInfoToFilerec(
LPOTHERINFO lpOI,
LPFILERECEXT lpFR
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
if (lpOI->ulIHPri != RETAIN_VALUE)
{
lpFR->sFR.uchIHPri = (UCHAR)(lpOI->ulIHPri);
}
if (lpOI->ulHintPri != RETAIN_VALUE)
{
lpFR->sFR.uchHintPri = (UCHAR)(lpOI->ulHintPri);
}
if (lpOI->ulRefPri != RETAIN_VALUE)
{
lpFR->sFR.uchRefPri = (UCHAR)((lpOI->ulRefPri <= MAX_PRI)?lpOI->ulRefPri:MAX_PRI);
}
if (lpOI->ulHintFlags != RETAIN_VALUE)
{
lpFR->sFR.uchHintFlags = (UCHAR)(lpOI->ulHintFlags);
}
return(0);
}
int CopySharerecToOtherInfo(LPSHAREREC lpSR, LPOTHERINFO lpOI)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
lpOI->ulRefPri = 0;
lpOI->ulRootStatus = (ULONG)(lpSR->usRootStatus);
lpOI->ulHintFlags = (ULONG)(lpSR->uchHintFlags);
lpOI->ulHintPri = (ULONG)(lpSR->uchHintPri);
return(0);
}
int CopyOtherInfoToSharerec(
LPOTHERINFO lpOI,
LPSHAREREC lpSR
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
if (lpOI->ulHintFlags != RETAIN_VALUE)
{
lpSR->uchHintFlags = (UCHAR)(lpOI->ulHintFlags);
}
if (lpOI->ulHintPri != RETAIN_VALUE)
{
lpSR->uchHintPri = (UCHAR)(lpOI->ulHintPri);
}
return(0);
}
int CopyPQToOtherInfo( LPPRIQREC lpPQ,
LPOTHERINFO lpOI)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
lpOI->ulRefPri = (ULONG)(lpPQ->uchRefPri);
lpOI->ulIHPri = (ULONG)(lpPQ->uchIHPri);
lpOI->ulHintFlags = (ULONG)(lpPQ->uchHintFlags);
lpOI->ulHintPri = (ULONG)(lpPQ->uchHintPri);
return(0);
}
int CopyOtherInfoToPQ( LPOTHERINFO lpOI,
LPPRIQREC lpPQ)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
if (lpOI->ulIHPri != RETAIN_VALUE)
{
lpPQ->uchIHPri = (UCHAR)(lpOI->ulIHPri);
}
if (lpOI->ulHintPri != RETAIN_VALUE)
{
lpPQ->uchHintPri = (UCHAR)(lpOI->ulHintPri);
}
if (lpOI->ulRefPri != RETAIN_VALUE)
{
lpPQ->uchRefPri = (UCHAR)((lpOI->ulRefPri <= MAX_PRI)?lpOI->ulRefPri:MAX_PRI);
}
if (lpOI->ulHintFlags != RETAIN_VALUE)
{
lpPQ->uchHintFlags = (UCHAR)(lpOI->ulHintFlags);
}
return(0);
}
int CopySharerecToFindInfo( LPSHAREREC lpSR,
LPFIND32 lpFind32
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
memset(lpFind32, 0, sizeof(WIN32_FIND_DATA));
// lpFind32->dwReserved0 = lpSR->ulShare;
// lpFind32->dwReserved1 = lpSR->ulidShadow;
lpFind32->dwFileAttributes = lpSR->dwFileAttrib & ~FILE_ATTRIBUTE_ENCRYPTED;
lpFind32->ftLastWriteTime = lpSR->ftLastWriteTime;
lpFind32->ftLastAccessTime = lpSR->ftOrgTime;
memset(lpFind32->cFileName, 0, sizeof(lpFind32->cFileName));
memcpy(lpFind32->cFileName, lpSR->rgPath, sizeof(lpSR->rgPath));
return(0);
}
int CopyFindInfoToSharerec(
LPFIND32 lpFind32,
LPSHAREREC lpSR
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
// be paranoid and or the directory attribute bit anyway
lpSR->dwFileAttrib = (lpFind32->dwFileAttributes | FILE_ATTRIBUTE_DIRECTORY);
lpSR->ftLastWriteTime = lpFind32->ftLastWriteTime;
return(0);
}
int
CopySharerecToShadowInfo(
LPSHAREREC lpSR,
LPSHADOWINFO lpSI
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
memset(lpSI, 0, sizeof(SHADOWINFO));
lpSI->hShare = lpSR->ulShare;
lpSI->hShadow = lpSR->ulidShadow;
lpSI->uStatus = (ULONG)(lpSR->uStatus);
lpSI->uRootStatus = (ULONG)(lpSR->usRootStatus);
lpSI->ulHintFlags = (ULONG)(lpSR->uchHintFlags);
lpSI->ulHintPri = (ULONG)(lpSR->uchHintPri);
return 0;
}
int CopyOtherInfoToShadowInfo(
LPOTHERINFO lpOI,
LPSHADOWINFO lpShadowInfo
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
lpShadowInfo->ulHintFlags = lpOI->ulHintFlags;
lpShadowInfo->ulHintPri = lpOI->ulHintPri;
lpShadowInfo->ftOrgTime = lpOI->ftOrgTime;
lpShadowInfo->ftLastRefreshTime = lpOI->ftLastRefreshTime;
lpShadowInfo->dwNameSpaceVersion = vdwCSCNameSpaceVersion;
return(0); //stop complaining about no return value
}
int InitOtherInfo(
LPOTHERINFO lpOI)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
memset(lpOI, 0xff, sizeof(OTHERINFO));
return(0);
}
int PUBLIC // ret
FindOpenHSHADOW( //
LPFINDSHADOW lpFindShadow,
LPHSHADOW lphShadow,
LPFIND32 lpFind32,
ULONG far *lpuShadowStatus,
LPOTHERINFO lpOI
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int iRet = SRET_ERROR;
MetaMatchInit(&(lpFindShadow->ulCookie));
if ((lpFindShadow->uSrchFlags & FLAG_FINDSHADOW_ALLOW_NORMAL)
&& ((lpFindShadow->uAttrib & 0xff) == FILE_ATTRIBUTE_LABEL))
{
BCSToUni(lpFind32->cFileName, vszShadowVolume, strlen(vszShadowVolume), BCS_OEM);
iRet = 1;
}
else
{
if (MetaMatch(lpFindShadow->hDir, lpFind32
, &(lpFindShadow->ulCookie)
, lphShadow, lpuShadowStatus
, lpOI, lpFindShadow->lpfnMMProc
, (LPVOID)lpFindShadow)==SRET_OK)
{
iRet = (*lphShadow)?SRET_OK:SRET_ERROR;
}
}
return (iRet);
}
int PUBLIC FindNextHSHADOW( //
LPFINDSHADOW lpFindShadow,
LPHSHADOW lphShadow,
LPFIND32 lpFind32,
ULONG far *lpuShadowStatus,
LPOTHERINFO lpOI
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int iRet = SRET_ERROR;
if ((lpFindShadow->uSrchFlags & FLAG_FINDSHADOW_ALLOW_NORMAL)
&& ((lpFindShadow->uAttrib & 0xff) == FILE_ATTRIBUTE_LABEL))
{
BCSToUni(lpFind32->cFileName, vszShadowVolume, strlen(vszShadowVolume), BCS_OEM);
iRet = SRET_OK;
}
else
{
if (MetaMatch(lpFindShadow->hDir, lpFind32
, &(lpFindShadow->ulCookie), lphShadow
, lpuShadowStatus, lpOI
, lpFindShadow->lpfnMMProc
, (LPVOID)lpFindShadow)==SRET_OK)
{
iRet = (*lphShadow)?SRET_OK:SRET_ERROR;
}
}
return (iRet);
}
int PUBLIC // ret
FindCloseHSHADOW( //
LPFINDSHADOW lpFS
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
return SRET_OK;
}
// Callback function for MetaMatch,
// Return values: -1 => not found, stop; 0 => found, stop; 1 => keep going
int FsobjMMProc(
LPFIND32 lpFind32,
HSHADOW hDir,
HSHADOW hShadow,
ULONG uStatus,
LPOTHERINFO lpOI,
LPFINDSHADOW lpFSH
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int matchSem, iRet;
BOOL fInvalid=FALSE, fIsDeleted, fIsSparse;
USHORT rgu83[11];
iRet = MM_RET_CONTINUE;
if (mNotFsobj(uStatus))
{
return (iRet);
}
#ifdef OFFLINE
if ((lpFSH->uSrchFlags & FLAG_FINDSHADOW_DONT_ALLOW_INSYNC)
&& !mShadowOutofSync(uStatus))
return (iRet);
#endif //OFFLINE
// we are enumerating a directory
if (hDir && !(lpFSH->uSrchFlags & FLAG_FINDSHADOW_ALL))
{
fIsDeleted = mShadowDeleted(uStatus);
fIsSparse = (!mIsDir(lpFind32) && mShadowSparse(uStatus));
fInvalid = ((!(lpFSH->uSrchFlags & FLAG_FINDSHADOW_ALLOW_DELETED)&& fIsDeleted)
||(!(lpFSH->uSrchFlags & FLAG_FINDSHADOW_ALLOW_SPARSE)&& fIsSparse)
||(!(lpFSH->uSrchFlags & FLAG_FINDSHADOW_ALLOW_NORMAL) && (!fIsDeleted && !fIsSparse)));
}
/* If the call came from an NT style API we will use NT
semantics to match BOTH long names and short name with the
given pattern.
If it came from an old style API we will use NT style semantics
with the short name
*/
if (lpFSH->uSrchFlags & FLAG_FINDSHADOW_NEWSTYLE)
matchSem = UFLG_NT;
else
matchSem = UFLG_DOS;
if (lpFSH->uSrchFlags & FLAG_FINDSHADOW_META)
matchSem |= UFLG_META;
if (lpFSH->uSrchFlags & FLAG_FINDSHADOW_NEWSTYLE)
{
if(IFSMgr_MetaMatch(lpFSH->lpPattern, lpFind32->cFileName, matchSem)||
(lpFind32->cAlternateFileName[0] && IFSMgr_MetaMatch(lpFSH->lpPattern, lpFind32->cAlternateFileName, matchSem)))
{
iRet = MM_RET_FOUND_BREAK;
}
}
else
{
// Check if there is an 83name. This can happen when in disconnected state
// we create an LFN object.
if (lpFind32->cAlternateFileName[0])
{
Conv83UniToFcbUni(lpFind32->cAlternateFileName, rgu83);
if(IFSMgr_MetaMatch(lpFSH->lpPattern, rgu83, matchSem))
{
// If this object has some attributes and they don't match with
// the search attributes passed in
if ((lpFind32->dwFileAttributes & FILE_ATTRIBUTE_EVERYTHING)
&& !(lpFind32->dwFileAttributes & lpFSH->uAttrib))
{
// If this is not a metamatch
if (!(lpFSH->uSrchFlags & FLAG_FINDSHADOW_META))
{
// terminate search
iRet = MM_RET_BREAK;
}
else
{
// metamatching is going on, let us continue
Assert(iRet==MM_RET_CONTINUE);
}
}
else
{
iRet = MM_RET_FOUND_BREAK;
}
}
}
}
if ((iRet==MM_RET_FOUND_BREAK) && fInvalid)
{
// we found this object but it is invalid, as per the flags
// passed in
if (!(matchSem & UFLG_META))
{
// We are not doing metamatching
iRet = MM_RET_BREAK; // Say not found, and break
}
else
{
//we are doing metamatching.
iRet = MM_RET_CONTINUE; // ask him to keep going
}
}
return (iRet);
}
int GetShadowWithChecksProc(
LPFIND32 lpFind32,
HSHADOW hDir,
HSHADOW hShadow,
ULONG uStatus,
LPOTHERINFO lpOI,
LPSHADOWCHECK lpSC
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int iRet = MM_RET_CONTINUE;
BOOL fHintMatch=FALSE, fObjMatch=FALSE;
ULONG ulHintFlagsThisLevel = HINT_EXCLUSION; // hint flags at this level
// Convert the patterns to uppercase, as demanded by metamatch
UniToUpper(lpFind32->cFileName, lpFind32->cFileName, sizeof(lpFind32->cFileName));
// This is a filesystem object and we haven't found our match yet
if (!mNotFsobj(uStatus) && !(lpSC->uFlagsOut & FLAG_OUT_SHADOWCHECK_FOUND))
{
// Is the source a name?
if (lpSC->uFlagsIn & FLAG_IN_SHADOWCHECK_NAME)
{
UniToUpper(lpFind32->cAlternateFileName, lpFind32->cAlternateFileName, sizeof(lpFind32->cFileName));
// check for normal name and it's alias
if((IFSMgr_MetaMatch(lpFind32->cFileName, lpSC->lpuName, UFLG_NT)||
//ACHTUNG UFLG_NT used even for short name because
// we are just checking from name coming down from ifsmgr as a path
// and it is never an FCB style name
IFSMgr_MetaMatch(lpFind32->cAlternateFileName, lpSC->lpuName, UFLG_NT)))
{
fObjMatch = TRUE;
}
}
else // The source is a shadow ID
{
fObjMatch = ((HSHADOW)(ULONG_PTR)(lpSC->lpuName)==hShadow);
}
if (fObjMatch)
{
if (lpSC->uFlagsIn & FLAG_IN_SHADOWCHECK_IGNOREHINTS)
{
// No hint checking needed, lets say we found it and stop
iRet = MM_RET_FOUND_BREAK;
}
else
{
// found it, mark it as being found.
lpSC->uFlagsOut |= FLAG_OUT_SHADOWCHECK_FOUND;
#ifdef MAYBE
lpSC->sOI = *lpOI;
#endif //MAYBE
if(fHintMatch = ((mIsHint(lpOI->ulHintFlags))!=0))
{
// Let this guy override all previous includes, because
// really speaking he is at a lower level in the hierarchy
// and by our logic, hints at lower level in the hierarchy
// dominate those coming from above
lpSC->ulHintPri = 0;
lpSC->ulHintFlags = 0;
iRet = MM_RET_FOUND_BREAK;
}
else
{
iRet = MM_RET_FOUND_CONTINUE;
}
}
}
}
else if (!(lpSC->uFlagsIn & FLAG_IN_SHADOWCHECK_IGNOREHINTS) // Don't ignore hints
&& mNotFsobj(uStatus) // This IS a hint
&& (!(lpSC->uFlagsIn & FLAG_IN_SHADOWCHECK_SUBTREE)
||mHintSubtree(lpOI->ulHintFlags)))
{
// This is a pure hint and
// we are either at the end, so we can look at all kinds of hints
// or we can look at only subtree hints
if(IFSMgr_MetaMatch(lpFind32->cFileName, lpSC->lpuType, UFLG_NT|UFLG_META))
{
// The type matches with the hint
fHintMatch = TRUE;
}
}
if (fHintMatch)
{
if (mHintExclude(lpOI->ulHintFlags))
{
// Is this an exclusion hint, and the object has not
// been included by a previous hint at this level, set it
if (mHintExclude(ulHintFlagsThisLevel))
{
// Assert(lpOI->ulHintPri == 0);
// lpSC->ulHintPri = lpOI->ulHintPri;
lpSC->ulHintPri = 0;
ulHintFlagsThisLevel = lpSC->ulHintFlags = lpOI->ulHintFlags;
}
}
else
{
// Inclusion hint, override earlier excludes, or lower priority hints
if (mHintExclude(lpSC->ulHintFlags) ||
(lpSC->ulHintPri < lpOI->ulHintPri))
{
lpSC->ulHintPri = lpOI->ulHintPri;
ulHintFlagsThisLevel = lpSC->ulHintFlags = lpOI->ulHintFlags;
}
}
}
return (iRet);
}
int
FindCreateShare(
USHORT *lpShareName,
BOOL fCreate,
LPSHADOWINFO lpSI,
BOOL *lpfCreated
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
ULONG uShadowStatus, hShare;
BOOL fCreated = FALSE;
int iRet = SRET_ERROR;
Assert(vfInShadowCrit != 0);
if (!IsPathUNC(lpShareName, MAX_SERVER_SHARE_NAME_FOR_CSC))
{
CShadowKdPrint(ALWAYS,("FindCreateShare: Invalid share name %ws\r\n", lpShareName));
// Assert(FALSE);
return (iRet);
}
if (lpfCreated)
{
*lpfCreated = FALSE;
}
if (GetShareFromPath(lpShareName, lpSI) <= SRET_ERROR)
{
CShadowKdPrint(FINDCREATESHARE,("FindCreateShare: Error creating server\r\n"));
return SRET_ERROR;
}
if (lpSI->hShare)
{
iRet = SRET_OK;
}
else
{
if (fCreate)
{
if(hShare = HCreateShareObj(lpShareName, lpSI))
{
if (lpfCreated)
{
*lpfCreated = TRUE;
}
iRet = SRET_OK;
}
else
{
CShadowKdPrint(FINDCREATESHARE,("FindCreateShare: Couldn't create server object \r\n"));
}
}
}
return (iRet);
}
#ifdef CSC_RECORDMANAGER_WINNT
int FindCreateShareForNt(
PUNICODE_STRING lpShareName,
BOOL fCreate,
LPSHADOWINFO lpSI,
BOOL *lpfCreated
)
{
int iRet, lenName;
int ShareNameLengthInChars;
BOOL fIsLoopBack = FALSE;
Assert(vfInShadowCrit != 0);
ShareNameLengthInChars = lpShareName->Length / sizeof(WCHAR);
if ( ShareNameLengthInChars >= (sizeof(vsFRExt.sFR.rgwName)-1))
{
return SRET_ERROR;
}
UseGlobalFilerecExt();
// plug the extra slash.
vsFRExt.sFR.rgwName[0] = (USHORT)('\\');
// append the rest of the share name
memcpy(&(vsFRExt.sFR.rgwName[1]), lpShareName->Buffer, lpShareName->Length);
// put in a terminating NULL
vsFRExt.sFR.rgwName[ShareNameLengthInChars + 1] = 0;
if (MRxSmbCscIsLoopbackServer(vsFRExt.sFR.rgwName, &fIsLoopBack)==STATUS_SUCCESS) {
if (fIsLoopBack){
UnUseGlobalFilerecExt();
return SRET_ERROR;
}
}
iRet = FindCreateShare(vsFRExt.sFR.rgwName, fCreate, lpSI, lpfCreated);
UnUseGlobalFilerecExt();
return iRet;
}
#endif
int
CShadowFindFilerecFromInode(
LPVOID lpdbID,
HSHADOW hDir,
HSHADOW hShadow,
LPPRIQREC lpPQ,
LPFILERECEXT lpFRUse
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int iRet = 0;
Assert(vfInShadowCrit != 0);
if(!FindFileRecFromInode(lpdbShadow, hDir, hShadow, lpPQ->ulrecDirEntry, lpFRUse))
{
SetCSCDatabaseErrorFlags(CSC_DATABASE_ERROR_MISSING_INODE);
SetLastErrorLocal(ERROR_FILE_NOT_FOUND);
CShadowKdPrint(ALWAYS,("ReadShadowInfo: !!! no filerec for pq entry Inode=%x\r\n",
hShadow));
// DeletePriQRecord(lpdbShadow, hDir, hShadow, lpPQ);
goto bailout;
}
if ((lpFRUse->sFR.ulidShadow != lpPQ->ulidShadow)||(lpFRUse->sFR.ulidShadow != hShadow))
{
CShadowKdPrint(ALWAYS,("ReadShadowInfo: !!! mismatched filerec for pq entry Inode=%x\r\n",
hShadow));
// try getting it the hard way.
if(!(lpPQ->ulrecDirEntry = FindFileRecFromInode(lpdbShadow, hDir, hShadow, INVALID_REC, lpFRUse)))
{
CShadowKdPrint(ALWAYS,("ReadShadowInfo: !!! no filerec for pq entry Inode=%x, deleting PQ entry\r\n",
hShadow));
// DeletePriQRecord(lpdbShadow, hDir, hShadow, lpPQ);
goto bailout;
}
else
{
// try updating this info.
// don't check for errors, if there is a problem we will fix it on the fly
// next time around
UpdatePriQRecord(lpdbShadow, hDir, hShadow, lpPQ);
}
}
iRet = lpPQ->ulrecDirEntry;
bailout:
return (iRet);
}
BOOL
CopySecurityContextToBuffer(
LPRECORDMANAGER_SECURITY_CONTEXT lpSecurityContext,
LPVOID lpSecurityBlob,
LPDWORD lpdwBlobSize
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
DWORD dwSizeCopied = 0;
if (lpdwBlobSize)
{
if (lpSecurityBlob)
{
dwSizeCopied = min(*lpdwBlobSize, sizeof(RECORDMANAGER_SECURITY_CONTEXT));
memcpy(lpSecurityBlob, lpSecurityContext, dwSizeCopied);
*lpdwBlobSize = dwSizeCopied;
}
else
{
// size needed
*lpdwBlobSize = sizeof(RECORDMANAGER_SECURITY_CONTEXT);
}
}
return ((lpSecurityBlob != NULL) && dwSizeCopied);
}
BOOL
CopyBufferToSecurityContext(
LPVOID lpSecurityBlob,
LPDWORD lpdwBlobSize,
LPRECORDMANAGER_SECURITY_CONTEXT lpSecurityContext
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
DWORD dwSizeCopied = 0;
if (lpdwBlobSize)
{
if (lpSecurityBlob)
{
dwSizeCopied = min(*lpdwBlobSize, sizeof(RECORDMANAGER_SECURITY_CONTEXT));
memcpy(lpSecurityContext, lpSecurityBlob, dwSizeCopied);
*lpdwBlobSize = dwSizeCopied;
}
else
{
// size copied
*lpdwBlobSize = 0;
}
}
// we have done some copying
return ((lpSecurityBlob != NULL) && dwSizeCopied);
}
int PathFromHShadow(
HSHADOW hDir,
HSHADOW hShadow,
USHORT *lpBuff,
int cBuff // # of WCHAR characters that lpBuff can fit
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int cCount, cRemain, iRet=-1;
LPFIND32 lpFind32;
ULONG uShadowStatus;
HSHADOW hTmp;
Assert(vfInShadowCrit != 0);
Assert(cBuff > 1);
if (!(lpFind32 = (LPFIND32)AllocMem(sizeof(WIN32_FIND_DATA))))
{
KdPrint(("PathFromHSHADOW:Error Allocating memory\r\n"));
goto bailout;
}
memset(lpBuff, 0, cBuff * sizeof(USHORT));
cRemain = cBuff-1;
// special case the root
if (!hDir)
{
lpBuff[--cRemain] = (USHORT)('\\');
}
else
{
do
{
// If we are not dealing with the root
if (hDir)
{
if(GetShadowInfo(hDir, hShadow, lpFind32, &uShadowStatus, NULL) < SRET_OK)
goto bailout;
// Count of characters
cCount = wstrlen(lpFind32->cFileName);
// We need count+1 for prepending a backslash
if (cCount >= cRemain)
goto bailout;
// Save the ending byte which may be destroyed by UniToBCS
// Convert
// UniToBCS(lpBuff+cRemain-cCount, lpFind32->cFileName, sizeof(lpFind32->cFileName), cCount, BCS_WANSI);
memcpy(lpBuff+cRemain-cCount, lpFind32->cFileName, cCount * sizeof(USHORT));
cRemain -= cCount;
}
lpBuff[--cRemain] = (USHORT)('\\');
if(GetAncestorsHSHADOW(hDir, &hTmp, NULL) < SRET_OK)
goto bailout;
hShadow = hDir;
hDir = hTmp;
}
while (hDir);
}
// !!ACHTUNG!! this should work because the overlap is in the right way
iRet = cBuff-cRemain;
memcpy(lpBuff, lpBuff+cRemain, iRet * sizeof(USHORT));
bailout:
if (lpFind32)
FreeMem(lpFind32);
return (iRet);
}
int
GetSecurityInfosFromBlob(
LPVOID lpvBlob,
DWORD dwBlobSize,
LPSECURITYINFO lpSecInfo,
DWORD *lpdwBytes
)
/*++
Routine Description:
Given security blob, this routine returns the information in form of an array of
SECURITYINFO structures.
Arguments:
lpvBlob blob buffer that is obtained from GetShadowEx or GetShadowInfoEx
dwBlobSize blob buffer size obtained from GetShadowEx or GetShadowInfoEx
lpSecInfo Array of SECURITYINFO strucutres where to output the info
lpdwBytes
Return Value:
ERROR_SUCCESS if successful, otherwise appropriate error
--*/
{
PACCESS_RIGHTS pAccessRights = (PACCESS_RIGHTS)lpvBlob;
DWORD i, cnt;
cnt = *lpdwBytes/sizeof(ACCESS_RIGHTS);
cnt = min(cnt, CSC_MAXIMUM_NUMBER_OF_CACHED_SID_INDEXES);
if (!lpSecInfo)
{
*lpdwBytes = CSC_MAXIMUM_NUMBER_OF_CACHED_SID_INDEXES * sizeof(ACCESS_RIGHTS);
return 0;
}
for (i=0; i<cnt; ++i)
{
(lpSecInfo+i)->ulPrincipalID = (pAccessRights + i)->SidIndex;
(lpSecInfo+i)->ulPermissions = (pAccessRights + i)->MaximalRights;
}
return TRUE;
}
int
GetDatabaseLocation(
LPSTR lpszBuff
)
/*++
Routine Description:
Returns the current location of the database in ANSI string.
Arguments:
lpszBuff buffer, must be MAX_PATH
Return Value:
returns SRET_OK if successfull else returns SRET_ERROR
--*/
{
return(QueryRecDB(lpszBuff, NULL, NULL, NULL, NULL) >= SRET_OK);
}
#if 0
int PUBLIC CopyFile(
LPPATH lpSrc,
ULONG ulidDir,
ULONG ulidNew
)
{
LPSTR lpszName = NULL;
int iRet=-1;
HFREMOTE hfSrc= (HFREMOTE)NULL;
CSCHFILE hfDst= NULL;
ULONG pos;
LPVOID lpBuff=NULL;
if (OpenFileRemoteEx(lpSrc, ACCESS_READONLY, ACTION_OPENEXISTING, 0, &hfSrc))
{
CShadowKdPrint(BADERRORS,("CopyFile: Can't open remote file\r\n"));
goto bailout;
}
if (!(lpBuff = AllocMem(COPY_BUFF_SIZE)))
{
goto bailout;
}
lpszName = AllocMem(MAX_PATH);
if (!lpszName)
{
goto bailout;
}
if(GetLocalNameHSHADOW(ulidNew, lpszName, MAX_PATH, FALSE)!=SRET_OK)
{
goto bailout;
}
// If the original file existed it would be truncated
if ( !(hfDst = R0OpenFile(ACCESS_READWRITE, ACTION_CREATEALWAYS, lpszName)))
{
CShadowKdPrint(BADERRORS,("CopyFile: Can't create %s\r\n", lpszName));
goto bailout;
}
CShadowKdPrint(COPYFILE,("Copying...\r\n"));
pos = 0;
// Both the files are correctly positioned
while ((iRet = ReadFileRemote(hfSrc, LpIoreqFromFileInfo(hfSrc)
, pos, lpBuff, COPY_BUFF_SIZE))>0)
{
if (WriteFileLocal(hfDst, pos, lpBuff, iRet) < 0)
{
CShadowKdPrint(BADERRORS,("CopyFile: Write Error\r\n"));
goto bailout;
}
pos += iRet;
}
CShadowKdPrint(COPYFILE,("Copy Complete\r\n"));
iRet = 1;
bailout:
if (hfSrc)
CloseFileRemote(hfSrc, NULL);
if (hfDst)
CloseFileLocal(hfDst);
if (lpBuff)
FreeMem(lpBuff);
if ((iRet==-1) && hfDst)
{
DeleteFileLocal(lpszName, ATTRIB_DEL_ANY);
}
if (lpszName)
{
FreeMem(lpszName);
}
return iRet;
}
#endif
#ifdef DEBUG
int
ValidatePri(
LPFILERECEXT lpFR
)
{
if (!(lpFR->sFR.dwFileAttrib & FILE_ATTRIBUTE_DIRECTORY))
{
if((lpFR->sFR.uchRefPri != MAX_PRI))
{
CShadowKdPrint(ALWAYS,("Bad refpri %x %ws\r\n",
lpFR->sFR.uchRefPri,
lpFR->sFR.rgw83Name));
return 0;
}
}
else
{
if((lpFR->sFR.uchRefPri != MIN_PRI))
{
CShadowKdPrint(ALWAYS,("Bad refpri %x %ws\r\n",
lpFR->sFR.uchRefPri,
lpFR->sFR.rgw83Name));
return 0;
}
}
return 1;
}
#endif
int
GetHShareFromUNCString(
USHORT *lpServer,
int cbServer,
int lenSkip,
BOOL fIsShareName,
HSHARE *lphShare,
ULONG *lpulHintFlags
)
/*++
Routine Description:
Arguments:
Return Value:
This is the ONLY routine that is called from rdr2 code that expects the ciritcal section not to be held
because of deadlock with FAT during paging writes, if the net goes down.
See comments in rdr2\rdbss\smb.mrx\csc.nt5\transitn.c
--*/
{
int iRet = -1, i;
GENERICHEADER sGH;
CSCHFILE hf = NULL;
ULONG ulRec;
SHAREREC sSR;
BOOL fCached;
USHORT uchDelimiter=(USHORT)'\\';
*lphShare = 0;
*lpulHintFlags = 0;
if ((cbServer/sizeof(USHORT)+lenSkip)>= (sizeof(sSR.rgPath)/sizeof(USHORT)))
{
return iRet;
}
if (fIsShareName)
{
uchDelimiter = 0;
}
if (!(hf = OpenInodeFileAndCacheHandle(lpdbShadow, ULID_SHARE, ACCESS_READWRITE, &fCached)))
{
goto bailout;
}
if(ReadHeader(hf, &sGH, sizeof(FILEHEADER)) < 0)
{
goto bailout;
}
for (ulRec=1; ulRec<=sGH.ulRecords; ulRec++)
{
if(ReadRecord(hf, &sGH, ulRec, (LPGENERICREC)&sSR) < 0)
{
goto bailout;
}
if (sSR.uchType != REC_DATA)
{
continue;
}
// 0 return means it matched
if(!wstrnicmp(lpServer, sSR.rgPath + lenSkip, cbServer))
{
Assert(sSR.ulShare);
if (sSR.rgPath[lenSkip+cbServer/sizeof(USHORT)] == uchDelimiter)
{
*lphShare = sSR.ulShare;
*lpulHintFlags = (ULONG)(sSR.uchHintFlags);
iRet = SRET_OK;
break;
}
}
}
iRet = SRET_OK;
bailout:
if (hf && !fCached)
{
Assert(vfStopHandleCaching);
CloseFileLocal(hf);
}
else
{
Assert(!hf || !vfStopHandleCaching);
}
return (iRet);
}
BOOL
EnableHandleCaching(
BOOL fEnable
)
/*++
Routine Description:
Arguments:
Return Value:
returns previous handlecaching value
--*/
{
BOOL fT, fT1;
Assert(vfInShadowCrit != 0);
fT = EnableHandleCachingSidFile(fEnable);
fT1 = EnableHandleCachingInodeFile(fEnable);
Assert(fT == fT1);
return (fT1);
}
int
RecreateHSHADOW(
HSHADOW hDir,
HSHADOW hShadow,
ULONG ulAttrib
)
/*++
Routine Description:
This routine recreates an inode data file. This is so that when the CSC directory is
marked for encryption/decryption, the newly created inode file will get encrypted.
Arguments:
hDir Inode directory
hShadow Inode whose file needs to be recreated
ulAttrib recreate with given attributes
Return Value:
--*/
{
return (RecreateInode(lpdbShadow, hShadow, ulAttrib));
}
VOID
AdjustSparseStaleDetectionCount(
ULONG hShare,
LPFILERECEXT lpFRUse
)
/*++
Routine Description:
This routine deals with a monotonically increasing (that is untill it wraps around), counter
that is essentially a tick count that indicates when was the last time the cshadow interface
created/set a sparse or a stale file.
This is used by the agent to decide whether to enumerate the priority Q or not.
Added code to also check if we're creating a file on a manually-cached share, and
if so then to start the agent so it will clean this file up later.
Arguments:
lpFRUse record for the file/dir
Return Value:
None
--*/
{
ULONG cStatus;
SHAREREC sSR = {0};
LONG iRet = SRET_ERROR;
// DbgPrint("AdjustSparseStaleDetectionCount(hShare=0x%x)\n", hShare);
//
// if this is a file and is stale or sparse
//
if (IsFile(lpFRUse->sFR.dwFileAttrib) &&
(lpFRUse->sFR.uStatus & (SHADOW_STALE|SHADOW_SPARSE))) {
++vdwSparseStaleDetecionCount;
// DbgPrint("####Pulsing agent #2 (1)\n");
MRxSmbCscSignalFillAgent(NULL, 0);
goto AllDone;
}
if (hShare != 0) {
//
// If we're creating a file on a manually-cached share, let the agent know
//
if (IsFile(lpFRUse->sFR.dwFileAttrib)) {
iRet = GetShareRecord(lpdbShadow, hShare, &sSR);
if (iRet < SRET_OK) {
// DbgPrint("AdjustSparseStaleDetectionCount exit (1) iRet = %d\n", iRet);
goto AllDone;
}
}
cStatus = sSR.uStatus & FLAG_CSC_SHARE_STATUS_CACHING_MASK;
// DbgPrint("AdjustSparseStaleDetectionCount cStatus=0x%x\n", cStatus);
if (cStatus == FLAG_CSC_SHARE_STATUS_MANUAL_REINT) {
++vdwManualFileDetectionCount;
// DbgPrint("####Pulsing agent #2 (2)\n");
MRxSmbCscSignalFillAgent(NULL, 0);
}
}
AllDone:
return;
}
VOID
QuerySparseStaleDetectionCount(
LPDWORD lpcnt
)
/*++
Routine Description:
Arguments:
lpcnt for returning the count
Return Value:
None
--*/
{
*lpcnt = vdwSparseStaleDetecionCount;
}
VOID
QueryManualFileDetectionCount(
LPDWORD lpcnt
)
/*++
Routine Description:
Arguments:
lpcnt for returning the count
Return Value:
None
--*/
{
*lpcnt = vdwManualFileDetectionCount;
}
ULONG
QueryDatabaseErrorFlags(
VOID
)
/*++
Routine Description:
Arguments:
Return Value:
None
--*/
{
return GetCSCDatabaseErrorFlags();
}
int
HasDescendentsHShadow(
HSHADOW hDir,
HSHADOW hShadow,
BOOLEAN *lpfDescendents
)
/*++
Routine Description:
Arguments:
Return Value:
None
--*/
{
*lpfDescendents = (!FInodeIsFile(lpdbShadow, hDir, hShadow) &&
HasDescendents(lpdbShadow, 0, hShadow));
return 0;
}
int PUBLIC AddStoreData(
LPTSTR lpdbID,
LPSTOREDATA lpSD
)
/*++
Routine Description:
Adds space and file/dir count to the database. This is used for purging
unpinned data.
Parameters:
Return Value:
Notes:
--*/
{
CSCHFILE hf;
SHAREHEADER sSH;
int iRet = -1;
BOOL fCached;
hf = OpenInodeFileAndCacheHandle(lpdbID, ULID_SHARE, ACCESS_READWRITE, &fCached);
if (!hf)
{
return -1;
}
if (lpSD->ulSize)
{
// RecordKdPrint(STOREDATA,("Adding %ld \r\n", lpSD->ulSize));
}
if ((iRet = ReadHeader(hf, (LPVOID)&sSH, sizeof(SHAREHEADER)))> 0)
{
if (lpSD->ulSize)
{
// RecordKdPrint(STOREDATA,("AddStoreData Before: %ld \r\n", sSH.sCur.ulSize));
}
sSH.sCur.ulSize += lpSD->ulSize;
sSH.sCur.ucntDirs += lpSD->ucntDirs;
sSH.sCur.ucntFiles += lpSD->ucntFiles;
// ensure that the data is always in clustersizes
Assert(!(lpSD->ulSize%(vdwClusterSizeMinusOne+1)));
if ((iRet = WriteHeader(hf, (LPVOID)&sSH, sizeof(SHAREHEADER))) < 0)
Assert(FALSE);
if (lpSD->ulSize)
{
// RecordKdPrint(STOREDATA,("AddStoreData After: %ld \r\n", sSH.sCur.ulSize));
}
//
// If we are at the full cache size, kick the agent so he'll
// free up some space.
//
if (sSH.sCur.ulSize > sSH.sMax.ulSize) {
// DbgPrint("Full cache, notifying agent...\n");
CscNotifyAgentOfFullCacheIfRequired();
}
}
if (hf && !fCached)
{
Assert(vfStopHandleCaching);
CloseFileLocal(hf);
}
else
{
Assert(!hf || !vfStopHandleCaching);
}
return iRet;
}
int PUBLIC SubtractStoreData(
LPTSTR lpdbID,
LPSTOREDATA lpSD
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
CSCHFILE hf;
SHAREHEADER sSH;
int iRet = -1;
BOOL fCached;
hf = OpenInodeFileAndCacheHandle(lpdbID, ULID_SHARE, ACCESS_READWRITE, &fCached);
if (!hf)
{
return -1;
}
if (lpSD->ulSize)
{
// RecordKdPrint(STOREDATA,("Subtracting %ld \r\n", lpSD->ulSize));
}
if ((iRet = ReadHeader(hf, (LPVOID)&sSH, sizeof(SHAREHEADER)))> 0)
{
// RecordKdPrint(STOREDATA,("SubtractStoreData Before: %ld \r\n", sSH.sCur.ulSize));
if (sSH.sCur.ulSize >lpSD->ulSize)
{
sSH.sCur.ulSize -= lpSD->ulSize;
}
else
{
sSH.sCur.ulSize = 0;
}
if (sSH.sCur.ucntDirs > lpSD->ucntDirs)
{
sSH.sCur.ucntDirs -= lpSD->ucntDirs;
}
else
{
sSH.sCur.ucntDirs = 0;
}
if (sSH.sCur.ucntFiles > lpSD->ucntFiles)
{
sSH.sCur.ucntFiles -= lpSD->ucntFiles;
}
else
{
sSH.sCur.ucntFiles = 0;
}
// ensure that the data is always in clustersizes
Assert(!(lpSD->ulSize%(vdwClusterSizeMinusOne+1)));
if ((iRet = WriteHeader(hf, (LPVOID)&sSH, sizeof(SHAREHEADER)))<0)
Assert(FALSE);
// RecordKdPrint(STOREDATA,("SubtractStoreData After: %ld \r\n", sSH.sCur.ulSize));
}
if (hf && !fCached)
{
Assert(vfStopHandleCaching);
CloseFileLocal(hf);
}
else
{
Assert(!hf || !vfStopHandleCaching);
}
return iRet;
}