747 lines
20 KiB
C
747 lines
20 KiB
C
/*++
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
HookCmmn.c
|
||
|
||
Abstract:
|
||
|
||
The purpose of this module is to have a common source for many routines
|
||
used by the hook on win95 and on NT. In this way, there'll be only one
|
||
place to change even if there's some code uglyness (ifdefs, etc.)
|
||
|
||
Initially, i (jll) have not actually removed any routines from the win95
|
||
hook....i have just made copies of them here. accordingly, everything is
|
||
initially under ifdef-NT. the rule that is being used is that anything that
|
||
requires visibility of the Rx Fcb structures will not be included here;
|
||
rather, it'll be in the minirdr part. the following are steps that need to be
|
||
accomplished:
|
||
|
||
1. ensure that the win95 shadow vxd can be built from these sources.
|
||
1a. juggle the win95 vxd compile to use precomp and stdcall.
|
||
2. juggle the record manager structs so that we'll be RISCable
|
||
3. remove any routines from hook.h that are actually here.
|
||
4. remove a number of other routines that i splated around from hook.c
|
||
under NT-ifdef and place them here.
|
||
|
||
Author:
|
||
|
||
Shishir Pardikar [Shishirp] 01-jan-1995
|
||
|
||
Revision History:
|
||
|
||
Joe Linn [JoeLinn] 10-mar-97 Initial munging for NT
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
#pragma hdrstop
|
||
|
||
#pragma code_seg("PAGE")
|
||
|
||
#undef RxDbgTrace
|
||
#define RxDbgTrace(a,b,__d__) {qweee __d__;}
|
||
|
||
#ifdef DEBUG
|
||
//cshadow dbgprint interface
|
||
#define HookCmmnKdPrint(__bit,__x) {\
|
||
if (((HOOKCMMN_KDP_##__bit)==0) || FlagOn(HookCmmnKdPrintVector,(HOOKCMMN_KDP_##__bit))) {\
|
||
KdPrint (__x);\
|
||
}\
|
||
}
|
||
#define HOOKCMMN_KDP_ALWAYS 0x00000000
|
||
#define HOOKCMMN_KDP_BADERRORS 0x00000001
|
||
#define HOOKCMMN_KDP_ISSPECIALAPP 0x00000002
|
||
#define HOOKCMMN_KDP_INITDATABASE 0x00000004
|
||
#define HOOKCMMN_KDP_TUNNELING 0x00000008
|
||
|
||
|
||
#define HOOKCMMN_KDP_GOOD_DEFAULT (HOOKCMMN_KDP_BADERRORS \
|
||
| 0)
|
||
|
||
ULONG HookCmmnKdPrintVector = HOOKCMMN_KDP_GOOD_DEFAULT;
|
||
ULONG HookCmmnKdPrintVectorDef = HOOKCMMN_KDP_GOOD_DEFAULT;
|
||
#else
|
||
#define HookCmmnKdPrint(__bit,__x) {NOTHING;}
|
||
#endif
|
||
|
||
//this is just for editing ease......
|
||
//#ifdef CSC_RECORDMANAGER_WINNT
|
||
//#endif //ifdef CSC_RECORDMANAGER_WINNT
|
||
|
||
|
||
#ifdef CSC_RECORDMANAGER_WINNT
|
||
BOOL fInitDB = FALSE; // Database Initialized
|
||
BOOL fReadInit = FALSE; // Init values have been read
|
||
BOOL fSpeadOpt = TRUE; // spead option, reads the cached files even when
|
||
// locks are set on the share
|
||
GLOBALSTATUS sGS; // Global status used for communicating with ring3
|
||
|
||
// Semaphore used to synchronize in memory structures
|
||
VMM_SEMAPHORE semHook;
|
||
|
||
// This strucutre is used as temporary I/O buffer only within Shadow critical
|
||
// section
|
||
WIN32_FIND_DATA vsFind32;
|
||
|
||
|
||
// Agent Info, obtained through IoctlRegisterAgent
|
||
ULONG hthreadReint=0; // Thred ID
|
||
ULONG hwndReint=0; // windows handle.
|
||
ULONG heventReint;
|
||
|
||
// upto 16 threads can temporarily enable and disable shadowing
|
||
ULONG rghthreadTemp[16];
|
||
|
||
|
||
// Reintegration happens one share at a time. If it is going on, then BeginReint
|
||
// in ioctl.c sets hShareReint to the share on which we are doing reint
|
||
// if vfBlockingReint is TRUE, then all operations on that share will fail
|
||
// when the share is reintegrating.
|
||
// If vfBlockingReint is not true, then if the dwActivityCount is non-zero
|
||
// the ioctls to change any state on any of the descendents of this share fail
|
||
// causing the agent to aboort reintegration
|
||
// The acitvycount is incremented based on a trigger from the redir/hook, when
|
||
// any namespace mutating operation is performed.
|
||
|
||
HSHARE hShareReint=0; // Share that is currently being reintegrated
|
||
BOOL vfBlockingReint = TRUE;
|
||
DWORD vdwActivityCount = 0;
|
||
//from shadow.asm ---------------------------------------------------
|
||
int fShadow = 0;
|
||
|
||
#if defined(_X86_)
|
||
int fLog = 1;
|
||
#else
|
||
int fLog = 0;
|
||
#endif
|
||
|
||
|
||
//tunnel cache
|
||
SH_TUNNEL rgsTunnel[10] = {0};
|
||
|
||
#ifdef DEBUG
|
||
ULONG cntReadHits=0;
|
||
tchar pathbuff[MAX_PATH+1];
|
||
#endif
|
||
|
||
|
||
|
||
BOOL FindTempAgentHandle(
|
||
ULONG hthread)
|
||
{
|
||
int i;
|
||
|
||
for (i=0; i < (sizeof(rghthreadTemp)/sizeof(ULONG)); ++i)
|
||
{
|
||
if (rghthreadTemp[i]==hthread)
|
||
{
|
||
return TRUE;
|
||
}
|
||
}
|
||
return FALSE;
|
||
|
||
}
|
||
|
||
BOOL
|
||
RegisterTempAgent(
|
||
VOID
|
||
)
|
||
{
|
||
int i;
|
||
ULONG hthread;
|
||
|
||
hthread = GetCurThreadHandle();
|
||
|
||
for (i=0; i< (sizeof(rghthreadTemp)/sizeof(ULONG)); ++i)
|
||
{
|
||
if (!rghthreadTemp[i])
|
||
{
|
||
rghthreadTemp[i] = hthread;
|
||
return TRUE;
|
||
}
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
BOOL
|
||
UnregisterTempAgent(
|
||
VOID
|
||
)
|
||
{
|
||
int i;
|
||
ULONG hthread;
|
||
|
||
hthread = GetCurThreadHandle();
|
||
|
||
for (i=0; i < (sizeof(rghthreadTemp)/sizeof(ULONG)); ++i)
|
||
{
|
||
if (rghthreadTemp[i]==hthread)
|
||
{
|
||
rghthreadTemp[i] = 0;
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
BOOL IsSpecialApp
|
||
(
|
||
VOID
|
||
)
|
||
{
|
||
ULONG hthread;
|
||
|
||
hthread = GetCurThreadHandle();
|
||
if ((hthread==hthreadReint) || FindTempAgentHandle(hthread))
|
||
{
|
||
HookCmmnKdPrint(ISSPECIALAPP,("This is our Special App \r\n"));
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
#define SetHintsFromList(a,b) ((-1))
|
||
int InitShadowDB(VOID)
|
||
{
|
||
//for NT, we don't have all this hint stuff....just return success
|
||
return(1);
|
||
#if 0
|
||
VMMHKEY hKeyShadow;
|
||
int iSize = sizeof(int), iRet = -1;
|
||
DWORD dwType;
|
||
extern char vszExcludeList[], vszIncludeList[];
|
||
BOOL fOpen = FALSE;
|
||
char rgchList[128];
|
||
if (_RegOpenKey(HKEY_LOCAL_MACHINE, REG_KEY_SHADOW, &hKeyShadow) == ERROR_SUCCESS)
|
||
{
|
||
fOpen = TRUE;
|
||
iSize = sizeof(rgchList);
|
||
if (_RegQueryValueEx(hKeyShadow, vszExcludeList, NULL, &dwType, rgchList, &iSize)==ERROR_SUCCESS)
|
||
{
|
||
if (SetHintsFromList(rgchList, TRUE) < 0)
|
||
goto bailout;
|
||
}
|
||
iSize = sizeof(rgchList);
|
||
if (_RegQueryValueEx(hKeyShadow, vszIncludeList, NULL, &dwType, rgchList, &iSize)==ERROR_SUCCESS)
|
||
{
|
||
if (SetHintsFromList(rgchList, FALSE) < 0)
|
||
goto bailout;
|
||
}
|
||
|
||
iRet = 1;
|
||
}
|
||
bailout:
|
||
if (fOpen)
|
||
{
|
||
_RegCloseKey(hKeyShadow);
|
||
}
|
||
return (iRet);
|
||
#endif //0
|
||
}
|
||
|
||
int ReinitializeDatabase(
|
||
LPSTR lpszLocation,
|
||
LPSTR lpszUserName,
|
||
DWORD nFileSizeHigh,
|
||
DWORD nFileSizeLow,
|
||
DWORD dwClusterSize
|
||
)
|
||
{
|
||
BOOL fDBReinited = FALSE;
|
||
if(OpenShadowDB(lpszLocation, lpszUserName, nFileSizeHigh, nFileSizeLow, dwClusterSize, TRUE, &fDBReinited) >= 0)
|
||
{
|
||
if (InitShadowDB() >= 0)
|
||
{
|
||
Assert(fDBReinited == TRUE);
|
||
fInitDB = 1;
|
||
}
|
||
else
|
||
{
|
||
CloseShadowDB();
|
||
}
|
||
}
|
||
if (fInitDB != 1)
|
||
{
|
||
fInitDB = -1;
|
||
fShadow = 0;
|
||
}
|
||
|
||
return (fInitDB);
|
||
}
|
||
|
||
int
|
||
InitDatabase(
|
||
LPSTR lpszLocation,
|
||
LPSTR lpszUserName,
|
||
DWORD nFileSizeHigh,
|
||
DWORD nFileSizeLow,
|
||
DWORD dwClusterSize,
|
||
BOOL fReformat,
|
||
BOOL *lpfNew
|
||
)
|
||
{
|
||
int iRet = 1;
|
||
BOOL fDBReinited = FALSE;
|
||
LPSTR PrefixedLocation = NULL;
|
||
|
||
HookCmmnKdPrint(INITDATABASE,("Opening database at %s for %s with size %d \r\n", lpszLocation, lpszUserName, nFileSizeLow));
|
||
|
||
//
|
||
// When CSC is started by the kernel as part of a remote boot, the input path
|
||
// will already be in NT format.
|
||
//
|
||
|
||
if (( _strnicmp(lpszLocation,"\\Device\\Harddisk",strlen("\\Device\\Harddisk")) != 0 ) &&
|
||
( _strnicmp(lpszLocation,"\\ArcName",strlen("\\ArcName")) != 0 )) {
|
||
|
||
//this would be NT only..........
|
||
PrefixedLocation = AllocMem(strlen(lpszLocation)+sizeof(NT_DB_PREFIX));
|
||
|
||
if (!PrefixedLocation)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
strcpy(PrefixedLocation, NT_DB_PREFIX);
|
||
strcat(PrefixedLocation, lpszLocation);
|
||
HookCmmnKdPrint(INITDATABASE,("Opening database at %s changing to %s \r\n", lpszLocation, PrefixedLocation));
|
||
|
||
//fortunately, this is call-by-value....so i can just overwrite the input parameter
|
||
lpszLocation = PrefixedLocation;
|
||
}
|
||
|
||
|
||
// Do onetime init
|
||
if (!fReadInit)
|
||
{
|
||
ReadInitValues();
|
||
memset(rghthreadTemp, 0, sizeof(rghthreadTemp));
|
||
fReadInit = TRUE;
|
||
}
|
||
|
||
// check if the database is not already initialized
|
||
if (!fInitDB)
|
||
{
|
||
// open/create it
|
||
iRet = OpenShadowDB(
|
||
lpszLocation,
|
||
lpszUserName,
|
||
nFileSizeHigh,
|
||
nFileSizeLow,
|
||
dwClusterSize,
|
||
fReformat,
|
||
&fDBReinited
|
||
);
|
||
|
||
// open/create DB succeeded?
|
||
if (iRet < 0)
|
||
{
|
||
//no
|
||
HookCmmnKdPrint(ALWAYS,("Error Opening/Createing shadow database \r\n"));
|
||
fInitDB = -1;
|
||
fShadow = 0;
|
||
}
|
||
else
|
||
{
|
||
*lpfNew = fDBReinited;
|
||
|
||
// did it exist in the first place?
|
||
if (fDBReinited)
|
||
{
|
||
// no it didn't, let use create things like the filters and such
|
||
iRet = InitShadowDB();
|
||
}
|
||
|
||
if (iRet >= 0)
|
||
{
|
||
fInitDB = 1;
|
||
}
|
||
else
|
||
{
|
||
CloseShadowDB();
|
||
}
|
||
}
|
||
}
|
||
|
||
if (PrefixedLocation)
|
||
{
|
||
FreeMem(PrefixedLocation);
|
||
}
|
||
return (iRet);
|
||
}
|
||
|
||
|
||
int
|
||
CloseDatabase(
|
||
VOID
|
||
)
|
||
{
|
||
if (fInitDB)
|
||
{
|
||
CloseShadowDB();
|
||
fInitDB = FALSE;
|
||
return (1);
|
||
}
|
||
return (0);
|
||
}
|
||
|
||
BOOL IsBusy
|
||
(
|
||
HSHADOW hShadow
|
||
)
|
||
{
|
||
DeclareFindFromShadowOnNtVars()
|
||
|
||
if (PFindFdbFromHShadow(hShadow))
|
||
return TRUE;
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
int PRIVATE DeleteShadowHelper
|
||
(
|
||
BOOL fMarkDeleted,
|
||
HSHADOW hDir,
|
||
HSHADOW hNew
|
||
)
|
||
{
|
||
int iRet = -1;
|
||
|
||
if (!fMarkDeleted)
|
||
{
|
||
if (DeleteShadow(hDir, hNew) < SRET_OK)
|
||
goto bailout;
|
||
}
|
||
else
|
||
{
|
||
if (TruncateDataHSHADOW(hDir, hNew) < SRET_OK)
|
||
goto bailout;
|
||
// ACHTUNG!! other people depend on status being SHADOW_DELETED
|
||
if (SetShadowInfo(hDir, hNew, NULL, SHADOW_DELETED, SHADOW_FLAGS_OR) < SRET_OK)
|
||
goto bailout;
|
||
}
|
||
iRet = 0;
|
||
|
||
bailout:
|
||
|
||
return (iRet);
|
||
}
|
||
|
||
|
||
/*+-------------------------------------------------------------------------*/
|
||
/* @doc INTERNAL HOOK
|
||
@func BOOL | InsertTunnelInfo | 2.0
|
||
|
||
The <f InsertTunnelInfo> function inserts file names
|
||
in a tunnelling table. These entries are considered
|
||
useful only for STALE_TUNNEL_INFO seconds. Tunnelling is
|
||
used to retain LPOTHERINFO for files that get renamed/deleted
|
||
and some other file is renamed to it. This typically done
|
||
by editors, spreadsheets and such while saving things.
|
||
|
||
@parm HSHADOW | hDir | Directory to which this guy belongs
|
||
@parm LPPE | lppe | PathELement for the file to be tunnelled
|
||
@parm LPOTHERINFO | lpOI | Info to be kept with the tunnelled entry
|
||
|
||
@comm >>comment_text, <p parm> etc...
|
||
|
||
@rdesc This function returns TRUE if successful. Otherwise the
|
||
return value is FALSE.
|
||
@xref >><f related_func>, <t RELATEDSTRUCT> ...
|
||
*/
|
||
|
||
|
||
BOOL InsertTunnelInfo(
|
||
HSHADOW hDir,
|
||
USHORT *lpcFileName,
|
||
USHORT *lpcAlternateFileName, // assume 14 USHORTs
|
||
LPOTHERINFO lpOI
|
||
)
|
||
{
|
||
int i, iHole = -1;
|
||
ULONG uTime = IFSMgr_Get_NetTime(), cbFileName;
|
||
|
||
cbFileName = (wstrlen(lpcFileName)+1)*sizeof(USHORT);
|
||
ASSERT(hDir!=0);
|
||
|
||
FreeStaleEntries();
|
||
for (i=0;i< (sizeof(rgsTunnel)/sizeof(SH_TUNNEL)); ++i)
|
||
{
|
||
if (!rgsTunnel[i].hDir && (iHole < 0))
|
||
{
|
||
iHole = i;
|
||
}
|
||
if ((rgsTunnel[i].hDir==hDir)
|
||
&& (!wstrnicmp(lpcFileName, rgsTunnel[i].lpcFileName, MAX_PATH*sizeof(USHORT))||
|
||
!wstrnicmp( lpcFileName,
|
||
rgsTunnel[i].cAlternateFileName,
|
||
sizeof(rgsTunnel[i].cAlternateFileName)))
|
||
) {
|
||
FreeEntry(&rgsTunnel[i]);
|
||
iHole = i;
|
||
break;
|
||
}
|
||
}
|
||
if (iHole >=0)
|
||
{
|
||
if (!(rgsTunnel[iHole].lpcFileName = (USHORT *)AllocMem(cbFileName)))
|
||
{
|
||
return (FALSE);
|
||
}
|
||
rgsTunnel[iHole].uTime = uTime;
|
||
rgsTunnel[iHole].hDir = hDir;
|
||
rgsTunnel[iHole].ubHintFlags = (UCHAR)(lpOI->ulHintFlags);
|
||
rgsTunnel[iHole].ubHintPri = (UCHAR)(lpOI->ulHintPri);
|
||
rgsTunnel[iHole].ubIHPri = (UCHAR)(lpOI->ulIHPri);
|
||
rgsTunnel[iHole].ubRefPri = (UCHAR)(lpOI->ulRefPri);
|
||
|
||
// copy without the NULL, we know that allocmem will have a NULL at the end
|
||
memcpy(rgsTunnel[iHole].lpcFileName, lpcFileName, cbFileName-sizeof(USHORT));
|
||
|
||
// assumes 14 USHORTS
|
||
memcpy( rgsTunnel[iHole].cAlternateFileName,
|
||
lpcAlternateFileName,
|
||
sizeof(rgsTunnel[iHole].cAlternateFileName));
|
||
|
||
HookCmmnKdPrint(TUNNELING,("InsertTunnelInfo: Inserting %ws/%ws, Hintpri=%d, HintFlags=%d RefPri=%d \r\n",
|
||
lpcFileName,lpcAlternateFileName,
|
||
lpOI->ulHintPri,
|
||
lpOI->ulHintFlags,
|
||
lpOI->ulRefPri
|
||
));
|
||
|
||
return (TRUE);
|
||
}
|
||
return (FALSE);
|
||
}
|
||
|
||
/*+-------------------------------------------------------------------------*/
|
||
/* @doc INTERNAL HOOK
|
||
@func BOOL | RetrieveTunnelInfo | 2.0
|
||
|
||
The <f RetrieveTunnelInfo> function returns to the caller
|
||
OTHERINFO structure containing priorities and such about
|
||
files which have been recently renamed or deleted. Entries
|
||
which are older than STALE_TUNNEL_INFO seconds are thrown
|
||
out.
|
||
|
||
@parm HSHADOW | hDir | Directory to which this guy belongs
|
||
@parm ushort *| lpcFileName| name of the file whose info is needed
|
||
@parm LPOTHERINFO | lpOI | Info to be retrieved from the tunnelled entry
|
||
|
||
@comm >>comment_text, <p parm> etc...
|
||
|
||
@rdesc This function returns TRUE if successful. Otherwise the
|
||
return value is FALSE.
|
||
@xref >><f related_func>, <t RELATEDSTRUCT> ...
|
||
*/
|
||
|
||
|
||
#ifndef MRXSMB_BUILD_FOR_CSC_DCON
|
||
BOOL RetrieveTunnelInfo(
|
||
#else
|
||
RETRIEVE_TUNNEL_INFO_RETURNS
|
||
RetrieveTunnelInfo(
|
||
#endif
|
||
HSHADOW hDir,
|
||
USHORT *lpcFileName,
|
||
WIN32_FIND_DATA *lpFind32, // if NULL, get only otherinfo
|
||
LPOTHERINFO lpOI
|
||
)
|
||
{
|
||
int i;
|
||
#ifdef MRXSMB_BUILD_FOR_CSC_DCON
|
||
RETRIEVE_TUNNEL_INFO_RETURNS RetVal;
|
||
#endif
|
||
|
||
ASSERT(hDir!=0);
|
||
FreeStaleEntries();
|
||
for (i=0;i< (sizeof(rgsTunnel)/sizeof(SH_TUNNEL)); ++i)
|
||
{
|
||
#ifndef MRXSMB_BUILD_FOR_CSC_DCON
|
||
if (rgsTunnel[i].hDir
|
||
&& (!wstrnicmp(lpcFileName, rgsTunnel[i].lpcFileName, MAX_PATH*sizeof(USHORT))||
|
||
!wstrnicmp( lpcFileName,
|
||
rgsTunnel[i].cAlternateFileName,
|
||
sizeof(rgsTunnel[i].cAlternateFileName)))
|
||
) {
|
||
#else
|
||
if (rgsTunnel[i].hDir==hDir)
|
||
{
|
||
if (!wstrnicmp(lpcFileName,
|
||
rgsTunnel[i].cAlternateFileName,
|
||
sizeof(rgsTunnel[i].cAlternateFileName)) ) {
|
||
RetVal = TUNNEL_RET_SHORTNAME_TUNNEL;
|
||
} else if ( !wstrnicmp(lpcFileName, rgsTunnel[i].lpcFileName, MAX_PATH*sizeof(USHORT)) ){
|
||
RetVal = TUNNEL_RET_LONGNAME_TUNNEL;
|
||
} else {
|
||
continue;
|
||
}
|
||
|
||
#endif
|
||
InitOtherInfo(lpOI);
|
||
|
||
lpOI->ulHintFlags = (ULONG)(rgsTunnel[i].ubHintFlags);
|
||
lpOI->ulHintPri = (ULONG)(rgsTunnel[i].ubHintPri);
|
||
lpOI->ulIHPri = (ULONG)(rgsTunnel[i].ubIHPri);
|
||
|
||
// don't copy the reference priority, it is assigned by the record manager
|
||
// lpOI->ulRefPri = (ULONG)(rgsTunnel[i].ubRefPri);
|
||
|
||
HookCmmnKdPrint(TUNNELING,("RetrieveTunnelInfo: %ws found, Hintpri=%d, HintFlags=%d RefPri=%d \r\n",
|
||
lpcFileName,
|
||
lpOI->ulHintPri,
|
||
lpOI->ulHintFlags,
|
||
lpOI->ulRefPri
|
||
));
|
||
|
||
if (lpFind32)
|
||
{
|
||
memcpy( lpFind32->cFileName,
|
||
rgsTunnel[i].lpcFileName,
|
||
(wstrlen(rgsTunnel[i].lpcFileName)+1)*sizeof(USHORT)
|
||
);
|
||
memcpy( lpFind32->cAlternateFileName,
|
||
rgsTunnel[i].cAlternateFileName,
|
||
sizeof(rgsTunnel[i].cAlternateFileName)
|
||
);
|
||
HookCmmnKdPrint(TUNNELING,("Recovered LFN %ws/%ws \r\n",
|
||
lpFind32->cFileName,
|
||
lpFind32->cAlternateFileName));
|
||
}
|
||
|
||
FreeEntry(&rgsTunnel[i]);
|
||
#ifndef MRXSMB_BUILD_FOR_CSC_DCON
|
||
return (TRUE);
|
||
}
|
||
}
|
||
return (FALSE);
|
||
#else
|
||
return (RetVal);
|
||
}
|
||
}
|
||
return (TUNNEL_RET_NOTFOUND);
|
||
#endif
|
||
}
|
||
|
||
VOID FreeStaleEntries()
|
||
{
|
||
int i;
|
||
ULONG uTime = IFSMgr_Get_NetTime();
|
||
|
||
for (i=0;i< (sizeof(rgsTunnel)/sizeof(SH_TUNNEL)); ++i)
|
||
{
|
||
if (rgsTunnel[i].lpcFileName
|
||
&& ((uTime- rgsTunnel[i].uTime)>STALE_TUNNEL_INFO))
|
||
{
|
||
FreeEntry(&rgsTunnel[i]);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
void FreeEntry(LPSH_TUNNEL lpshTunnel)
|
||
{
|
||
FreeMem(lpshTunnel->lpcFileName);
|
||
memset(lpshTunnel, 0, sizeof(SH_TUNNEL));
|
||
}
|
||
|
||
//got this from hook.c...not the same because w95 looks at the
|
||
//resource flags directly
|
||
BOOL IsShadowVisible(
|
||
#ifdef MRXSMB_BUILD_FOR_CSC_DCON
|
||
BOOLEAN Disconnected,
|
||
#else
|
||
PRESOURCE pResource,
|
||
#endif //ifdef MRXSMB_BUILD_FOR_CSC_DCON
|
||
DWORD dwAttr,
|
||
ULONG uShadowStatus
|
||
)
|
||
{
|
||
BOOL fVisible = 1;
|
||
|
||
// To a filesystem API the shadow is never visible when it is marked
|
||
// as being deleted
|
||
|
||
if (mShadowDeleted(uShadowStatus))
|
||
return (0);
|
||
|
||
#ifdef MRXSMB_BUILD_FOR_CSC_DCON
|
||
if (Disconnected)
|
||
#else
|
||
if (mIsDisconnected(pResource))
|
||
#endif //ifdef MRXSMB_BUILD_FOR_CSC_DCON
|
||
{
|
||
if (IsFile(dwAttr))
|
||
{
|
||
#ifdef OFFLINE
|
||
#ifdef CSC_RECORDMANAGER_WINNT
|
||
ASSERT(FALSE);
|
||
#endif //ifdef CSC_RECORDMANAGER_WINNT
|
||
if (mIsOfflineConnection(pResource))
|
||
{ // offline connection
|
||
if (!mShadowOutofSync(uShadowStatus))
|
||
{
|
||
fVisible = 0;
|
||
}
|
||
}
|
||
else
|
||
#endif //OFFLINE
|
||
{// pure disconnected state
|
||
// ignore sparse files
|
||
if (mShadowSparse(uShadowStatus))
|
||
{
|
||
fVisible = 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{ // connected state, bypass all out of ssync files, doesn't include
|
||
// stale, because we can handle staleness during open
|
||
if (IsFile(dwAttr))
|
||
{
|
||
if (mShadowOutofSync(uShadowStatus))
|
||
{
|
||
fVisible = 0;
|
||
}
|
||
}
|
||
else if (dwAttr & FILE_ATTRIBUTE_DIRECTORY)
|
||
{ // and locallycreated or orphaned directories
|
||
if (mQueryBits(uShadowStatus, SHADOW_LOCALLY_CREATED|SHADOW_ORPHAN))
|
||
{
|
||
fVisible = 0;
|
||
}
|
||
}
|
||
}
|
||
return (fVisible);
|
||
}
|
||
|
||
|
||
//got this from hook.c...not the same because w95 looks at the
|
||
//resource flags directly
|
||
|
||
|
||
//CODE.IMPROVEMENT we should define a common header for RESOURCE and FDB so that most stuff
|
||
// would just work.
|
||
int MarkShareDirty(
|
||
PUSHORT ShareStatus,
|
||
ULONG hShare
|
||
)
|
||
{
|
||
|
||
if (!mQueryBits(*ShareStatus, SHARE_REINT))
|
||
{
|
||
SetShareStatus(hShare, SHARE_REINT, SHADOW_FLAGS_OR);
|
||
mSetBits(*ShareStatus, SHARE_REINT);
|
||
}
|
||
return SRET_OK;
|
||
}
|
||
|
||
#endif //ifdef CSC_RECORDMANAGER_WINNT
|
||
|