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.
4081 lines
121 KiB
4081 lines
121 KiB
#define UNICODE
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <windows.h>
|
|
#include <winioctl.h>
|
|
#include <shdcom.h>
|
|
#include <shellapi.h>
|
|
#include <smbdebug.h>
|
|
#include <time.h>
|
|
|
|
#include "struct.h"
|
|
#include "messages.h"
|
|
#include "cscapi.h"
|
|
|
|
CHAR *ProgName = "cscutil";
|
|
|
|
#define CSC_MERGE_KEEP_LOCAL 1
|
|
#define CSC_MERGE_KEEP_NETWORK 2
|
|
#define CSC_MERGE_KEEP_BOTH 3
|
|
|
|
//
|
|
// Arguments (ie '/arg:')
|
|
//
|
|
MAKEARG(Pin);
|
|
MAKEARG(UnPin);
|
|
MAKEARG(Delete);
|
|
MAKEARG(DeleteShadow);
|
|
MAKEARG(GetShadow);
|
|
MAKEARG(GetShadowInfo);
|
|
MAKEARG(ShareId);
|
|
MAKEARG(Fill);
|
|
MAKEARG(Db);
|
|
MAKEARG(SetShareStatus);
|
|
MAKEARG(Purge);
|
|
MAKEARG(IsServerOffline);
|
|
MAKEARG(EnumForStats);
|
|
MAKEARG(SetSpace);
|
|
MAKEARG(Merge);
|
|
MAKEARG(QueryFile);
|
|
MAKEARG(QueryFileEx);
|
|
MAKEARG(QueryShare);
|
|
MAKEARG(Check);
|
|
MAKEARG(ExclusionList);
|
|
MAKEARG(BWConservationList);
|
|
MAKEARG(Disconnect);
|
|
MAKEARG(Reconnect);
|
|
MAKEARG(Enum);
|
|
MAKEARG(Move);
|
|
MAKEARG(Bitcopy);
|
|
MAKEARG(RandW);
|
|
MAKEARG(Offset);
|
|
MAKEARG(MoveShare);
|
|
|
|
//
|
|
// Switches (ie '/arg')
|
|
//
|
|
SWITCH(Info);
|
|
SWITCH(Fcblist);
|
|
SWITCH(DBStatus);
|
|
SWITCH(PQEnum);
|
|
SWITCH(User);
|
|
SWITCH(System);
|
|
SWITCH(Inherit);
|
|
SWITCH(Recurse);
|
|
SWITCH(Abort);
|
|
SWITCH(Skip);
|
|
SWITCH(Ask);
|
|
SWITCH(Eof);
|
|
SWITCH(Retry);
|
|
SWITCH(Touch);
|
|
SWITCH(Enable);
|
|
SWITCH(Disable);
|
|
SWITCH(Ioctl);
|
|
SWITCH(Flags);
|
|
SWITCH(GetSpace);
|
|
SWITCH(Encrypt);
|
|
SWITCH(Decrypt);
|
|
SWITCH(Db);
|
|
SWITCH(Set);
|
|
SWITCH(Clear);
|
|
SWITCH(Purge);
|
|
SWITCH(Detector);
|
|
SWITCH(Switches);
|
|
|
|
SWITCH(Debug);
|
|
SWITCH(Help);
|
|
SWITCH(HelpHelp);
|
|
SWITCH(Enum);
|
|
SWITCH(Resid);
|
|
SWITCH(Full);
|
|
|
|
//
|
|
// The macro can not make these
|
|
//
|
|
|
|
WCHAR SwQ[] = L"/?";
|
|
BOOLEAN fSwQ;
|
|
WCHAR SwQQ[] = L"/??";
|
|
BOOLEAN fSwQQ;
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
LPWSTR pwszDisconnectArg = NULL;
|
|
LPWSTR pwszExclusionListArg = NULL;
|
|
LPWSTR pwszBWConservationListArg = NULL;
|
|
LPWSTR pwszSetShareStatusArg = NULL;
|
|
LPWSTR pwszIsServerOfflineArg = NULL;
|
|
LPWSTR pwszPurgeArg = NULL;
|
|
LPWSTR pwszPinUnPinArg = NULL;
|
|
LPWSTR pwszDeleteArg = NULL;
|
|
LPWSTR pwszDeleteShadowArg = NULL;
|
|
LPWSTR pwszGetShadowArg = NULL;
|
|
LPWSTR pwszGetShadowInfoArg = NULL;
|
|
LPWSTR pwszShareIdArg = NULL;
|
|
LPWSTR pwszReconnectArg = NULL;
|
|
LPWSTR pwszQueryFileArg = NULL;
|
|
LPWSTR pwszQueryFileExArg = NULL;
|
|
LPWSTR pwszDbArg = NULL;
|
|
LPWSTR pwszSetSpaceArg = NULL;
|
|
LPWSTR pwszQueryShareArg = NULL;
|
|
LPWSTR pwszMoveArg = NULL;
|
|
LPWSTR pwszMergeArg = NULL;
|
|
LPWSTR pwszFillArg = NULL;
|
|
LPWSTR pwszEnumArg = NULL;
|
|
LPWSTR pwszRandWArg = NULL;
|
|
LPWSTR pwszBitcopyArg = NULL;
|
|
LPWSTR pwszOffsetArg = NULL;
|
|
LPWSTR pwszEnumForStatsArg = NULL;
|
|
LPWSTR pwszCheckArg = NULL;
|
|
|
|
char statusName[4][32] = {
|
|
"Local Path",
|
|
"Offline Share",
|
|
"Online Share",
|
|
"No CSC"
|
|
};
|
|
|
|
DWORD
|
|
Usage(
|
|
BOOLEAN fHelpHelp);
|
|
|
|
BOOLEAN
|
|
CmdProcessArg(
|
|
LPWSTR Arg);
|
|
|
|
DWORD
|
|
CmdInfo(
|
|
ULONG Cmd);
|
|
|
|
DWORD
|
|
CmdDBStatus(
|
|
VOID);
|
|
|
|
DWORD
|
|
CmdPurge(
|
|
PWSTR PurgeArg);
|
|
|
|
DWORD
|
|
CmdDetector(
|
|
VOID);
|
|
|
|
DWORD
|
|
CmdPQEnum(
|
|
VOID);
|
|
|
|
DWORD
|
|
CmdGetSpace(
|
|
VOID);
|
|
|
|
DWORD
|
|
CmdSwitches(
|
|
VOID);
|
|
|
|
DWORD
|
|
CmdDisconnect(
|
|
PWSTR DisconnectArg);
|
|
|
|
DWORD
|
|
CmdExclusionList(
|
|
PWSTR ExclusionListArg);
|
|
|
|
DWORD
|
|
CmdBWConservationList(
|
|
PWSTR BWConservationListArg);
|
|
|
|
DWORD
|
|
CmdSetShareStatus(
|
|
PWSTR SetShareStatusArg);
|
|
|
|
DWORD
|
|
CmdIsServerOffline(
|
|
PWSTR IsServerOfflineArg);
|
|
|
|
DWORD
|
|
CmdReconnect(
|
|
PWSTR ReconnectArg);
|
|
|
|
DWORD
|
|
CmdQueryFile(
|
|
PWSTR QueryFileArg);
|
|
|
|
DWORD
|
|
CmdQueryFileEx(
|
|
PWSTR QueryFileExArg);
|
|
|
|
DWORD
|
|
CmdDb(
|
|
PWSTR DbArg);
|
|
|
|
DWORD
|
|
CmdSetSpace(
|
|
PWSTR SetSpaceArg);
|
|
|
|
DWORD
|
|
CmdQueryShare(
|
|
PWSTR QueryShareArg);
|
|
|
|
DWORD
|
|
CmdMove(
|
|
PWSTR MoveArg);
|
|
|
|
DWORD
|
|
CmdMerge(
|
|
PWSTR MergeArg);
|
|
|
|
DWORD
|
|
CmdEncryptDecrypt(
|
|
BOOL fEncrypt);
|
|
|
|
DWORD
|
|
CmdFill(
|
|
PWSTR FillArg);
|
|
|
|
DWORD
|
|
CmdCheck(
|
|
PWSTR CheckArg);
|
|
|
|
DWORD
|
|
CmdEnum(
|
|
PWSTR CmdEnumArg);
|
|
|
|
DWORD
|
|
CmdRandW(
|
|
PWSTR CmdRandWArg);
|
|
|
|
DWORD
|
|
CmdBitcopy(
|
|
PWSTR CmdBitcopyArg);
|
|
|
|
DWORD
|
|
CmdEnumForStats(
|
|
PWSTR EnumForStatsArg);
|
|
|
|
DWORD
|
|
CmdDelete(
|
|
PWSTR DeleteArg);
|
|
|
|
DWORD
|
|
CmdGetShadow(
|
|
PWSTR GetShadowArg);
|
|
|
|
DWORD
|
|
CmdGetShadowInfo(
|
|
PWSTR GetShadowInfoArg);
|
|
|
|
DWORD
|
|
CmdShareId(
|
|
PWSTR ShareIdArg);
|
|
|
|
DWORD
|
|
CmdDeleteShadow(
|
|
PWSTR DeleteArg);
|
|
|
|
DWORD
|
|
CmdPinUnPin(
|
|
BOOL fPin,
|
|
PWSTR PinArg);
|
|
|
|
DWORD
|
|
CmdMoveShare(
|
|
PWSTR source,
|
|
PWSTR dest);
|
|
|
|
SHARESTATUS
|
|
GetCSCStatus (
|
|
const WCHAR * pwszPath);
|
|
|
|
BOOL
|
|
GetShareStatus (
|
|
const WCHAR * pwszShare,
|
|
DWORD * pdwStatus,
|
|
DWORD * pdwPinCount,
|
|
DWORD * pdwHints);
|
|
|
|
void
|
|
MoveDirInCSC (
|
|
const WCHAR * pwszSource,
|
|
const WCHAR * pwszDest,
|
|
const WCHAR * pwszSkipSubdir,
|
|
SHARESTATUS StatusFrom, SHARESTATUS StatusTo,
|
|
BOOL bAllowRdrTimeoutForDel,
|
|
BOOL bAllowRdrTimeoutForRen);
|
|
|
|
DWORD
|
|
DoCSCRename (
|
|
const WCHAR * pwszSource,
|
|
const WCHAR * pwszDest,
|
|
BOOL bOverwrite,
|
|
BOOL bAllowRdrTimeout);
|
|
|
|
DWORD
|
|
DeleteCSCFileTree (
|
|
const WCHAR * pwszSource,
|
|
const WCHAR * pwszSkipSubdir,
|
|
BOOL bAllowRdrTimeout);
|
|
|
|
DWORD
|
|
DeleteCSCFile (
|
|
const WCHAR * pwszPath,
|
|
BOOL bAllowRdrTimeout);
|
|
|
|
DWORD
|
|
DeleteCSCShareIfEmpty (
|
|
LPCTSTR pwszFileName,
|
|
SHARESTATUS shStatus);
|
|
|
|
DWORD
|
|
MergePinInfo (
|
|
LPCTSTR pwszSource,
|
|
LPCTSTR pwszDest,
|
|
SHARESTATUS StatusFrom,
|
|
SHARESTATUS StatusTo);
|
|
|
|
DWORD
|
|
PinIfNecessary (
|
|
const WCHAR * pwszPath,
|
|
SHARESTATUS shStatus);
|
|
|
|
DWORD
|
|
CscMergeFillAsk(
|
|
LPCWSTR lpszFullPath);
|
|
|
|
DWORD
|
|
MyCscMergeProcW(
|
|
LPCWSTR lpszFullPath,
|
|
DWORD dwStatus,
|
|
DWORD dwHintFlags,
|
|
DWORD dwPinCount,
|
|
WIN32_FIND_DATAW *lpFind32,
|
|
DWORD dwReason,
|
|
DWORD dwParam1,
|
|
DWORD dwParam2,
|
|
DWORD_PTR dwContext);
|
|
|
|
DWORD
|
|
MyCscFillProcW(
|
|
LPCWSTR lpszFullPath,
|
|
DWORD dwStatus,
|
|
DWORD dwHintFlags,
|
|
DWORD dwPinCount,
|
|
WIN32_FIND_DATAW *lpFind32,
|
|
DWORD dwReason,
|
|
DWORD dwParam1,
|
|
DWORD dwParam2,
|
|
DWORD_PTR dwContext);
|
|
|
|
DWORD
|
|
MyEncryptDecryptProcW(
|
|
LPCWSTR lpszFullPath,
|
|
DWORD dwStatus,
|
|
DWORD dwHintFlags,
|
|
DWORD dwPinCount,
|
|
WIN32_FIND_DATAW *lpFind32,
|
|
DWORD dwReason,
|
|
DWORD dwParam1,
|
|
DWORD dwParam2,
|
|
DWORD_PTR dwContext);
|
|
|
|
DWORD
|
|
MyEnumForStatsProcW(
|
|
LPCWSTR lpszFullPath,
|
|
DWORD dwStatus,
|
|
DWORD dwHintFlags,
|
|
DWORD dwPinCount,
|
|
WIN32_FIND_DATAW *lpFind32,
|
|
DWORD dwReason,
|
|
DWORD dwParam1,
|
|
DWORD dwParam2,
|
|
DWORD_PTR dwContext);
|
|
|
|
DWORD
|
|
FileStatusToEnglish(
|
|
DWORD Status,
|
|
LPWSTR OutputBuffer);
|
|
|
|
DWORD
|
|
HintsToEnglish(
|
|
DWORD Hint,
|
|
LPWSTR OutputBuffer);
|
|
|
|
DWORD
|
|
ShareStatusToEnglish(
|
|
DWORD Status,
|
|
LPWSTR OutputBuffer);
|
|
|
|
BOOLEAN
|
|
LooksToBeAShare(LPWSTR Name);
|
|
|
|
LONG
|
|
CountOffsetArgs(
|
|
PWSTR OffsetArg,
|
|
ULONG OffsetArray[]);
|
|
|
|
DWORD
|
|
DumpBitMap(
|
|
LPWSTR lpszTempName);
|
|
|
|
VOID
|
|
ErrorMessage(
|
|
IN HRESULT hr,
|
|
...);
|
|
|
|
WCHAR NameBuf[MAX_PATH + 25];
|
|
|
|
WCHAR vtzDefaultExclusionList[] = L" *.SLM *.MDB *.LDB *.MDW *.MDE *.PST *.DB?"; // from ui.c
|
|
|
|
//
|
|
// These functions were added for Windows XP, and so we do a loadlibrary on them, so that
|
|
// this utility will work on both Windows 2000 and Windows XP
|
|
//
|
|
typedef BOOL (*CSCQUERYFILESTATUSEXW)(LPCWSTR, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD);
|
|
typedef BOOL (*CSCQUERYSHARESTATUSW)(LPCWSTR, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD);
|
|
typedef BOOL (*CSCPURGEUNPINNEDFILES)(ULONG, PULONG, PULONG);
|
|
typedef BOOL (*CSCENCRYPTDECRYPTDATABASE)(BOOL, LPCSCPROCW, DWORD_PTR);
|
|
typedef BOOL (*CSCSHAREIDTOSHARENAME)(ULONG, PBYTE, PULONG);
|
|
|
|
_cdecl
|
|
main(int argc, char *argv[])
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
LPWSTR CommandLine;
|
|
LPWSTR *argvw;
|
|
int argx;
|
|
int argcw;
|
|
|
|
// fSwDebug = TRUE;
|
|
|
|
if (!CSCIsCSCEnabled()) {
|
|
Usage(FALSE);
|
|
ErrorMessage(MSG_CSC_DISABLED);
|
|
return 1;
|
|
}
|
|
|
|
//
|
|
// Get the command line in Unicode
|
|
//
|
|
|
|
CommandLine = GetCommandLine();
|
|
|
|
argvw = CommandLineToArgvW(CommandLine, &argcw);
|
|
|
|
if ( argvw == NULL ) {
|
|
MyPrintf(L"cscutil:Can't convert command line to Unicode: %d\r\n", GetLastError() );
|
|
return 1;
|
|
}
|
|
|
|
//
|
|
// Get the arguments
|
|
//
|
|
if (argcw <= 1) {
|
|
Usage(FALSE);
|
|
dwErr = ERROR_SUCCESS;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Process arguments
|
|
//
|
|
|
|
for (argx = 1; argx < argcw; argx++) {
|
|
if (CmdProcessArg(argvw[argx]) != TRUE) {
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto Cleanup;
|
|
}
|
|
if (fArgMoveShare) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (fSwDebug == TRUE) {
|
|
MyPrintf(L"Do special debug stuff here\r\n");
|
|
}
|
|
|
|
//
|
|
// Do the work
|
|
//
|
|
if (fSwHelp == TRUE || fSwQ == TRUE) {
|
|
dwErr = Usage(FALSE);
|
|
} else if (fSwHelpHelp == TRUE || fSwQQ == TRUE) {
|
|
dwErr = Usage(TRUE);
|
|
} else if (fSwInfo == TRUE) {
|
|
dwErr = CmdInfo(DEBUG_INFO_SERVERLIST);
|
|
} else if (fSwFcblist == TRUE) {
|
|
dwErr = CmdInfo(DEBUG_INFO_CSCFCBSLIST);
|
|
} else if (fSwGetSpace == TRUE) {
|
|
dwErr = CmdGetSpace();
|
|
} else if (fSwDBStatus == TRUE) {
|
|
dwErr = CmdDBStatus();
|
|
} else if (fArgPurge == TRUE) {
|
|
dwErr = CmdPurge(pwszPurgeArg);
|
|
} else if (fSwPurge == TRUE) {
|
|
dwErr = CmdPurge(NULL);
|
|
} else if (fSwDetector == TRUE) {
|
|
dwErr = CmdDetector();
|
|
} else if (fSwPQEnum == TRUE) {
|
|
dwErr = CmdPQEnum();
|
|
} else if (fSwFlags == TRUE) {
|
|
ErrorMessage(MSG_FLAGS);
|
|
dwErr = ERROR_SUCCESS;
|
|
} else if (fSwEnable == TRUE) {
|
|
dwErr = (CSCDoEnableDisable(TRUE) == TRUE) ? ERROR_SUCCESS : GetLastError();
|
|
} else if (fSwDisable == TRUE) {
|
|
dwErr = (CSCDoEnableDisable(FALSE) == TRUE) ? ERROR_SUCCESS : GetLastError();
|
|
} else if (fSwSwitches == TRUE) {
|
|
dwErr = CmdSwitches();
|
|
} else if (fArgDisconnect == TRUE) {
|
|
dwErr = CmdDisconnect(pwszDisconnectArg);
|
|
} else if (fArgExclusionList == TRUE) {
|
|
dwErr = CmdExclusionList(pwszExclusionListArg);
|
|
} else if (fArgBWConservationList == TRUE) {
|
|
dwErr = CmdBWConservationList(pwszBWConservationListArg);
|
|
} else if (fArgSetShareStatus == TRUE) {
|
|
dwErr = CmdSetShareStatus(pwszSetShareStatusArg);
|
|
} else if (fArgIsServerOffline == TRUE) {
|
|
dwErr = CmdIsServerOffline(pwszIsServerOfflineArg);
|
|
} else if (fArgReconnect == TRUE) {
|
|
dwErr = CmdReconnect(pwszReconnectArg);
|
|
} else if (fArgQueryFile == TRUE) {
|
|
dwErr = CmdQueryFile(pwszQueryFileArg);
|
|
} else if (fArgQueryFileEx == TRUE) {
|
|
dwErr = CmdQueryFileEx(pwszQueryFileExArg);
|
|
#if defined(CSCUTIL_INTERNAL)
|
|
} else if (fArgDb == TRUE) {
|
|
dwErr = CmdDb(pwszDbArg);
|
|
} else if (fSwDb == TRUE) {
|
|
dwErr = CmdDb(NULL);
|
|
} else if (fArgBitcopy == TRUE) {
|
|
dwErr = CmdBitcopy(pwszBitcopyArg);
|
|
#endif // CSCUTIL_INTERNAL
|
|
} else if (fArgSetSpace == TRUE) {
|
|
dwErr = CmdSetSpace(pwszSetSpaceArg);
|
|
} else if (fArgQueryShare == TRUE) {
|
|
dwErr = CmdQueryShare(pwszQueryShareArg);
|
|
} else if (fArgMerge == TRUE) {
|
|
dwErr = CmdMerge(pwszMergeArg);
|
|
} else if (fArgMove == TRUE) {
|
|
dwErr = CmdMove(pwszMoveArg);
|
|
} else if (fSwEncrypt == TRUE) {
|
|
dwErr = CmdEncryptDecrypt(TRUE);
|
|
} else if (fSwDecrypt == TRUE) {
|
|
dwErr = CmdEncryptDecrypt(FALSE);
|
|
} else if (fArgFill == TRUE) {
|
|
dwErr = CmdFill(pwszFillArg);
|
|
} else if (fArgCheck == TRUE) {
|
|
dwErr = CmdCheck(pwszCheckArg);
|
|
} else if (fArgEnum == TRUE) {
|
|
dwErr = CmdEnum(pwszEnumArg);
|
|
} else if (fSwEnum == TRUE) {
|
|
dwErr = CmdEnum(NULL);
|
|
} else if (fArgRandW == TRUE) {
|
|
dwErr = CmdRandW(pwszRandWArg);
|
|
} else if (fArgEnumForStats == TRUE) {
|
|
dwErr = CmdEnumForStats(pwszEnumForStatsArg);
|
|
} else if (fArgGetShadow == TRUE) {
|
|
dwErr = CmdGetShadow(pwszGetShadowArg);
|
|
} else if (fArgGetShadowInfo == TRUE) {
|
|
dwErr = CmdGetShadowInfo(pwszGetShadowInfoArg);
|
|
} else if (fArgShareId == TRUE) {
|
|
dwErr = CmdShareId(pwszShareIdArg);
|
|
} else if (fArgDelete == TRUE) {
|
|
dwErr = CmdDelete(pwszDeleteArg);
|
|
} else if (fArgDeleteShadow == TRUE) {
|
|
dwErr = CmdDeleteShadow(pwszDeleteShadowArg);
|
|
} else if (fArgPin == TRUE || fArgUnPin == TRUE) {
|
|
dwErr = CmdPinUnPin(fArgPin, pwszPinUnPinArg);
|
|
} else if (fArgMoveShare == TRUE) {
|
|
if (argcw == 4) {
|
|
dwErr = CmdMoveShare(argvw[2], argvw[3]);
|
|
}
|
|
else {
|
|
dwErr = Usage(FALSE);
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
}
|
|
} else {
|
|
dwErr = Usage(FALSE);
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
if (dwErr == ERROR_SUCCESS) {
|
|
ErrorMessage(MSG_SUCCESSFUL);
|
|
} else {
|
|
LPWSTR MessageBuffer;
|
|
DWORD dwBufferLength;
|
|
|
|
dwBufferLength = FormatMessage(
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
|
NULL,
|
|
dwErr,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
(LPWSTR) &MessageBuffer,
|
|
0,
|
|
NULL);
|
|
|
|
ErrorMessage(MSG_ERROR, dwErr);
|
|
if (dwBufferLength > 0) {
|
|
MyPrintf(L"%ws\r\n", MessageBuffer);
|
|
LocalFree(MessageBuffer);
|
|
}
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
BOOLEAN
|
|
CmdProcessArg(LPWSTR Arg)
|
|
{
|
|
LONG ArgLen;
|
|
BOOLEAN dwErr = FALSE;
|
|
BOOLEAN FoundAnArg = FALSE;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"ProcessArg(%ws)\r\n", Arg);
|
|
|
|
if ( Arg != NULL && wcslen(Arg) > 1) {
|
|
|
|
dwErr = TRUE;
|
|
ArgLen = wcslen(Arg);
|
|
|
|
//
|
|
// Commands with args
|
|
//
|
|
if (_wcsnicmp(Arg, ArgDisconnect, ArgLenDisconnect) == 0) {
|
|
FoundAnArg = fArgDisconnect = TRUE;
|
|
if (ArgLen > ArgLenDisconnect)
|
|
pwszDisconnectArg = &Arg[ArgLenDisconnect];
|
|
} else if (_wcsnicmp(Arg, ArgEnum, ArgLenEnum) == 0) {
|
|
FoundAnArg = fArgEnum = TRUE;
|
|
if (ArgLen > ArgLenEnum)
|
|
pwszEnumArg = &Arg[ArgLenEnum];
|
|
} else if (_wcsnicmp(Arg, ArgMoveShare, ArgLenMoveShare) == 0) {
|
|
FoundAnArg = fArgMoveShare = TRUE;
|
|
#if defined(CSCUTIL_INTERNAL)
|
|
} else if (_wcsnicmp(Arg, ArgReconnect, ArgLenReconnect) == 0) {
|
|
FoundAnArg = fArgReconnect = TRUE;
|
|
if (ArgLen > ArgLenReconnect)
|
|
pwszReconnectArg = &Arg[ArgLenReconnect];
|
|
} else if (_wcsnicmp(Arg, ArgPin, ArgLenPin) == 0) {
|
|
FoundAnArg = fArgPin = TRUE;
|
|
if (ArgLen > ArgLenPin)
|
|
pwszPinUnPinArg = &Arg[ArgLenPin];
|
|
} else if (_wcsnicmp(Arg, ArgUnPin, ArgLenUnPin) == 0) {
|
|
FoundAnArg = fArgUnPin = TRUE;
|
|
if (ArgLen > ArgLenUnPin)
|
|
pwszPinUnPinArg = &Arg[ArgLenUnPin];
|
|
} else if (_wcsnicmp(Arg, ArgDelete, ArgLenDelete) == 0) {
|
|
FoundAnArg = fArgDelete = TRUE;
|
|
if (ArgLen > ArgLenDelete)
|
|
pwszDeleteArg = &Arg[ArgLenDelete];
|
|
} else if (_wcsnicmp(Arg, ArgExclusionList, ArgLenExclusionList) == 0) {
|
|
FoundAnArg = fArgExclusionList = TRUE;
|
|
if (ArgLen > ArgLenExclusionList)
|
|
pwszExclusionListArg = &Arg[ArgLenExclusionList];
|
|
} else if (_wcsnicmp(Arg, ArgBWConservationList, ArgLenBWConservationList) == 0) {
|
|
FoundAnArg = fArgBWConservationList = TRUE;
|
|
if (ArgLen > ArgLenBWConservationList)
|
|
pwszBWConservationListArg = &Arg[ArgLenBWConservationList];
|
|
} else if (_wcsnicmp(Arg, ArgSetShareStatus, ArgLenSetShareStatus) == 0) {
|
|
FoundAnArg = fArgSetShareStatus = TRUE;
|
|
if (ArgLen > ArgLenSetShareStatus)
|
|
pwszSetShareStatusArg = &Arg[ArgLenSetShareStatus];
|
|
} else if (_wcsnicmp(Arg, ArgIsServerOffline, ArgLenIsServerOffline) == 0) {
|
|
FoundAnArg = fArgIsServerOffline = TRUE;
|
|
if (ArgLen > ArgLenIsServerOffline)
|
|
pwszIsServerOfflineArg = &Arg[ArgLenIsServerOffline];
|
|
} else if (_wcsnicmp(Arg, ArgPurge, ArgLenPurge) == 0) {
|
|
FoundAnArg = fArgPurge = TRUE;
|
|
if (ArgLen > ArgLenPurge)
|
|
pwszPurgeArg = &Arg[ArgLenPurge];
|
|
} else if (_wcsnicmp(Arg, ArgRandW, ArgLenRandW) == 0) {
|
|
FoundAnArg = fArgRandW = TRUE;
|
|
if (ArgLen > ArgLenRandW)
|
|
pwszRandWArg = &Arg[ArgLenRandW];
|
|
} else if (_wcsnicmp(Arg, ArgBitcopy, ArgLenBitcopy) == 0) {
|
|
FoundAnArg = fArgBitcopy = TRUE;
|
|
if (ArgLen > ArgLenBitcopy)
|
|
pwszBitcopyArg = &Arg[ArgLenBitcopy];
|
|
} else if (_wcsnicmp(Arg, ArgOffset, ArgLenOffset) == 0) {
|
|
FoundAnArg = fArgOffset = TRUE;
|
|
if (ArgLen > ArgLenOffset)
|
|
pwszOffsetArg = &Arg[ArgLenOffset];
|
|
} else if (_wcsnicmp(Arg, ArgDeleteShadow, ArgLenDeleteShadow) == 0) {
|
|
FoundAnArg = fArgDeleteShadow = TRUE;
|
|
if (ArgLen > ArgLenDeleteShadow)
|
|
pwszDeleteShadowArg = &Arg[ArgLenDeleteShadow];
|
|
} else if (_wcsnicmp(Arg, ArgQueryFile, ArgLenQueryFile) == 0) {
|
|
FoundAnArg = fArgQueryFile = TRUE;
|
|
if (ArgLen > ArgLenQueryFile)
|
|
pwszQueryFileArg = &Arg[ArgLenQueryFile];
|
|
} else if (_wcsnicmp(Arg, ArgQueryFileEx, ArgLenQueryFileEx) == 0) {
|
|
FoundAnArg = fArgQueryFileEx = TRUE;
|
|
if (ArgLen > ArgLenQueryFileEx)
|
|
pwszQueryFileExArg = &Arg[ArgLenQueryFileEx];
|
|
} else if (_wcsnicmp(Arg, ArgDb, ArgLenDb) == 0) {
|
|
FoundAnArg = fArgDb = TRUE;
|
|
if (ArgLen > ArgLenDb)
|
|
pwszDbArg = &Arg[ArgLenDb];
|
|
} else if (_wcsnicmp(Arg, ArgSetSpace, ArgLenSetSpace) == 0) {
|
|
FoundAnArg = fArgSetSpace = TRUE;
|
|
if (ArgLen > ArgLenSetSpace)
|
|
pwszSetSpaceArg = &Arg[ArgLenSetSpace];
|
|
} else if (_wcsnicmp(Arg, ArgGetShadow, ArgLenGetShadow) == 0) {
|
|
FoundAnArg = fArgGetShadow = TRUE;
|
|
if (ArgLen > ArgLenGetShadow)
|
|
pwszGetShadowArg = &Arg[ArgLenGetShadow];
|
|
} else if (_wcsnicmp(Arg, ArgGetShadowInfo, ArgLenGetShadowInfo) == 0) {
|
|
FoundAnArg = fArgGetShadowInfo = TRUE;
|
|
if (ArgLen > ArgLenGetShadowInfo)
|
|
pwszGetShadowInfoArg = &Arg[ArgLenGetShadowInfo];
|
|
} else if (_wcsnicmp(Arg, ArgShareId, ArgLenShareId) == 0) {
|
|
FoundAnArg = fArgShareId = TRUE;
|
|
if (ArgLen > ArgLenShareId)
|
|
pwszShareIdArg = &Arg[ArgLenShareId];
|
|
} else if (_wcsnicmp(Arg, ArgQueryShare, ArgLenQueryShare) == 0) {
|
|
FoundAnArg = fArgQueryShare = TRUE;
|
|
if (ArgLen > ArgLenQueryShare)
|
|
pwszQueryShareArg = &Arg[ArgLenQueryShare];
|
|
} else if (_wcsnicmp(Arg, ArgMove, ArgLenMove) == 0) {
|
|
FoundAnArg = fArgMove = TRUE;
|
|
if (ArgLen > ArgLenMove)
|
|
pwszMoveArg = &Arg[ArgLenMove];
|
|
} else if (_wcsnicmp(Arg, ArgMerge, ArgLenMerge) == 0) {
|
|
FoundAnArg = fArgMerge = TRUE;
|
|
if (ArgLen > ArgLenMerge)
|
|
pwszMergeArg = &Arg[ArgLenMerge];
|
|
} else if (_wcsnicmp(Arg, ArgFill, ArgLenFill) == 0) {
|
|
FoundAnArg = fArgFill = TRUE;
|
|
if (ArgLen > ArgLenFill)
|
|
pwszFillArg = &Arg[ArgLenFill];
|
|
} else if (_wcsnicmp(Arg, ArgCheck, ArgLenCheck) == 0) {
|
|
FoundAnArg = fArgCheck = TRUE;
|
|
if (ArgLen > ArgLenCheck)
|
|
pwszCheckArg = &Arg[ArgLenCheck];
|
|
} else if (_wcsnicmp(Arg, ArgEnumForStats, ArgLenEnumForStats) == 0) {
|
|
FoundAnArg = fArgEnumForStats = TRUE;
|
|
if (ArgLen > ArgLenEnumForStats)
|
|
pwszEnumForStatsArg = &Arg[ArgLenEnumForStats];
|
|
#endif // CSCUTIL_INTERNAL
|
|
}
|
|
|
|
// Switches go at the end!!
|
|
|
|
if (_wcsicmp(Arg, SwHelp) == 0) {
|
|
FoundAnArg = fSwHelp = TRUE;
|
|
} else if (_wcsicmp(Arg, SwResid) == 0) {
|
|
FoundAnArg = fSwTouch = fSwEnum = fSwRecurse = TRUE;
|
|
} else if (_wcsicmp(Arg, SwFull) == 0) {
|
|
FoundAnArg = fSwFull = TRUE;
|
|
} else if (_wcsicmp(Arg, SwTouch) == 0) {
|
|
FoundAnArg = fSwTouch = TRUE;
|
|
} else if (_wcsicmp(Arg, SwEnum) == 0) {
|
|
FoundAnArg = fSwEnum = TRUE;
|
|
} else if (_wcsicmp(Arg, SwQQ) == 0) {
|
|
FoundAnArg = fSwQQ = TRUE;
|
|
} else if (_wcsicmp(Arg, SwQ) == 0) {
|
|
FoundAnArg = fSwQ = TRUE;
|
|
} else if (_wcsicmp(Arg, SwRecurse) == 0) {
|
|
FoundAnArg = fSwRecurse = TRUE;
|
|
|
|
#if defined(CSCUTIL_INTERNAL)
|
|
} else if (_wcsicmp(Arg, SwDebug) == 0) {
|
|
FoundAnArg = fSwDebug = TRUE;
|
|
} else if (_wcsicmp(Arg, SwHelpHelp) == 0) {
|
|
FoundAnArg = fSwHelpHelp = TRUE;
|
|
} else if (_wcsicmp(Arg, SwPQEnum) == 0) {
|
|
FoundAnArg = fSwPQEnum = TRUE;
|
|
} else if (_wcsicmp(Arg, SwInfo) == 0) {
|
|
FoundAnArg = fSwInfo = TRUE;
|
|
} else if (_wcsicmp(Arg, SwDBStatus) == 0) {
|
|
FoundAnArg = fSwDBStatus = TRUE;
|
|
} else if (_wcsicmp(Arg, SwPurge) == 0) {
|
|
FoundAnArg = fSwPurge = TRUE;
|
|
} else if (_wcsicmp(Arg, SwDetector) == 0) {
|
|
FoundAnArg = fSwDetector = TRUE;
|
|
} else if (_wcsicmp(Arg, SwGetSpace) == 0) {
|
|
FoundAnArg = fSwGetSpace = TRUE;
|
|
} else if (_wcsicmp(Arg, SwDb) == 0) {
|
|
FoundAnArg = fSwDb = TRUE;
|
|
} else if (_wcsicmp(Arg, SwFcblist) == 0) {
|
|
FoundAnArg = fSwFcblist = TRUE;
|
|
} else if (_wcsicmp(Arg, SwEnable) == 0) {
|
|
FoundAnArg = fSwEnable = TRUE;
|
|
} else if (_wcsicmp(Arg, SwDisable) == 0) {
|
|
FoundAnArg = fSwDisable = TRUE;
|
|
} else if (_wcsicmp(Arg, SwSwitches) == 0) {
|
|
FoundAnArg = fSwSwitches = TRUE;
|
|
} else if (_wcsicmp(Arg, SwUser) == 0) {
|
|
FoundAnArg = fSwUser = TRUE;
|
|
} else if (_wcsicmp(Arg, SwSystem) == 0) {
|
|
FoundAnArg = fSwSystem = TRUE;
|
|
} else if (_wcsicmp(Arg, SwInherit) == 0) {
|
|
FoundAnArg = fSwInherit = TRUE;
|
|
} else if (_wcsicmp(Arg, SwAbort) == 0) {
|
|
FoundAnArg = fSwAbort = TRUE;
|
|
} else if (_wcsicmp(Arg, SwSkip) == 0) {
|
|
FoundAnArg = fSwSkip = TRUE;
|
|
} else if (_wcsicmp(Arg, SwAsk) == 0) {
|
|
FoundAnArg = fSwAsk = TRUE;
|
|
} else if (_wcsicmp(Arg, SwEof) == 0) {
|
|
FoundAnArg = fSwEof = TRUE;
|
|
} else if (_wcsicmp(Arg, SwRetry) == 0) {
|
|
FoundAnArg = fSwRetry = TRUE;
|
|
} else if (_wcsicmp(Arg, SwSet) == 0) {
|
|
FoundAnArg = fSwSet = TRUE;
|
|
} else if (_wcsicmp(Arg, SwClear) == 0) {
|
|
FoundAnArg = fSwClear = TRUE;
|
|
} else if (_wcsicmp(Arg, SwFlags) == 0) {
|
|
FoundAnArg = fSwFlags = TRUE;
|
|
} else if (_wcsicmp(Arg, SwIoctl) == 0) {
|
|
FoundAnArg = fSwIoctl = TRUE;
|
|
} else if (_wcsicmp(Arg, SwEncrypt) == 0) {
|
|
FoundAnArg = fSwEncrypt = TRUE;
|
|
} else if (_wcsicmp(Arg, SwDecrypt) == 0) {
|
|
FoundAnArg = fSwDecrypt = TRUE;
|
|
#endif // CSCUTIL_INTERNAL
|
|
}
|
|
|
|
if (FoundAnArg == FALSE) {
|
|
ErrorMessage(MSG_UNRECOGNIZED_OPTION, &Arg[1]);
|
|
dwErr = FALSE;
|
|
goto AllDone;
|
|
}
|
|
|
|
}
|
|
|
|
AllDone:
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"ProcessArg exit %d\r\n", dwErr);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
Usage(
|
|
BOOLEAN fHelpHelp)
|
|
{
|
|
#if defined(CSCUTIL_INTERNAL)
|
|
ErrorMessage(MSG_USAGE);
|
|
if (fHelpHelp == TRUE)
|
|
ErrorMessage(MSG_USAGE_EX);
|
|
#else
|
|
ErrorMessage(MSG_USAGE2);
|
|
if (fHelpHelp == TRUE)
|
|
ErrorMessage(MSG_USAGE_EX2);
|
|
#endif // CSCUTIL_INTERNAL
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
DWORD
|
|
CmdMoveShare(
|
|
PWSTR source,
|
|
PWSTR dest)
|
|
{
|
|
SHARESTATUS sFrom, sTo;
|
|
|
|
//printf( "Attempting move from %ws to %ws.\n", source, dest );
|
|
|
|
sFrom = GetCSCStatus(source);
|
|
//printf( "INFO: %ws status = %s\n", source, statusName[sFrom] );
|
|
|
|
sTo = GetCSCStatus(dest);
|
|
//printf( "INFO: %ws status = %s\n", dest, statusName[sTo] );
|
|
|
|
// Check and make sure this is valid
|
|
if( (sFrom == PathLocal) || (sTo == PathLocal) )
|
|
{
|
|
ErrorMessage(MSG_TO_LOCAL);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if( (sFrom == NoCSC) || (sTo == NoCSC) )
|
|
{
|
|
ErrorMessage(MSG_NO_CSC);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if( sTo == ShareOffline )
|
|
{
|
|
ErrorMessage(MSG_NOT_ONLINE);
|
|
return ERROR_CSCSHARE_OFFLINE;
|
|
}
|
|
|
|
MoveDirInCSC( source, dest, NULL, ShareOnline, ShareOnline, TRUE, TRUE );
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: MoveDirInCSC
|
|
//
|
|
// Synopsis: this function moves a directory within the CSC cache without
|
|
// prejudice. If the destination is a local path, it just deletes
|
|
// the source tree from the cache
|
|
//
|
|
// Arguments: [in] pwszSource : the source path
|
|
// [in] pwszDest : the dest path
|
|
// [in] pwszSkipSubdir : the directory to skip while moving
|
|
// [in] StatusFrom : the CSC status of the source path
|
|
// [in] StatusTo : the CSC status of the dest. path
|
|
// [in] bAllowRdrTimeout : if stuff needs to be deleted from the
|
|
// cache, we may not succeed immediately since
|
|
// the rdr keeps the handles to recently opened
|
|
// files open. This paramaters tells the function
|
|
// whether it needs to wait and retry
|
|
//
|
|
// Returns: nothing. it just tries its best.
|
|
//
|
|
// History: 11/21/1998 RahulTh created
|
|
//
|
|
// Notes: the value of bAllowRdrTimeout is always ignored for the
|
|
// in-cache rename operation. we always want to wait for
|
|
// the timeout.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
void MoveDirInCSC (const WCHAR * pwszSource, const WCHAR * pwszDest,
|
|
const WCHAR * pwszSkipSubdir,
|
|
SHARESTATUS StatusFrom, SHARESTATUS StatusTo,
|
|
BOOL bAllowRdrTimeoutForDel,
|
|
BOOL bAllowRdrTimeoutForRen)
|
|
{
|
|
WIN32_FIND_DATA findData;
|
|
DWORD dwFileStatus;
|
|
DWORD dwPinCount;
|
|
HANDLE hCSCFind;
|
|
DWORD dwHintFlags;
|
|
FILETIME origTime;
|
|
WCHAR * pwszPath;
|
|
WCHAR * pwszEnd;
|
|
int len;
|
|
DWORD StatusCSCRen = ERROR_SUCCESS;
|
|
|
|
if (PathLocal == StatusFrom)
|
|
return; //there is nothing to do. nothing was cached.
|
|
|
|
if (PathLocal == StatusTo)
|
|
{
|
|
//the destination is a local path, so we should just delete the
|
|
//files from the source
|
|
DeleteCSCFileTree (pwszSource, pwszSkipSubdir, bAllowRdrTimeoutForDel);
|
|
}
|
|
else
|
|
{
|
|
pwszPath = (WCHAR *) malloc (sizeof (WCHAR) * ((len = wcslen (pwszSource)) + MAX_PATH + 2));
|
|
if (!pwszPath || len <= 0)
|
|
return;
|
|
wcscpy (pwszPath, pwszSource);
|
|
pwszEnd = pwszPath + len;
|
|
if (L'\\' != pwszEnd[-1])
|
|
{
|
|
*pwszEnd++ = L'\\';
|
|
}
|
|
hCSCFind = CSCFindFirstFile (pwszSource, &findData, &dwFileStatus,
|
|
&dwPinCount, &dwHintFlags, &origTime);
|
|
|
|
if (INVALID_HANDLE_VALUE != hCSCFind)
|
|
{
|
|
do
|
|
{
|
|
if (0 != _wcsicmp (L".", findData.cFileName) &&
|
|
0 != _wcsicmp (L"..", findData.cFileName) &&
|
|
(!pwszSkipSubdir || (0 != _wcsicmp (findData.cFileName, pwszSkipSubdir))))
|
|
{
|
|
wcscpy (pwszEnd, findData.cFileName);
|
|
if (ERROR_SUCCESS == StatusCSCRen)
|
|
{
|
|
StatusCSCRen = DoCSCRename (pwszPath, pwszDest, TRUE, bAllowRdrTimeoutForRen);
|
|
}
|
|
else
|
|
{
|
|
StatusCSCRen = DoCSCRename (pwszPath, pwszDest, TRUE, FALSE);
|
|
}
|
|
}
|
|
|
|
} while ( CSCFindNextFile (hCSCFind, &findData, &dwFileStatus,
|
|
&dwPinCount, &dwHintFlags, &origTime)
|
|
);
|
|
|
|
CSCFindClose (hCSCFind);
|
|
}
|
|
|
|
//merge the pin info. at the top level folder
|
|
MergePinInfo (pwszSource, pwszDest, StatusFrom, StatusTo);
|
|
|
|
//remove the share - Navjot.
|
|
if (!CSCDeleteW(pwszSource))
|
|
StatusCSCRen = GetLastError();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: DoCSCRename
|
|
//
|
|
// Synopsis: does a file rename within the CSC cache.
|
|
//
|
|
// Arguments: [in] pwszSource : full source path
|
|
// [in] pwszDest : full path to destination directory
|
|
// [in] bOverwrite : overwrite if the file/folder exists at
|
|
// the destination
|
|
// [in] bAllowRdrTimeout : if TRUE, retry for 10 seconds on failure
|
|
// so that rdr and mem. mgr. get enough time to
|
|
// release the handles.
|
|
//
|
|
// Returns: ERROR_SUCCESS if the rename was successful.
|
|
// an error code otherwise.
|
|
//
|
|
// History: 5/26/1999 RahulTh created
|
|
//
|
|
// Notes: no validation of parameters is done. The caller is responsible
|
|
// for that
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
DWORD DoCSCRename (const WCHAR * pwszSource, const WCHAR * pwszDest,
|
|
BOOL bOverwrite, BOOL bAllowRdrTimeout)
|
|
{
|
|
DWORD Status = ERROR_SUCCESS;
|
|
BOOL bStatus;
|
|
int i;
|
|
|
|
bStatus = CSCDoLocalRename (pwszSource, pwszDest, bOverwrite);
|
|
if (!bStatus)
|
|
{
|
|
Status = GetLastError();
|
|
if (ERROR_SUCCESS != Status &&
|
|
ERROR_FILE_NOT_FOUND != Status &&
|
|
ERROR_PATH_NOT_FOUND != Status &&
|
|
ERROR_INVALID_PARAMETER != Status &&
|
|
ERROR_BAD_NETPATH != Status)
|
|
{
|
|
if (bAllowRdrTimeout)
|
|
{
|
|
if (!bOverwrite && ERROR_FILE_EXISTS == Status)
|
|
{
|
|
Status = ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < 11; i++)
|
|
{
|
|
Sleep (1000); //wait for the handle to be released
|
|
bStatus = CSCDoLocalRename (pwszSource, pwszDest, bOverwrite);
|
|
if (bStatus)
|
|
{
|
|
Status = ERROR_SUCCESS;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Status = ERROR_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: DeleteCSCFileTree
|
|
//
|
|
// Synopsis: deletes a file tree from the CSC
|
|
//
|
|
// Arguments: [in] pwszSource : the path to the folder whose contents should
|
|
// be deleted
|
|
// [in] pwszSkipSubdir : name of the subdirectory to be skipped.
|
|
// [in] bAllowRdrTimeout : if true, makes multiple attempts to
|
|
// delete the file since the rdr may have left
|
|
// the handle open for sometime which can result
|
|
// in an ACCESS_DENIED message.
|
|
//
|
|
// Returns: ERROR_SUCCESS if the deletion was successful. An error code
|
|
// otherwise.
|
|
//
|
|
// History: 11/21/1998 RahulTh created
|
|
//
|
|
// Notes:
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
DWORD DeleteCSCFileTree (const WCHAR * pwszSource, const WCHAR * pwszSkipSubdir,
|
|
BOOL bAllowRdrTimeout)
|
|
{
|
|
WIN32_FIND_DATA findData;
|
|
DWORD dwFileStatus;
|
|
DWORD dwPinCount;
|
|
HANDLE hCSCFind;
|
|
DWORD dwHintFlags;
|
|
FILETIME origTime;
|
|
WCHAR * pwszPath;
|
|
WCHAR * pwszEnd;
|
|
int len;
|
|
DWORD Status = ERROR_SUCCESS;
|
|
|
|
|
|
pwszPath = (WCHAR *) malloc (sizeof(WCHAR) * ((len = wcslen(pwszSource)) + MAX_PATH + 2));
|
|
if (!pwszPath)
|
|
return ERROR_OUTOFMEMORY; //nothing much we can do if we run out of memory
|
|
|
|
if (len <= 0)
|
|
return ERROR_BAD_PATHNAME;
|
|
|
|
wcscpy (pwszPath, pwszSource);
|
|
pwszEnd = pwszPath + len;
|
|
if (L'\\' != pwszEnd[-1])
|
|
{
|
|
*pwszEnd++ = L'\\';
|
|
}
|
|
|
|
hCSCFind = CSCFindFirstFile (pwszSource, &findData, &dwFileStatus,
|
|
&dwPinCount, &dwHintFlags, &origTime);
|
|
|
|
if (INVALID_HANDLE_VALUE != hCSCFind)
|
|
{
|
|
do
|
|
{
|
|
if (0 != _wcsicmp (L".", findData.cFileName) &&
|
|
0 != _wcsicmp (L"..", findData.cFileName) &&
|
|
(!pwszSkipSubdir || (0 != _wcsicmp (pwszSkipSubdir, findData.cFileName))))
|
|
{
|
|
wcscpy (pwszEnd, findData.cFileName);
|
|
|
|
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
if (ERROR_SUCCESS != Status)
|
|
{
|
|
//no point delaying the deletes since a delete has already
|
|
//failed.
|
|
DeleteCSCFileTree (pwszPath, NULL, FALSE);
|
|
}
|
|
else
|
|
{
|
|
Status = DeleteCSCFileTree (pwszPath, NULL, bAllowRdrTimeout);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ERROR_SUCCESS != Status)
|
|
{
|
|
//no point delaying the delete if we have already failed.
|
|
DeleteCSCFile (pwszPath, FALSE);
|
|
}
|
|
else
|
|
{
|
|
Status = DeleteCSCFile (pwszPath, bAllowRdrTimeout);
|
|
}
|
|
}
|
|
}
|
|
|
|
} while ( CSCFindNextFile (hCSCFind, &findData, &dwFileStatus,
|
|
&dwPinCount, &dwHintFlags, &origTime)
|
|
);
|
|
|
|
CSCFindClose (hCSCFind);
|
|
}
|
|
|
|
if (ERROR_SUCCESS != Status)
|
|
{
|
|
//no point in delaying the delete if we have already failed.
|
|
DeleteCSCFile (pwszSource, FALSE);
|
|
}
|
|
else
|
|
{
|
|
Status = DeleteCSCFile (pwszSource, bAllowRdrTimeout);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: DeleteCSCFile
|
|
//
|
|
// Synopsis: deletes the given path. but might make repeated attempts to
|
|
// make sure that the rdr has enough time to release any handles
|
|
// that it holds.
|
|
//
|
|
// Arguments: [in] pwszPath : the path to delete.
|
|
// [in] bAllowRdrTimeout : make multiple attempts to delete the
|
|
// file with waits in between so that the rdr has
|
|
// enough time to release any held handles.
|
|
//
|
|
// Returns: ERROR_SUCCES if the delete was successful. An error code
|
|
// otherwise.
|
|
//
|
|
// History: 5/26/1999 RahulTh created
|
|
//
|
|
// Notes:
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
DWORD DeleteCSCFile (const WCHAR * pwszPath, BOOL bAllowRdrTimeout)
|
|
{
|
|
BOOL bStatus;
|
|
DWORD Status = ERROR_SUCCESS;
|
|
int i;
|
|
|
|
bStatus = CSCDelete (pwszPath);
|
|
if (!bStatus)
|
|
{
|
|
Status = GetLastError();
|
|
if (ERROR_SUCCESS != Status &&
|
|
ERROR_FILE_NOT_FOUND != Status &&
|
|
ERROR_PATH_NOT_FOUND != Status &&
|
|
ERROR_INVALID_PARAMETER != Status)
|
|
{
|
|
//this is a valid error.
|
|
//so based on the value of bAllowRdrTimeout and based
|
|
//on whether we have already failed in deleting something
|
|
//we will try repeatedly to delete the file for 10 seconds
|
|
if (bAllowRdrTimeout)
|
|
{
|
|
for (i = 0; i < 11; i++)
|
|
{
|
|
Sleep (1000); //wait for 1 second and try again
|
|
bStatus = CSCDelete (pwszPath);
|
|
if (bStatus)
|
|
{
|
|
Status = ERROR_SUCCESS;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Status = ERROR_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: DeleteCSCShareIfEmpty
|
|
//
|
|
// Synopsis: given a file name, this function deletes from the local cache
|
|
// the share to which the file belongs if the local cache for that
|
|
// share is empty
|
|
//
|
|
// Arguments: [in] pwszFileName : the full file name -- must be UNC
|
|
// [in] shStatus : the share status - online, offline, local etc.
|
|
//
|
|
// Returns: ERROR_SUCCESS : if successful
|
|
// a win32 error code if something goes wrong
|
|
//
|
|
// History: 4/22/1999 RahulTh created
|
|
//
|
|
// Notes: we do not have to explicitly check if the share is empty
|
|
// because if it is not, then the delete will fail anyway
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
DWORD DeleteCSCShareIfEmpty (LPCTSTR pwszFileName, SHARESTATUS shStatus)
|
|
{
|
|
DWORD Status;
|
|
WCHAR * pwszFullPath = NULL;
|
|
WCHAR * pwszCurr = NULL;
|
|
int len;
|
|
WCHAR * pwszShrEnd;
|
|
|
|
if (PathLocal == shStatus || NoCSC == shStatus)
|
|
return ERROR_SUCCESS;
|
|
|
|
if (ShareOffline == shStatus)
|
|
return ERROR_FILE_OFFLINE;
|
|
|
|
len = wcslen (pwszFileName);
|
|
|
|
if (len <= 2)
|
|
return ERROR_BAD_PATHNAME;
|
|
|
|
if (pwszFileName[0] != L'\\' || pwszFileName[1] != L'\\')
|
|
return ERROR_BAD_PATHNAME;
|
|
|
|
pwszFullPath = (WCHAR *) malloc (sizeof (WCHAR) * (len + 1));
|
|
if (NULL == pwszFullPath)
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
if (NULL == _wfullpath(pwszFullPath, pwszFileName, len + 1))
|
|
return ERROR_BAD_PATHNAME; //canonicalization was unsuccessful.
|
|
// -- rarely happens
|
|
|
|
pwszShrEnd = wcschr (pwszFullPath + 2, L'\\');
|
|
|
|
if (NULL == pwszShrEnd)
|
|
return ERROR_BAD_PATHNAME; //the path does not have the share component
|
|
|
|
pwszShrEnd++;
|
|
|
|
pwszShrEnd = wcschr (pwszShrEnd, L'\\');
|
|
|
|
if (NULL == pwszShrEnd)
|
|
{
|
|
//we already have the path in \\server\share form, so just try to
|
|
//delete the share.
|
|
if (!CSCDelete (pwszFullPath))
|
|
return GetLastError();
|
|
}
|
|
|
|
//if we are here, then we have a path longer than just \\server\share.
|
|
//so try to delete all the way up to the share name. This is necessary
|
|
//because a user might be redirected to something like
|
|
// \\server\share\folder\%username% and we wouldn't want only \\server\share
|
|
// and \\server\share\folder to be cached.
|
|
Status = ERROR_SUCCESS;
|
|
do
|
|
{
|
|
pwszCurr = wcsrchr (pwszFullPath, L'\\');
|
|
if (NULL == pwszCurr)
|
|
break;
|
|
*pwszCurr = L'\0';
|
|
if (!CSCDelete (pwszFullPath))
|
|
{
|
|
Status = GetLastError();
|
|
if (ERROR_SUCCESS == Status ||
|
|
ERROR_INVALID_PARAMETER == Status ||
|
|
ERROR_FILE_NOT_FOUND == Status ||
|
|
ERROR_PATH_NOT_FOUND == Status)
|
|
{
|
|
Status = ERROR_SUCCESS;
|
|
}
|
|
}
|
|
if (ERROR_SUCCESS != Status)
|
|
break;
|
|
} while ( pwszCurr > pwszShrEnd );
|
|
|
|
return Status;
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: MergePinInfo
|
|
//
|
|
// Synopsis: merges the pin info. from the source to destination
|
|
//
|
|
// Arguments: [in] pwszSource : the full path to the source
|
|
// [in] pwszDest : the full path to the destination
|
|
// [in] StatusFrom : CSC status of the source share
|
|
// [in] StatusTo : CSC status of the destination share
|
|
//
|
|
// Returns: ERROR_SUCCESS : if it was successful
|
|
// a Win32 error code otherwise
|
|
//
|
|
// History: 4/23/1999 RahulTh created
|
|
//
|
|
// Notes: the hint flags are a union of the source hint flags and
|
|
// destination hint flags. The pin count is the greater of the
|
|
// source and destination pin count
|
|
//
|
|
// Usually this function should only be called for folders. The
|
|
// CSC rename API handles files well. But this function will work
|
|
// for files as well.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
DWORD MergePinInfo (LPCTSTR pwszSource, LPCTSTR pwszDest,
|
|
SHARESTATUS StatusFrom, SHARESTATUS StatusTo)
|
|
{
|
|
BOOL bStatus;
|
|
DWORD dwSourceStat, dwDestStat;
|
|
DWORD dwSourcePinCount, dwDestPinCount;
|
|
DWORD dwSourceHints, dwDestHints;
|
|
DWORD Status = ERROR_SUCCESS;
|
|
DWORD i;
|
|
|
|
if (ShareOffline == StatusFrom || ShareOffline == StatusTo)
|
|
return ERROR_FILE_OFFLINE;
|
|
|
|
if (ShareOnline != StatusFrom || ShareOnline != StatusTo)
|
|
return ERROR_SUCCESS; //there is nothing to do if one of the shares
|
|
//is local.
|
|
if (!pwszSource || !pwszDest ||
|
|
0 == wcslen(pwszSource) || 0 == wcslen(pwszDest))
|
|
return ERROR_BAD_PATHNAME;
|
|
|
|
bStatus = CSCQueryFileStatus (pwszSource, &dwSourceStat, &dwSourcePinCount,
|
|
&dwSourceHints);
|
|
if (!bStatus)
|
|
return GetLastError();
|
|
|
|
bStatus = CSCQueryFileStatus (pwszDest, &dwDestStat, &dwDestPinCount,
|
|
&dwDestHints);
|
|
if (!bStatus)
|
|
return GetLastError();
|
|
|
|
//first set the hint flags on the destination
|
|
if (dwDestHints != dwSourceHints)
|
|
{
|
|
bStatus = CSCPinFile (pwszDest, dwSourceHints, &dwDestStat,
|
|
&dwDestPinCount, &dwDestHints);
|
|
if (!bStatus)
|
|
Status = GetLastError(); //note: we do not bail out here. we try
|
|
//to at least merge the pin count before
|
|
//leaving
|
|
}
|
|
|
|
//now merge the pin count : there is nothing to be done if the destination
|
|
//pin count is greater than or equal to the source pin count
|
|
if (dwDestPinCount < dwSourcePinCount)
|
|
{
|
|
for (i = 0, bStatus = TRUE; i < (dwSourcePinCount - dwDestPinCount) &&
|
|
bStatus;
|
|
i++)
|
|
{
|
|
bStatus = CSCPinFile( pwszDest,
|
|
FLAG_CSC_HINT_COMMAND_ALTER_PIN_COUNT,
|
|
NULL, NULL, NULL );
|
|
}
|
|
|
|
if (!bStatus && ERROR_SUCCESS == Status)
|
|
Status = GetLastError();
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: PinIfNecessary
|
|
//
|
|
// Synopsis: this function pins a file if necessary.
|
|
//
|
|
// Arguments: [in] pwszPath : full path of the file/folder to be pinned
|
|
// [in] shStatus : CSC status of the share.
|
|
//
|
|
// Returns: ERROR_SUCCESS if it was successful. An error code otherwise.
|
|
//
|
|
// History: 5/27/1999 RahulTh created
|
|
//
|
|
// Notes:
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
DWORD PinIfNecessary (const WCHAR * pwszPath, SHARESTATUS shStatus)
|
|
{
|
|
DWORD Status = ERROR_SUCCESS;
|
|
BOOL bStatus;
|
|
DWORD dwStatus;
|
|
DWORD dwPinCount;
|
|
DWORD dwHints;
|
|
|
|
if (!pwszPath || !pwszPath[0])
|
|
return ERROR_BAD_NETPATH;
|
|
|
|
|
|
if (ShareOffline == shStatus)
|
|
return ERROR_FILE_OFFLINE;
|
|
else if (PathLocal == shStatus || NoCSC == shStatus)
|
|
return ERROR_SUCCESS;
|
|
|
|
bStatus = CSCQueryFileStatus (pwszPath, &dwStatus, &dwPinCount, &dwHints);
|
|
if (!bStatus || dwPinCount <= 0)
|
|
{
|
|
bStatus = CSCPinFile (pwszPath,
|
|
FLAG_CSC_HINT_COMMAND_ALTER_PIN_COUNT,
|
|
NULL, NULL, NULL);
|
|
if (!bStatus)
|
|
Status = GetLastError();
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: GetCSCStatus
|
|
//
|
|
// Synopsis: given a path, finds out if it is local and if it is not
|
|
// whether it is online or offline.
|
|
//
|
|
// Arguments: [in] pwszPath : the path to the file
|
|
//
|
|
// Returns: Local/Online/Offline
|
|
//
|
|
// History: 11/20/1998 RahulTh created
|
|
//
|
|
// Notes: it is important that the path passed to this function is a
|
|
// a full path and not a relative path
|
|
//
|
|
// this function will return offline if the share is not live or
|
|
// if the share is live but CSC thinks that it is offline
|
|
//
|
|
// it will return PathLocal if the path is local or if the path
|
|
// is a network path that cannot be handled by CSC e.g. a network
|
|
// share with a pathname longer than what csc can handle or if it
|
|
// is a netware share. in this case it makes sense to return
|
|
// PathLocal because CSC won't maintain a database for these shares
|
|
// -- same as for a local path. so as far as CSC is concerned, this
|
|
// is as good as a local path.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
SHARESTATUS GetCSCStatus (const WCHAR * pwszPath)
|
|
{
|
|
WCHAR * pwszAbsPath = NULL;
|
|
WCHAR * pwszCurr = NULL;
|
|
int len;
|
|
BOOL bRetVal;
|
|
DWORD Status;
|
|
DWORD dwPinCount;
|
|
DWORD dwHints;
|
|
|
|
if (!pwszPath)
|
|
return ShareOffline; //a path must be provided
|
|
|
|
len = wcslen (pwszPath);
|
|
|
|
pwszAbsPath = (WCHAR *) malloc (sizeof (WCHAR) * (len + 1));
|
|
|
|
if (!pwszAbsPath)
|
|
{
|
|
//we are out of memory, so it is safest to return ShareOffline
|
|
//so that we can bail out of redirection.
|
|
return ShareOffline;
|
|
}
|
|
|
|
//get the absolute path
|
|
pwszCurr = _wfullpath (pwszAbsPath, pwszPath, len + 1);
|
|
|
|
if (!pwszCurr)
|
|
{
|
|
//in order for _wfullpath to fail, something really bad has to happen
|
|
//so it is best to return ShareOffline so that we can bail out of
|
|
//redirection
|
|
return ShareOffline;
|
|
}
|
|
|
|
len = wcslen (pwszAbsPath);
|
|
|
|
if (! (
|
|
(2 <= len) &&
|
|
(L'\\' == pwszAbsPath[0]) &&
|
|
(L'\\' == pwszAbsPath[1])
|
|
)
|
|
)
|
|
{
|
|
//it is a local path if it does not begin with 2 backslashes
|
|
return PathLocal;
|
|
}
|
|
|
|
//this is a UNC path; so extract the \\server\share part
|
|
pwszCurr = wcschr ( & (pwszAbsPath[2]), L'\\');
|
|
|
|
//first make sure that it is at least of the form \\server\share
|
|
//watch out for the \\server\ case
|
|
if (!pwszCurr || !pwszCurr[1])
|
|
return ShareOffline; //it is an invalid path (no share name)
|
|
|
|
//the path is of the form \\server\share
|
|
//note: the use _wfullpath automatically protects us against the \\server\\ case
|
|
pwszCurr = wcschr (&(pwszCurr[1]), L'\\');
|
|
if (pwszCurr) //if it is of the form \\server\share\...
|
|
*pwszCurr = L'\0';
|
|
|
|
//now pwszAbsPath is a share name
|
|
bRetVal = CSCCheckShareOnline (pwszAbsPath);
|
|
|
|
if (!bRetVal)
|
|
{
|
|
if (ERROR_SUCCESS != GetLastError())
|
|
{
|
|
//either there is really a problem (e.g. invalid share name) or
|
|
//it is just a share that is not handled by CSC e.g. a netware share
|
|
//or a share with a name that is longer than can be handled by CSC
|
|
//so check if the share actually exists
|
|
if (0xFFFFFFFF != GetFileAttributes(pwszAbsPath))
|
|
{
|
|
//this can still be a share that is offline since GetFileAttributes
|
|
//will return the attributes stored in the cache
|
|
Status = 0;
|
|
bRetVal = GetShareStatus (pwszAbsPath, &Status, &dwPinCount,
|
|
&dwHints);
|
|
if (! bRetVal || (! (FLAG_CSC_SHARE_STATUS_DISCONNECTED_OP & Status)))
|
|
return PathLocal; //this is simply a valid path that CSC cannot handle
|
|
else if (bRetVal &&
|
|
(FLAG_CSC_SHARE_STATUS_NO_CACHING ==
|
|
(FLAG_CSC_SHARE_STATUS_CACHING_MASK & Status)))
|
|
return PathLocal; //CSC caching is not turned on for the share.
|
|
}
|
|
}
|
|
|
|
//it is indeed an inaccessble share
|
|
return ShareOffline; //for all other cases, treat this as offline
|
|
}
|
|
else
|
|
{
|
|
//this means that the share is live, but CSC might still think that it
|
|
//is offline.
|
|
Status = 0;
|
|
bRetVal = GetShareStatus (pwszAbsPath, &Status, &dwPinCount,
|
|
&dwHints);
|
|
if (bRetVal && (FLAG_CSC_SHARE_STATUS_DISCONNECTED_OP & Status))
|
|
return ShareOffline; //CSC thinks that the share is offline
|
|
else if (bRetVal &&
|
|
(FLAG_CSC_SHARE_STATUS_NO_CACHING ==
|
|
(FLAG_CSC_SHARE_STATUS_CACHING_MASK & Status)))
|
|
return PathLocal; //CSC caching is not turned on for the share
|
|
else if (!bRetVal)
|
|
return ShareOffline;
|
|
|
|
//in all other cases, consider the share as online since
|
|
//CSCCheckShareOnline has already returned TRUE
|
|
return ShareOnline;
|
|
}
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: GetShareStatus
|
|
//
|
|
// Synopsis: this function is a wrapper for CSCQueryFileStatus.
|
|
// basically CSCQueryFileStatus can fail if there was never a net
|
|
// use to a share. So this function tries to create a net use to
|
|
// the share if CSCQueryFileStatus fails and then re-queries the
|
|
// file status
|
|
//
|
|
// Arguments: [in] pwszShare : the share name
|
|
// [out] pdwStatus : the share Status
|
|
// [out] pdwPinCount : the pin count
|
|
// [out] pdwHints : the hints
|
|
//
|
|
// Returns: TRUE : if everything was successful.
|
|
// FALSE : if there was an error. In this case, it GetLastError()
|
|
// will contain the specific error code.
|
|
//
|
|
// History: 5/11/1999 RahulTh created
|
|
//
|
|
// Notes: it is very important that this function be passed a share name
|
|
// it does not do any parameter validation. So under no
|
|
// circumstance should this function be passed a filename.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
BOOL GetShareStatus (const WCHAR * pwszShare, DWORD * pdwStatus,
|
|
DWORD * pdwPinCount, DWORD * pdwHints)
|
|
{
|
|
NETRESOURCE nr;
|
|
DWORD dwResult;
|
|
DWORD dwErr = NO_ERROR;
|
|
BOOL bStatus;
|
|
|
|
bStatus = CSCQueryFileStatus(pwszShare, pdwStatus, pdwPinCount, pdwHints);
|
|
|
|
if (!bStatus)
|
|
{
|
|
//try to connect to the share
|
|
ZeroMemory ((PVOID) (&nr), sizeof (NETRESOURCE));
|
|
nr.dwType = RESOURCETYPE_DISK;
|
|
nr.lpLocalName = NULL;
|
|
nr.lpRemoteName = (LPTSTR) pwszShare;
|
|
nr.lpProvider = NULL;
|
|
|
|
dwErr = WNetUseConnection(NULL, &nr, NULL, NULL, 0,
|
|
NULL, NULL, &dwResult);
|
|
|
|
if (NO_ERROR == dwErr)
|
|
{
|
|
bStatus = CSCQueryFileStatus (pwszShare, pdwStatus, pdwPinCount, pdwHints);
|
|
if (!bStatus)
|
|
dwErr = GetLastError();
|
|
else
|
|
dwErr = NO_ERROR;
|
|
|
|
WNetCancelConnection2 (pwszShare, 0, FALSE);
|
|
}
|
|
else
|
|
{
|
|
bStatus = FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
SetLastError(dwErr);
|
|
return bStatus;
|
|
}
|
|
|
|
|
|
DWORD
|
|
CmdReconnect(
|
|
PWSTR ReconnectArg)
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
BOOL fRet;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdReconnect(%ws)\r\n", ReconnectArg);
|
|
|
|
fRet = CSCTransitionServerOnlineW(ReconnectArg);
|
|
if (fRet == FALSE)
|
|
Error = GetLastError();
|
|
|
|
return Error;
|
|
}
|
|
|
|
DWORD
|
|
CmdQueryFile(
|
|
PWSTR QueryFileArg)
|
|
{
|
|
DWORD HintFlags = 0;
|
|
DWORD PinCount = 0;
|
|
DWORD Status = 0;
|
|
DWORD Error = ERROR_SUCCESS;
|
|
BOOL fRet;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdQueryFile(%ws)\r\n", QueryFileArg);
|
|
|
|
fRet = CSCQueryFileStatusW(
|
|
QueryFileArg,
|
|
&Status,
|
|
&PinCount,
|
|
&HintFlags);
|
|
|
|
if (fRet == FALSE) {
|
|
Error = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
if (fSwFull != TRUE) {
|
|
MyPrintf(
|
|
L"QueryFile of %ws:\r\n"
|
|
L"Status: 0x%x\r\n"
|
|
L"PinCount: %d\r\n"
|
|
L"HintFlags: 0x%x\r\n",
|
|
QueryFileArg,
|
|
Status,
|
|
PinCount,
|
|
HintFlags);
|
|
} else {
|
|
WCHAR StatusBuffer[0x100];
|
|
WCHAR HintBuffer[0x100];
|
|
|
|
if (LooksToBeAShare(QueryFileArg) == TRUE)
|
|
ShareStatusToEnglish(Status, StatusBuffer);
|
|
else
|
|
FileStatusToEnglish(Status, StatusBuffer);
|
|
HintsToEnglish(HintFlags, HintBuffer);
|
|
MyPrintf(
|
|
L"QueryFile of %ws:\r\n"
|
|
L"Status: 0x%x %ws\r\n"
|
|
L"PinCount: %d\r\n"
|
|
L"HintFlags: 0x%x %ws\r\n",
|
|
QueryFileArg,
|
|
Status,
|
|
StatusBuffer,
|
|
PinCount,
|
|
HintFlags,
|
|
HintBuffer);
|
|
}
|
|
|
|
AllDone:
|
|
return Error;
|
|
}
|
|
|
|
DWORD
|
|
CmdQueryFileEx(
|
|
PWSTR QueryFileExArg)
|
|
{
|
|
DWORD HintFlags = 0;
|
|
DWORD PinCount = 0;
|
|
DWORD Status = 0;
|
|
DWORD UserPerms = 0;
|
|
DWORD OtherPerms = 0;
|
|
DWORD Error = ERROR_SUCCESS;
|
|
BOOL fRet;
|
|
HMODULE hmodCscDll = LoadLibrary(TEXT("cscdll.dll"));
|
|
CSCQUERYFILESTATUSEXW pCSCQueryFileStatusExW = NULL;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdQueryFileEx(%ws)\r\n", QueryFileExArg);
|
|
|
|
if (hmodCscDll == NULL) {
|
|
Error = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
pCSCQueryFileStatusExW = (CSCQUERYFILESTATUSEXW) GetProcAddress(
|
|
hmodCscDll,
|
|
"CSCQueryFileStatusExW");
|
|
if (pCSCQueryFileStatusExW == NULL) {
|
|
Error = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
fRet = (pCSCQueryFileStatusExW)(
|
|
QueryFileExArg,
|
|
&Status,
|
|
&PinCount,
|
|
&HintFlags,
|
|
&UserPerms,
|
|
&OtherPerms);
|
|
|
|
if (fRet == FALSE) {
|
|
Error = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
if (fSwFull != TRUE) {
|
|
MyPrintf(
|
|
L"Query of %ws:\r\n"
|
|
L"Status: 0x%x\r\n"
|
|
L"PinCount: %d\r\n"
|
|
L"HintFlags: 0x%x\r\n"
|
|
L"UserPerms: 0x%x\r\n"
|
|
L"OtherPerms: 0x%x\r\n",
|
|
QueryFileExArg,
|
|
Status,
|
|
PinCount,
|
|
HintFlags,
|
|
UserPerms,
|
|
OtherPerms);
|
|
} else {
|
|
WCHAR StatusBuffer[0x100] = {0};
|
|
WCHAR HintBuffer[0x100] = {0};
|
|
|
|
if (LooksToBeAShare(QueryFileExArg) == TRUE)
|
|
ShareStatusToEnglish(Status, StatusBuffer);
|
|
else
|
|
FileStatusToEnglish(Status, StatusBuffer);
|
|
HintsToEnglish(HintFlags, HintBuffer);
|
|
MyPrintf(
|
|
L"Query of %ws:\r\n"
|
|
L"Status: 0x%x %ws\r\n"
|
|
L"PinCount: %d\r\n"
|
|
L"HintFlags: 0x%x %ws\r\n"
|
|
L"UserPerms: 0x%x\r\n"
|
|
L"OtherPerms: 0x%x\r\n",
|
|
QueryFileExArg,
|
|
Status,
|
|
StatusBuffer,
|
|
PinCount,
|
|
HintFlags,
|
|
HintBuffer,
|
|
UserPerms,
|
|
OtherPerms);
|
|
}
|
|
|
|
AllDone:
|
|
if (hmodCscDll != NULL)
|
|
FreeLibrary(hmodCscDll);
|
|
return Error;
|
|
}
|
|
|
|
DWORD
|
|
CmdSetSpace(
|
|
PWSTR SetSpaceArg)
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
DWORD MaxSpaceHigh = 0;
|
|
DWORD MaxSpaceLow;
|
|
BOOL fRet;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdSetSpace(%ws)\r\n", SetSpaceArg);
|
|
|
|
swscanf(SetSpaceArg, L"%d", &MaxSpaceLow);
|
|
|
|
fRet = CSCSetMaxSpace(
|
|
MaxSpaceHigh,
|
|
MaxSpaceLow);
|
|
|
|
if (fRet == FALSE) {
|
|
Error = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
CmdGetSpace();
|
|
|
|
AllDone:
|
|
return Error;
|
|
}
|
|
|
|
DWORD
|
|
CmdQueryShare(
|
|
PWSTR QueryShareArg)
|
|
{
|
|
DWORD HintFlags = 0;
|
|
DWORD PinCount = 0;
|
|
DWORD Status = 0;
|
|
DWORD UserPerms = 0;
|
|
DWORD OtherPerms = 0;
|
|
DWORD Error = ERROR_SUCCESS;
|
|
BOOL fRet;
|
|
HMODULE hmodCscDll = LoadLibrary(TEXT("cscdll.dll"));
|
|
CSCQUERYSHARESTATUSW pCSCQueryShareStatusW = NULL;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdQueryShare(%ws)\r\n", QueryShareArg);
|
|
|
|
if (hmodCscDll == NULL) {
|
|
Error = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
pCSCQueryShareStatusW = (CSCQUERYSHARESTATUSW) GetProcAddress(
|
|
hmodCscDll,
|
|
"CSCQueryShareStatusW");
|
|
if (pCSCQueryShareStatusW == NULL) {
|
|
Error = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
fRet = (pCSCQueryShareStatusW)(
|
|
QueryShareArg,
|
|
&Status,
|
|
&PinCount,
|
|
&HintFlags,
|
|
&UserPerms,
|
|
&OtherPerms);
|
|
|
|
if (fRet == FALSE) {
|
|
Error = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
if (fSwFull != TRUE) {
|
|
MyPrintf(
|
|
L"Query of %ws:\r\n"
|
|
L"Status: 0x%x\r\n"
|
|
L"PinCount: %d\r\n"
|
|
L"HintFlags: 0x%x\r\n"
|
|
L"UserPerms: 0x%x\r\n"
|
|
L"OtherPerms: 0x%x\r\n",
|
|
QueryShareArg,
|
|
Status,
|
|
PinCount,
|
|
HintFlags,
|
|
UserPerms,
|
|
OtherPerms);
|
|
} else {
|
|
WCHAR StatusBuffer[0x100] = {0};
|
|
WCHAR HintBuffer[0x100] = {0};
|
|
|
|
ShareStatusToEnglish(Status, StatusBuffer);
|
|
HintsToEnglish(HintFlags, HintBuffer);
|
|
MyPrintf(
|
|
L"Query of %ws:\r\n"
|
|
L"Status: 0x%x %ws\r\n"
|
|
L"PinCount: %d\r\n"
|
|
L"HintFlags: 0x%x %ws\r\n"
|
|
L"UserPerms: 0x%x\r\n"
|
|
L"OtherPerms: 0x%x\r\n",
|
|
QueryShareArg,
|
|
Status,
|
|
StatusBuffer,
|
|
PinCount,
|
|
HintFlags,
|
|
HintBuffer,
|
|
UserPerms,
|
|
OtherPerms);
|
|
}
|
|
AllDone:
|
|
if (hmodCscDll != NULL)
|
|
FreeLibrary(hmodCscDll);
|
|
return Error;
|
|
}
|
|
|
|
DWORD
|
|
CmdMerge(
|
|
PWSTR MergeArg)
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
DWORD HowToRespond = CSCPROC_RETURN_CONTINUE; // JMH
|
|
BOOL fRet;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdMerge(%ws)\r\n", MergeArg);
|
|
|
|
fRet = CSCMergeShareW(MergeArg, MyCscMergeProcW, HowToRespond);
|
|
if (fRet == FALSE) {
|
|
Error = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
fRet = CSCTransitionServerOnlineW(MergeArg);
|
|
if (fRet == FALSE)
|
|
Error = GetLastError();
|
|
|
|
AllDone:
|
|
return Error;
|
|
}
|
|
|
|
DWORD
|
|
CmdMove(
|
|
PWSTR MoveArg)
|
|
{
|
|
|
|
DWORD Error = ERROR_FILE_NOT_FOUND;
|
|
LPWSTR lpszTempName = NULL;
|
|
|
|
if (!CSCCopyReplicaW(MoveArg, &lpszTempName)) {
|
|
Error = GetLastError();
|
|
} else {
|
|
Error = ERROR_SUCCESS;
|
|
}
|
|
|
|
if (Error == ERROR_SUCCESS)
|
|
MyPrintf(L"Copy is %ws\r\n", lpszTempName);
|
|
|
|
return Error;
|
|
}
|
|
|
|
|
|
DWORD
|
|
CmdEncryptDecrypt(
|
|
BOOL fEncrypt)
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
DWORD EncryptDecryptType = 0;
|
|
BOOL fRet;
|
|
HMODULE hmodCscDll = LoadLibrary(TEXT("cscdll.dll"));
|
|
CSCENCRYPTDECRYPTDATABASE pCSCEncryptDecryptDatabase = NULL;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdEncryptDecrypt(%ws)\r\n", fEncrypt == TRUE ? L"Encrypt" : L"Decrypt");
|
|
|
|
if (hmodCscDll == NULL) {
|
|
Error = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
pCSCEncryptDecryptDatabase = (CSCENCRYPTDECRYPTDATABASE) GetProcAddress(
|
|
hmodCscDll,
|
|
"CSCEncryptDecryptDatabase");
|
|
if (pCSCEncryptDecryptDatabase == NULL) {
|
|
Error = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
fRet = (pCSCEncryptDecryptDatabase)(fEncrypt, MyEncryptDecryptProcW, EncryptDecryptType);
|
|
if (fRet == FALSE) {
|
|
Error = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
AllDone:
|
|
|
|
if (hmodCscDll != NULL)
|
|
FreeLibrary(hmodCscDll);
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdEncryptDecrypt exit %d\r\n", Error);
|
|
|
|
return Error;
|
|
}
|
|
|
|
DWORD
|
|
CmdFill(
|
|
PWSTR FillArg)
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
DWORD HowToRespond = CSCPROC_RETURN_CONTINUE;
|
|
BOOL fRet;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdFill(%ws, %d)\r\n", FillArg, fSwFull);
|
|
|
|
fRet = CSCFillSparseFilesW(FillArg, fSwFull, MyCscFillProcW, HowToRespond);
|
|
if (fRet == FALSE) {
|
|
Error = GetLastError();
|
|
}
|
|
|
|
return Error;
|
|
}
|
|
|
|
DWORD
|
|
CmdCheck(
|
|
PWSTR CheckArg)
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
DWORD Speed = 0;
|
|
BOOL fOnline = FALSE;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdCheck(%ws)\r\n", CheckArg);
|
|
|
|
fOnline = CSCCheckShareOnlineExW(CheckArg, &Speed);
|
|
|
|
MyPrintf(
|
|
L"%ws is %s\r\n",
|
|
CheckArg,
|
|
(fOnline == FALSE) ? L"Offline" : L"Online");
|
|
|
|
return Error;
|
|
}
|
|
|
|
DWORD
|
|
CmdDBStatus(
|
|
VOID)
|
|
{
|
|
GLOBALSTATUS sGS = {0};
|
|
ULONG DBStatus = 0;
|
|
ULONG DBErrorFlags = 0;
|
|
BOOL bResult;
|
|
HANDLE hDBShadow = INVALID_HANDLE_VALUE;
|
|
ULONG junk;
|
|
ULONG Status = 0;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdDBStatus()\r\n");
|
|
|
|
hDBShadow = CreateFile(
|
|
L"\\\\.\\shadow",
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
|
|
if (hDBShadow == INVALID_HANDLE_VALUE) {
|
|
MyPrintf(L"CmdDBStatus:Failed open of shadow device\r\n");
|
|
Status = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
bResult = DeviceIoControl(
|
|
hDBShadow, // device
|
|
IOCTL_GETGLOBALSTATUS, // control code
|
|
(LPVOID)&sGS, // in buffer
|
|
0, // inbuffer size
|
|
NULL, // out buffer
|
|
0, // out buffer size
|
|
&junk, // bytes returned
|
|
NULL); // overlapped
|
|
|
|
if (!bResult) {
|
|
MyPrintf(L"CmdDBStatus:DeviceIoControl IOCTL_GETGLOBALSTATUS failed\n");
|
|
Status = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
DBStatus = sGS.sST.uFlags;
|
|
DBErrorFlags = sGS.uDatabaseErrorFlags;
|
|
|
|
if (DBStatus & FLAG_DATABASESTATUS_DIRTY)
|
|
MyPrintf(L"FLAG_DATABASESTATUS_DIRTY\r\n");
|
|
if (DBStatus & FLAG_DATABASESTATUS_UNENCRYPTED)
|
|
MyPrintf(L"FLAG_DATABASESTATUS_UNENCRYPTED\r\n");
|
|
if (DBStatus & FLAG_DATABASESTATUS_PARTIALLY_UNENCRYPTED)
|
|
MyPrintf(L"FLAG_DATABASESTATUS_PARTIALLY_UNENCRYPTED\r\n");
|
|
if (DBStatus & FLAG_DATABASESTATUS_ENCRYPTED)
|
|
MyPrintf(L"FLAG_DATABASESTATUS_ENCRYPTED\r\n");
|
|
if (DBStatus & FLAG_DATABASESTATUS_PARTIALLY_ENCRYPTED)
|
|
MyPrintf(L"FLAG_DATABASESTATUS_PARTIALLY_ENCRYPTED\r\n");
|
|
|
|
MyPrintf(L"Database Error Flags : 0x%x\r\n", DBErrorFlags);
|
|
|
|
AllDone:
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdDBStatus exit %d\r\n", Status);
|
|
|
|
if (hDBShadow != INVALID_HANDLE_VALUE)
|
|
CloseHandle(hDBShadow);
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
CmdPurge(
|
|
PWSTR PurgeArg)
|
|
{
|
|
ULONG nFiles = 0;
|
|
ULONG nYoungFiles = 0;
|
|
ULONG Status = ERROR_SUCCESS;
|
|
ULONG Timeout = 120;
|
|
BOOL fRet = FALSE;
|
|
HMODULE hmodCscDll = LoadLibrary(TEXT("cscdll.dll"));
|
|
CSCPURGEUNPINNEDFILES pCSCPurgeUnpinnedFiles = NULL;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdPurge(%ws)\r\n", PurgeArg);
|
|
|
|
if (hmodCscDll == NULL) {
|
|
Status = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
pCSCPurgeUnpinnedFiles = (CSCPURGEUNPINNEDFILES) GetProcAddress(
|
|
hmodCscDll,
|
|
"CSCPurgeUnpinnedFiles");
|
|
if (pCSCPurgeUnpinnedFiles == NULL) {
|
|
Status = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
if (PurgeArg != NULL)
|
|
swscanf(PurgeArg, L"%d", &Timeout);
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"Timeout=%d seconds\r\n", Timeout);
|
|
|
|
fRet = (pCSCPurgeUnpinnedFiles)(Timeout, &nFiles, &nYoungFiles);
|
|
if (fRet == FALSE) {
|
|
Status = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
MyPrintf(L"nFiles = %d nYoungFiles=%d\n", nFiles, nYoungFiles);
|
|
|
|
AllDone:
|
|
if (hmodCscDll != NULL)
|
|
FreeLibrary(hmodCscDll);
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdPurge exit %d\r\n", Status);
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
CmdPQEnum(
|
|
VOID)
|
|
{
|
|
PQPARAMS PQP = {0};
|
|
BOOL bResult;
|
|
HANDLE hDBShadow = INVALID_HANDLE_VALUE;
|
|
ULONG junk;
|
|
ULONG Status = 0;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdPQEnum()\r\n");
|
|
|
|
hDBShadow = CreateFile(
|
|
L"\\\\.\\shadow",
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
|
|
if (hDBShadow == INVALID_HANDLE_VALUE) {
|
|
MyPrintf(L"CmdPQEnum:Failed open of shadow device\r\n");
|
|
Status = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
MyPrintf(L" POS SHARE DIR SHADOW STATUS REFPRI HPRI HINTFLG HINTPRI VER\r\n");
|
|
|
|
bResult = DeviceIoControl(
|
|
hDBShadow, // device
|
|
IOCTL_SHADOW_BEGIN_PQ_ENUM, // control code
|
|
(LPVOID)&PQP, // in buffer
|
|
0, // inbuffer size
|
|
NULL, // out buffer
|
|
0, // out buffer size
|
|
&junk, // bytes returned
|
|
NULL); // overlapped
|
|
|
|
if (!bResult) {
|
|
MyPrintf(L"CmdPQEnum:DeviceIoControl IOCTL_SHADOW_BEGIN_PQ_ENUM failed\n");
|
|
Status = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
do {
|
|
bResult = DeviceIoControl(
|
|
hDBShadow, // device
|
|
IOCTL_SHADOW_NEXT_PRI_SHADOW, // control code
|
|
(LPVOID)&PQP, // in buffer
|
|
0, // inbuffer size
|
|
NULL, // out buffer
|
|
0, // out buffer size
|
|
&junk, // bytes returned
|
|
NULL); // overlapped
|
|
if (bResult) {
|
|
MyPrintf(L"%5d %5x %8x %8x %8x %6d %6x %7d %7d %4d\r\n",
|
|
PQP.uPos,
|
|
PQP.hShare,
|
|
PQP.hDir,
|
|
PQP.hShadow,
|
|
PQP.ulStatus,
|
|
PQP.ulRefPri,
|
|
PQP.ulIHPri,
|
|
PQP.ulHintFlags,
|
|
PQP.ulHintPri,
|
|
PQP.dwPQVersion);
|
|
}
|
|
} while (bResult && PQP.uPos != 0);
|
|
|
|
bResult = DeviceIoControl(
|
|
hDBShadow, // device
|
|
IOCTL_SHADOW_END_PQ_ENUM, // control code
|
|
(LPVOID)&PQP, // in buffer
|
|
0, // inbuffer size
|
|
NULL, // out buffer
|
|
0, // out buffer size
|
|
&junk, // bytes returned
|
|
NULL); // overlapped
|
|
|
|
AllDone:
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdPQEnum exit %d\r\n", Status);
|
|
|
|
if (hDBShadow != INVALID_HANDLE_VALUE)
|
|
CloseHandle(hDBShadow);
|
|
|
|
return Status;
|
|
}
|
|
|
|
LPWSTR
|
|
ConvertGmtTimeToString(
|
|
FILETIME Time,
|
|
LPWSTR OutputBuffer)
|
|
{
|
|
FILETIME LocalTime;
|
|
SYSTEMTIME SystemTime;
|
|
|
|
static FILETIME ftNone = {0, 0};
|
|
|
|
if (memcmp(&Time, &ftNone, sizeof(FILETIME)) == 0) {
|
|
wsprintf (OutputBuffer, L"<none>");
|
|
} else {
|
|
FileTimeToLocalFileTime( &Time , &LocalTime );
|
|
FileTimeToSystemTime( &LocalTime, &SystemTime );
|
|
wsprintf(
|
|
OutputBuffer,
|
|
L"%02u/%02u/%04u %02u:%02u:%02u ",
|
|
SystemTime.wMonth,
|
|
SystemTime.wDay,
|
|
SystemTime.wYear,
|
|
SystemTime.wHour,
|
|
SystemTime.wMinute,
|
|
SystemTime.wSecond );
|
|
}
|
|
return( OutputBuffer );
|
|
}
|
|
|
|
VOID
|
|
DumpCscEntryInfo(
|
|
LPWSTR Path,
|
|
PWIN32_FIND_DATA Find32,
|
|
DWORD Status,
|
|
DWORD PinCount,
|
|
DWORD HintFlags,
|
|
PFILETIME OrgTime)
|
|
{
|
|
WCHAR TimeBuf1[40];
|
|
WCHAR TimeBuf2[40];
|
|
FILE *fp = NULL;
|
|
|
|
if (fSwTouch == TRUE) {
|
|
if (Path == NULL) {
|
|
wsprintf(NameBuf, L"%ws", Find32->cFileName);
|
|
} else {
|
|
wsprintf(NameBuf, L"%ws\\%ws", Path, Find32->cFileName);
|
|
}
|
|
MyPrintf(L"%ws\r\n", NameBuf);
|
|
if ((Find32->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
|
|
fp = _wfopen(NameBuf, L"rb");
|
|
if (fp != NULL)
|
|
fclose(fp);
|
|
}
|
|
} else if (fSwFull == TRUE) {
|
|
WCHAR StatusBuffer[0x100];
|
|
WCHAR HintBuffer[0x100];
|
|
|
|
if (Path != NULL)
|
|
MyPrintf(L"Directory %ws\r\n", Path);
|
|
ConvertGmtTimeToString(Find32->ftLastWriteTime, TimeBuf1);
|
|
MyPrintf(
|
|
L"LFN: %s\r\n"
|
|
L"SFN: %s\r\n"
|
|
L"Attr: 0x%x\r\n"
|
|
L"Size: 0x%x:0x%x\r\n"
|
|
L"LastWriteTime: %ws\r\n",
|
|
Find32->cFileName,
|
|
Find32->cAlternateFileName,
|
|
Find32->dwFileAttributes,
|
|
Find32->nFileSizeHigh, Find32->nFileSizeLow,
|
|
TimeBuf1);
|
|
|
|
if (OrgTime) {
|
|
ConvertGmtTimeToString(*OrgTime, TimeBuf1);
|
|
MyPrintf(L"ORGTime: %ws\r\n", TimeBuf1);
|
|
}
|
|
StatusBuffer[0] = L'\0';
|
|
HintBuffer[0] = L'\0';
|
|
if (Path == NULL) {
|
|
ShareStatusToEnglish(Status, StatusBuffer);
|
|
HintsToEnglish(HintFlags, HintBuffer);
|
|
} else {
|
|
if (LooksToBeAShare(Path) == TRUE)
|
|
ShareStatusToEnglish(Status, StatusBuffer);
|
|
else
|
|
FileStatusToEnglish(Status, StatusBuffer);
|
|
HintsToEnglish(HintFlags, HintBuffer);
|
|
}
|
|
MyPrintf(
|
|
L"Status: 0x%x %ws\r\n"
|
|
L"PinCount: %d\r\n"
|
|
L"HintFlags: 0x%x %ws\r\n\r\n",
|
|
Status,
|
|
StatusBuffer,
|
|
PinCount,
|
|
HintFlags,
|
|
HintBuffer);
|
|
} else {
|
|
if (Path == NULL) {
|
|
MyPrintf(L"%ws\r\n", Find32->cFileName);
|
|
} else {
|
|
MyPrintf(L"%ws\\%ws\r\n", Path, Find32->cFileName);
|
|
}
|
|
MyPrintf(L" Attr=0x%x Size=0x%x:0x%x Status=0x%x PinCount=%d HintFlags=0x%x\r\n",
|
|
Find32->dwFileAttributes,
|
|
Find32->nFileSizeHigh, Find32->nFileSizeLow,
|
|
Status,
|
|
PinCount,
|
|
HintFlags);
|
|
ConvertGmtTimeToString(Find32->ftLastWriteTime, TimeBuf1);
|
|
if (OrgTime)
|
|
ConvertGmtTimeToString(*OrgTime, TimeBuf2);
|
|
else
|
|
wcscpy(TimeBuf2, L"<none>");
|
|
MyPrintf(L" LastWriteTime: %ws OrgTime: %ws\r\n",
|
|
TimeBuf1,
|
|
TimeBuf2);
|
|
MyPrintf(L"\r\n");
|
|
}
|
|
}
|
|
|
|
DWORD
|
|
CmdEnum(
|
|
PWSTR EnumArg)
|
|
{
|
|
HANDLE hFind;
|
|
DWORD Error = ERROR_SUCCESS;
|
|
DWORD Status = 0;
|
|
DWORD PinCount = 0;
|
|
DWORD HintFlags = 0;
|
|
FILETIME ftOrgTime = {0};
|
|
WIN32_FIND_DATAW sFind32 = {0};
|
|
WCHAR FullPath[MAX_PATH];
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdEnum(%ws)\r\n", EnumArg);
|
|
|
|
hFind = CSCFindFirstFileW(EnumArg, &sFind32, &Status, &PinCount, &HintFlags, &ftOrgTime);
|
|
if (hFind == INVALID_HANDLE_VALUE) {
|
|
Error = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
DumpCscEntryInfo(EnumArg, &sFind32, Status, PinCount, HintFlags, &ftOrgTime);
|
|
if (fSwRecurse == TRUE && (sFind32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
|
if (EnumArg != NULL) {
|
|
wcscpy(FullPath, EnumArg);
|
|
wcscat(FullPath, L"\\");
|
|
} else {
|
|
wcscpy(FullPath, L"");
|
|
}
|
|
wcscat(FullPath, sFind32.cFileName);
|
|
CmdEnum(FullPath);
|
|
}
|
|
while (CSCFindNextFileW(hFind, &sFind32, &Status, &PinCount, &HintFlags, &ftOrgTime)) {
|
|
DumpCscEntryInfo(EnumArg, &sFind32, Status, PinCount, HintFlags, &ftOrgTime);
|
|
if (fSwRecurse == TRUE && (sFind32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
|
if (EnumArg != NULL) {
|
|
wcscpy(FullPath, EnumArg);
|
|
wcscat(FullPath, L"\\");
|
|
} else {
|
|
wcscpy(FullPath, L"");
|
|
}
|
|
wcscat(FullPath, sFind32.cFileName);
|
|
CmdEnum(FullPath);
|
|
}
|
|
}
|
|
CSCFindClose(hFind);
|
|
|
|
AllDone:
|
|
return (Error);
|
|
}
|
|
|
|
DWORD
|
|
CmdEnumForStats(
|
|
PWSTR EnumForStatsArg)
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
DWORD EnumForStatsType = 0;
|
|
BOOL fRet;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdEnumForStats()\r\n");
|
|
|
|
fRet = CSCEnumForStatsW(EnumForStatsArg, MyEnumForStatsProcW, EnumForStatsType);
|
|
if (fRet == FALSE) {
|
|
Error = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
AllDone:
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdEnumForStats exit %d\r\n", Error);
|
|
|
|
return Error;
|
|
}
|
|
|
|
DWORD
|
|
CmdDelete(
|
|
PWSTR DeleteArg)
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
DWORD Status = 0;
|
|
DWORD PinCount = 0;
|
|
DWORD HintFlags = 0;
|
|
FILETIME ftOrgTime = {0};
|
|
BOOL fResult;
|
|
HANDLE hFind;
|
|
WIN32_FIND_DATAW sFind32 = {0};
|
|
WCHAR FullPath[MAX_PATH];
|
|
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdDelete(%ws)\r\n", DeleteArg);
|
|
|
|
//
|
|
// Non-recursive delete
|
|
//
|
|
if (fSwRecurse == FALSE) {
|
|
fResult = CSCDeleteW(DeleteArg);
|
|
if (fResult == FALSE)
|
|
Error = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
//
|
|
// Delete recursively, using eumeration
|
|
//
|
|
hFind = CSCFindFirstFileW(DeleteArg, &sFind32, &Status, &PinCount, &HintFlags, &ftOrgTime);
|
|
if (hFind == INVALID_HANDLE_VALUE) {
|
|
Error = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
if (DeleteArg != NULL) {
|
|
wcscpy(FullPath, DeleteArg);
|
|
wcscat(FullPath, L"\\");
|
|
} else {
|
|
wcscpy(FullPath, L"");
|
|
}
|
|
wcscat(FullPath, sFind32.cFileName);
|
|
if (sFind32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
CmdDelete(FullPath);
|
|
MyPrintf(L"CSCDeleteW(%ws) -> %d\r\n", FullPath, CSCDeleteW(FullPath));
|
|
while (CSCFindNextFileW(hFind, &sFind32, &Status, &PinCount, &HintFlags, &ftOrgTime)) {
|
|
if (DeleteArg != NULL) {
|
|
wcscpy(FullPath, DeleteArg);
|
|
wcscat(FullPath, L"\\");
|
|
} else {
|
|
wcscpy(FullPath, L"");
|
|
}
|
|
wcscat(FullPath, sFind32.cFileName);
|
|
if (sFind32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
CmdDelete(FullPath);
|
|
MyPrintf(L"CSCDeleteW(%ws) -> %d\r\n", FullPath, CSCDeleteW(FullPath));
|
|
}
|
|
CSCFindClose(hFind);
|
|
|
|
AllDone:
|
|
return (Error);
|
|
}
|
|
|
|
DWORD
|
|
CmdDeleteShadow(
|
|
PWSTR DeleteShadowArg)
|
|
{
|
|
HSHADOW hDir;
|
|
HSHADOW hShadow;
|
|
SHADOWINFO sSI;
|
|
BOOL bResult;
|
|
HANDLE hDBShadow = INVALID_HANDLE_VALUE;
|
|
ULONG junk;
|
|
ULONG Status = 0;
|
|
ULONG hShare;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdDeleteShadow(%ws)\r\n", DeleteShadowArg);
|
|
|
|
hDBShadow = CreateFile(
|
|
L"\\\\.\\shadow",
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
|
|
if (hDBShadow == INVALID_HANDLE_VALUE) {
|
|
MyPrintf(L"CmdDeleteShadow:Failed open of shadow device\r\n");
|
|
Status = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
swscanf(DeleteShadowArg, L"0x%x:0x%x", &hDir, &hShadow);
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdDeleteShadow: hDir:0x%x hShadow:0x%x\r\n", hDir, hShadow);
|
|
|
|
memset(&sSI, 0, sizeof(SHADOWINFO));
|
|
sSI.hDir = hDir;
|
|
sSI.hShadow = hShadow;
|
|
|
|
bResult = DeviceIoControl(
|
|
hDBShadow, // device
|
|
IOCTL_SHADOW_DELETE, // control code
|
|
(LPVOID)&sSI, // in buffer
|
|
0, // inbuffer size
|
|
NULL, // out buffer
|
|
0, // out buffer size
|
|
&junk, // bytes returned
|
|
NULL); // overlapped
|
|
|
|
if (!bResult) {
|
|
MyPrintf(
|
|
L"CmdDeleteShadow:DeviceIoControl IOCTL_SHADOW_DELETE failed 0x%x\n",
|
|
sSI.dwError);
|
|
Status = sSI.dwError;
|
|
goto AllDone;
|
|
}
|
|
|
|
AllDone:
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdDeleteShadow exit %d\r\n", Status);
|
|
|
|
if (hDBShadow != INVALID_HANDLE_VALUE)
|
|
CloseHandle(hDBShadow);
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
CmdPinUnPin(
|
|
BOOL fPin,
|
|
PWSTR PinArg)
|
|
{
|
|
BOOL fRet;
|
|
HANDLE hFind;
|
|
DWORD Error = ERROR_SUCCESS;
|
|
DWORD Status = 0;
|
|
DWORD PinCount = 0;
|
|
DWORD HintFlags = 0;
|
|
FILETIME ftOrgTime = {0};
|
|
WIN32_FIND_DATAW sFind32 = {0};
|
|
WCHAR FullPath[MAX_PATH];
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdPinUnPin(%d,%ws)\r\n", fPin, PinArg);
|
|
|
|
if (fSwUser == TRUE && fSwSystem == TRUE) {
|
|
MyPrintf(L"Can not use both /SYSTEM and /USER\r\n");
|
|
goto AllDone;
|
|
}
|
|
|
|
if (fSwUser == TRUE) {
|
|
if (fSwInherit == TRUE)
|
|
HintFlags |= FLAG_CSC_HINT_PIN_INHERIT_USER;
|
|
else
|
|
HintFlags |= FLAG_CSC_HINT_PIN_USER;
|
|
}
|
|
if (fSwSystem == TRUE) {
|
|
if (fSwInherit == TRUE)
|
|
HintFlags |= FLAG_CSC_HINT_PIN_INHERIT_SYSTEM;
|
|
else
|
|
HintFlags |= FLAG_CSC_HINT_PIN_SYSTEM;
|
|
}
|
|
|
|
if (fSwRecurse == TRUE && fPin == TRUE) {
|
|
MyPrintf(L"Can not pin recursively.\r\n");
|
|
goto AllDone;
|
|
}
|
|
//
|
|
// Pin/Unpin one file
|
|
//
|
|
if (fSwRecurse == FALSE) {
|
|
if (fPin == TRUE) {
|
|
fRet = CSCPinFileW(PinArg, HintFlags, &Status, &PinCount, &HintFlags);
|
|
} else {
|
|
fRet = CSCUnpinFileW(PinArg, HintFlags, &Status, &PinCount, &HintFlags);
|
|
}
|
|
|
|
if (fRet == FALSE) {
|
|
Error = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
MyPrintf(
|
|
L"%ws of %ws:\r\n"
|
|
L"Status: 0x%x\r\n"
|
|
L"PinCount: %d\r\n"
|
|
L"HintFlags: 0x%x\r\n",
|
|
fPin ? L"Pin" : L"Unpin",
|
|
PinArg,
|
|
Status,
|
|
PinCount,
|
|
HintFlags);
|
|
|
|
goto AllDone;
|
|
}
|
|
//
|
|
// Unpin recursively, using eumeration
|
|
//
|
|
hFind = CSCFindFirstFileW(PinArg, &sFind32, &Status, &PinCount, &HintFlags, &ftOrgTime);
|
|
if (hFind == INVALID_HANDLE_VALUE) {
|
|
Error = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
if (PinArg != NULL) {
|
|
wcscpy(FullPath, PinArg);
|
|
wcscat(FullPath, L"\\");
|
|
} else {
|
|
wcscpy(FullPath, L"");
|
|
}
|
|
wcscat(FullPath, sFind32.cFileName);
|
|
if (sFind32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
CmdPinUnPin(fPin, FullPath);
|
|
fRet = CSCUnpinFileW(FullPath, HintFlags, &Status, &PinCount, &HintFlags);
|
|
MyPrintf(L"CSCUnpinFile(%ws) -> %d\r\n", FullPath, fRet);
|
|
while (CSCFindNextFileW(hFind, &sFind32, &Status, &PinCount, &HintFlags, &ftOrgTime)) {
|
|
if (PinArg != NULL) {
|
|
wcscpy(FullPath, PinArg);
|
|
wcscat(FullPath, L"\\");
|
|
} else {
|
|
wcscpy(FullPath, L"");
|
|
}
|
|
wcscat(FullPath, sFind32.cFileName);
|
|
if (sFind32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
CmdPinUnPin(fPin, FullPath);
|
|
fRet = CSCUnpinFileW(FullPath, HintFlags, &Status, &PinCount, &HintFlags);
|
|
MyPrintf(L"CSCUnpinFile(%ws) -> %d\r\n", FullPath, fRet);
|
|
}
|
|
CSCFindClose(hFind);
|
|
|
|
AllDone:
|
|
|
|
return Error;
|
|
}
|
|
|
|
DWORD
|
|
MyCscMergeProcW(
|
|
LPCWSTR lpszFullPath,
|
|
DWORD dwStatus,
|
|
DWORD dwHintFlags,
|
|
DWORD dwPinCount,
|
|
WIN32_FIND_DATAW *lpFind32,
|
|
DWORD dwReason,
|
|
DWORD dwParam1,
|
|
DWORD dwParam2,
|
|
DWORD_PTR dwContext)
|
|
{
|
|
if (dwReason == CSCPROC_REASON_BEGIN || dwReason == CSCPROC_REASON_MORE_DATA) {
|
|
if (dwReason == CSCPROC_REASON_BEGIN) {
|
|
MyPrintf( L"BEGIN[%ws][%d/%d]",
|
|
(lpszFullPath) ? lpszFullPath : L"None",
|
|
dwParam1,
|
|
dwParam2);
|
|
} else if (dwReason == CSCPROC_REASON_MORE_DATA) {
|
|
MyPrintf( L"MORE_DATA[%ws][%d/%d]",
|
|
(lpszFullPath) ? lpszFullPath : L"None",
|
|
dwParam1,
|
|
dwParam2);
|
|
}
|
|
if (fSwAbort) {
|
|
MyPrintf(L":Abort\r\n");
|
|
return CSCPROC_RETURN_ABORT;
|
|
} else if (fSwSkip) {
|
|
MyPrintf(L":Skip\r\n");
|
|
return CSCPROC_RETURN_SKIP;
|
|
} else if (fSwRetry) {
|
|
MyPrintf(L"Retry\r\n");
|
|
return CSCPROC_RETURN_RETRY;
|
|
} else if (fSwAsk) {
|
|
MyPrintf(L" - (R)etry/(A)bort/(S)kip/(C)ontinue:");
|
|
return CscMergeFillAsk(lpszFullPath);
|
|
} else {
|
|
MyPrintf(L"Continue\r\n");
|
|
return (DWORD)dwContext;
|
|
}
|
|
}
|
|
|
|
MyPrintf( L"END[%ws]:", (lpszFullPath) ? lpszFullPath : L"None");
|
|
if (dwParam2 == ERROR_SUCCESS) {
|
|
MyPrintf(L"SUCCEEDED\r\n");
|
|
} else {
|
|
MyPrintf(L"ERROR=%d \r\n", dwParam2);
|
|
}
|
|
return (DWORD)dwContext;
|
|
}
|
|
|
|
DWORD
|
|
MyCscFillProcW(
|
|
LPCWSTR lpszFullPath,
|
|
DWORD dwStatus,
|
|
DWORD dwHintFlags,
|
|
DWORD dwPinCount,
|
|
WIN32_FIND_DATAW *lpFind32,
|
|
DWORD dwReason,
|
|
DWORD dwParam1,
|
|
DWORD dwParam2,
|
|
DWORD_PTR dwContext)
|
|
{
|
|
if (dwReason == CSCPROC_REASON_BEGIN || dwReason == CSCPROC_REASON_MORE_DATA) {
|
|
if (dwReason == CSCPROC_REASON_BEGIN) {
|
|
MyPrintf( L"BEGIN[%ws][%d/%d]",
|
|
(lpszFullPath) ? lpszFullPath : L"None",
|
|
dwParam1,
|
|
dwParam2);
|
|
} else if (dwReason == CSCPROC_REASON_MORE_DATA) {
|
|
MyPrintf( L"MORE_DATA[%ws][%d/%d]",
|
|
(lpszFullPath) ? lpszFullPath : L"None",
|
|
dwParam1,
|
|
dwParam2);
|
|
}
|
|
if (fSwAbort) {
|
|
MyPrintf(L":Abort\r\n");
|
|
return CSCPROC_RETURN_ABORT;
|
|
} else if (fSwSkip) {
|
|
MyPrintf(L":Skip\r\n");
|
|
return CSCPROC_RETURN_SKIP;
|
|
} else if (fSwRetry) {
|
|
MyPrintf(L"Retry\r\n");
|
|
return CSCPROC_RETURN_RETRY;
|
|
} else if (fSwAsk) {
|
|
MyPrintf(L" - (R)etry/(A)bort/(S)kip/(C)ontinue:");
|
|
return CscMergeFillAsk(lpszFullPath);
|
|
} else {
|
|
MyPrintf(L"Continue\r\n");
|
|
return (DWORD)dwContext;
|
|
}
|
|
}
|
|
|
|
MyPrintf( L"END[%ws]:", (lpszFullPath) ? lpszFullPath : L"None");
|
|
if (dwParam2 == ERROR_SUCCESS) {
|
|
MyPrintf(L"SUCCEEDED\r\n");
|
|
} else {
|
|
MyPrintf(L"ERROR=%d \r\n", dwParam2);
|
|
}
|
|
return (DWORD)dwContext;
|
|
}
|
|
|
|
DWORD
|
|
CscMergeFillAsk(LPCWSTR lpszFullPath)
|
|
{
|
|
WCHAR wch;
|
|
ULONG ulid;
|
|
LONG cnt;
|
|
WCHAR rgwch[256];
|
|
PWCHAR lpBuff = NULL;
|
|
|
|
do {
|
|
lpBuff = rgwch;
|
|
memset(rgwch, 0, sizeof(rgwch));
|
|
if (!fgetws(rgwch, sizeof(rgwch)/sizeof(WCHAR), stdin))
|
|
break;
|
|
// Chop leading blanks
|
|
if (lpBuff != NULL)
|
|
while (*lpBuff != L'\0' && *lpBuff == L' ')
|
|
lpBuff++;
|
|
|
|
cnt = swscanf(lpBuff, L"%c", &wch);
|
|
|
|
if (!cnt)
|
|
continue;
|
|
|
|
switch (wch) {
|
|
case L's': case L'S':
|
|
return CSCPROC_RETURN_SKIP;
|
|
case L'c': case L'C':
|
|
return CSCPROC_RETURN_CONTINUE;
|
|
case L'a': case L'A':
|
|
return CSCPROC_RETURN_ABORT;
|
|
case L'r': case L'R':
|
|
return CSCPROC_RETURN_RETRY;
|
|
}
|
|
} while (1);
|
|
|
|
return CSCPROC_RETURN_CONTINUE;
|
|
}
|
|
|
|
DWORD
|
|
MyEncryptDecryptProcW(
|
|
LPCWSTR lpszFullPath,
|
|
DWORD dwStatus,
|
|
DWORD dwHintFlags,
|
|
DWORD dwPinCount,
|
|
WIN32_FIND_DATAW *lpFind32,
|
|
DWORD dwReason,
|
|
DWORD dwParam1,
|
|
DWORD dwParam2,
|
|
DWORD_PTR dwContext)
|
|
{
|
|
if (dwReason == CSCPROC_REASON_BEGIN) {
|
|
return CSCPROC_RETURN_CONTINUE;
|
|
} else if (dwReason == CSCPROC_REASON_MORE_DATA) {
|
|
MyPrintf(L"%ws\r\n", (lpszFullPath != NULL) ? lpszFullPath : L"None");
|
|
return CSCPROC_RETURN_CONTINUE;
|
|
}
|
|
//
|
|
// CSC_PROC_END
|
|
//
|
|
if (dwParam2 == ERROR_SUCCESS) {
|
|
MyPrintf(L"Succeeded\r\n");
|
|
} else {
|
|
MyPrintf(L"Error=%d \r\n", dwParam2);
|
|
}
|
|
return CSCPROC_RETURN_CONTINUE;
|
|
}
|
|
|
|
DWORD
|
|
MyEnumForStatsProcW(
|
|
LPCWSTR lpszFullPath,
|
|
DWORD dwStatus,
|
|
DWORD dwHintFlags,
|
|
DWORD dwPinCount,
|
|
WIN32_FIND_DATAW *lpFind32,
|
|
DWORD dwReason,
|
|
DWORD dwParam1,
|
|
DWORD dwParam2,
|
|
DWORD_PTR dwContext)
|
|
{
|
|
if (dwReason == CSCPROC_REASON_BEGIN) {
|
|
MyPrintf(L"(1)%ws ", (lpszFullPath != NULL) ? lpszFullPath : L"None");
|
|
if (lpFind32 != NULL)
|
|
MyPrintf(L"[%ws]\r\n", lpFind32->cFileName);
|
|
MyPrintf(L" Status=0x%02x HintFlags=0x%02x "
|
|
L"Pincount=%3d Reason=0x%x Param1=0x%x Param2=0x%x\r\n",
|
|
dwStatus,
|
|
dwHintFlags,
|
|
dwPinCount,
|
|
dwReason,
|
|
dwParam1,
|
|
dwParam2);
|
|
return CSCPROC_RETURN_CONTINUE;
|
|
} else if (dwReason == CSCPROC_REASON_MORE_DATA) {
|
|
MyPrintf(L"(2)%ws ", (lpszFullPath != NULL) ? lpszFullPath : L"None");
|
|
if (lpFind32 != NULL)
|
|
MyPrintf(L" %ws\r\n", lpFind32->cFileName);
|
|
MyPrintf(L" Status=0x%02x HintFlags=0x%02x "
|
|
L"Pincount=%3d Reason=0x%x Param1=0x%x Param2=0x%x\r\n",
|
|
dwStatus,
|
|
dwHintFlags,
|
|
dwPinCount,
|
|
dwReason,
|
|
dwParam1,
|
|
dwParam2);
|
|
return CSCPROC_RETURN_CONTINUE;
|
|
}
|
|
//
|
|
// CSC_PROC_END
|
|
//
|
|
MyPrintf(L"(3)%ws\r\n", (lpszFullPath != NULL) ? lpszFullPath : L"None");
|
|
if (dwParam2 == ERROR_SUCCESS) {
|
|
MyPrintf(L"Succeeded\r\n");
|
|
} else {
|
|
MyPrintf(L"Error=%d \r\n", dwParam2);
|
|
}
|
|
return CSCPROC_RETURN_CONTINUE;
|
|
}
|
|
|
|
struct {
|
|
DWORD ShareStatus;
|
|
LPWSTR ShareStatusName;
|
|
} ShareStatusStuff[] = {
|
|
{ FLAG_CSC_SHARE_STATUS_MODIFIED_OFFLINE, L"MODIFIED_OFFLINE " },
|
|
{ FLAG_CSC_SHARE_STATUS_CONNECTED, L"CONNECTED " },
|
|
{ FLAG_CSC_SHARE_STATUS_FILES_OPEN, L"FILES_OPEN " },
|
|
{ FLAG_CSC_SHARE_STATUS_FINDS_IN_PROGRESS, L"FINDS_IN_PROGRESS " },
|
|
{ FLAG_CSC_SHARE_STATUS_DISCONNECTED_OP, L"DISCONNECTED_OP " },
|
|
{ FLAG_CSC_SHARE_MERGING, L"MERGING " },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
DWORD
|
|
ShareStatusToEnglish(
|
|
DWORD Status,
|
|
LPWSTR OutputBuffer)
|
|
{
|
|
ULONG i;
|
|
|
|
OutputBuffer[0] = L'\0';
|
|
for (i = 0; ShareStatusStuff[i].ShareStatusName; i++) {
|
|
if (Status & ShareStatusStuff[i].ShareStatus)
|
|
wcscat(OutputBuffer, ShareStatusStuff[i].ShareStatusName);
|
|
}
|
|
if ((Status & FLAG_CSC_SHARE_STATUS_CACHING_MASK) == FLAG_CSC_SHARE_STATUS_MANUAL_REINT)
|
|
wcscat(OutputBuffer, L"MANUAL_REINT ");
|
|
else if ((Status & FLAG_CSC_SHARE_STATUS_CACHING_MASK) == FLAG_CSC_SHARE_STATUS_AUTO_REINT)
|
|
wcscat(OutputBuffer, L"AUTO_REINT ");
|
|
else if ((Status & FLAG_CSC_SHARE_STATUS_CACHING_MASK) == FLAG_CSC_SHARE_STATUS_VDO)
|
|
wcscat(OutputBuffer, L"VDO ");
|
|
else if ((Status & FLAG_CSC_SHARE_STATUS_CACHING_MASK) == FLAG_CSC_SHARE_STATUS_NO_CACHING)
|
|
wcscat(OutputBuffer, L"NO_CACHING ");
|
|
return 0;
|
|
}
|
|
|
|
struct {
|
|
DWORD FileStatus;
|
|
LPWSTR FileStatusName;
|
|
} FileStatusStuff[] = {
|
|
{ FLAG_CSC_COPY_STATUS_DATA_LOCALLY_MODIFIED, L"DATA_LOCALLY_MODIFIED " },
|
|
{ FLAG_CSC_COPY_STATUS_ATTRIB_LOCALLY_MODIFIED, L"ATTRIB_LOCALLY_MODIFIED " },
|
|
{ FLAG_CSC_COPY_STATUS_TIME_LOCALLY_MODIFIED, L"TIME_LOCALLY_MODIFIED " },
|
|
{ FLAG_CSC_COPY_STATUS_STALE, L"STALE " },
|
|
{ FLAG_CSC_COPY_STATUS_LOCALLY_DELETED, L"LOCALLY_DELETED " },
|
|
{ FLAG_CSC_COPY_STATUS_SPARSE, L"SPARSE " },
|
|
{ FLAG_CSC_COPY_STATUS_ORPHAN, L"ORPHAN " },
|
|
{ FLAG_CSC_COPY_STATUS_SUSPECT, L"SUSPECT " },
|
|
{ FLAG_CSC_COPY_STATUS_LOCALLY_CREATED, L"LOCALLY_CREATED " },
|
|
{ 0x00010000, L"USER_READ " },
|
|
{ 0x00020000, L"USER_WRITE " },
|
|
{ 0x00040000, L"GUEST_READ " },
|
|
{ 0x00080000, L"GUEST_WRITE " },
|
|
{ 0x00100000, L"OTHER_READ " },
|
|
{ 0x00200000, L"OTHER_WRITE " },
|
|
{ FLAG_CSC_COPY_STATUS_IS_FILE, L"IS_FILE " },
|
|
{ FLAG_CSC_COPY_STATUS_FILE_IN_USE, L"FILE_IN_USE " },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
DWORD
|
|
FileStatusToEnglish(
|
|
DWORD Status,
|
|
LPWSTR OutputBuffer)
|
|
{
|
|
ULONG i;
|
|
|
|
OutputBuffer[0] = L'\0';
|
|
for (i = 0; FileStatusStuff[i].FileStatusName; i++) {
|
|
if (Status & FileStatusStuff[i].FileStatus)
|
|
wcscat(OutputBuffer, FileStatusStuff[i].FileStatusName);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
struct {
|
|
DWORD HintFlag;
|
|
LPWSTR HintName;
|
|
} HintStuff[] = {
|
|
{ FLAG_CSC_HINT_PIN_USER, L"PIN_USER " },
|
|
{ FLAG_CSC_HINT_PIN_INHERIT_USER, L"PIN_INHERIT_USER " },
|
|
{ FLAG_CSC_HINT_PIN_INHERIT_SYSTEM, L"PIN_INHERIT_SYSTEM " },
|
|
{ FLAG_CSC_HINT_CONSERVE_BANDWIDTH, L"CONSERVE_BANDWIDTH " },
|
|
{ FLAG_CSC_HINT_PIN_SYSTEM, L"PIN_SYSTEM " },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
DWORD
|
|
HintsToEnglish(
|
|
DWORD Hint,
|
|
LPWSTR OutputBuffer)
|
|
{
|
|
ULONG i;
|
|
|
|
OutputBuffer[0] = L'\0';
|
|
for (i = 0; HintStuff[i].HintName; i++) {
|
|
if (Hint & HintStuff[i].HintFlag)
|
|
wcscat(OutputBuffer, HintStuff[i].HintName);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
BOOLEAN
|
|
LooksToBeAShare(LPWSTR Name)
|
|
{
|
|
//
|
|
// See if we have \\server\share or \\server\share\<something>
|
|
// Assume a valid name passed in...
|
|
//
|
|
|
|
ULONG Len = wcslen(Name);
|
|
ULONG i;
|
|
ULONG SlashCount = 0;
|
|
|
|
// Remove any trailing '\'s
|
|
while (Len >= 1) {
|
|
if (Name[Len-1] == L'\\') {
|
|
Name[Len-1] = L'\0';
|
|
Len--;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
for (i = 0; Name[i]; i++) {
|
|
if (Name[i] == L'\\')
|
|
SlashCount++;
|
|
}
|
|
if (SlashCount > 3)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD
|
|
CmdDisconnect(
|
|
PWSTR DisconnectArg)
|
|
{
|
|
HSHADOW hDir;
|
|
SHADOWINFO sSI;
|
|
BOOL bResult;
|
|
HANDLE hDBShadow = INVALID_HANDLE_VALUE;
|
|
ULONG junk;
|
|
ULONG Status = 0;
|
|
ULONG hShare;
|
|
PWCHAR wCp;
|
|
ULONG SlashCount = 0;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdDisconnect(%ws)\r\n", DisconnectArg);
|
|
|
|
GetFileAttributes(DisconnectArg);
|
|
|
|
Status = GetLastError();
|
|
if (Status != NO_ERROR)
|
|
goto AllDone;
|
|
|
|
SlashCount = 0;
|
|
for (wCp = DisconnectArg; *wCp; wCp++) {
|
|
if (*wCp == L'\\')
|
|
SlashCount++;
|
|
if (SlashCount == 3) {
|
|
*wCp = L'\0';
|
|
break;
|
|
}
|
|
}
|
|
|
|
hDBShadow = CreateFile(
|
|
L"\\\\.\\shadow",
|
|
FILE_EXECUTE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
|
|
if (hDBShadow == INVALID_HANDLE_VALUE) {
|
|
MyPrintf(L"CmdDisconnect:Failed open of shadow device\r\n");
|
|
Status = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
memset(&sSI, 0, sizeof(SHADOWINFO));
|
|
sSI.cbBufferSize = (wcslen(DisconnectArg)+1) * sizeof(WCHAR);
|
|
sSI.lpBuffer = DisconnectArg;
|
|
|
|
bResult = DeviceIoControl(
|
|
hDBShadow, // device
|
|
IOCTL_TAKE_SERVER_OFFLINE, // control code
|
|
(LPVOID)&sSI, // in buffer
|
|
0, // inbuffer size
|
|
NULL, // out buffer
|
|
0, // out buffer size
|
|
&junk, // bytes returned
|
|
NULL); // overlapped
|
|
|
|
if (!bResult) {
|
|
MyPrintf(L"CmdDisconnect:DeviceIoControl IOCTL_TAKE_SERVER_OFFLINE failed\n");
|
|
Status = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
AllDone:
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdDisconnect exit %d\r\n", Status);
|
|
|
|
if (hDBShadow != INVALID_HANDLE_VALUE)
|
|
CloseHandle(hDBShadow);
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
CmdGetShadow(
|
|
PWSTR GetShadowArg)
|
|
{
|
|
DWORD Status = 0;
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
HANDLE hDBShadow = INVALID_HANDLE_VALUE;
|
|
HSHADOW hShadow = 0;
|
|
HSHADOW hDir = 0;
|
|
WIN32_FIND_DATAW sFind32 = {0};
|
|
SHADOWINFO sSI = {0};
|
|
PWCHAR wCp = NULL;
|
|
BOOL bResult = FALSE;
|
|
DWORD junk;
|
|
WCHAR TimeBuf1[40];
|
|
WCHAR TimeBuf2[40];
|
|
WCHAR TimeBuf3[40];
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdGetShadow(%ws)\r\n", GetShadowArg);
|
|
|
|
if (GetShadowArg == NULL) {
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto AllDone;
|
|
}
|
|
|
|
swscanf(GetShadowArg, L"%x:", &hDir);
|
|
for (wCp = GetShadowArg; *wCp && *wCp != L':'; wCp++)
|
|
;
|
|
if (*wCp != L':') {
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto AllDone;
|
|
}
|
|
wCp++;
|
|
if (wcslen(wCp) >= MAX_PATH) {
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto AllDone;
|
|
}
|
|
wcscpy(sFind32.cFileName, wCp);
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"hDir=0x%x cFileName=[%ws]\r\n", hDir, sFind32.cFileName);
|
|
|
|
hDBShadow = CreateFile(
|
|
L"\\\\.\\shadow",
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
|
|
if (hDBShadow == INVALID_HANDLE_VALUE) {
|
|
MyPrintf(L"CmdGetShadow:Failed open of shadow device\r\n");
|
|
dwErr = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
sSI.hDir = hDir;
|
|
sSI.lpFind32 = &sFind32;
|
|
|
|
bResult = DeviceIoControl(
|
|
hDBShadow, // device
|
|
IOCTL_GETSHADOW, // control code
|
|
(LPVOID)&sSI, // in buffer
|
|
0, // inbuffer size
|
|
NULL, // out buffer
|
|
0, // out buffer size
|
|
&junk, // bytes returned
|
|
NULL); // overlapped
|
|
|
|
if (!bResult) {
|
|
MyPrintf(L"CmdGetShadow:DeviceIoControl IOCTL_GETSHADOW failed\n");
|
|
dwErr = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
ConvertGmtTimeToString(sFind32.ftCreationTime, TimeBuf1);
|
|
ConvertGmtTimeToString(sFind32.ftLastAccessTime, TimeBuf2);
|
|
ConvertGmtTimeToString(sFind32.ftLastWriteTime, TimeBuf3);
|
|
|
|
MyPrintf(L"\r\n");
|
|
MyPrintf(L"%ws:\r\n"
|
|
L" Size=0x%x:0x%x Attr=0x%x\r\n"
|
|
L" CreationTime: %ws\r\n"
|
|
L" LastAccessTime: %ws\r\n"
|
|
L" LastWriteTime: %ws\r\n",
|
|
sFind32.cFileName,
|
|
sFind32.nFileSizeHigh,
|
|
sFind32.nFileSizeLow,
|
|
sFind32.dwFileAttributes,
|
|
TimeBuf1,
|
|
TimeBuf2,
|
|
TimeBuf3);
|
|
MyPrintf(L" hShare=0x%x hDir=0x%x hShadow=0x%x Status=0x%x HintFlags=0x%x\r\n",
|
|
sSI.hShare,
|
|
sSI.hDir,
|
|
sSI.hShadow,
|
|
sSI.uStatus,
|
|
sSI.ulHintFlags);
|
|
MyPrintf(L"\r\n");
|
|
|
|
AllDone:
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdGetShadowArg exit %d\r\n", Status);
|
|
|
|
if (hDBShadow != INVALID_HANDLE_VALUE)
|
|
CloseHandle(hDBShadow);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
CmdGetShadowInfo(
|
|
PWSTR GetShadowInfoArg)
|
|
{
|
|
DWORD Status = 0;
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
HANDLE hDBShadow = INVALID_HANDLE_VALUE;
|
|
HSHADOW hShadow = 0;
|
|
HSHADOW hDir = 0;
|
|
WIN32_FIND_DATAW sFind32 = {0};
|
|
SHADOWINFO sSI = {0};
|
|
BOOL bResult = FALSE;
|
|
DWORD junk;
|
|
WCHAR TimeBuf1[40];
|
|
WCHAR TimeBuf2[40];
|
|
WCHAR TimeBuf3[40];
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdGetShadowInfo(%ws)\r\n", GetShadowInfoArg);
|
|
|
|
if (GetShadowInfoArg == NULL) {
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto AllDone;
|
|
}
|
|
|
|
swscanf(GetShadowInfoArg, L"%x:%x", &hDir, &hShadow);
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"hDir=0x%x hShadow=0x%x\r\n", hDir, hShadow);
|
|
|
|
hDBShadow = CreateFile(
|
|
L"\\\\.\\shadow",
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
|
|
if (hDBShadow == INVALID_HANDLE_VALUE) {
|
|
MyPrintf(L"CmdGetShadowInfo:Failed open of shadow device\r\n");
|
|
dwErr = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
sSI.hDir = hDir;
|
|
sSI.hShadow = hShadow;
|
|
sSI.lpFind32 = &sFind32;
|
|
|
|
bResult = DeviceIoControl(
|
|
hDBShadow, // device
|
|
IOCTL_SHADOW_GET_SHADOW_INFO, // control code
|
|
(LPVOID)&sSI, // in buffer
|
|
0, // inbuffer size
|
|
NULL, // out buffer
|
|
0, // out buffer size
|
|
&junk, // bytes returned
|
|
NULL); // overlapped
|
|
|
|
if (!bResult) {
|
|
MyPrintf(L"CmdGetShadowInfo:DeviceIoControl IOCTL_SHADOW_GET_SHADOW_INFO failed\n");
|
|
dwErr = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
ConvertGmtTimeToString(sFind32.ftCreationTime, TimeBuf1);
|
|
ConvertGmtTimeToString(sFind32.ftLastAccessTime, TimeBuf2);
|
|
ConvertGmtTimeToString(sFind32.ftLastWriteTime, TimeBuf3);
|
|
|
|
MyPrintf(L"\r\n");
|
|
MyPrintf(L"%ws:\r\n"
|
|
L" Size=0x%x:0x%x Attr=0x%x\r\n"
|
|
L" CreationTime: %ws\r\n"
|
|
L" LastAccessTime: %ws\r\n"
|
|
L" LastWriteTime: %ws\r\n",
|
|
sFind32.cFileName,
|
|
sFind32.nFileSizeHigh,
|
|
sFind32.nFileSizeLow,
|
|
sFind32.dwFileAttributes,
|
|
TimeBuf1,
|
|
TimeBuf2,
|
|
TimeBuf3);
|
|
MyPrintf(L"\r\n");
|
|
|
|
AllDone:
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdGetShadowInfoArg exit %d\r\n", Status);
|
|
|
|
if (hDBShadow != INVALID_HANDLE_VALUE)
|
|
CloseHandle(hDBShadow);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
CmdShareId(
|
|
PWSTR ShareIdArg)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
ULONG ShareId = 0;
|
|
BOOL fRet;
|
|
WCHAR Buffer[100];
|
|
ULONG BufSize = sizeof(Buffer);
|
|
HMODULE hmodCscDll = LoadLibrary(TEXT("cscdll.dll"));
|
|
CSCSHAREIDTOSHARENAME pCSCShareIdToShareName = NULL;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdShareId(%ws)\r\n", ShareIdArg);
|
|
|
|
if (ShareIdArg == NULL) {
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto AllDone;
|
|
}
|
|
|
|
swscanf(ShareIdArg, L"%x", &ShareId);
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"ShareId=0x%x\r\n", ShareId);
|
|
|
|
if (hmodCscDll == NULL) {
|
|
dwErr = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
pCSCShareIdToShareName = (CSCSHAREIDTOSHARENAME) GetProcAddress(
|
|
hmodCscDll,
|
|
"CSCShareIdToShareName");
|
|
if (pCSCShareIdToShareName == NULL) {
|
|
dwErr = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
fRet = (pCSCShareIdToShareName)(ShareId, (PBYTE)Buffer, &BufSize);
|
|
if (fRet == FALSE) {
|
|
dwErr = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
MyPrintf(L"ShareId 0x%x = %ws\r\n", ShareId, Buffer);
|
|
|
|
AllDone:
|
|
|
|
if (hmodCscDll != NULL)
|
|
FreeLibrary(hmodCscDll);
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdShareIdToShareName exit %d\r\n", dwErr);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
CmdExclusionList(
|
|
PWSTR ExclusionListArg)
|
|
{
|
|
HSHADOW hDir;
|
|
SHADOWINFO sSI;
|
|
BOOL bResult;
|
|
HANDLE hDBShadow = INVALID_HANDLE_VALUE;
|
|
ULONG junk;
|
|
ULONG Status = 0;
|
|
ULONG hShare;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdExclusionList(%ws)\r\n", ExclusionListArg);
|
|
|
|
if (ExclusionListArg == NULL) {
|
|
ExclusionListArg = vtzDefaultExclusionList;
|
|
}
|
|
MyPrintf(L"Setting exclusion list to \"%ws\"\r\n", ExclusionListArg);
|
|
|
|
hDBShadow = CreateFile(
|
|
L"\\\\.\\shadow",
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
|
|
if (hDBShadow == INVALID_HANDLE_VALUE) {
|
|
MyPrintf(L"CmdExclusionList:Failed open of shadow device\r\n");
|
|
Status = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
memset(&sSI, 0, sizeof(SHADOWINFO));
|
|
sSI.uSubOperation = SHADOW_SET_EXCLUSION_LIST;
|
|
sSI.lpBuffer = ExclusionListArg;
|
|
sSI.cbBufferSize = (wcslen(ExclusionListArg)+1) * sizeof(WCHAR);
|
|
|
|
bResult = DeviceIoControl(
|
|
hDBShadow, // device
|
|
IOCTL_DO_SHADOW_MAINTENANCE, // control code
|
|
(LPVOID)&sSI, // in buffer
|
|
0, // inbuffer size
|
|
NULL, // out buffer
|
|
0, // out buffer size
|
|
&junk, // bytes returned
|
|
NULL); // overlapped
|
|
|
|
AllDone:
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdExclusionList exit %d\r\n", Status);
|
|
|
|
if (hDBShadow != INVALID_HANDLE_VALUE)
|
|
CloseHandle(hDBShadow);
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
CmdBWConservationList(
|
|
PWSTR BWConservationListArg)
|
|
{
|
|
HSHADOW hDir;
|
|
SHADOWINFO sSI;
|
|
BOOL bResult;
|
|
HANDLE hDBShadow = INVALID_HANDLE_VALUE;
|
|
ULONG junk;
|
|
ULONG Status = 0;
|
|
ULONG hShare;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdBWConservationList(%ws)\r\n", BWConservationListArg);
|
|
|
|
if (BWConservationListArg == NULL) {
|
|
BWConservationListArg = L" ";
|
|
}
|
|
|
|
MyPrintf(L"Setting BWConservation list to \"%ws\"\r\n", BWConservationListArg);
|
|
|
|
hDBShadow = CreateFile(
|
|
L"\\\\.\\shadow",
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
|
|
if (hDBShadow == INVALID_HANDLE_VALUE) {
|
|
MyPrintf(L"CmdBWConservationList:Failed open of shadow device\r\n");
|
|
Status = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
memset(&sSI, 0, sizeof(SHADOWINFO));
|
|
sSI.uSubOperation = SHADOW_SET_BW_CONSERVE_LIST;
|
|
sSI.lpBuffer = BWConservationListArg;
|
|
sSI.cbBufferSize = (wcslen(BWConservationListArg)+1) * sizeof(WCHAR);
|
|
|
|
bResult = DeviceIoControl(
|
|
hDBShadow, // device
|
|
IOCTL_DO_SHADOW_MAINTENANCE, // control code
|
|
(LPVOID)&sSI, // in buffer
|
|
0, // inbuffer size
|
|
NULL, // out buffer
|
|
0, // out buffer size
|
|
&junk, // bytes returned
|
|
NULL); // overlapped
|
|
|
|
AllDone:
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdBWConservationList exit %d\r\n", Status);
|
|
|
|
if (hDBShadow != INVALID_HANDLE_VALUE)
|
|
CloseHandle(hDBShadow);
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
CmdDetector(
|
|
VOID)
|
|
{
|
|
HSHADOW hDir;
|
|
SHADOWINFO sSI;
|
|
BOOL bResult;
|
|
HANDLE hDBShadow = INVALID_HANDLE_VALUE;
|
|
ULONG junk;
|
|
ULONG Status = ERROR_SUCCESS;
|
|
ULONG hShare;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdDetector()\r\n");
|
|
|
|
hDBShadow = CreateFile(
|
|
L"\\\\.\\shadow",
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
|
|
if (hDBShadow == INVALID_HANDLE_VALUE) {
|
|
MyPrintf(L"CmdDetector:Failed open of shadow device\r\n");
|
|
Status = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
memset(&sSI, 0, sizeof(SHADOWINFO));
|
|
sSI.uSubOperation = SHADOW_SPARSE_STALE_DETECTION_COUNTER;
|
|
|
|
bResult = DeviceIoControl(
|
|
hDBShadow, // device
|
|
IOCTL_DO_SHADOW_MAINTENANCE, // control code
|
|
(LPVOID)&sSI, // in buffer
|
|
0, // inbuffer size
|
|
NULL, // out buffer
|
|
0, // out buffer size
|
|
&junk, // bytes returned
|
|
NULL); // overlapped
|
|
|
|
if (bResult)
|
|
MyPrintf(L"%d\r\n", sSI.dwError);
|
|
else
|
|
Status = sSI.dwError;
|
|
|
|
AllDone:
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdDetector exit %d\r\n", Status);
|
|
|
|
if (hDBShadow != INVALID_HANDLE_VALUE)
|
|
CloseHandle(hDBShadow);
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
CmdSwitches(
|
|
VOID)
|
|
{
|
|
HSHADOW hDir;
|
|
SHADOWINFO sSI;
|
|
BOOL bResult;
|
|
HANDLE hDBShadow = INVALID_HANDLE_VALUE;
|
|
ULONG junk;
|
|
ULONG Status = ERROR_SUCCESS;
|
|
ULONG hShare;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdSwitches()\r\n");
|
|
|
|
hDBShadow = CreateFile(
|
|
L"\\\\.\\shadow",
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
|
|
if (hDBShadow == INVALID_HANDLE_VALUE) {
|
|
MyPrintf(L"CmdSwitches:Failed open of shadow device\r\n");
|
|
Status = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
memset(&sSI, 0, sizeof(SHADOWINFO));
|
|
sSI.uOp = SHADOW_SWITCH_GET_STATE;
|
|
|
|
bResult = DeviceIoControl(
|
|
hDBShadow, // device
|
|
IOCTL_SWITCHES, // control code
|
|
(LPVOID)&sSI, // in buffer
|
|
0, // inbuffer size
|
|
NULL, // out buffer
|
|
0, // out buffer size
|
|
&junk, // bytes returned
|
|
NULL); // overlapped
|
|
|
|
if (bResult) {
|
|
MyPrintf(L"0x%08x", sSI.uStatus);
|
|
if (sSI.uStatus != 0) {
|
|
MyPrintf(L" (");
|
|
if (sSI.uStatus & SHADOW_SWITCH_SHADOWING)
|
|
MyPrintf(L"SHADOW_SWITCH_SHADOWING ");
|
|
if (sSI.uStatus & SHADOW_SWITCH_LOGGING)
|
|
MyPrintf(L"SHADOW_SWITCH_LOGGING ");
|
|
if (sSI.uStatus & SHADOW_SWITCH_SPEAD_OPTIMIZE)
|
|
MyPrintf(L"SHADOW_SWITCH_SPEAD_OPTIMIZE ");
|
|
MyPrintf(L")");
|
|
}
|
|
if ((sSI.uStatus & SHADOW_SWITCH_SHADOWING) == 0)
|
|
MyPrintf(L" ... csc is disabled");
|
|
else
|
|
MyPrintf(L" ... csc is enabled");
|
|
MyPrintf(L"\r\n");
|
|
} else {
|
|
Status = sSI.dwError;
|
|
}
|
|
|
|
AllDone:
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdSwitches exit %d\r\n", Status);
|
|
|
|
if (hDBShadow != INVALID_HANDLE_VALUE)
|
|
CloseHandle(hDBShadow);
|
|
|
|
return Status;
|
|
}
|
|
|
|
DWORD
|
|
CmdGetSpace(
|
|
VOID)
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
WCHAR szVolume[MAX_PATH];
|
|
LARGE_INTEGER MaxSpace;
|
|
LARGE_INTEGER CurrentSpace;
|
|
DWORD TotalFiles;
|
|
DWORD TotalDirs;
|
|
BOOL fRet;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdGetSpace()\r\n");
|
|
|
|
fRet = CSCGetSpaceUsageW(
|
|
szVolume,
|
|
sizeof(szVolume)/sizeof(WCHAR),
|
|
&MaxSpace.HighPart,
|
|
&MaxSpace.LowPart,
|
|
&CurrentSpace.HighPart,
|
|
&CurrentSpace.LowPart,
|
|
&TotalFiles,
|
|
&TotalDirs);
|
|
|
|
if (fRet == FALSE) {
|
|
Error = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
MyPrintf(
|
|
L"Volume: %ws\r\n"
|
|
L"MaxSpace: 0x%x:0x%x (%d)\r\n"
|
|
L"CurrentSpace: 0x%x:0x%x (%d)\r\n"
|
|
L"TotalFiles: %d\r\n"
|
|
L"TotalDirs: %d\r\n",
|
|
szVolume,
|
|
MaxSpace.HighPart,
|
|
MaxSpace.LowPart,
|
|
MaxSpace.LowPart,
|
|
CurrentSpace.HighPart,
|
|
CurrentSpace.LowPart,
|
|
CurrentSpace.LowPart,
|
|
TotalFiles,
|
|
TotalDirs);
|
|
|
|
AllDone:
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdGetSpace exit %d\r\n", Error);
|
|
|
|
return Error;
|
|
}
|
|
|
|
DWORD
|
|
CmdIsServerOffline(
|
|
PWSTR IsServerOfflineArg)
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
BOOL fRet;
|
|
BOOL fOffline = FALSE;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdIsServerOffline(%ws)\r\n", IsServerOfflineArg);
|
|
|
|
fRet = CSCIsServerOfflineW(
|
|
IsServerOfflineArg,
|
|
&fOffline);
|
|
|
|
if (fRet == FALSE) {
|
|
Error = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
if (fOffline == TRUE)
|
|
MyPrintf(L"Offline\r\n");
|
|
else
|
|
MyPrintf(L"Online\r\n");
|
|
|
|
AllDone:
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdIsServerOffline exit %d\r\n", Error);
|
|
|
|
return Error;
|
|
}
|
|
|
|
DWORD
|
|
CmdSetShareStatus(
|
|
PWSTR SetShareStatusArg)
|
|
{
|
|
HSHADOW hDir;
|
|
SHADOWINFO sSI;
|
|
BOOL bResult;
|
|
HANDLE hDBShadow = INVALID_HANDLE_VALUE;
|
|
ULONG junk;
|
|
ULONG Status = 0;
|
|
ULONG StatusToSet = 0;
|
|
ULONG hShare = 0;
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdSetShareStatus(%ws)\r\n", SetShareStatusArg);
|
|
|
|
if (fSwSet == TRUE && fSwClear == TRUE) {
|
|
MyPrintf(L"Can't have both SET and CLEAR\r\n");
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
goto AllDone;
|
|
}
|
|
|
|
hDBShadow = CreateFile(
|
|
L"\\\\.\\shadow",
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
|
|
if (hDBShadow == INVALID_HANDLE_VALUE) {
|
|
MyPrintf(L"CmdSetShareStatus:Failed open of shadow device\r\n");
|
|
Status = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
swscanf(SetShareStatusArg, L"%x:%x", &hShare, &StatusToSet);
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdSetShareStatus hShare=0x%x StatusToSet=0x%x\r\n", hShare, StatusToSet);
|
|
|
|
memset(&sSI, 0, sizeof(SHADOWINFO));
|
|
sSI.hShare = hShare;
|
|
if (fSwSet == TRUE) {
|
|
sSI.uStatus = StatusToSet;
|
|
sSI.uOp = SHADOW_FLAGS_OR;
|
|
} else if (fSwClear == TRUE) {
|
|
sSI.uStatus = ~StatusToSet;
|
|
sSI.uOp = SHADOW_FLAGS_AND;
|
|
} else {
|
|
MyPrintf(L"Missing /SET or /CLEAR\r\n");
|
|
Status = ERROR_INVALID_PARAMETER;
|
|
goto AllDone;
|
|
}
|
|
|
|
bResult = DeviceIoControl(
|
|
hDBShadow, // device
|
|
IOCTL_SET_SHARE_STATUS, // control code
|
|
(LPVOID)&sSI, // in buffer
|
|
0, // inbuffer size
|
|
NULL, // out buffer
|
|
0, // out buffer size
|
|
&junk, // bytes returned
|
|
NULL); // overlapped
|
|
|
|
if (!bResult) {
|
|
MyPrintf(L"CmdSetShareStatus:DeviceIoControl IOCTL_SET_SHARE_STATUS failed\n");
|
|
Status = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
|
|
AllDone:
|
|
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdSetShareStatus exit %d\r\n", Status);
|
|
|
|
if (hDBShadow != INVALID_HANDLE_VALUE)
|
|
CloseHandle(hDBShadow);
|
|
|
|
return Status;
|
|
}
|
|
|
|
#define MAX_OFFSETS 256
|
|
#define PAGESIZE 4096
|
|
ULONG OffsetArgs[MAX_OFFSETS];
|
|
|
|
DWORD
|
|
CmdRandW(
|
|
PWSTR CmdRandWArg)
|
|
{
|
|
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
DWORD dwFileSize;
|
|
DWORD dwOffset;
|
|
DWORD dwOffsetHigh;
|
|
UCHAR uchData;
|
|
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
ULONG i;
|
|
LONG WriteCount = 0;
|
|
LONG PageCount = 0;
|
|
PBYTE wArray = NULL;
|
|
|
|
if (fSwDebug == TRUE) {
|
|
MyPrintf(L"CmdRandW(%ws)\r\n", CmdRandWArg);
|
|
if (fArgOffset == TRUE)
|
|
MyPrintf(L" OFFSET [%ws]\r\n", pwszOffsetArg);
|
|
}
|
|
|
|
srand( (unsigned)time( NULL ) );
|
|
|
|
hFile = CreateFileW(
|
|
CmdRandWArg, // name
|
|
GENERIC_READ|GENERIC_WRITE, // access mode
|
|
FILE_SHARE_READ|FILE_SHARE_WRITE, // share mode
|
|
NULL, // security descriptor
|
|
OPEN_EXISTING, // create disposition
|
|
0, // file statributes if created
|
|
NULL); // template handle
|
|
if (hFile == INVALID_HANDLE_VALUE) {
|
|
dwError = GetLastError();
|
|
goto AllDone;
|
|
}
|
|
dwFileSize = GetFileSize(hFile, NULL);
|
|
MyPrintf(L"File size = %d bytes\r\n", dwFileSize);
|
|
|
|
if (fArgOffset == TRUE) {
|
|
WriteCount = CountOffsetArgs(pwszOffsetArg, OffsetArgs);
|
|
if (WriteCount == 0) {
|
|
MyPrintf(L"No offsets specified, or - nothing to do.\r\n");
|
|
goto AllDone;
|
|
} else if (WriteCount < 0) {
|
|
MyPrintf(L"Error in offset list. Exiting.\r\n");
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
goto AllDone;
|
|
}
|
|
} else {
|
|
PageCount = (dwFileSize / PAGESIZE);
|
|
WriteCount = rand() % PageCount;
|
|
}
|
|
if (fSwDebug == TRUE) {
|
|
wArray = calloc(1, PageCount * sizeof(BYTE));
|
|
MyPrintf(L"There are %d pages in the file\r\n", PageCount);
|
|
}
|
|
|
|
if (dwFileSize == -1) {
|
|
dwError = GetLastError();
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"GetFileSize() failed %d\r\n", dwError);
|
|
goto AllDone;
|
|
}
|
|
if (dwFileSize == 0) {
|
|
MyPrintf(L"0 sized file - nothing to do.\r\n");
|
|
goto AllDone;
|
|
}
|
|
MyPrintf(L"Writing %d times\r\n", WriteCount);
|
|
for (i = 0; i < (ULONG)WriteCount; ++i) {
|
|
DWORD dwReturn;
|
|
|
|
if (fArgOffset == TRUE)
|
|
dwOffset = OffsetArgs[i];
|
|
else
|
|
dwOffset = ((rand() % PageCount) * PAGESIZE) + (rand() % PAGESIZE);
|
|
uchData = (UCHAR)rand();
|
|
if (SetFilePointer(hFile, dwOffset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
|
|
dwError = GetLastError();
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"SetFilePointer() failed %d\r\n", dwError);
|
|
goto AllDone;
|
|
}
|
|
MyPrintf(L"writing 0x02%x Page %d offset %d (offset %d(0x%x))\r\n", uchData,
|
|
dwOffset / PAGESIZE,
|
|
dwOffset % PAGESIZE,
|
|
dwOffset,
|
|
dwOffset);
|
|
if (wArray)
|
|
wArray[dwOffset/PAGESIZE]++;
|
|
if (!WriteFile(hFile, &uchData, 1, &dwReturn, NULL)) {
|
|
dwError = GetLastError();
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"WriteFile() failed %d\r\n", dwError);
|
|
goto AllDone;
|
|
}
|
|
}
|
|
|
|
if (wArray) {
|
|
for (i = 0; i < (ULONG)PageCount; i++) {
|
|
MyPrintf(L"%d", wArray[i]);
|
|
if ((i % 50) == 0)
|
|
MyPrintf(L"\r\n");
|
|
}
|
|
MyPrintf(L"\r\n");
|
|
}
|
|
|
|
// If EOF is specified, truncate the file to a random length
|
|
if (fSwEof == TRUE) {
|
|
ULONG xx = rand() % 5;
|
|
ULONG NewLen = (rand() * rand()) % (dwFileSize * 2);
|
|
if (xx == 0 || xx == 1) {
|
|
MyPrintf(L"New EOF = %d\r\n", NewLen);
|
|
SetFilePointer(hFile, NewLen, 0, FILE_BEGIN);
|
|
SetEndOfFile(hFile);
|
|
} else {
|
|
MyPrintf(L"No EOF change.\r\n");
|
|
}
|
|
}
|
|
|
|
AllDone:
|
|
if (hFile != INVALID_HANDLE_VALUE)
|
|
CloseHandle(hFile);
|
|
if (wArray)
|
|
free(wArray);
|
|
if (fSwDebug == TRUE)
|
|
MyPrintf(L"CmdRandW exit %d\r\n", dwError);
|
|
return dwError;
|
|
}
|
|
|
|
|
|
|
|
|
|
LONG
|
|
CountOffsetArgs(
|
|
PWSTR OffsetArg,
|
|
ULONG OffsetArray[])
|
|
{
|
|
// Expect a string of the form "N,N,N,N" where each N can be hex OR decimal.
|
|
// Store results in OffsetArray[]
|
|
// Limit is MAX_OFFSETS offsets, to make things easy.
|
|
|
|
ULONG i;
|
|
PWCHAR wCp = OffsetArg;
|
|
PWCHAR wNum = NULL;
|
|
ULONG iRet;
|
|
|
|
for (i = 0; i < MAX_OFFSETS; i++) {
|
|
if (*wCp == L'\0')
|
|
break;
|
|
wNum = wCp;
|
|
while (*wCp != L',' && *wCp != L'\0')
|
|
wCp++;
|
|
if (*wCp == L',')
|
|
*wCp++ = L'\0';
|
|
iRet = swscanf(wNum, L"%Li", &OffsetArray[i]);
|
|
if (iRet <= 0)
|
|
return -1;
|
|
}
|
|
if (fSwDebug == TRUE) {
|
|
ULONG j;
|
|
for (j = 0; j < i; j++)
|
|
MyPrintf(L"[%d]-0x%x(%d)\r\n", j, OffsetArray[j], OffsetArray[j]);
|
|
MyPrintf(L"CountOffsetArgs returning %d\r\n", i);
|
|
}
|
|
return i;
|
|
}
|
|
|
|
#if defined(CSCUTIL_INTERNAL)
|
|
DWORD
|
|
CmdBitcopy(
|
|
PWSTR BitcopyArg)
|
|
{
|
|
DWORD Error = ERROR_FILE_NOT_FOUND;
|
|
LPWSTR lpszTempName = NULL;
|
|
|
|
if (!CSCCopyReplicaW(BitcopyArg, &lpszTempName)) {
|
|
Error = GetLastError();
|
|
} else {
|
|
Error = ERROR_SUCCESS;
|
|
}
|
|
|
|
if (Error == ERROR_SUCCESS) {
|
|
Error = DumpBitMap(lpszTempName);
|
|
DeleteFile(lpszTempName);
|
|
}
|
|
|
|
return Error;
|
|
}
|
|
#endif // CSCUTIL_INTERNAL
|