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.
747 lines
20 KiB
747 lines
20 KiB
/*++
|
|
|
|
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
|
|
|