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.
1213 lines
30 KiB
1213 lines
30 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Log.c
|
|
|
|
Abstract:
|
|
|
|
none.
|
|
|
|
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")
|
|
|
|
/********************************************************************/
|
|
/** Copyright(c) Microsoft Corp., 1990-1991 **/
|
|
/********************************************************************/
|
|
|
|
// Hook Processing
|
|
|
|
/******************************* Include Files ******************************/
|
|
|
|
#ifndef CSC_RECORDMANAGER_WINNT
|
|
#define WIN32_APIS
|
|
#include "cshadow.h"
|
|
#endif //ifndef CSC_RECORDMANAGER_WINNT
|
|
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
// #include "error.h"
|
|
#include "vxdwraps.h"
|
|
#include "logdat.h"
|
|
|
|
/******************************* defines/typedefs ***************************/
|
|
#define MAX_SHADOW_LOG_ENTRY 512
|
|
#define MAX_LOG_SIZE 100000
|
|
|
|
#ifdef DEBUG
|
|
#define SHADOW_TIMER_INTERVAL 30000
|
|
#define STATS_FLUSH_COUNT 10
|
|
#endif //DEBUG
|
|
|
|
#define ENTERCRIT_LOG { if (!fLogInit) InitShadowLog();\
|
|
if (fLogInit==-1) return; \
|
|
Wait_Semaphore(semLog, BLOCK_SVC_INTS);}
|
|
#define LEAVECRIT_LOG Signal_Semaphore(semLog);
|
|
|
|
#ifdef CSC_RECORDMANAGER_WINNT
|
|
|
|
//ntdef has already define TIME differently....fortuntely by macros....
|
|
//so we undo this for the remainder of this file. the RIGHT solution is
|
|
//to use a name like CSC_LOG_TIME.
|
|
|
|
#undef _TIME
|
|
#undef TIME
|
|
#undef PTIME
|
|
|
|
#endif //ifdef CSC_RECORDMANAGER_WINNT
|
|
|
|
typedef struct tagTIME
|
|
{
|
|
WORD seconds;
|
|
WORD minutes;
|
|
WORD hours;
|
|
WORD day;
|
|
WORD month;
|
|
WORD year;
|
|
}
|
|
TIME, FAR *LPTIME;
|
|
#pragma intrinsic (memcmp, memcpy, memset, strcat, strcmp, strcpy, strlen)
|
|
|
|
/******************************* Function Prototypes ************************/
|
|
int vxd_vsprintf(char * lpOut, char * lpFmt, CONST VOID * lpParms);
|
|
int PrintLog( LPSTR lpFmt, ...);
|
|
void PrintNetTime(LONG ltime);
|
|
void PrintNetShortTime(LONG ltime);
|
|
void ExplodeTime( ULONG time, LPTIME lpTime );
|
|
void LogPreamble(int, LPSTR, int, LPSTR);
|
|
int WriteStats(BOOL);
|
|
|
|
//need this for NT
|
|
int WriteLog(void);
|
|
/******************************** Static/Global data ************************/
|
|
|
|
#ifdef CSC_RECORDMANAGER_WINNT
|
|
#define UniToBCSPath(a,b,c,d)
|
|
#define IFSMgr_DosToNetTime(a) ((0))
|
|
#endif //ifdef CSC_RECORDMANAGER_WINNT
|
|
|
|
AssertData;
|
|
AssertError;
|
|
|
|
|
|
char logpathbuff[MAX_PATH+1], rgchLogFileName[MAX_PATH];
|
|
char chLogginBuffer[COPY_BUFF_SIZE];
|
|
|
|
extern int fLog;
|
|
extern LPSTR vlpszShadowDir;
|
|
int fLogInit = FALSE;
|
|
LPSTR lpLogBuff = chLogginBuffer;
|
|
int cBuffSize = COPY_BUFF_SIZE;
|
|
int indxCur = 0;
|
|
VMM_SEMAPHORE semLog = 0L;
|
|
#define FOURYEARS (3*365+366)
|
|
|
|
ULONG ulMaxLogSize=0x00020000; // 128K log filesize by default
|
|
|
|
#ifndef CSC_RECORDMANAGER_WINNT
|
|
BOOL fPersistLog = TRUE;
|
|
#else
|
|
BOOL fPersistLog = FALSE;
|
|
#endif
|
|
|
|
#define DAYSECONDS (60L*60L*24L) // number of seconds in a day
|
|
|
|
#define BIAS_70_TO_80 0x12CEA600L
|
|
|
|
// days in a month
|
|
|
|
int MonTab[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
|
|
|
/* structure stores intl settings for datetime format */
|
|
char szCSCLog[] = "\\csc.log"; // keep this size below 8
|
|
char szCRLF[] = "\r\n";
|
|
char szBegin[] = "Begin";
|
|
char szEnd[] = "End";
|
|
char szContinue[] = "Continue";
|
|
char szEndMarker[] = "END\n";
|
|
|
|
ULONG ulMaxLogfileSize;
|
|
DWORD dwDebugLogVector = DEBUG_LOG_BIT_RECORD|DEBUG_LOG_BIT_CSHADOW; // by default record manager logging is on
|
|
#ifdef DEBUG
|
|
ULONG cntVfnDelete=0, cntVfnCreateDir=0, cntVfnDeleteDir=0, cntVfnCheckDir=0, cntVfnGetAttrib=0;
|
|
ULONG cntVfnSetAttrib=0, cntVfnFlush=0, cntVfnGetDiskInfo=0, cntVfnOpen=0;
|
|
ULONG cntVfnRename=0, cntVfnSearchFirst=0, cntVfnSearchNext=0;
|
|
ULONG cntVfnQuery=0, cntVfnDisconnect=0, cntVfnUncPipereq=0, cntVfnIoctl16Drive=0;
|
|
ULONG cntVfnGetDiskParms=0, cntVfnFindOpen=0, cntVfnDasdIO=0;
|
|
|
|
ULONG cntHfnFindNext=0, cntHfnFindClose=0;
|
|
ULONG cntHfnRead=0, cntHfnWrite=0, cntHfnSeek=0, cntHfnClose=0, cntHfnCommit=0;
|
|
ULONG cntHfnSetFileLocks=0, cntHfnRelFileLocks=0, cntHfnGetFileTimes=0, cntHfnSetFileTimes=0;
|
|
ULONG cntHfnPipeRequest=0, cntHfnHandleInfo=0, cntHfnEnumHandle=0;
|
|
ULONG cbReadLow=0, cbReadHigh=0, cbWriteLow=0, cbWriteHigh=0;
|
|
ULONG cntVfnConnect=0;
|
|
ULONG cntLastTotal=0;
|
|
#endif //DEBUG
|
|
|
|
/****************************************************************************/
|
|
#ifndef CSC_RECORDMANAGER_WINNT
|
|
#pragma VxD_LOCKED_CODE_SEG
|
|
#endif //ifndef CSC_RECORDMANAGER_WINNT
|
|
|
|
int InitShadowLog(
|
|
)
|
|
{
|
|
int iRet = -1, lenT;
|
|
|
|
if (fLog && !fLogInit && vlpszShadowDir)
|
|
{
|
|
if (!(semLog = Create_Semaphore(1)))
|
|
goto bailout;
|
|
|
|
strcpy(rgchLogFileName, (LPSTR)vlpszShadowDir);
|
|
strcat(rgchLogFileName, szCSCLog);
|
|
|
|
PrintLog(szCRLF);
|
|
PrintNetTime(IFSMgr_Get_NetTime());
|
|
PrintLog(szCRLF);
|
|
fLogInit = 1;
|
|
iRet = 0;
|
|
}
|
|
else
|
|
{
|
|
iRet = 0;
|
|
}
|
|
|
|
bailout:
|
|
if (iRet)
|
|
{
|
|
if (semLog)
|
|
Destroy_Semaphore(semLog);
|
|
semLog = 0L;
|
|
}
|
|
return iRet;
|
|
}
|
|
|
|
int ShadowLog(
|
|
LPSTR lpFmt,
|
|
...
|
|
)
|
|
{
|
|
int pos, iRet = -1;
|
|
if (!fLogInit)
|
|
{
|
|
InitShadowLog();
|
|
}
|
|
|
|
if (fLogInit)
|
|
{
|
|
if ((cBuffSize-indxCur+sizeof(szEndMarker)) < MAX_SHADOW_LOG_ENTRY)
|
|
{
|
|
iRet = WriteLog();
|
|
#if 0
|
|
PrintLog(szCRLF);
|
|
PrintNetTime(IFSMgr_Get_NetTime());
|
|
PrintLog(szCRLF);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
indxCur += vxd_vsprintf(lpLogBuff+indxCur, lpFmt, (LPSTR)&lpFmt+sizeof(lpFmt));
|
|
|
|
// deliberately don't move the index pointer after writing the end marker
|
|
// so when the next real log entry is written, the endmarker will be overwritten
|
|
memcpy(lpLogBuff+indxCur, szEndMarker, sizeof(szEndMarker)-1);
|
|
iRet = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
iRet = 0;
|
|
}
|
|
return (iRet);
|
|
}
|
|
|
|
|
|
int TerminateShadowLog(
|
|
)
|
|
{
|
|
int iRet = -1;
|
|
if (fLogInit)
|
|
{
|
|
iRet = WriteLog();
|
|
Destroy_Semaphore(semLog);
|
|
semLog = 0L;
|
|
fLogInit = 0;
|
|
}
|
|
else
|
|
{
|
|
iRet = 0;
|
|
}
|
|
return (iRet);
|
|
}
|
|
|
|
int FlushLog(
|
|
)
|
|
{
|
|
int iRet = 0;
|
|
if (!fLogInit)
|
|
{
|
|
InitShadowLog();
|
|
}
|
|
if (fLogInit==1)
|
|
{
|
|
Wait_Semaphore(semLog, BLOCK_SVC_INTS);
|
|
iRet = WriteLog();
|
|
Signal_Semaphore(semLog);
|
|
}
|
|
else
|
|
{
|
|
iRet = -1;
|
|
}
|
|
return (iRet);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
int WriteLog(
|
|
)
|
|
{
|
|
int iRet = -1;
|
|
CSCHFILE hfShadowLog = CSCHFILE_NULL;
|
|
ULONG pos;
|
|
|
|
if (fLogInit && vlpszShadowDir)
|
|
{
|
|
if (fPersistLog)
|
|
{
|
|
if (!(hfShadowLog = CreateFileLocal(rgchLogFileName)))
|
|
{
|
|
KdPrint(("WriteLog: Couldn't open log file\r\n"));
|
|
goto bailout;
|
|
}
|
|
if(GetFileSizeLocal(hfShadowLog, &pos))
|
|
{
|
|
KdPrint(("ShadowLog: log file error\r\n"));
|
|
goto bailout;
|
|
}
|
|
if ((pos+indxCur) > ulMaxLogSize)
|
|
{
|
|
#if 0
|
|
CloseFileLocal(hfShadowLog);
|
|
DeleteFileLocal(lpszLogAlt, ATTRIB_DEL_ANY);
|
|
RenameFileLocal(szLog, szLogAlt);
|
|
if (!(hfShadowLog = CreateFileLocal(szLog)))
|
|
{
|
|
KdPrint(("WriteLog: Couldn't open shadow file\r\n"));
|
|
goto bailout;
|
|
}
|
|
#endif
|
|
pos=0; // wraparound the logfile
|
|
}
|
|
if (WriteFileLocal(hfShadowLog, pos, lpLogBuff, indxCur) != indxCur)
|
|
{
|
|
KdPrint(("ShadowLog: error writing the log at position %x \r\n", pos));
|
|
goto bailout;
|
|
}
|
|
}
|
|
|
|
iRet = 0;
|
|
}
|
|
bailout:
|
|
if (hfShadowLog)
|
|
{
|
|
CloseFileLocal(hfShadowLog);
|
|
}
|
|
|
|
// no matter what happens, reset the index to 0
|
|
indxCur = 0;
|
|
return iRet;
|
|
}
|
|
#else
|
|
int
|
|
WriteLog(
|
|
VOID
|
|
)
|
|
{
|
|
// no matter what happens, reset the index to 0
|
|
indxCur = 0;
|
|
return 1;
|
|
}
|
|
#endif //DEBUG
|
|
|
|
void EnterLogCrit(void)
|
|
{
|
|
ENTERCRIT_LOG;
|
|
}
|
|
|
|
void LeaveLogCrit(void)
|
|
{
|
|
LEAVECRIT_LOG;
|
|
}
|
|
|
|
/*
|
|
* PrintNetTime
|
|
*
|
|
* Adds a time and a date to the end of a string.
|
|
* Time is seconds since 1/1/70.
|
|
*
|
|
*/
|
|
void PrintNetTime(LONG ltime)
|
|
{
|
|
TIME tm;
|
|
int d1, d2, d3;
|
|
|
|
ExplodeTime( ltime, &tm );
|
|
d1 = tm.month; d2 = tm.day; d3 = tm.year%100;
|
|
|
|
PrintLog(szTimeDateFormat, tm.hours, tm.minutes, tm.seconds, d1, d2, d3);
|
|
}
|
|
|
|
/*
|
|
* PrintNetTime
|
|
*
|
|
* Adds a time and a date to the end of a string.
|
|
* Time is seconds since 1/1/70.
|
|
*
|
|
*/
|
|
void PrintNetShortTime( LONG ltime
|
|
)
|
|
{
|
|
TIME tm;
|
|
|
|
ExplodeTime( ltime, &tm );
|
|
|
|
PrintLog(szTimeFormat, tm.hours, tm.minutes, tm.seconds);
|
|
}
|
|
|
|
int PrintLog(
|
|
LPSTR lpFmt,
|
|
...
|
|
)
|
|
{
|
|
indxCur += vxd_vsprintf(lpLogBuff+indxCur, lpFmt, (LPSTR)&lpFmt+sizeof(lpFmt));
|
|
return(0);
|
|
}
|
|
|
|
VOID
|
|
_cdecl
|
|
DbgPrintLog(
|
|
LPSTR lpFmt,
|
|
...
|
|
)
|
|
{
|
|
ENTERCRIT_LOG;
|
|
indxCur += vxd_vsprintf(lpLogBuff+indxCur, lpFmt, (LPSTR)&lpFmt+sizeof(lpFmt));
|
|
LEAVECRIT_LOG;
|
|
}
|
|
|
|
void ExplodeTime( ULONG time, LPTIME lpTime )
|
|
{
|
|
ULONG date;
|
|
WORD cLeaps;
|
|
LONG days;
|
|
WORD dpy;
|
|
int i;
|
|
|
|
time -= BIAS_70_TO_80;
|
|
|
|
date = time / DAYSECONDS;
|
|
time %= DAYSECONDS;
|
|
|
|
lpTime->seconds = (WORD)(time % 60L);
|
|
time /= 60L;
|
|
lpTime->minutes = (WORD)(time % 60L);
|
|
lpTime->hours = (WORD)(time / 60L);
|
|
|
|
cLeaps = (WORD)(date / FOURYEARS); // # of full leap years
|
|
days = date % FOURYEARS; // remaining days
|
|
|
|
lpTime->year = cLeaps * 4 + 1980; // correct year
|
|
MonTab[1] = 29; // set # days in Feb for leap years
|
|
dpy = 366;
|
|
days -= dpy;
|
|
if (days >= 0) { // this is not a leap year
|
|
dpy--;
|
|
while (days >= 0) {
|
|
lpTime->year++;
|
|
days -= dpy;
|
|
}
|
|
MonTab[1] = 28; // set # days in Feb for non-leap years
|
|
}
|
|
|
|
days += dpy; // days = # days left in this year
|
|
|
|
for (i=0; days >= MonTab[i]; i++)
|
|
days -= MonTab[i];
|
|
|
|
lpTime->month = (WORD)i + 1; // calculate 1-based month
|
|
lpTime->day = (WORD)days + 1; // calculate 1-based day
|
|
}
|
|
|
|
|
|
void LogVfnDelete( PIOREQ pir
|
|
)
|
|
{
|
|
TIME tm;
|
|
#ifdef DEBUG
|
|
++cntVfnDelete;
|
|
#endif //DEBUG
|
|
if (fLog)
|
|
{
|
|
ENTERCRIT_LOG;
|
|
memset(logpathbuff, 0, sizeof(logpathbuff));
|
|
UniToBCSPath(logpathbuff, &pir->ir_ppath->pp_elements[0], MAX_PATH, BCS_OEM);
|
|
logpathbuff[MAX_PATH]=0;
|
|
LogPreamble(VFNLOG_DELETE, logpathbuff, pir->ir_error, szCR);
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
void LogVfnDir( PIOREQ pir
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
if (pir->ir_flags == CREATE_DIR)
|
|
++cntVfnCreateDir;
|
|
else if (pir->ir_flags == DELETE_DIR)
|
|
++cntVfnDeleteDir;
|
|
else
|
|
++cntVfnCheckDir;
|
|
#endif //DEBUG
|
|
|
|
if (fLog)
|
|
{
|
|
ENTERCRIT_LOG;
|
|
UniToBCSPath(logpathbuff, &pir->ir_ppath->pp_elements[0], MAX_PATH, BCS_OEM);
|
|
logpathbuff[MAX_PATH]=0;
|
|
if (pir->ir_flags==CREATE_DIR)
|
|
LogPreamble(VFNLOG_CREATE_DIR, logpathbuff, pir->ir_error, szCR);
|
|
else if (pir->ir_flags==DELETE_DIR)
|
|
LogPreamble(VFNLOG_DELETE_DIR, logpathbuff, pir->ir_error, szCR);
|
|
else if (pir->ir_flags==CHECK_DIR)
|
|
LogPreamble(VFNLOG_CHECK_DIR, logpathbuff, pir->ir_error, szCR);
|
|
else if (pir->ir_flags==QUERY83_DIR)
|
|
{
|
|
LogPreamble(VFNLOG_QUERY83_DIR, logpathbuff, pir->ir_error, NULL);
|
|
UniToBCSPath(logpathbuff, &pir->ir_ppath2->pp_elements[0], MAX_PATH, BCS_OEM);
|
|
ShadowLog(" %s\r\n", logpathbuff);
|
|
}
|
|
else
|
|
{
|
|
LogPreamble(VFNLOG_QUERYLONG_DIR, logpathbuff, pir->ir_error, NULL);
|
|
UniToBCSPath(logpathbuff, &pir->ir_ppath2->pp_elements[0], MAX_PATH, BCS_OEM);
|
|
ShadowLog(" %s\r\n", logpathbuff);
|
|
}
|
|
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
|
|
void LogVfnFileAttrib( PIOREQ pir
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
if (pir->ir_flags == GET_ATTRIBUTES)
|
|
++cntVfnGetAttrib;
|
|
else
|
|
++cntVfnSetAttrib;
|
|
|
|
#endif //DEBUG
|
|
if (fLog)
|
|
{
|
|
ENTERCRIT_LOG;
|
|
memset(logpathbuff, 0, sizeof(logpathbuff));
|
|
UniToBCSPath(logpathbuff, &pir->ir_ppath->pp_elements[0], MAX_PATH, BCS_OEM);
|
|
|
|
if (pir->ir_flags == GET_ATTRIBUTES)
|
|
{
|
|
LogPreamble(VFNLOG_GET_ATTRB, logpathbuff, pir->ir_error, NULL);
|
|
ShadowLog(rgsLogCmd[VFNLOG_GET_ATTRB].lpFmt, pir->ir_attr);
|
|
}
|
|
else
|
|
{
|
|
LogPreamble(VFNLOG_SET_ATTRB, logpathbuff, pir->ir_error, NULL);
|
|
ShadowLog(rgsLogCmd[VFNLOG_SET_ATTRB].lpFmt, pir->ir_attr);
|
|
}
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
|
|
void LogVfnFlush( PIOREQ pir
|
|
)
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
++cntVfnFlush;
|
|
#endif //DEBUG
|
|
|
|
if (fLog)
|
|
{
|
|
ENTERCRIT_LOG;
|
|
PpeToSvr(((PRESOURCE)(pir->ir_rh))->pp_elements, logpathbuff, sizeof(logpathbuff), BCS_OEM);
|
|
LogPreamble(VFNLOG_FLUSH, logpathbuff, pir->ir_error, szCR);
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
|
|
void LogVfnGetDiskInfo( PIOREQ pir
|
|
)
|
|
{
|
|
if (fLog)
|
|
{
|
|
ENTERCRIT_LOG;
|
|
PpeToSvr(((PRESOURCE)(pir->ir_rh))->pp_elements, logpathbuff, sizeof(logpathbuff), BCS_OEM);
|
|
LogPreamble(VFNLOG_GETDISKINFO, logpathbuff, pir->ir_error, szCR);
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
|
|
void LogVfnGetDiskParms( PIOREQ pir
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
++cntVfnGetDiskParms;
|
|
#endif //DEBUG
|
|
if (fLog)
|
|
{
|
|
ENTERCRIT_LOG;
|
|
PpeToSvr(((PRESOURCE)(pir->ir_rh))->pp_elements, logpathbuff, sizeof(logpathbuff), BCS_OEM);
|
|
LogPreamble(VFNLOG_GETDISKPARAMS, logpathbuff, pir->ir_error, szCR);
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
void LogVfnOpen( PIOREQ pir
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
++cntVfnOpen;
|
|
#endif //DEBUG
|
|
if (fLog)
|
|
{
|
|
ENTERCRIT_LOG;
|
|
memset(logpathbuff, 0, sizeof(logpathbuff));
|
|
UniToBCSPath(logpathbuff, &pir->ir_ppath->pp_elements[0], MAX_PATH, BCS_OEM);
|
|
logpathbuff[MAX_PATH]=0;
|
|
LogPreamble(VFNLOG_OPEN, logpathbuff, pir->ir_error, NULL);
|
|
ShadowLog(rgsLogCmd[VFNLOG_OPEN].lpFmt,(ULONG)(pir->ir_flags), (ULONG)(pir->ir_options)
|
|
, (ULONG)(pir->ir_attr), (ULONG)(pir->ir_size));
|
|
PrintNetTime(IFSMgr_DosToNetTime(pir->ir_dostime));
|
|
ShadowLog(szCR);
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
void LogVfnRename( PIOREQ pir
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
++cntVfnRename;
|
|
#endif //DEBUG
|
|
if (fLog)
|
|
{
|
|
ENTERCRIT_LOG;
|
|
memset(logpathbuff, 0, sizeof(logpathbuff));
|
|
UniToBCSPath(logpathbuff, &pir->ir_ppath->pp_elements[0], MAX_PATH, BCS_OEM);
|
|
logpathbuff[MAX_PATH]=0;
|
|
LogPreamble(VFNLOG_RENAME, logpathbuff, pir->ir_error, NULL);
|
|
UniToBCSPath(logpathbuff, &pir->ir_ppath2->pp_elements[0], MAX_PATH, BCS_OEM);
|
|
logpathbuff[MAX_PATH]=0;
|
|
ShadowLog(rgsLogCmd[VFNLOG_RENAME].lpFmt, logpathbuff);
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
void LogVfnSearch( PIOREQ pir
|
|
)
|
|
{
|
|
srch_entry *pse = (srch_entry *)(pir->ir_data);
|
|
char szName[sizeof(pse->se_name)+1];
|
|
#ifdef DEBUG
|
|
if (pir->ir_flags == SEARCH_FIRST)
|
|
++cntVfnSearchFirst;
|
|
else
|
|
++cntVfnSearchNext;
|
|
|
|
#endif //DEBUG
|
|
|
|
if (fLog)
|
|
{
|
|
ENTERCRIT_LOG;
|
|
// BUGBUG expand this
|
|
memset(szName, 0, sizeof(szName));
|
|
memcpy(logpathbuff, pse->se_name, sizeof(pse->se_name));
|
|
if (pir->ir_flags == SEARCH_FIRST)
|
|
{
|
|
memset(logpathbuff, 0, sizeof(logpathbuff));
|
|
UniToBCSPath(logpathbuff, &pir->ir_ppath->pp_elements[0], MAX_PATH, BCS_OEM);
|
|
LogPreamble(VFNLOG_SRCHFRST, logpathbuff, pir->ir_error, NULL);
|
|
ShadowLog(rgsLogCmd[VFNLOG_SRCHFRST].lpFmt, pir->ir_attr, szName);
|
|
}
|
|
else
|
|
{
|
|
LogPreamble(VFNLOG_SRCHNEXT, szDummy, pir->ir_error, NULL);
|
|
ShadowLog(rgsLogCmd[VFNLOG_SRCHNEXT].lpFmt, szName);
|
|
}
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
void LogVfnQuery( PIOREQ pir,
|
|
USHORT options
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
++cntVfnQuery;
|
|
#endif //DEBUG
|
|
if (fLog)
|
|
{
|
|
ENTERCRIT_LOG;
|
|
memset(logpathbuff, 0, sizeof(logpathbuff));
|
|
PpeToSvr(((PRESOURCE)(pir->ir_rh))->pp_elements, logpathbuff, sizeof(logpathbuff), BCS_OEM);
|
|
if (options==0)
|
|
{
|
|
LogPreamble(VFNLOG_QUERY0, logpathbuff, pir->ir_error, szCR);
|
|
}
|
|
if (options==1)
|
|
{
|
|
LogPreamble(VFNLOG_QUERY0, logpathbuff, pir->ir_error, NULL);
|
|
ShadowLog(rgsLogCmd[VFNLOG_QUERY1].lpFmt, (ULONG)(pir->ir_options));
|
|
}
|
|
else if (options==2)
|
|
{
|
|
LogPreamble(VFNLOG_QUERY0, logpathbuff, pir->ir_error, NULL);
|
|
ShadowLog(rgsLogCmd[VFNLOG_QUERY2].lpFmt, (ULONG)(pir->ir_options), (ULONG)(pir->ir_length >> 16), (ULONG)(pir->ir_length & 0xffff));
|
|
}
|
|
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
void LogVfnConnect( PIOREQ pir
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
++cntVfnConnect;
|
|
#endif //DEBUG
|
|
if (fLog)
|
|
{
|
|
ENTERCRIT_LOG;
|
|
memset(logpathbuff, 0, sizeof(logpathbuff));
|
|
UniToBCSPath(logpathbuff, &pir->ir_ppath->pp_elements[0], MAX_PATH, BCS_OEM);
|
|
LogPreamble(VFNLOG_CONNECT, logpathbuff, pir->ir_error, NULL);
|
|
ShadowLog(rgsLogCmd[VFNLOG_CONNECT].lpFmt, pir->ir_flags);
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
void LogVfnDisconnect( PIOREQ pir
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
++cntVfnDisconnect;
|
|
#endif //DEBUG
|
|
if (fLog)
|
|
{
|
|
ENTERCRIT_LOG;
|
|
PpeToSvr(((PRESOURCE)(pir->ir_rh))->pp_elements, logpathbuff, sizeof(logpathbuff), BCS_OEM);
|
|
LogPreamble(VFNLOG_DISCONNECT, logpathbuff, pir->ir_error, szCR);
|
|
WriteLog();
|
|
// TerminateShadowLog();
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
void LogVfnUncPipereq(
|
|
PIOREQ pir
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
++cntVfnUncPipereq;
|
|
#endif //DEBUG
|
|
}
|
|
|
|
void LogVfnIoctl16Drive (
|
|
PIOREQ pir
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
++cntVfnIoctl16Drive ;
|
|
#endif //DEBUG
|
|
}
|
|
|
|
void LogVfnDasdIO(
|
|
PIOREQ pir
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
++cntVfnDasdIO;
|
|
#endif //DEBUG
|
|
}
|
|
|
|
|
|
void LogVfnFindOpen( PIOREQ pir
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
++cntVfnFindOpen;
|
|
#endif //DEBUG
|
|
if (fLog)
|
|
{
|
|
ENTERCRIT_LOG;
|
|
memset(logpathbuff, 0, sizeof(logpathbuff));
|
|
UniToBCSPath(logpathbuff, &pir->ir_ppath->pp_elements[0], MAX_PATH, BCS_OEM);
|
|
logpathbuff[MAX_PATH]=0;
|
|
LogPreamble(VFNLOG_FINDOPEN, logpathbuff, pir->ir_error, NULL);
|
|
if (!pir->ir_error)
|
|
{
|
|
memset(logpathbuff, 0, sizeof(logpathbuff));
|
|
UniToBCS(logpathbuff, ((LPFIND32)(pir->ir_data))->cFileName, sizeof(((LPFIND32)(pir->ir_data))->cFileName)
|
|
, sizeof(logpathbuff)-1, BCS_OEM);
|
|
ShadowLog(rgsLogCmd[VFNLOG_FINDOPEN].lpFmt, pir->ir_attr, logpathbuff);
|
|
}
|
|
else
|
|
{
|
|
ShadowLog(szCR);
|
|
}
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
void LogHfnFindNext( PIOREQ pir
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
++cntHfnFindNext;
|
|
#endif //DEBUG
|
|
if (fLog)
|
|
{
|
|
ENTERCRIT_LOG;
|
|
LogPreamble(HFNLOG_FINDNEXT, szDummy, pir->ir_error, NULL);
|
|
|
|
if (!pir->ir_error)
|
|
{
|
|
memset(logpathbuff, 0, sizeof(logpathbuff));
|
|
UniToBCS(logpathbuff, ((LPFIND32)(pir->ir_data))->cFileName, sizeof(((LPFIND32)(pir->ir_data))->cFileName)
|
|
, sizeof(logpathbuff)-1, BCS_OEM);
|
|
ShadowLog(rgsLogCmd[HFNLOG_FINDNEXT].lpFmt, logpathbuff);
|
|
}
|
|
else
|
|
{
|
|
ShadowLog(szCR);
|
|
}
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
void LogHfnFindClose( PIOREQ pir
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
++cntHfnFindClose;
|
|
#endif //DEBUG
|
|
if (fLog)
|
|
{
|
|
ENTERCRIT_LOG;
|
|
LogPreamble(HFNLOG_FINDCLOSE, szDummy, pir->ir_error, szCR);
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
void LogHfnRead
|
|
(
|
|
PIOREQ pir
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
++cntHfnRead;
|
|
#endif //DEBUG
|
|
#ifdef MAYBE
|
|
Incr64Bit(cbReadHigh, cbReadLow, (ULONG)(pir->ir_length));
|
|
#endif //MAYBE
|
|
if (fLog)
|
|
{
|
|
PFILEINFO pFileInfo = (PFILEINFO)(pir->ir_fh);
|
|
ENTERCRIT_LOG;
|
|
memset(logpathbuff, 0, sizeof(logpathbuff));
|
|
UniToBCSPath(logpathbuff, &(pFileInfo->pFdb->sppathRemoteFile.pp_elements[0]), MAX_PATH, BCS_OEM);
|
|
LogPreamble(HFNLOG_READ, logpathbuff, pir->ir_error, NULL);
|
|
ShadowLog(rgsLogCmd[HFNLOG_READ].lpFmt,
|
|
(ULONG)(pir->ir_pos)-(ULONG)(pir->ir_length),
|
|
(ULONG)(pir->ir_length));
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
void LogHfnWrite
|
|
(
|
|
PIOREQ pir
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
++cntHfnWrite;
|
|
#endif //DEBUG
|
|
#ifdef MAYBE
|
|
Incr64Bit(cbWriteHigh, cbWriteLow, (ULONG)(pir->ir_length));
|
|
#endif //MAYBE
|
|
if (fLog)
|
|
{
|
|
PFILEINFO pFileInfo = (PFILEINFO)(pir->ir_fh);
|
|
ENTERCRIT_LOG;
|
|
memset(logpathbuff, 0, sizeof(logpathbuff));
|
|
UniToBCSPath(logpathbuff, &(pFileInfo->pFdb->sppathRemoteFile.pp_elements[0]), MAX_PATH, BCS_OEM);
|
|
LogPreamble(HFNLOG_WRITE, logpathbuff, pir->ir_error, NULL);
|
|
ShadowLog(rgsLogCmd[HFNLOG_WRITE].lpFmt,
|
|
(ULONG)(pir->ir_pos)-(ULONG)(pir->ir_length),
|
|
(ULONG)(pir->ir_length));
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
void LogHfnClose
|
|
(
|
|
PIOREQ pir,
|
|
int closetype
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
++cntHfnClose;
|
|
#endif //DEBUG
|
|
if (fLog)
|
|
{
|
|
PFILEINFO pFileInfo = (PFILEINFO)(pir->ir_fh);
|
|
ENTERCRIT_LOG;
|
|
memset(logpathbuff, 0, sizeof(logpathbuff));
|
|
UniToBCSPath(logpathbuff, &(pFileInfo->pFdb->sppathRemoteFile.pp_elements[0]), MAX_PATH, BCS_OEM);
|
|
LogPreamble(HFNLOG_CLOSE, logpathbuff, pir->ir_error, NULL);
|
|
ShadowLog(rgsLogCmd[HFNLOG_CLOSE].lpFmt, closetype);
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
void LogHfnSeek
|
|
(
|
|
PIOREQ pir
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
++cntHfnSeek;
|
|
#endif //DEBUG
|
|
if (fLog)
|
|
{
|
|
PFILEINFO pFileInfo = (PFILEINFO)(pir->ir_fh);
|
|
ENTERCRIT_LOG;
|
|
memset(logpathbuff, 0, sizeof(logpathbuff));
|
|
UniToBCSPath(logpathbuff, &(pFileInfo->pFdb->sppathRemoteFile.pp_elements[0]), MAX_PATH, BCS_OEM);
|
|
LogPreamble(HFNLOG_SEEK, logpathbuff, pir->ir_error, NULL);
|
|
ShadowLog(rgsLogCmd[HFNLOG_SEEK].lpFmt, (ULONG)(pir->ir_pos), pir->ir_flags);
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
void LogHfnCommit
|
|
(
|
|
PIOREQ pir
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
++cntHfnCommit;
|
|
#endif //DEBUG
|
|
if (fLog)
|
|
{
|
|
PFILEINFO pFileInfo = (PFILEINFO)(pir->ir_fh);
|
|
ENTERCRIT_LOG;
|
|
memset(logpathbuff, 0, sizeof(logpathbuff));
|
|
UniToBCSPath(logpathbuff, &(pFileInfo->pFdb->sppathRemoteFile.pp_elements[0]), MAX_PATH, BCS_OEM);
|
|
LogPreamble(HFNLOG_COMMIT, logpathbuff, pir->ir_error, szCR);
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
|
|
void LogHfnFileLocks
|
|
(
|
|
PIOREQ pir
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
if (pir->ir_flags == LOCK_REGION)
|
|
++cntHfnSetFileLocks;
|
|
else
|
|
++cntHfnRelFileLocks;
|
|
#endif //DEBUG
|
|
if (fLog)
|
|
{
|
|
PFILEINFO pFileInfo = (PFILEINFO)(pir->ir_fh);
|
|
ENTERCRIT_LOG;
|
|
memset(logpathbuff, 0, sizeof(logpathbuff));
|
|
UniToBCSPath(logpathbuff, &(pFileInfo->pFdb->sppathRemoteFile.pp_elements[0]), MAX_PATH, BCS_OEM);
|
|
LogPreamble((pir->ir_flags==LOCK_REGION)?HFNLOG_FLOCK:HFNLOG_FUNLOCK, logpathbuff, pir->ir_error, NULL);
|
|
if (!pir->ir_error)
|
|
{
|
|
ShadowLog(rgsLogCmd[HFNLOG_FLOCK].lpFmt
|
|
, pir->ir_pos
|
|
, pir->ir_locklen);
|
|
}
|
|
else
|
|
{
|
|
ShadowLog(szCR);
|
|
}
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
void LogHfnFileTimes
|
|
(
|
|
PIOREQ pir
|
|
)
|
|
{
|
|
#ifdef DEBUG
|
|
if ((pir->ir_flags == GET_MODIFY_DATETIME)||(pir->ir_flags == GET_LAST_ACCESS_DATETIME))
|
|
++cntHfnGetFileTimes;
|
|
else
|
|
++cntHfnSetFileTimes;
|
|
#endif //DEBUG
|
|
if (fLog)
|
|
{
|
|
PFILEINFO pFileInfo = (PFILEINFO)(pir->ir_fh);
|
|
int indxFn = pir->ir_flags;
|
|
|
|
if (indxFn==GET_MODIFY_DATETIME)
|
|
{
|
|
indxFn = HFNLOG_GET_TIME;
|
|
}
|
|
else if (indxFn==SET_MODIFY_DATETIME)
|
|
{
|
|
indxFn = HFNLOG_SET_TIME;
|
|
}
|
|
else if (indxFn==GET_LAST_ACCESS_DATETIME)
|
|
{
|
|
indxFn = HFNLOG_GET_LATIME;
|
|
}
|
|
else
|
|
{
|
|
indxFn = HFNLOG_SET_LATIME;
|
|
}
|
|
|
|
ENTERCRIT_LOG;
|
|
memset(logpathbuff, 0, sizeof(logpathbuff));
|
|
UniToBCSPath(logpathbuff, &(pFileInfo->pFdb->sppathRemoteFile.pp_elements[0]), MAX_PATH, BCS_OEM);
|
|
LogPreamble(indxFn, logpathbuff, pir->ir_error, NULL);
|
|
if (!pir->ir_error)
|
|
{
|
|
PrintNetTime(IFSMgr_DosToNetTime(pir->ir_dostime));
|
|
}
|
|
ShadowLog(szCR);
|
|
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
void LogHfnPipeRequest
|
|
(
|
|
PIOREQ pir
|
|
)
|
|
{
|
|
}
|
|
|
|
void LogHfnHandleInfo(
|
|
PIOREQ pir
|
|
)
|
|
{
|
|
if (fLog)
|
|
{
|
|
PFILEINFO pFileInfo = (PFILEINFO)(pir->ir_fh);
|
|
|
|
ENTERCRIT_LOG;
|
|
memset(logpathbuff, 0, sizeof(logpathbuff));
|
|
UniToBCSPath(logpathbuff, &(pFileInfo->pFdb->sppathRemoteFile.pp_elements[0]), MAX_PATH, BCS_OEM);
|
|
LogPreamble(HFNLOG_ENUMHANDLE, logpathbuff, pir->ir_error, NULL);
|
|
ShadowLog(szCR);
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
void LogHfnEnumHandle(
|
|
PIOREQ pir
|
|
)
|
|
{
|
|
if (fLog)
|
|
{
|
|
PFILEINFO pFileInfo = (PFILEINFO)(pir->ir_fh);
|
|
ENTERCRIT_LOG;
|
|
memset(logpathbuff, 0, sizeof(logpathbuff));
|
|
UniToBCSPath(logpathbuff, &(pFileInfo->pFdb->sppathRemoteFile.pp_elements[0]), MAX_PATH, BCS_OEM);
|
|
LogPreamble(HFNLOG_ENUMHANDLE, logpathbuff, pir->ir_error, NULL);
|
|
ShadowLog(rgsLogCmd[HFNLOG_ENUMHANDLE].lpFmt, pir->ir_flags);
|
|
LEAVECRIT_LOG;
|
|
}
|
|
}
|
|
|
|
void LogTiming(
|
|
int verbosity,
|
|
int stage
|
|
)
|
|
{
|
|
if (fLog >= verbosity)
|
|
{
|
|
ShadowLog("%s: ", (stage==STAGE_BEGIN)
|
|
?szBegin:((stage==STAGE_END)?szEnd:szContinue));
|
|
PrintNetShortTime(IFSMgr_Get_NetTime());
|
|
ShadowLog(szCR);
|
|
}
|
|
}
|
|
|
|
|
|
void LogPreamble( int indxFn,
|
|
LPSTR lpSubject,
|
|
int errCode,
|
|
LPSTR lpPreTerm
|
|
)
|
|
{
|
|
TIME tm;
|
|
|
|
ExplodeTime(IFSMgr_Get_NetTime(), &tm);
|
|
ShadowLog(szPreFmt
|
|
, rgsLogCmd[indxFn].lpCmd
|
|
, tm.hours, tm.minutes, tm.seconds
|
|
, errCode
|
|
, lpSubject);
|
|
if (lpPreTerm)
|
|
{
|
|
ShadowLog(lpPreTerm);
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef MAYBE
|
|
int Incr64Bit(
|
|
ULONG uHigh,
|
|
ULONG uLow,
|
|
ULONG uIncr
|
|
)
|
|
{
|
|
ULONG uTemp = uLow;
|
|
|
|
uLow += uIncr;
|
|
if (uLow < uTemp)
|
|
++uHigh;
|
|
return 1;
|
|
}
|
|
#endif //MAYBE
|
|
|
|
#ifdef DEBUG
|
|
int WriteStats( BOOL fForce)
|
|
{
|
|
ULONG cntTotal;
|
|
SHADOWSTORE sSS;
|
|
|
|
cntTotal = cntVfnDelete+ cntVfnCreateDir+ cntVfnDeleteDir+ cntVfnCheckDir+ cntVfnGetAttrib+
|
|
cntVfnSetAttrib+ cntVfnFlush+ cntVfnGetDiskInfo+ cntVfnOpen+
|
|
cntVfnRename+ cntVfnSearchFirst+ cntVfnSearchNext+
|
|
cntVfnQuery+ cntVfnDisconnect+ cntVfnUncPipereq+ cntVfnIoctl16Drive+
|
|
cntVfnGetDiskParms+ cntVfnFindOpen+ cntVfnDasdIO+
|
|
cntHfnFindNext+ cntHfnFindClose+
|
|
cntHfnRead+ cntHfnWrite+ cntHfnSeek+ cntHfnClose+ cntHfnCommit+
|
|
cntHfnSetFileLocks+ cntHfnRelFileLocks+ cntHfnGetFileTimes+ cntHfnSetFileTimes+
|
|
cntHfnPipeRequest+ cntHfnHandleInfo+ cntHfnEnumHandle;
|
|
|
|
ShadowLog("\r!***** Stats Begin *******\r");
|
|
|
|
PrintNetTime(IFSMgr_Get_NetTime());
|
|
ShadowLog("\r");
|
|
if (!fForce && (cntTotal == cntLastTotal))
|
|
{
|
|
KdPrint(("No new network activity \r"));
|
|
goto bailout;
|
|
}
|
|
cntLastTotal = cntTotal;
|
|
if (!cntTotal)
|
|
{
|
|
cntTotal = 1;
|
|
}
|
|
ShadowLog("Total remote operations=%d \r", cntTotal);
|
|
|
|
GetShadowSpaceInfo(&sSS);
|
|
ShadowLog("Space used=%d, Files=%d, Dirs=%d\r",
|
|
sSS.sCur.ulSize, sSS.sCur.ucntFiles, sSS.sCur.ucntDirs);
|
|
|
|
ShadowLog("\rFile Operations:\r");
|
|
ShadowLog("Open=%d%%, Close=%d%% \r",
|
|
(cntVfnOpen * 100/cntTotal),
|
|
(cntHfnClose * 100/cntTotal));
|
|
|
|
ShadowLog("Read=%d%%, Write=%d%%, Seek=%d%%\r",
|
|
(cntHfnRead * 100/cntTotal),
|
|
(cntHfnWrite * 100/cntTotal),
|
|
(cntHfnSeek * 100/cntTotal));
|
|
if (!cntHfnRead)
|
|
{
|
|
cntHfnRead = 1;
|
|
}
|
|
ShadowLog("ReadHits=%d%% of total reads\r", (cntReadHits*100)/cntHfnRead);
|
|
|
|
ShadowLog("GetFileTime=%d%% SetFileTime=%d%%\r",
|
|
(cntHfnGetFileTimes * 100/cntTotal),
|
|
(cntHfnSetFileTimes * 100/cntTotal));
|
|
|
|
|
|
ShadowLog("SetLock=%d%%, ReleaseLock=%d%% \r",
|
|
(cntHfnSetFileLocks * 100/cntTotal),
|
|
(cntHfnRelFileLocks * 100/cntTotal));
|
|
|
|
ShadowLog("Directory Operations: ");
|
|
ShadowLog("CreateDir=%d%%, DeleteDir=%d%%, CheckDir=%d%% \r",
|
|
(cntVfnCreateDir*100/cntTotal),
|
|
(cntVfnDeleteDir*100/cntTotal),
|
|
(cntVfnCheckDir*100/cntTotal));
|
|
|
|
ShadowLog("Find/Search Operations:\r");
|
|
ShadowLog("FindOpen=%d%%, FindNext=%d%%, FindClose=%d%% \r",
|
|
(cntVfnFindOpen * 100/cntTotal),
|
|
(cntHfnFindNext * 100/cntTotal),
|
|
(cntHfnFindClose * 100/cntTotal));
|
|
ShadowLog("SearchFirst=%d%%, SearchNext=%d%%\r",
|
|
(cntVfnSearchFirst * 100/cntTotal),
|
|
(cntVfnSearchNext * 100/cntTotal));
|
|
|
|
ShadowLog("Attributes: ");
|
|
ShadowLog("SetAttributes=%d%%, GetAttributes=%d%%\r",
|
|
(cntVfnSetAttrib * 100/cntTotal),
|
|
(cntVfnGetAttrib * 100/cntTotal));
|
|
|
|
ShadowLog("Name Mutations: ");
|
|
ShadowLog("Rename=%d%%, Delete=%d%% \r",
|
|
(cntVfnRename * 100/cntTotal),
|
|
(cntVfnDelete * 100/cntTotal));
|
|
|
|
bailout:
|
|
ShadowLog("\r***** Stats End ******* \r");
|
|
return 1;
|
|
}
|
|
|
|
void ShadowRestrictedEventCallback
|
|
(
|
|
)
|
|
{
|
|
FlushLog();
|
|
ENTERCRIT_LOG;
|
|
WriteStats(0); // Don't force him to write
|
|
LEAVECRIT_LOG;
|
|
FlushLog();
|
|
}
|
|
#endif //DEBUG
|
|
|