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.
4033 lines
89 KiB
4033 lines
89 KiB
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
api.c
|
|
|
|
Abstract:
|
|
|
|
reintegration functions
|
|
|
|
Contents:
|
|
|
|
Author:
|
|
Shishir Pardikar
|
|
|
|
|
|
Environment:
|
|
|
|
Win32 (user-mode) DLL
|
|
|
|
Revision History:
|
|
|
|
4/24/97 Created shishirp
|
|
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
|
|
|
|
#ifdef CSC_ON_NT
|
|
#include <winioctl.h>
|
|
#define UNICODE
|
|
#endif //CSC_ON_NT
|
|
|
|
#include "shdcom.h"
|
|
#include "shdsys.h"
|
|
#include "reint.h"
|
|
#include "utils.h"
|
|
#include "resource.h"
|
|
#include "strings.h"
|
|
// this sets flags in a couple of headers to not include some defs.
|
|
#define REINT
|
|
#include "lib3.h"
|
|
#include "cscapi.h"
|
|
|
|
//
|
|
// Defines/structures
|
|
//
|
|
|
|
#define SHADOW_FIND_SIGNATURE 0x61626162 // abab
|
|
#define FLAG_SHADOW_FIND_TERMINATED 0x00000001
|
|
|
|
|
|
typedef struct tagSHADOW_FIND
|
|
{
|
|
DWORD dwSignature; // for validation
|
|
DWORD dwFlags;
|
|
HANDLE hShadowDB;
|
|
ULONG ulPrincipalID;
|
|
CSC_ENUMCOOKIE uEnumCookie;
|
|
}
|
|
SHADOW_FIND, *LPSHADOW_FIND;
|
|
|
|
typedef struct tagMST_LIST
|
|
{
|
|
struct tagMST_LIST *lpNext;
|
|
HSHADOW hDir;
|
|
} MST_LIST, *LPMST_LIST;
|
|
|
|
typedef struct tagMOVE_SUBTREE
|
|
{
|
|
DWORD dwFlags;
|
|
DWORD cntFail;
|
|
HSHARE hShareTo;
|
|
LPCTSTR lptzSource;
|
|
LPCTSTR lptzDestination;
|
|
LPMST_LIST lpTos;
|
|
MST_LIST sTos;
|
|
SHADOWINFO sSI;
|
|
WIN32_FIND_DATA sFind32;
|
|
} MOVE_SUBTREE, *LPMOVE_SUBTREE;
|
|
|
|
#define MST_REPLACE_IF_EXISTS 0x00000001
|
|
#define MST_SHARE_MARKED_DIRTY 0x00000002
|
|
#define MST_MARK_AS_LOCAL 0x00000004
|
|
|
|
typedef struct tagSET_SUBTREE_STATUS
|
|
{
|
|
DWORD dwFlags;
|
|
ULONG uStatus;
|
|
ULONG uOp;
|
|
|
|
} SET_SUBTREE_STATUS, *LPSET_SUBTREE_STATUS;
|
|
|
|
|
|
|
|
#define EDS_FLAG_ERROR_ENCOUNTERED 0x00000001
|
|
|
|
typedef struct tagENCRYPT_DECRYPT_SUBTREE
|
|
{
|
|
DWORD dwFlags;
|
|
BOOL fEncrypt;
|
|
LPCSCPROCW lpfnEnumProgress;
|
|
DWORD_PTR dwContext;
|
|
DWORD dwEndingNameSpaceVersion;
|
|
}ENCRYPT_DECRYPT_SUBTREE, *LPENCRYPT_DECRYPT_SUBTREE;
|
|
|
|
BOOL
|
|
CheckCSCAccessForThread(
|
|
HSHADOW hDir,
|
|
HSHADOW hShadow,
|
|
BOOL fWrite
|
|
);
|
|
|
|
int
|
|
MoveSubtree(
|
|
HANDLE hShadowDB,
|
|
LPSECURITYINFO pShareSecurityInfo,
|
|
LPTSTR lptzFullPath,
|
|
DWORD dwCallbackReason,
|
|
WIN32_FIND_DATA *lpFind32,
|
|
SHADOWINFO *lpSI,
|
|
LPMOVE_SUBTREE lpMst
|
|
);
|
|
|
|
int
|
|
SetSubtreeStatus(
|
|
HANDLE hShadowDB,
|
|
LPSECURITYINFO pShareSecurityInfo,
|
|
LPTSTR lptzFullPath,
|
|
DWORD dwCallbackReason,
|
|
WIN32_FIND_DATA *lpFind32,
|
|
SHADOWINFO *lpSI,
|
|
LPSET_SUBTREE_STATUS lpSss
|
|
);
|
|
|
|
int
|
|
EncryptDecryptSubtree(
|
|
HANDLE hShadowDB,
|
|
LPSECURITYINFO pShareSecurityInfo,
|
|
LPTSTR lptzFullPath,
|
|
DWORD dwCallbackReason,
|
|
WIN32_FIND_DATA *lpFind32,
|
|
SHADOWINFO *lpSI,
|
|
LPENCRYPT_DECRYPT_SUBTREE lpEds
|
|
);
|
|
|
|
BOOL
|
|
UncPathToDfsPath(
|
|
PWCHAR UncPath,
|
|
PWCHAR DfsPath,
|
|
ULONG cbLen);
|
|
|
|
BOOL
|
|
IsPersonal(VOID);
|
|
|
|
//
|
|
// local data
|
|
//
|
|
static TCHAR vszStarDotStar[] = _TEXT("*.*");
|
|
static TCHAR vszStar[] = _TEXT("*");
|
|
|
|
static TCHAR vszPrefix[] = _TEXT("CSC");
|
|
AssertData;
|
|
AssertError;
|
|
|
|
|
|
//
|
|
// functions
|
|
//
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCIsCSCEnabled(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
unsigned ulSwitch = SHADOW_SWITCH_SHADOWING;
|
|
|
|
if(ShadowSwitches(INVALID_HANDLE_VALUE, &ulSwitch, SHADOW_SWITCH_GET_STATE))
|
|
{
|
|
return((ulSwitch & SHADOW_SWITCH_SHADOWING)!=0);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCGetSpaceUsageA(
|
|
LPSTR lptzLocation,
|
|
DWORD dwSize,
|
|
LPDWORD lpdwMaxSpaceHigh,
|
|
LPDWORD lpdwMaxSpaceLow,
|
|
LPDWORD lpdwCurrentSpaceHigh,
|
|
LPDWORD lpdwCurrentSpaceLow,
|
|
LPDWORD lpcntTotalFiles,
|
|
LPDWORD lpcntTotalDirs
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifdef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
SHADOWSTORE sST;
|
|
WIN32_FIND_DATA sFind32;
|
|
BOOL fRet = FALSE;
|
|
DWORD dwLen;
|
|
|
|
// NTRAID#455247-1/31/2000-shishirp parameter validation
|
|
if (GetShadowDatabaseLocation(INVALID_HANDLE_VALUE, &sFind32))
|
|
{
|
|
memset(lptzLocation, 0, sizeof(dwSize));
|
|
WideCharToMultiByte(CP_ACP, 0, sFind32.cFileName, wcslen(sFind32.cFileName), lptzLocation, dwSize, NULL, NULL);
|
|
|
|
if (GetSpaceStats(INVALID_HANDLE_VALUE, &sST))
|
|
{
|
|
*lpdwMaxSpaceHigh = 0;
|
|
*lpdwMaxSpaceLow = sST.sMax.ulSize;
|
|
*lpdwCurrentSpaceHigh = 0;
|
|
*lpdwCurrentSpaceLow = sST.sCur.ulSize;
|
|
*lpcntTotalFiles = sST.sCur.ucntFiles;
|
|
*lpcntTotalFiles = sST.sCur.ucntDirs;
|
|
fRet = TRUE;
|
|
}
|
|
|
|
}
|
|
return fRet;
|
|
#endif
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCGetSpaceUsageW(
|
|
LPTSTR lptzLocation,
|
|
DWORD dwSize,
|
|
LPDWORD lpdwMaxSpaceHigh,
|
|
LPDWORD lpdwMaxSpaceLow,
|
|
LPDWORD lpdwCurrentSpaceHigh,
|
|
LPDWORD lpdwCurrentSpaceLow,
|
|
LPDWORD lpcntTotalFiles,
|
|
LPDWORD lpcntTotalDirs
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifndef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
SHADOWSTORE sST;
|
|
WIN32_FIND_DATA sFind32;
|
|
BOOL fRet = FALSE;
|
|
|
|
// NTRAID#455247-1/31/2000-shishirp parameter validation
|
|
if (GetShadowDatabaseLocation(INVALID_HANDLE_VALUE, &sFind32))
|
|
{
|
|
memset(lptzLocation, 0, dwSize);
|
|
wcsncpy(lptzLocation, sFind32.cFileName, dwSize/sizeof(USHORT)-1);
|
|
|
|
if (GetSpaceStats(INVALID_HANDLE_VALUE, &sST))
|
|
{
|
|
*lpdwMaxSpaceHigh = 0;
|
|
*lpdwMaxSpaceLow = sST.sMax.ulSize;
|
|
*lpdwCurrentSpaceHigh = 0;
|
|
*lpdwCurrentSpaceLow = sST.sCur.ulSize;
|
|
*lpcntTotalFiles = sST.sCur.ucntFiles;
|
|
*lpcntTotalDirs = sST.sCur.ucntDirs;
|
|
fRet = TRUE;
|
|
}
|
|
|
|
}
|
|
return fRet;
|
|
#endif
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCSetMaxSpace(
|
|
DWORD nFileSizeHigh,
|
|
DWORD nFileSizeLow
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
int iRet;
|
|
|
|
// 2GB is our limit
|
|
if ((nFileSizeHigh)||(nFileSizeLow > 0x7fffffff))
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
iRet = SetMaxShadowSpace(INVALID_HANDLE_VALUE, (long)nFileSizeHigh, (long)nFileSizeLow);
|
|
|
|
if (iRet<0)
|
|
{
|
|
SetLastError(ERROR_INTERNAL_ERROR);
|
|
}
|
|
|
|
return (iRet >= 1);
|
|
}
|
|
|
|
BOOL
|
|
CSCPinFileInternal(
|
|
LPCTSTR lpszFileName,
|
|
DWORD dwHintFlags,
|
|
LPDWORD lpdwStatus,
|
|
LPDWORD lpdwPinCount,
|
|
LPDWORD lpdwHintFlags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
WIN32_FIND_DATA sFind32;
|
|
SHADOWINFO sSI;
|
|
BOOL fCreated, fRet = FALSE;
|
|
DWORD dwError = ERROR_GEN_FAILURE;
|
|
|
|
// NTRAID#455247-1/31/2000-shishirp parameter validation !!!!
|
|
|
|
|
|
if (BeginInodeTransactionHSHADOW())
|
|
{
|
|
if(FindCreateShadowFromPath(lpszFileName, TRUE, &sFind32, &sSI, &fCreated))
|
|
{
|
|
sSI.ulHintFlags = dwHintFlags;
|
|
|
|
fRet = (AddHintFromInode( INVALID_HANDLE_VALUE,
|
|
sSI.hDir,
|
|
sSI.hShadow,
|
|
&(sSI.ulHintPri),
|
|
&(sSI.ulHintFlags)
|
|
) != 0);
|
|
|
|
if (fRet)
|
|
{
|
|
if (lpdwStatus)
|
|
{
|
|
*lpdwStatus = sSI.uStatus;
|
|
}
|
|
if (lpdwPinCount)
|
|
{
|
|
*lpdwPinCount = sSI.ulHintPri;
|
|
}
|
|
if (lpdwHintFlags)
|
|
{
|
|
*lpdwHintFlags = sSI.ulHintFlags;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
dwError = ERROR_INVALID_FUNCTION;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwError = GetLastError();
|
|
}
|
|
|
|
EndInodeTransactionHSHADOW();
|
|
}
|
|
if (!fRet)
|
|
{
|
|
Assert(dwError != ERROR_SUCCESS);
|
|
SetLastError(dwError);
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CSCUnpinFileInternal(
|
|
LPCTSTR lpszFileName,
|
|
IN DWORD dwHintFlags,
|
|
LPDWORD lpdwStatus,
|
|
LPDWORD lpdwPinCount,
|
|
LPDWORD lpdwHintFlags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
WIN32_FIND_DATA sFind32;
|
|
SHADOWINFO sSI;
|
|
BOOL fRet = FALSE;
|
|
DWORD dwError = ERROR_GEN_FAILURE;
|
|
|
|
// NTRAID#455247-1/31/2000-shishirp parameter validation !!!!
|
|
|
|
|
|
if (BeginInodeTransactionHSHADOW())
|
|
{
|
|
if(FindCreateShadowFromPath(lpszFileName, FALSE, &sFind32, &sSI, NULL))
|
|
{
|
|
sSI.ulHintFlags = dwHintFlags;
|
|
|
|
fRet = (DeleteHintFromInode( INVALID_HANDLE_VALUE,
|
|
sSI.hDir,
|
|
sSI.hShadow,
|
|
&(sSI.ulHintPri),
|
|
&(sSI.ulHintFlags)
|
|
) != 0);
|
|
|
|
if (fRet)
|
|
{
|
|
if (lpdwStatus)
|
|
{
|
|
*lpdwStatus = sSI.uStatus;
|
|
}
|
|
if (lpdwPinCount)
|
|
{
|
|
*lpdwPinCount = sSI.ulHintPri;
|
|
}
|
|
if (lpdwHintFlags)
|
|
{
|
|
*lpdwHintFlags = sSI.ulHintFlags;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwError = ERROR_INVALID_FUNCTION;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
dwError = GetLastError();
|
|
}
|
|
|
|
EndInodeTransactionHSHADOW();
|
|
|
|
}
|
|
|
|
if (!fRet)
|
|
{
|
|
SetLastError(dwError);
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
BOOL
|
|
CSCQueryFileStatusInternal(
|
|
LPCTSTR lpszFileName,
|
|
LPDWORD lpdwStatus,
|
|
LPDWORD lpdwPinCount,
|
|
LPDWORD lpdwHintFlags,
|
|
LPDWORD lpdwUserPerms,
|
|
LPDWORD lpdwOtherPerms
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
|
|
WIN32_FIND_DATA sFind32;
|
|
SHADOWINFO sSI;
|
|
|
|
// NTRAID#455247-1/31/2000-shishirp parameter validation !!!!
|
|
|
|
|
|
if (FindCreateShadowFromPath(lpszFileName, FALSE, &sFind32, &sSI, NULL) != TRUE)
|
|
return FALSE;
|
|
|
|
if (lpdwStatus != NULL) {
|
|
*lpdwStatus = sSI.uStatus;
|
|
// return accessmask for files or the root
|
|
if ((sSI.uStatus & SHADOW_IS_FILE)||(!sSI.hDir)) {
|
|
if (sSI.hShadow) {
|
|
ULONG ulPrincipalID;
|
|
|
|
if (!GetCSCPrincipalID(&ulPrincipalID))
|
|
ulPrincipalID = CSC_GUEST_PRINCIPAL_ID;
|
|
|
|
GetCSCAccessMaskForPrincipalEx(
|
|
ulPrincipalID,
|
|
sSI.hDir,
|
|
sSI.hShadow,
|
|
lpdwStatus,
|
|
lpdwUserPerms,
|
|
lpdwOtherPerms);
|
|
|
|
Assert((*lpdwStatus & ~FLAG_CSC_ACCESS_MASK) == sSI.uStatus);
|
|
|
|
if (lpdwUserPerms != NULL && lpdwOtherPerms != NULL) {
|
|
|
|
ULONG i;
|
|
ULONG GuestIdx = CSC_MAXIMUM_NUMBER_OF_CACHED_PRINCIPAL_IDS;
|
|
ULONG UserIdx = CSC_MAXIMUM_NUMBER_OF_CACHED_PRINCIPAL_IDS;
|
|
SECURITYINFO rgsSecurityInfo[CSC_MAXIMUM_NUMBER_OF_CACHED_PRINCIPAL_IDS];
|
|
_TCHAR tchBuff[MAX_SERVER_SHARE_NAME_FOR_CSC];
|
|
ULONG nRet = 0;
|
|
DWORD dwDummy;
|
|
WIN32_FIND_DATA sFind32;
|
|
SHADOWINFO sSI2;
|
|
BOOL fDone = FALSE;
|
|
|
|
// DbgPrint("CSCQueryFileStatusInternal(%ws)\n", lpszFileName);
|
|
|
|
if (lstrlen(lpszFileName) >= MAX_SERVER_SHARE_NAME_FOR_CSC)
|
|
goto AllDone;
|
|
|
|
lstrcpy(tchBuff, lpszFileName);
|
|
|
|
if (!LpBreakPath(tchBuff, TRUE, &fDone))
|
|
goto AllDone;
|
|
|
|
// DbgPrint(" tchBuff=%ws\n", tchBuff);
|
|
|
|
if (!FindCreateShadowFromPath(tchBuff, FALSE, &sFind32, &sSI2, NULL))
|
|
goto AllDone;
|
|
|
|
// DbgPrint("CSCQueryFileStatusInternal: hShare=0x%x,hShadow=0x%x,hDir=0x%x\n",
|
|
// sSI2.hShare,
|
|
// sSI2.hShadow,
|
|
// sSI2.hDir);
|
|
|
|
dwDummy = sizeof(rgsSecurityInfo);
|
|
nRet = GetSecurityInfoForCSC(
|
|
INVALID_HANDLE_VALUE,
|
|
0,
|
|
sSI2.hShadow,
|
|
rgsSecurityInfo,
|
|
&dwDummy);
|
|
|
|
// DbgPrint(" GetSecurityInfoForCSC returned %d\n", nRet);
|
|
|
|
if (nRet == 0)
|
|
goto AllDone;
|
|
|
|
//
|
|
// Find the user's and guest's entries
|
|
//
|
|
for (i = 0; i < CSC_MAXIMUM_NUMBER_OF_CACHED_PRINCIPAL_IDS; i++) {
|
|
if (rgsSecurityInfo[i].ulPrincipalID == ulPrincipalID)
|
|
UserIdx = i;
|
|
if (rgsSecurityInfo[i].ulPrincipalID == CSC_GUEST_PRINCIPAL_ID)
|
|
GuestIdx = i;
|
|
}
|
|
if (GuestIdx < CSC_MAXIMUM_NUMBER_OF_CACHED_PRINCIPAL_IDS) {
|
|
if (UserIdx >= CSC_MAXIMUM_NUMBER_OF_CACHED_PRINCIPAL_IDS)
|
|
UserIdx = GuestIdx;
|
|
|
|
*lpdwUserPerms &= rgsSecurityInfo[UserIdx].ulPermissions;
|
|
*lpdwOtherPerms &= rgsSecurityInfo[GuestIdx].ulPermissions;
|
|
|
|
// DbgPrint("UserPerms=0x%x,OtherPerms=0x%x\n",
|
|
// *lpdwUserPerms,
|
|
// *lpdwOtherPerms);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
AllDone:
|
|
|
|
if (lpdwPinCount) {
|
|
*lpdwPinCount = sSI.ulHintPri;
|
|
}
|
|
if (lpdwHintFlags) {
|
|
*lpdwHintFlags = sSI.ulHintFlags;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
HANDLE
|
|
CSCFindFirstFileInternal(
|
|
LPCTSTR lpszFileName,
|
|
ULONG ulPrincipalID,
|
|
WIN32_FIND_DATA *lpFind32,
|
|
LPDWORD lpdwStatus,
|
|
LPDWORD lpdwPinCount,
|
|
LPDWORD lpdwHintFlags,
|
|
FILETIME *lpOrgFileTime
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
SHADOWINFO sSI;
|
|
BOOL fRet = FALSE;
|
|
LPSHADOW_FIND lpShadowFind = NULL;
|
|
|
|
// NTRAID#455247-1/31/2000-shishirp parameter validation !!!!
|
|
|
|
|
|
if (lpszFileName && *lpszFileName)
|
|
{
|
|
fRet = FindCreateShadowFromPath(
|
|
lpszFileName, // UNC path
|
|
FALSE, // don't create
|
|
lpFind32,
|
|
&sSI,
|
|
NULL);
|
|
|
|
if (fRet && !sSI.hShadow)
|
|
{
|
|
// a situation where, the share is connected but it's entry is
|
|
// not in the database
|
|
fRet = FALSE;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
memset(&sSI, 0, sizeof(sSI)); // sSI.hShadow is 0 => we are enumerating all shares
|
|
lpFind32->dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
|
|
fRet = TRUE;
|
|
}
|
|
|
|
if (fRet)
|
|
{
|
|
fRet = FALSE;
|
|
|
|
// Found the shadow
|
|
if (lpShadowFind = AllocMem(sizeof(SHADOW_FIND)))
|
|
{
|
|
lpShadowFind->dwSignature = SHADOW_FIND_SIGNATURE;
|
|
lpShadowFind->hShadowDB = INVALID_HANDLE_VALUE;
|
|
|
|
if (ulPrincipalID != CSC_INVALID_PRINCIPAL_ID)
|
|
{
|
|
lpShadowFind->ulPrincipalID = ulPrincipalID;
|
|
}
|
|
else
|
|
{
|
|
if (!GetCSCPrincipalID(&lpShadowFind->ulPrincipalID))
|
|
{
|
|
lpShadowFind->ulPrincipalID = CSC_GUEST_PRINCIPAL_ID;
|
|
}
|
|
}
|
|
|
|
if (!(lpFind32->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
{
|
|
lpShadowFind->dwFlags |= FLAG_SHADOW_FIND_TERMINATED;
|
|
fRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// lpShadowFind->hShadowDB = OpenShadowDatabaseIO();
|
|
|
|
// if (lpShadowFind->hShadowDB != INVALID_HANDLE_VALUE)
|
|
{
|
|
#ifndef CSC_ON_NT
|
|
lstrcpy(lpFind32->cFileName, vszStarDotStar);
|
|
#else
|
|
lstrcpy(lpFind32->cFileName, vszStar);
|
|
#endif
|
|
|
|
if(FindOpenShadow(
|
|
lpShadowFind->hShadowDB,
|
|
sSI.hShadow,
|
|
FINDOPEN_SHADOWINFO_ALL,
|
|
lpFind32,
|
|
&sSI
|
|
))
|
|
{
|
|
lpShadowFind->uEnumCookie = sSI.uEnumCookie;
|
|
|
|
fRet = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!fRet)
|
|
{
|
|
if (lpShadowFind)
|
|
{
|
|
if (lpShadowFind->hShadowDB != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseShadowDatabaseIO(lpShadowFind->hShadowDB);
|
|
}
|
|
|
|
FreeMem(lpShadowFind);
|
|
|
|
}
|
|
|
|
EndInodeTransactionHSHADOW();
|
|
|
|
return (INVALID_HANDLE_VALUE);
|
|
}
|
|
else
|
|
{
|
|
|
|
if (lpdwStatus)
|
|
{
|
|
*lpdwStatus = (DWORD)(sSI.uStatus);
|
|
|
|
// return accessmask for files or the root
|
|
if ((sSI.uStatus & SHADOW_IS_FILE)||(!sSI.hDir))
|
|
{
|
|
GetCSCAccessMaskForPrincipal(lpShadowFind->ulPrincipalID, sSI.hDir, sSI.hShadow, lpdwStatus);
|
|
Assert((*lpdwStatus & ~FLAG_CSC_ACCESS_MASK) == sSI.uStatus);
|
|
}
|
|
|
|
}
|
|
if (lpdwPinCount)
|
|
{
|
|
*lpdwPinCount = (DWORD)(sSI.ulHintPri);
|
|
}
|
|
if (lpdwHintFlags)
|
|
{
|
|
*lpdwHintFlags = sSI.ulHintFlags;
|
|
}
|
|
if (lpOrgFileTime)
|
|
{
|
|
*lpOrgFileTime = lpFind32->ftLastAccessTime;
|
|
}
|
|
|
|
return ((HANDLE)lpShadowFind);
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
CSCFindNextFileInternal(
|
|
HANDLE hFind,
|
|
WIN32_FIND_DATA *lpFind32,
|
|
LPDWORD lpdwStatus,
|
|
LPDWORD lpdwPinCount,
|
|
LPDWORD lpdwHintFlags,
|
|
FILETIME *lpOrgFileTime
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
LPSHADOW_FIND lpShadowFind = (LPSHADOW_FIND)hFind;
|
|
BOOL fRet = FALSE;
|
|
SHADOWINFO sSI;
|
|
|
|
// validate parameters !!!!
|
|
|
|
if (lpShadowFind->dwFlags & FLAG_SHADOW_FIND_TERMINATED)
|
|
{
|
|
SetLastError(ERROR_NO_MORE_FILES);
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
if (!FindNextShadow( lpShadowFind->hShadowDB,
|
|
lpShadowFind->uEnumCookie,
|
|
lpFind32,
|
|
&sSI
|
|
))
|
|
{
|
|
lpShadowFind->dwFlags |= FLAG_SHADOW_FIND_TERMINATED;
|
|
SetLastError(ERROR_NO_MORE_FILES);
|
|
}
|
|
else
|
|
{
|
|
if (lpdwStatus)
|
|
{
|
|
*lpdwStatus = (DWORD)(sSI.uStatus);
|
|
|
|
// return accessmask for files or the root
|
|
if ((sSI.uStatus & SHADOW_IS_FILE)||(!sSI.hDir))
|
|
{
|
|
GetCSCAccessMaskForPrincipal(lpShadowFind->ulPrincipalID, sSI.hDir, sSI.hShadow, lpdwStatus);
|
|
Assert((*lpdwStatus & ~FLAG_CSC_ACCESS_MASK) == sSI.uStatus);
|
|
}
|
|
}
|
|
if (lpdwPinCount)
|
|
{
|
|
*lpdwPinCount = (DWORD)(sSI.ulHintPri);
|
|
}
|
|
if (lpdwHintFlags)
|
|
{
|
|
*lpdwHintFlags = sSI.ulHintFlags;
|
|
}
|
|
|
|
if (lpOrgFileTime)
|
|
{
|
|
*lpOrgFileTime = lpFind32->ftLastAccessTime;
|
|
}
|
|
fRet = TRUE;
|
|
}
|
|
}
|
|
return (fRet);
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCFindClose(
|
|
HANDLE hFind
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
LPSHADOW_FIND lpShadowFind = (LPSHADOW_FIND)hFind;
|
|
|
|
if (lpShadowFind->uEnumCookie)
|
|
{
|
|
// don't check any errors
|
|
FindCloseShadow(lpShadowFind->hShadowDB, lpShadowFind->uEnumCookie);
|
|
}
|
|
|
|
if (lpShadowFind->hShadowDB != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseShadowDatabaseIO(lpShadowFind->hShadowDB);
|
|
}
|
|
|
|
FreeMem(lpShadowFind);
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
BOOL
|
|
CSCDeleteInternal(
|
|
LPCTSTR lpszName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
WIN32_FIND_DATA sFind32;
|
|
SHADOWINFO sSI;
|
|
BOOL fRet = FALSE;
|
|
DWORD dwError = ERROR_GEN_FAILURE;
|
|
DWORD dwStatus = 0;
|
|
BOOL DoDelete = FALSE;
|
|
|
|
// NTRAID#455247 -1/31/2000-shishirp parameter validation !!!!
|
|
|
|
ReintKdPrint(API, ("Delete %ls\r\n", lpszName));
|
|
|
|
if(CSCQueryFileStatus(lpszName, &dwStatus, NULL, NULL))
|
|
{
|
|
// Shouls check if the user has the permission to delete this file - Bug 524237
|
|
if(!(FLAG_CSC_COPY_STATUS_IS_FILE & dwStatus) || //is directory or
|
|
(((dwStatus & FLAG_CSC_GUEST_ACCESS_MASK) & // the guest has write permission
|
|
FLAG_CSC_WRITE_ACCESS << FLAG_CSC_GUEST_ACCESS_SHIFT_COUNT) ||
|
|
((dwStatus & FLAG_CSC_USER_ACCESS_MASK) & // or the user has write permission
|
|
FLAG_CSC_WRITE_ACCESS << FLAG_CSC_USER_ACCESS_SHIFT_COUNT)))
|
|
{
|
|
if (BeginInodeTransactionHSHADOW())
|
|
{
|
|
|
|
if(FindCreateShadowFromPath(lpszName, FALSE, &sFind32, &sSI, NULL))
|
|
{
|
|
|
|
ReintKdPrint(API, ("Delete Inode %x %x\r\n", sSI.hDir, sSI.hShadow));
|
|
|
|
if (DeleteShadow(INVALID_HANDLE_VALUE, sSI.hDir, sSI.hShadow))
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
dwError = ERROR_ACCESS_DENIED;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
dwError = GetLastError();
|
|
}
|
|
|
|
EndInodeTransactionHSHADOW();
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
dwError = ERROR_ACCESS_DENIED;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!fRet)
|
|
{
|
|
SetLastError(dwError);
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CSCFillSparseFilesInternal(
|
|
IN LPCTSTR lpszShareOrFileName,
|
|
IN BOOL fFullSync,
|
|
IN LPCSCPROC lpfnFillProgress,
|
|
IN DWORD_PTR dwContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
WIN32_FIND_DATA sFind32;
|
|
SHADOWINFO sSI;
|
|
DWORD dwError = ERROR_INVALID_PARAMETER, dwRet;
|
|
LPCOPYPARAMS lpCP = NULL;
|
|
ULONG ulPrincipalID;
|
|
|
|
if (!GetCSCPrincipalID(&ulPrincipalID))
|
|
{
|
|
ulPrincipalID = CSC_GUEST_PRINCIPAL_ID;
|
|
}
|
|
if(FindCreateShadowFromPath(lpszShareOrFileName, FALSE, &sFind32, &sSI, NULL))
|
|
{
|
|
if (!sSI.hDir)
|
|
{
|
|
dwError = NO_ERROR;
|
|
|
|
// if this is a share
|
|
dwRet = (*lpfnFillProgress)(
|
|
lpszShareOrFileName,
|
|
sSI.uStatus,
|
|
sSI.ulHintFlags,
|
|
sSI.ulHintPri,
|
|
&sFind32,
|
|
CSCPROC_REASON_BEGIN,
|
|
0,
|
|
0,
|
|
dwContext
|
|
);
|
|
if (dwRet == CSCPROC_RETURN_CONTINUE)
|
|
{
|
|
AttemptCacheFill(sSI.hShare, DO_ALL, fFullSync, ulPrincipalID, lpfnFillProgress, dwContext);
|
|
}
|
|
else
|
|
{
|
|
if (dwRet == CSCPROC_RETURN_ABORT)
|
|
{
|
|
dwError = ERROR_OPERATION_ABORTED;
|
|
}
|
|
}
|
|
|
|
(*lpfnFillProgress)(
|
|
lpszShareOrFileName,
|
|
sSI.uStatus,
|
|
sSI.ulHintFlags,
|
|
sSI.ulHintPri,
|
|
&sFind32,
|
|
CSCPROC_REASON_END,
|
|
0,
|
|
0,
|
|
dwContext
|
|
);
|
|
}
|
|
else if (!(sFind32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
{
|
|
BOOL fStalenessCheck;
|
|
dwError = NO_ERROR;
|
|
|
|
fStalenessCheck = (fFullSync || (sSI.uStatus & SHADOW_STALE));
|
|
|
|
if (fStalenessCheck)
|
|
{
|
|
if (!(lpCP = LpAllocCopyParams()))
|
|
{
|
|
dwError = GetLastError();
|
|
Assert(dwError != NO_ERROR);
|
|
|
|
}
|
|
else if(!GetUNCPath(INVALID_HANDLE_VALUE, sSI.hShare, sSI.hDir, sSI.hShadow, lpCP))
|
|
{
|
|
Assert(lpCP);
|
|
FreeCopyParams(lpCP);
|
|
dwError = GetLastError();
|
|
Assert(dwError != NO_ERROR);
|
|
}
|
|
}
|
|
|
|
if ((dwError == NO_ERROR) &&
|
|
(fStalenessCheck || (sSI.uStatus & SHADOW_SPARSE))) {
|
|
|
|
dwError = DoSparseFill( INVALID_HANDLE_VALUE,
|
|
(LPTSTR)lpszShareOrFileName,
|
|
NULL,
|
|
&sSI,
|
|
&sFind32,
|
|
lpCP,
|
|
fStalenessCheck,
|
|
ulPrincipalID,
|
|
lpfnFillProgress,
|
|
dwContext);
|
|
}
|
|
|
|
if (lpCP)
|
|
{
|
|
FreeCopyParams(lpCP);
|
|
lpCP = NULL;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwError = GetLastError();
|
|
}
|
|
|
|
if (dwError != NO_ERROR)
|
|
{
|
|
SetLastError(dwError);
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
CSCMergeShareInternal(
|
|
IN LPCTSTR lpszShareName,
|
|
IN LPCSCPROC lpfnMergeProgress,
|
|
IN DWORD_PTR dwContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
|
|
WIN32_FIND_DATA sFind32;
|
|
SHADOWINFO sSI;
|
|
int cntDriveMapped = 0;
|
|
BOOL fTransitionedToOnline = FALSE, fDone=FALSE;
|
|
_TCHAR tchBuff[MAX_SERVER_SHARE_NAME_FOR_CSC];
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
ULONG ulPrincipalID;
|
|
|
|
if (!GetCSCPrincipalID(&ulPrincipalID))
|
|
{
|
|
ulPrincipalID = CSC_GUEST_PRINCIPAL_ID;
|
|
}
|
|
|
|
if (lstrlen(lpszShareName) >= MAX_SERVER_SHARE_NAME_FOR_CSC)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
lstrcpy(tchBuff, lpszShareName);
|
|
|
|
if (!LpBreakPath(tchBuff, TRUE, &fDone) && !fDone)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
if(FindCreateShadowFromPath(tchBuff, FALSE, &sFind32, &sSI, NULL))
|
|
{
|
|
|
|
fDone = ReintOneShare(sSI.hShare, sSI.hShadow, NULL, NULL, NULL, ulPrincipalID, lpfnMergeProgress, dwContext);
|
|
|
|
if (!fDone)
|
|
{
|
|
dwError = GetLastError();
|
|
}
|
|
|
|
// TransitionShareToOnline(INVALID_HANDLE_VALUE, sSI.hShare);
|
|
|
|
if (!fDone)
|
|
{
|
|
SetLastError(dwError);
|
|
}
|
|
|
|
return fDone;
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
CSCCopyReplicaInternal(
|
|
IN LPCTSTR lpszFullPath,
|
|
OUT LPTSTR *lplpszLocalName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
|
|
WIN32_FIND_DATA sFind32;
|
|
SHADOWINFO sSI;
|
|
BOOL fRet = FALSE;
|
|
DWORD dwError = ERROR_GEN_FAILURE;
|
|
|
|
if (BeginInodeTransactionHSHADOW())
|
|
{
|
|
if(FindCreateShadowFromPath(lpszFullPath, FALSE, &sFind32, &sSI, NULL))
|
|
{
|
|
if (sFind32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
goto bailout;
|
|
}
|
|
|
|
if (!CheckCSCAccessForThread(sSI.hDir, sSI.hShadow, FALSE))
|
|
{
|
|
dwError = GetLastError();
|
|
goto bailout;
|
|
}
|
|
|
|
if (!(*lplpszLocalName = GetTempFileForCSC(NULL)))
|
|
{
|
|
goto bailout;
|
|
}
|
|
|
|
if(!CopyShadow(INVALID_HANDLE_VALUE, sSI.hDir, sSI.hShadow, *lplpszLocalName))
|
|
{
|
|
LocalFree(*lplpszLocalName);
|
|
*lplpszLocalName = NULL;
|
|
goto bailout;
|
|
}
|
|
|
|
fRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
dwError = GetLastError();
|
|
}
|
|
|
|
EndInodeTransactionHSHADOW();
|
|
}
|
|
bailout:
|
|
if (!fRet)
|
|
{
|
|
SetLastError(dwError);
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
BOOL
|
|
CSCEnumForStatsInternal(
|
|
IN LPCTSTR lpszShareName,
|
|
IN LPCSCPROC lpfnEnumProgress,
|
|
IN BOOL fPeruserInfo,
|
|
IN BOOL fUpdateShareReintBit,
|
|
IN DWORD_PTR dwContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
WIN32_FIND_DATA sFind32;
|
|
SHADOWINFO sSI;
|
|
BOOL fRet = TRUE;
|
|
PQPARAMS sPQP;
|
|
HANDLE hShadowDB = INVALID_HANDLE_VALUE;
|
|
DWORD dwRet;
|
|
ULONG ulPrincipalID = CSC_INVALID_PRINCIPAL_ID;
|
|
|
|
if (lpszShareName)
|
|
{
|
|
|
|
if(!FindCreateShadowFromPath(lpszShareName, FALSE, &sFind32, &sSI, NULL))
|
|
{
|
|
fRet = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sSI.hShare = 0;
|
|
}
|
|
if (fRet)
|
|
{
|
|
fRet = FALSE;
|
|
|
|
if ((hShadowDB = OpenShadowDatabaseIO())==INVALID_HANDLE_VALUE)
|
|
{
|
|
goto bailout;
|
|
}
|
|
|
|
if (lpfnEnumProgress)
|
|
{
|
|
dwRet = (*lpfnEnumProgress)(NULL, 0, 0, 0, NULL, CSCPROC_REASON_BEGIN, 0, 0, dwContext);
|
|
|
|
if (dwRet != CSCPROC_RETURN_CONTINUE )
|
|
{
|
|
goto bailout;
|
|
}
|
|
}
|
|
|
|
if (fPeruserInfo)
|
|
{
|
|
|
|
if (!GetCSCPrincipalID(&ulPrincipalID))
|
|
{
|
|
ulPrincipalID = CSC_GUEST_PRINCIPAL_ID;
|
|
}
|
|
}
|
|
|
|
memset(&sPQP, 0, sizeof(sPQP));
|
|
|
|
if(BeginPQEnum(hShadowDB, &sPQP) == 0) {
|
|
goto bailout;
|
|
}
|
|
|
|
do {
|
|
|
|
if(NextPriShadow(hShadowDB, &sPQP) == 0) {
|
|
break;
|
|
}
|
|
|
|
if (!sPQP.hShadow) {
|
|
break;
|
|
}
|
|
|
|
if (!sSI.hShare || (sSI.hShare == sPQP.hShare))
|
|
{
|
|
if (fPeruserInfo)
|
|
{
|
|
|
|
// return accessmask for files or the root
|
|
if ((sPQP.ulStatus & SHADOW_IS_FILE)||(!sPQP.hDir))
|
|
{
|
|
GetCSCAccessMaskForPrincipal(ulPrincipalID, sPQP.hDir, sPQP.hShadow, &sPQP.ulStatus);
|
|
}
|
|
}
|
|
|
|
if (lpfnEnumProgress)
|
|
{
|
|
// if we are enumerating for a particular share
|
|
// besides status, report whether file or directory and whether a root or a non-root
|
|
dwRet = (*lpfnEnumProgress)(NULL, sPQP.ulStatus & ~SHADOW_IS_FILE, sPQP.ulHintFlags, sPQP.ulHintPri, NULL, CSCPROC_REASON_MORE_DATA, (mShadowIsFile(sPQP.ulStatus) != 0), (sPQP.hDir==0), dwContext);
|
|
|
|
if (dwRet != CSCPROC_RETURN_CONTINUE )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// if we are enumerating for a particular share
|
|
// then make sure that the share dirty bit matches with what we got on the
|
|
// actual files
|
|
if (fUpdateShareReintBit && sSI.hShare && (sSI.hShare == sPQP.hShare))
|
|
{
|
|
if (mShadowNeedReint(sPQP.ulStatus) && !(sSI.uStatus & SHARE_REINT))
|
|
{
|
|
if(SetShareStatus(hShadowDB, sSI.hShare, SHARE_REINT, SHADOW_FLAGS_OR))
|
|
{
|
|
sSI.uStatus |= SHARE_REINT;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
} while (sPQP.uPos);
|
|
|
|
// Close the enumeration
|
|
EndPQEnum(hShadowDB, &sPQP);
|
|
|
|
if (lpfnEnumProgress)
|
|
{
|
|
dwRet = (*lpfnEnumProgress)(NULL, 0, 0, 0, NULL, CSCPROC_REASON_END, 0, 0, dwContext);
|
|
}
|
|
|
|
fRet = TRUE;
|
|
}
|
|
|
|
bailout:
|
|
|
|
if (hShadowDB != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseShadowDatabaseIO(hShadowDB);
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCPinFileA(
|
|
IN LPCSTR lpszFileName,
|
|
IN DWORD dwHintFlags,
|
|
IN LPDWORD lpdwStatus,
|
|
IN LPDWORD lpdwPinCount,
|
|
IN LPDWORD lpdwHintFlags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifdef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return (CSCPinFileInternal(lpszFileName, dwHintFlags, lpdwStatus, lpdwPinCount, lpdwHintFlags));
|
|
#endif
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCUnpinFileA(
|
|
IN LPCSTR lpszFileName,
|
|
IN DWORD dwHintFlags,
|
|
IN LPDWORD lpdwStatus,
|
|
IN LPDWORD lpdwPinCount,
|
|
IN LPDWORD lpdwHintFlags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifdef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return (CSCUnpinFileInternal(lpszFileName, dwHintFlags, lpdwStatus, lpdwPinCount, lpdwHintFlags));
|
|
#endif
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCQueryFileStatusA(
|
|
LPCSTR lpszFileName,
|
|
LPDWORD lpdwStatus,
|
|
LPDWORD lpdwPinCount,
|
|
LPDWORD lpdwHintFlags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifdef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return (CSCQueryFileStatusInternal(
|
|
lpszFileName,
|
|
lpdwStatus,
|
|
lpdwPinCount,
|
|
lpdwHintFlags,
|
|
NULL,
|
|
NULL));
|
|
#endif
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCQueryFileStatusExA(
|
|
LPCSTR lpszFileName,
|
|
LPDWORD lpdwStatus,
|
|
LPDWORD lpdwPinCount,
|
|
LPDWORD lpdwHintFlags,
|
|
LPDWORD lpdwUserPerms,
|
|
LPDWORD lpdwOtherPerms
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifdef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return (CSCQueryFileStatusInternal(
|
|
lpszFileName,
|
|
lpdwStatus,
|
|
lpdwPinCount,
|
|
lpdwHintFlags,
|
|
lpdwUserPerms,
|
|
llpdwOtherPerms));
|
|
#endif
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCQueryShareStatusA(
|
|
LPCSTR lpszFileName,
|
|
LPDWORD lpdwStatus,
|
|
LPDWORD lpdwPinCount,
|
|
LPDWORD lpdwHintFlags,
|
|
LPDWORD lpdwUserPerms,
|
|
LPDWORD lpdwOtherPerms)
|
|
{
|
|
#ifdef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return (CSCQueryFileStatusInternal(
|
|
lpszFileName,
|
|
lpdwStatus,
|
|
lpdwPinCount,
|
|
lpdwHintFlags,
|
|
lpdwUserPerms,
|
|
llpdwOtherPerms));
|
|
#endif
|
|
}
|
|
|
|
HANDLE
|
|
WINAPI
|
|
CSCFindFirstFileA(
|
|
LPCSTR lpszFileName,
|
|
WIN32_FIND_DATA *lpFind32,
|
|
LPDWORD lpdwStatus,
|
|
LPDWORD lpdwPinCount,
|
|
LPDWORD lpdwHintFlags,
|
|
FILETIME *lpOrgFileTime
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifdef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return (CSCFindFirstFileInternal(
|
|
lpszFileName,
|
|
CSC_INVALID_PRINCIPAL_ID,
|
|
lpFind32,
|
|
lpdwStatus,
|
|
lpdwPinCount,
|
|
lpdwHintFlags,
|
|
lpOrgFileTime
|
|
));
|
|
#endif
|
|
|
|
}
|
|
|
|
HANDLE
|
|
WINAPI
|
|
CSCFindFirstFileForSidA(
|
|
LPCSTR lpszFileName,
|
|
PSID pSid,
|
|
WIN32_FIND_DATA *lpFind32,
|
|
LPDWORD lpdwStatus,
|
|
LPDWORD lpdwPinCount,
|
|
LPDWORD lpdwHintFlags,
|
|
FILETIME *lpOrgFileTime
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCFindNextFileA(
|
|
HANDLE hFind,
|
|
WIN32_FIND_DATA *lpFind32,
|
|
LPDWORD lpdwStatus,
|
|
LPDWORD lpdwPinCount,
|
|
LPDWORD lpdwHintFlags,
|
|
FILETIME *lpOrgFileTime
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifdef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return(CSCFindNextFileInternal(
|
|
hFind,
|
|
lpFind32,
|
|
lpdwStatus,
|
|
lpdwPinCount,
|
|
lpdwHintFlags,
|
|
lpOrgFileTime
|
|
));
|
|
#endif
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCDeleteA(
|
|
LPCSTR lpszFileName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifdef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
|
|
return (CSCDeleteInternal(lpszFileName));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCFillSparseFilesA(
|
|
IN LPCSTR lpszShareName,
|
|
IN BOOL fFullSync,
|
|
IN LPCSCPROCA lpfnFillProgress,
|
|
IN DWORD_PTR dwContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifdef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return (CSCFillSparseFilesInternal(
|
|
lpszShareName,
|
|
fFullSync,
|
|
lpfnFillProgress,
|
|
dwContext));
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCMergeShareA(
|
|
IN LPCSTR lpszShareName,
|
|
IN LPCSCPROCA lpfnMergeProgress,
|
|
IN DWORD_PTR dwContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifdef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return(CSCMergeShareInternal(
|
|
lpszShareName,
|
|
lpfnMergeProgress,
|
|
dwContext));
|
|
#endif
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCCopyReplicaA(
|
|
IN LPCSTR lpszFullPath,
|
|
OUT LPSTR *lplpszLocalName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifdef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return(CSCCopyReplicaInternal(
|
|
lpszFullPath,
|
|
lplpszLocalName));
|
|
#endif
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCEnumForStatsA(
|
|
IN LPCSTR lpszShareName,
|
|
IN LPCSCPROCA lpfnEnumProgress,
|
|
IN DWORD_PTR dwContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
|
|
#ifdef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return(CSCEnumForStatsInternal(
|
|
lpszShareName,
|
|
lpfnEnumProgress,
|
|
FALSE,
|
|
FALSE,
|
|
dwContext));
|
|
#endif
|
|
}
|
|
BOOL
|
|
WINAPI
|
|
CSCPinFileW(
|
|
IN LPCWSTR lpszFileName,
|
|
IN DWORD dwHintFlags,
|
|
IN LPDWORD lpdwStatus,
|
|
IN LPDWORD lpdwPinCount,
|
|
IN LPDWORD lpdwHintFlags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifndef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return (CSCPinFileInternal(lpszFileName, dwHintFlags, lpdwStatus, lpdwPinCount, lpdwHintFlags));
|
|
#endif
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCUnpinFileW(
|
|
IN LPCWSTR lpszFileName,
|
|
IN DWORD dwHintFlags,
|
|
IN LPDWORD lpdwStatus,
|
|
IN LPDWORD lpdwPinCount,
|
|
IN LPDWORD lpdwHintFlags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifndef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return (CSCUnpinFileInternal(lpszFileName, dwHintFlags, lpdwStatus, lpdwPinCount, lpdwHintFlags));
|
|
#endif
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCQueryFileStatusW(
|
|
LPCWSTR lpszFileName,
|
|
LPDWORD lpdwStatus,
|
|
LPDWORD lpdwPinCount,
|
|
LPDWORD lpdwHintFlags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifndef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return (CSCQueryFileStatusInternal(
|
|
lpszFileName,
|
|
lpdwStatus,
|
|
lpdwPinCount,
|
|
lpdwHintFlags,
|
|
NULL,
|
|
NULL));
|
|
#endif
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCQueryFileStatusExW(
|
|
LPCWSTR lpszFileName,
|
|
LPDWORD lpdwStatus,
|
|
LPDWORD lpdwPinCount,
|
|
LPDWORD lpdwHintFlags,
|
|
LPDWORD lpdwUserPerms,
|
|
LPDWORD lpdwOtherPerms
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifndef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return (CSCQueryFileStatusInternal(
|
|
lpszFileName,
|
|
lpdwStatus,
|
|
lpdwPinCount,
|
|
lpdwHintFlags,
|
|
lpdwUserPerms,
|
|
lpdwOtherPerms));
|
|
#endif
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCQueryShareStatusW(
|
|
LPCWSTR lpszFileName,
|
|
LPDWORD lpdwStatus,
|
|
LPDWORD lpdwPinCount,
|
|
LPDWORD lpdwHintFlags,
|
|
LPDWORD lpdwUserPerms,
|
|
LPDWORD lpdwOtherPerms)
|
|
{
|
|
BOOL fStatus = FALSE;
|
|
BOOL fDfsStatus = FALSE;
|
|
DWORD dwDfsStatus;
|
|
WCHAR lpszOrgPath[MAX_PATH];
|
|
WCHAR lpszDfsPath[MAX_PATH];
|
|
PWCHAR wCp;
|
|
ULONG sCount;
|
|
|
|
#ifndef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
|
|
// DbgPrint("CSCQueryShareStatusW(%ws)\n", lpszFileName);
|
|
|
|
//
|
|
// Save a copy of the original path passed in
|
|
//
|
|
wcscpy(lpszOrgPath, lpszFileName);
|
|
|
|
// Now truncate to just \\server\share
|
|
for (sCount = 0, wCp = lpszOrgPath; *wCp !=L'\0'; wCp++) {
|
|
if (*wCp == L'\\') {
|
|
if (++sCount == 4) {
|
|
*wCp = L'\0';
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// DbgPrint(" OrgPath=%ws\n", lpszOrgPath);
|
|
fStatus = CSCQueryFileStatusInternal(
|
|
lpszOrgPath,
|
|
lpdwStatus,
|
|
lpdwPinCount,
|
|
lpdwHintFlags,
|
|
lpdwUserPerms,
|
|
lpdwOtherPerms);
|
|
|
|
//
|
|
// If we found info, check if DFS, and (if so)
|
|
// adjust Status
|
|
//
|
|
if (fStatus == TRUE) {
|
|
DWORD Junk;
|
|
|
|
lpszDfsPath[0] = L'\0';
|
|
fDfsStatus = UncPathToDfsPath(
|
|
(PWCHAR)lpszFileName,
|
|
lpszDfsPath,
|
|
sizeof(lpszDfsPath));
|
|
|
|
if (fDfsStatus != TRUE)
|
|
goto AllDone;
|
|
|
|
// DbgPrint("DfsPath(1)=%ws\n", lpszDfsPath);
|
|
|
|
// turn into just \\server\share
|
|
for (sCount = 0, wCp = lpszDfsPath; *wCp !=L'\0'; wCp++) {
|
|
if (*wCp == L'\\') {
|
|
if (++sCount == 4) {
|
|
*wCp = L'\0';
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// DbgPrint("DfsPath(2)=%ws\n", lpszDfsPath);
|
|
fDfsStatus = CSCQueryFileStatusInternal(
|
|
lpszDfsPath,
|
|
&dwDfsStatus,
|
|
&Junk,
|
|
&Junk,
|
|
&Junk,
|
|
&Junk);
|
|
if (
|
|
fDfsStatus == TRUE
|
|
&&
|
|
(dwDfsStatus & FLAG_CSC_SHARE_STATUS_CACHING_MASK) == FLAG_CSC_SHARE_STATUS_NO_CACHING
|
|
) {
|
|
*lpdwStatus &= ~FLAG_CSC_SHARE_STATUS_CACHING_MASK;
|
|
*lpdwStatus |= FLAG_CSC_SHARE_STATUS_NO_CACHING;
|
|
// DbgPrint("New Status=0x%x\n", dwDfsStatus);
|
|
}
|
|
}
|
|
AllDone:
|
|
return fStatus;
|
|
#endif
|
|
}
|
|
|
|
HANDLE
|
|
WINAPI
|
|
CSCFindFirstFileW(
|
|
LPCWSTR lpszFileName,
|
|
WIN32_FIND_DATAW *lpFind32,
|
|
LPDWORD lpdwStatus,
|
|
LPDWORD lpdwPinCount,
|
|
LPDWORD lpdwHintFlags,
|
|
FILETIME *lpOrgFileTime
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifndef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (INVALID_HANDLE_VALUE);
|
|
#else
|
|
return (CSCFindFirstFileInternal(
|
|
lpszFileName,
|
|
CSC_INVALID_PRINCIPAL_ID,
|
|
lpFind32,
|
|
lpdwStatus,
|
|
lpdwPinCount,
|
|
lpdwHintFlags,
|
|
lpOrgFileTime
|
|
));
|
|
#endif
|
|
|
|
}
|
|
|
|
HANDLE
|
|
WINAPI
|
|
CSCFindFirstFileForSidW(
|
|
LPCWSTR lpszFileName,
|
|
PSID pSid,
|
|
WIN32_FIND_DATAW *lpFind32,
|
|
LPDWORD lpdwStatus,
|
|
LPDWORD lpdwPinCount,
|
|
LPDWORD lpdwHintFlags,
|
|
FILETIME *lpOrgFileTime
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
ULONG ulPrincipalID;
|
|
|
|
#ifndef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (INVALID_HANDLE_VALUE);
|
|
#else
|
|
if (pSid)
|
|
{
|
|
if(!FindCreatePrincipalIDFromSID(INVALID_HANDLE_VALUE, pSid, GetLengthSid(pSid), &ulPrincipalID, FALSE))
|
|
{
|
|
return INVALID_HANDLE_VALUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ulPrincipalID = CSC_INVALID_PRINCIPAL_ID;
|
|
}
|
|
|
|
return (CSCFindFirstFileInternal(
|
|
lpszFileName,
|
|
ulPrincipalID,
|
|
lpFind32,
|
|
lpdwStatus,
|
|
lpdwPinCount,
|
|
lpdwHintFlags,
|
|
lpOrgFileTime
|
|
));
|
|
#endif
|
|
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCFindNextFileW(
|
|
HANDLE hFind,
|
|
WIN32_FIND_DATAW *lpFind32,
|
|
LPDWORD lpdwStatus,
|
|
LPDWORD lpdwPinCount,
|
|
LPDWORD lpdwHintFlags,
|
|
FILETIME *lpOrgFileTime
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifndef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return(CSCFindNextFileInternal(
|
|
hFind,
|
|
lpFind32,
|
|
lpdwStatus,
|
|
lpdwPinCount,
|
|
lpdwHintFlags,
|
|
lpOrgFileTime
|
|
));
|
|
#endif
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCDeleteW(
|
|
LPCWSTR lpszFileName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifndef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
|
|
return (CSCDeleteInternal(lpszFileName));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCFillSparseFilesW(
|
|
IN LPCWSTR lpszShareName,
|
|
IN BOOL fFullSync,
|
|
IN LPCSCPROCW lpfnFillProgress,
|
|
IN DWORD_PTR dwContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifndef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return (CSCFillSparseFilesInternal(
|
|
lpszShareName,
|
|
fFullSync,
|
|
lpfnFillProgress,
|
|
dwContext));
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCMergeShareW(
|
|
IN LPCWSTR lpszShareName,
|
|
IN LPCSCPROCW lpfnMergeProgress,
|
|
IN DWORD_PTR dwContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifndef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return(CSCMergeShareInternal(
|
|
lpszShareName,
|
|
lpfnMergeProgress,
|
|
dwContext));
|
|
#endif
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCCopyReplicaW(
|
|
IN LPCWSTR lpszFullPath,
|
|
OUT LPWSTR *lplpszLocalName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifndef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return(CSCCopyReplicaInternal(
|
|
lpszFullPath,
|
|
lplpszLocalName));
|
|
#endif
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCEnumForStatsW(
|
|
IN LPCWSTR lpszShareName,
|
|
IN LPCSCPROCW lpfnEnumProgress,
|
|
IN DWORD_PTR dwContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifndef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return(CSCEnumForStatsInternal(
|
|
lpszShareName,
|
|
lpfnEnumProgress,
|
|
FALSE,
|
|
FALSE,
|
|
dwContext));
|
|
#endif
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCEnumForStatsExA(
|
|
IN LPCSTR lpszShareName,
|
|
IN LPCSCPROCA lpfnEnumProgress,
|
|
IN DWORD_PTR dwContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCEnumForStatsExW(
|
|
IN LPCWSTR lpszShareName,
|
|
IN LPCSCPROCW lpfnEnumProgress,
|
|
IN DWORD_PTR dwContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
#ifndef UNICODE
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
#else
|
|
return(CSCEnumForStatsInternal(
|
|
lpszShareName,
|
|
lpfnEnumProgress,
|
|
TRUE,
|
|
FALSE,
|
|
dwContext));
|
|
#endif
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCFreeSpace(
|
|
DWORD nFileSizeHigh,
|
|
DWORD nFileSizeLow
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
SHADOWSTORE sSTLast, sST;
|
|
BOOL fRet = FALSE;
|
|
|
|
if(!GetSpaceStats(INVALID_HANDLE_VALUE, &sSTLast))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
do
|
|
{
|
|
if (!FreeShadowSpace(INVALID_HANDLE_VALUE, nFileSizeHigh, nFileSizeLow, FALSE))
|
|
{
|
|
break;
|
|
}
|
|
|
|
if(!GetSpaceStats(INVALID_HANDLE_VALUE, &sST))
|
|
{
|
|
break;
|
|
}
|
|
|
|
// check if we are making any progress over successive
|
|
// free space calls. If the current space used is greater than
|
|
// after we last called, just quit.
|
|
|
|
if (sST.sCur.ulSize >= sSTLast.sCur.ulSize)
|
|
{
|
|
fRet = TRUE;
|
|
break;
|
|
}
|
|
|
|
sSTLast = sST;
|
|
|
|
}
|
|
while (TRUE);
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCIsServerOfflineW(
|
|
LPCWSTR lptzServerName,
|
|
BOOL *lpfOffline
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
return(IsServerOfflineW(INVALID_HANDLE_VALUE, lptzServerName, lpfOffline));
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCIsServerOfflineA(
|
|
LPCSTR lptzServerName,
|
|
BOOL *lpfOffline
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
return(IsServerOfflineA(INVALID_HANDLE_VALUE, lptzServerName, lpfOffline));
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCTransitionServerOnlineW(
|
|
IN LPCWSTR lpszShareName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine transitions the server for the given share to online.
|
|
|
|
Arguments:
|
|
|
|
lpszShareName
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
|
|
WIN32_FIND_DATA sFind32;
|
|
SHADOWINFO sSI;
|
|
BOOL fTransitionedToOnline = FALSE, fDone=FALSE;
|
|
_TCHAR tchBuff[MAX_SERVER_SHARE_NAME_FOR_CSC], tzDrive[4];
|
|
DWORD i;
|
|
|
|
if (lstrlen(lpszShareName) >= MAX_SERVER_SHARE_NAME_FOR_CSC)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
lstrcpy(tchBuff, lpszShareName);
|
|
|
|
if (!LpBreakPath(tchBuff, TRUE, &fDone) && !fDone)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
tzDrive[0] = 0;
|
|
|
|
if(FindCreateShadowFromPath(tchBuff, FALSE, &sFind32, &sSI, NULL))
|
|
{
|
|
LPCONNECTINFO lpHead = NULL;
|
|
BOOL fServerIsOffline = FALSE;
|
|
|
|
fServerIsOffline = ((sSI.uStatus & SHARE_DISCONNECTED_OP) != 0);
|
|
|
|
|
|
if(FGetConnectionListEx(&lpHead, tchBuff, TRUE, fServerIsOffline, NULL))
|
|
{
|
|
// take an extra reference, just in case there are some credentials on the server entry
|
|
// with the redir
|
|
// if it fails, don't stop going online
|
|
// the worst that could happen is that the user might get an extra popup
|
|
// for the explicit credential case
|
|
DWORD dwError;
|
|
|
|
dwError = DWConnectNet(tchBuff, tzDrive, NULL, NULL, NULL, 0, NULL);
|
|
if ((dwError != WN_SUCCESS) && (dwError != WN_CONNECTED_OTHER_PASSWORD_DEFAULT))
|
|
{
|
|
tzDrive[0] = 0;
|
|
}
|
|
|
|
DisconnectList(&lpHead, NULL, 0);
|
|
}
|
|
|
|
fTransitionedToOnline = TransitionShareToOnline(INVALID_HANDLE_VALUE, sSI.hShare);
|
|
|
|
for (i=2;i<MAX_SERVER_SHARE_NAME_FOR_CSC;++i)
|
|
{
|
|
if (tchBuff[i] == '\\')
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
Assert(i< MAX_SERVER_SHARE_NAME_FOR_CSC);
|
|
|
|
// going online
|
|
ReportTransitionToDfs(tchBuff, FALSE, i*sizeof(_TCHAR));
|
|
|
|
if (lpHead)
|
|
{
|
|
ReconnectList(&lpHead, NULL);
|
|
ClearConnectionList(&lpHead);
|
|
|
|
}
|
|
|
|
// if there was an extra reference,
|
|
// remove it
|
|
if (tzDrive[0])
|
|
{
|
|
DWDisconnectDriveMappedNet(tzDrive, TRUE);
|
|
}
|
|
}
|
|
|
|
return(fTransitionedToOnline);
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCTransitionServerOnlineA(
|
|
IN LPCSTR lpszShareName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCCheckShareOnlineExW(
|
|
IN LPCWSTR lpszShareName,
|
|
LPDWORD lpdwSpeed
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine checks whether a given share is available online.
|
|
|
|
Arguments:
|
|
|
|
lpszShareName
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
|
|
_TCHAR tchBuff[MAX_SERVER_SHARE_NAME_FOR_CSC], tzDrive[4];
|
|
BOOL fIsOnline = FALSE, fDone;
|
|
DWORD dwError;
|
|
|
|
if (lstrlen(lpszShareName) >= MAX_SERVER_SHARE_NAME_FOR_CSC)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
lstrcpy(tchBuff, lpszShareName);
|
|
|
|
if (!LpBreakPath(tchBuff, TRUE, &fDone) && !fDone)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
dwError = DWConnectNet(tchBuff, tzDrive, NULL, NULL, NULL, 0, NULL);
|
|
if ((dwError == WN_SUCCESS) || (dwError == WN_CONNECTED_OTHER_PASSWORD_DEFAULT))
|
|
{
|
|
fIsOnline = TRUE;
|
|
|
|
if (lpdwSpeed)
|
|
{
|
|
GetConnectionInfoForDriveBasedName(tzDrive, lpdwSpeed);
|
|
}
|
|
DWDisconnectDriveMappedNet(tzDrive, TRUE);
|
|
}
|
|
else
|
|
{
|
|
SetLastError(dwError);
|
|
}
|
|
|
|
return(fIsOnline);
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCCheckShareOnlineW(
|
|
IN LPCWSTR lpszShareName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine checks whether a given share is available online.
|
|
|
|
Arguments:
|
|
|
|
lpszShareName
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
return (CSCCheckShareOnlineExW(lpszShareName, NULL));
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCCheckShareOnlineA(
|
|
IN LPCSTR lpszShareName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCDoLocalRenameW(
|
|
IN LPCWSTR lpszSource,
|
|
IN LPCWSTR lpszDestination,
|
|
IN BOOL fReplaceFileIfExists
|
|
)
|
|
{
|
|
return CSCDoLocalRenameExW(lpszSource, lpszDestination, NULL, FALSE, fReplaceFileIfExists);
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCDoLocalRenameExW(
|
|
IN LPCWSTR lpszSource,
|
|
IN LPCWSTR lpszDestination,
|
|
IN WIN32_FIND_DATAW *lpFind32,
|
|
IN BOOL fMarkAsLocal,
|
|
IN BOOL fReplaceFileIfExists
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine does a rename in the datbase. The rename operation can be across shares
|
|
|
|
Arguments:
|
|
|
|
lpszSource Fully qualified source name (must be UNC)
|
|
|
|
lpszDestination Fully qualified destination directory name (must be UNC)
|
|
|
|
lpFind32 New name in the destination directory, given the long name
|
|
the shortnmae is locally generated. For this reason, when
|
|
a new name is given, fMarkAsLocal is forced TRUE.
|
|
|
|
fMarkAsLocal Mark the newly created entry as locally created (except see lpFind32)
|
|
|
|
fReplaceFileIfExists replace destination file with the source if it exists
|
|
|
|
Returns:
|
|
|
|
TRUE if successfull, FALSE otherwise. If the API fails, GetLastError returns the specific
|
|
errorcode.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
|
|
DWORD dwError = NO_ERROR;
|
|
WIN32_FIND_DATA sFind32;
|
|
BOOL fDone=FALSE, fRet = FALSE, fBeginInodeTransaction = FALSE, fSourceIsFile=FALSE;
|
|
SHADOWINFO sSI;
|
|
HSHADOW hDirFrom, hShadowFrom, hDirTo, hShadowTo=0;
|
|
HSHARE hShareFrom, hShareTo;
|
|
HANDLE hShadowDB;
|
|
DWORD lenSrc=0, lenDst=0;
|
|
|
|
ReintKdPrint(API, ("DoLocalRenameEx %ls %ls %x %x %x\r\n", lpszSource, lpszDestination, lpFind32, fMarkAsLocal, fReplaceFileIfExists));
|
|
|
|
try
|
|
{
|
|
if ((lenSrc = lstrlen(lpszSource)) >= MAX_PATH)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
lstrcpy(sFind32.cFileName, lpszSource);
|
|
|
|
if (!LpBreakPath(sFind32.cFileName, TRUE, &fDone) && fDone)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
}
|
|
except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
try
|
|
{
|
|
if ((lenDst = lstrlen(lpszDestination)) >= MAX_PATH)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
// if source is not greater than the destination
|
|
// verify that we are not renaming the parent under it's own child
|
|
|
|
if (lenSrc <= lenDst)
|
|
{
|
|
lstrcpy(sFind32.cFileName, lpszDestination);
|
|
sFind32.cFileName[lenSrc] = 0;
|
|
|
|
// make a case insensitive comparison
|
|
if(!lstrcmpi(lpszSource, sFind32.cFileName))
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if ((hShadowDB = OpenShadowDatabaseIO()) ==INVALID_HANDLE_VALUE)
|
|
{
|
|
ReintKdPrint(BADERRORS, ("failed to open database\r\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
if(BeginInodeTransactionHSHADOW())
|
|
{
|
|
fBeginInodeTransaction = TRUE;
|
|
|
|
if(!FindCreateShadowFromPath(lpszSource, FALSE, &sFind32, &sSI, NULL))
|
|
{
|
|
goto bailout;
|
|
}
|
|
|
|
ReintKdPrint(API, ("Source Share = %x Inode %x %x\r\n", sSI.hShare, sSI.hDir, sSI.hShadow));
|
|
|
|
hDirFrom = sSI.hDir;
|
|
hShadowFrom = sSI.hShadow;
|
|
hShareFrom = sSI.hShare;
|
|
fSourceIsFile = ((sFind32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)==0);
|
|
|
|
if(!FindCreateShadowFromPath(lpszDestination, TRUE, &sFind32, &sSI, NULL))
|
|
{
|
|
goto bailout;
|
|
}
|
|
|
|
ReintKdPrint(API, ("Destination Share = %x Inode %x %x\r\n", sSI.hShare, sSI.hDir, sSI.hShadow));
|
|
hShareTo = sSI.hShare;
|
|
hDirTo = sSI.hShadow;
|
|
|
|
// if we are creating a new entry in the database, we say it was created
|
|
// offline
|
|
if (lpFind32)
|
|
{
|
|
fMarkAsLocal = TRUE;
|
|
fReplaceFileIfExists = FALSE;
|
|
}
|
|
|
|
if (((hShareFrom == hShareTo) && !fReplaceFileIfExists) ||fSourceIsFile)
|
|
{
|
|
// do the rename only if the source directory is not the same as the destination directory.
|
|
// or the destination name is different, otherwise there is nothing to do
|
|
if ((hDirFrom != sSI.hShadow)||(lpFind32))
|
|
{
|
|
|
|
if (RenameShadow(hShadowDB, hDirFrom, hShadowFrom, hDirTo, lpFind32, fReplaceFileIfExists, &hShadowTo))
|
|
{
|
|
//
|
|
fRet = SetShareStatus(hShadowDB, hShareTo, SHARE_REINT, SHADOW_FLAGS_OR);
|
|
|
|
if (fMarkAsLocal)
|
|
{
|
|
Assert(hShadowTo);
|
|
if (fSourceIsFile)
|
|
{
|
|
fRet = SetShadowInfo(hShadowDB, hDirTo, hShadowTo, NULL, SHADOW_LOCALLY_CREATED, SHADOW_FLAGS_ASSIGN);
|
|
}
|
|
else
|
|
{
|
|
SET_SUBTREE_STATUS sSSS;
|
|
memset(&sSSS, 0, sizeof(sSSS));
|
|
sSSS.uStatus = SHADOW_LOCALLY_CREATED;
|
|
sSSS.uOp = SHADOW_FLAGS_ASSIGN;
|
|
fRet = (TraverseOneDirectory(hShadowDB, NULL, hDirTo, hShadowTo, (LPTSTR)lpszSource, SetSubtreeStatus, &sSSS)!=TOD_ABORT);
|
|
}
|
|
}
|
|
if (!fRet)
|
|
{
|
|
dwError = GetLastError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwError = GetLastError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MOVE_SUBTREE sMST;
|
|
|
|
memset(&sMST, 0, sizeof(sMST));
|
|
|
|
sMST.lptzSource = lpszSource;
|
|
sMST.lptzDestination = lpszDestination;
|
|
sMST.lpTos = &sMST.sTos;
|
|
sMST.sTos.hDir = hDirTo;
|
|
sMST.hShareTo = hShareTo;
|
|
|
|
if (fReplaceFileIfExists)
|
|
{
|
|
sMST.dwFlags |= MST_REPLACE_IF_EXISTS;
|
|
}
|
|
|
|
TraverseOneDirectory(hShadowDB, NULL, hDirFrom, hShadowFrom, (LPTSTR)lpszSource, MoveSubtree, &sMST);
|
|
|
|
fRet = (sMST.cntFail == 0);
|
|
|
|
Assert(sMST.lpTos == &sMST.sTos);
|
|
Assert(sMST.sTos.lpNext == NULL);
|
|
}
|
|
}
|
|
|
|
bailout:
|
|
if (fBeginInodeTransaction)
|
|
{
|
|
EndInodeTransactionHSHADOW();
|
|
}
|
|
if (!fRet)
|
|
{
|
|
SetLastError(dwError);
|
|
}
|
|
|
|
CloseShadowDatabaseIO(hShadowDB);
|
|
|
|
return fRet;
|
|
}
|
|
|
|
BOOL
|
|
CreateDirectoryAndSetHints(
|
|
HANDLE hShadowDB,
|
|
LPTSTR lptzFullPath,
|
|
DWORD dwCallbackReason,
|
|
WIN32_FIND_DATA *lpFind32,
|
|
SHADOWINFO *lpSI,
|
|
LPMOVE_SUBTREE lpMst
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine creates a copy of a source directory under a destination directory
|
|
|
|
Arguments:
|
|
|
|
hShadowDB Handle to issue ioctls to the redir
|
|
|
|
lptzFullPath fully qualified path to the item
|
|
|
|
dwCallbackReason TOD_CALLBACK_REASON_XXX (BEGIN, NEXT_ITEM or END)
|
|
|
|
lpFind32 local win32info
|
|
|
|
lpSI other info such as priority, pincount etc.
|
|
|
|
lpMst MOVE_SUBTREE structure which contains the rlevant info about this move
|
|
|
|
|
|
Returns:
|
|
|
|
TRUE if successfull, FALSE otherwise. If the API fails, GetLastError returns the specific
|
|
errorcode.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
BOOL fRet = FALSE;
|
|
|
|
lpMst->sFind32 = *lpFind32;
|
|
if(GetShadowEx(hShadowDB, lpMst->lpTos->hDir, &lpMst->sFind32, &lpMst->sSI))
|
|
{
|
|
// if it doesn't exist, create it and set it's hints to those found on the source
|
|
if (!lpMst->sSI.hShadow)
|
|
{
|
|
if (CreateShadow(hShadowDB, lpMst->lpTos->hDir, &lpMst->sFind32, lpSI->uStatus, &lpMst->sSI.hShadow))
|
|
{
|
|
lpMst->sSI.ulHintPri = lpSI->ulHintPri;
|
|
lpMst->sSI.ulHintFlags = lpSI->ulHintFlags;
|
|
|
|
if(AddHintFromInode(hShadowDB, lpMst->lpTos->hDir, lpMst->sSI.hShadow, &(lpMst->sSI.ulHintPri), &(lpMst->sSI.ulHintFlags)) != 0)
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCDoLocalRenameA(
|
|
IN LPCSTR lpszSource,
|
|
IN LPCSTR lpszDestination,
|
|
IN BOOL fReplcaeFileIfExists
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine does a rename in the datbase. The rename operation can be across shares
|
|
|
|
Arguments:
|
|
|
|
lpszSource Fully qualified source name (must be UNC)
|
|
|
|
lpszDestination Fully qualified destination name (must be UNC)
|
|
|
|
Returns:
|
|
|
|
TRUE if successfull, FALSE otherwise. If the API fails, GetLastError returns the specific
|
|
errorcode.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
return (FALSE);
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCDoEnableDisable(
|
|
BOOL fEnable
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine enables/disables CSC
|
|
|
|
Arguments:
|
|
|
|
fEnable enable CSC if TRUE, else disable CSC
|
|
|
|
Returns:
|
|
|
|
TRUE if successfull, FALSE otherwise. If the API fails, GetLastError returns the specific
|
|
errorcode.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
BOOL fRet = FALSE, fReformat = FALSE;
|
|
char szDBDir[MAX_PATH+1];
|
|
DWORD dwDBCapacity, dwClusterSize;
|
|
|
|
if (IsPersonal() == TRUE) {
|
|
SetLastError(ERROR_INVALID_OPERATION);
|
|
return FALSE;
|
|
}
|
|
|
|
if (fEnable)
|
|
{
|
|
if (InitValues(szDBDir, sizeof(szDBDir), &dwDBCapacity, &dwClusterSize))
|
|
{
|
|
fReformat = QueryFormatDatabase();
|
|
|
|
fRet = EnableShadowingForUser(INVALID_HANDLE_VALUE, szDBDir, NULL, 0, dwDBCapacity, dwClusterSize, fReformat);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fRet = DisableShadowingForUser(INVALID_HANDLE_VALUE);
|
|
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
|
|
int
|
|
MoveSubtree(
|
|
HANDLE hShadowDB,
|
|
LPSECURITYINFO pShareSecurityInfo,
|
|
LPTSTR lptzFullPath,
|
|
DWORD dwCallbackReason,
|
|
WIN32_FIND_DATA *lpFind32,
|
|
SHADOWINFO *lpSI,
|
|
LPMOVE_SUBTREE lpMst
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is a callback routine to TraverseOneDirectory. It moves the subtree from one place
|
|
in the hierarchy to another. It would be necessary to call this routine only when
|
|
the subtree is being moved from one share to another.
|
|
|
|
Arguments:
|
|
|
|
hShadowDB Handle to issue ioctls to the redir
|
|
|
|
lptzFullPath fully qualified path to the item
|
|
|
|
dwCallbackReason TOD_CALLBACK_REASON_XXX (BEGIN, NEXT_ITEM or END)
|
|
|
|
lpFind32 local win32info
|
|
|
|
lpSI other info such as priority, pincount etc.
|
|
|
|
lpMst MOVE_SUBTREE structure which contains the rlevant info about this move
|
|
|
|
|
|
Returns:
|
|
|
|
return code, whether continue, cancel etc.
|
|
|
|
Notes:
|
|
|
|
As TravesreOneDirectory descends the source subtree, this routine creates directories in the
|
|
corresponding location in the destination subtree. It then moves the files from one subtree
|
|
to another. At the end of the enumeration of any directory, it tries to delete the source
|
|
directory. The delete succeeds only if there are no more descedents left to the source
|
|
directory
|
|
|
|
--*/
|
|
{
|
|
BOOL fRet = FALSE;
|
|
LPMST_LIST lpT;
|
|
|
|
ReintKdPrint(API, ("MoveSubTree %ls\r\n", lptzFullPath));
|
|
|
|
switch (dwCallbackReason)
|
|
{
|
|
case TOD_CALLBACK_REASON_BEGIN:
|
|
{
|
|
ReintKdPrint(API, ("MST Begin source Inode %x %x\r\n", lpSI->hDir, lpSI->hShadow));
|
|
|
|
// Get the source directory info
|
|
if (GetShadowInfoEx(hShadowDB, lpSI->hDir, lpSI->hShadow, lpFind32, lpSI))
|
|
{
|
|
fRet = CreateDirectoryAndSetHints(hShadowDB, lptzFullPath, dwCallbackReason, lpFind32, lpSI, lpMst);
|
|
}
|
|
// if all is well, then make this directory the parent directory for
|
|
// all subsequent creates and renames
|
|
|
|
if (fRet)
|
|
{
|
|
|
|
lpT = (LPMST_LIST)LocalAlloc(LPTR, sizeof(MST_LIST));
|
|
|
|
if (!lpT)
|
|
{
|
|
return TOD_ABORT;
|
|
}
|
|
|
|
lpT->hDir = lpMst->sSI.hShadow;
|
|
lpT->lpNext = lpMst->lpTos;
|
|
lpMst->lpTos = lpT;
|
|
|
|
// mark the destination share dirty, if necessary
|
|
if (lpSI->uStatus & SHADOW_MODFLAGS)
|
|
{
|
|
if (!(lpMst->dwFlags & MST_SHARE_MARKED_DIRTY))
|
|
{
|
|
ReintKdPrint(API, ("Setting Share %x dirty \n", lpMst->hShareTo));
|
|
|
|
if(SetShareStatus(hShadowDB, lpMst->hShareTo, SHARE_REINT, SHADOW_FLAGS_OR))
|
|
{
|
|
lpMst->dwFlags |= MST_SHARE_MARKED_DIRTY;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lpMst->cntFail++;
|
|
}
|
|
}
|
|
break;
|
|
case TOD_CALLBACK_REASON_NEXT_ITEM:
|
|
// if the source is a file, then move it
|
|
ReintKdPrint(API, ("MST next source Inode %x %x\r\n", lpSI->hDir, lpSI->hShadow));
|
|
if(!(lpFind32->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
{
|
|
ReintKdPrint(API, ("MST rename file SrcInode %x %x to destdir %x\r\n", lpSI->hDir, lpSI->hShadow, lpMst->lpTos->hDir));
|
|
if (RenameShadow(hShadowDB, lpSI->hDir, lpSI->hShadow, lpMst->lpTos->hDir, NULL,
|
|
((lpMst->dwFlags & MST_REPLACE_IF_EXISTS)!=0), NULL))
|
|
{
|
|
fRet = TRUE;
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(CreateDirectoryAndSetHints(hShadowDB, lptzFullPath, dwCallbackReason, lpFind32, lpSI, lpMst))
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
}
|
|
|
|
if (!fRet)
|
|
{
|
|
lpMst->cntFail++;
|
|
}
|
|
// mark the destination share dirty, if necessary
|
|
if (lpSI->uStatus & SHADOW_MODFLAGS)
|
|
{
|
|
if (!(lpMst->dwFlags & MST_SHARE_MARKED_DIRTY))
|
|
{
|
|
if(SetShareStatus(hShadowDB, lpMst->hShareTo, SHARE_REINT, SHADOW_FLAGS_OR))
|
|
{
|
|
lpMst->dwFlags |= MST_SHARE_MARKED_DIRTY;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case TOD_CALLBACK_REASON_END:
|
|
Assert(lpMst->lpTos);
|
|
lpT = lpMst->lpTos;
|
|
lpMst->lpTos = lpMst->lpTos->lpNext;
|
|
LocalFree(lpT);
|
|
fRet = TRUE;
|
|
|
|
ReintKdPrint(API, ("MST End Delete Inode %x %x \r\n", lpSI->hDir, lpSI->hShadow));
|
|
DeleteShadow(hShadowDB, lpSI->hDir, lpSI->hShadow);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return (fRet?TOD_CONTINUE:TOD_ABORT);
|
|
}
|
|
|
|
int
|
|
SetSubtreeStatus(
|
|
HANDLE hShadowDB,
|
|
LPSECURITYINFO pShareSecurityInfo,
|
|
LPTSTR lptzFullPath,
|
|
DWORD dwCallbackReason,
|
|
WIN32_FIND_DATA *lpFind32,
|
|
SHADOWINFO *lpSI,
|
|
LPSET_SUBTREE_STATUS lpSss
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is a callback routine to TraverseOneDirectory. It moves the subtree from one place
|
|
in the hierarchy to another. It would be necessary to call this routine only when
|
|
the subtree is being moved from one share to another.
|
|
|
|
Arguments:
|
|
|
|
hShadowDB Handle to issue ioctls to the redir
|
|
|
|
lptzFullPath fully qualified path to the item
|
|
|
|
dwCallbackReason TOD_CALLBACK_REASON_XXX (BEGIN, NEXT_ITEM or END)
|
|
|
|
lpFind32 local win32info
|
|
|
|
lpSI other info such as priority, pincount etc.
|
|
|
|
lpSss SET_SUBTREE_STATE structure which contains the relevant info about this state setting
|
|
|
|
|
|
Returns:
|
|
|
|
return code, whether continue, cancel etc.
|
|
|
|
Notes:
|
|
|
|
As TravesreOneDirectory descends the source subtree, this routine sets the required bits
|
|
|
|
--*/
|
|
{
|
|
|
|
ReintKdPrint(API, ("SetSubTreeState %ls\r\n", lptzFullPath));
|
|
|
|
if(SetShadowInfo(hShadowDB, lpSI->hDir, lpSI->hShadow, NULL, lpSss->uStatus, lpSss->uOp) == TRUE)
|
|
{
|
|
return TOD_CONTINUE;
|
|
}
|
|
else
|
|
{
|
|
return TOD_ABORT;
|
|
}
|
|
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCBeginSynchronizationW(
|
|
IN LPCTSTR lpszShareName,
|
|
LPDWORD lpdwSpeed,
|
|
LPDWORD lpdwContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
|
|
--*/
|
|
{
|
|
_TCHAR tchBuff[MAX_SERVER_SHARE_NAME_FOR_CSC], tzDrive[4];
|
|
BOOL fIsOnline = FALSE, fDone, fExplicitCredentials=FALSE, fIsDfs;
|
|
DWORD dwError;
|
|
|
|
if (lstrlen(lpszShareName) >= MAX_SERVER_SHARE_NAME_FOR_CSC)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
lstrcpy(tchBuff, lpszShareName);
|
|
|
|
if (!LpBreakPath(tchBuff, TRUE, &fDone) && !fDone)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
ReintKdPrint(API, (" CSCBeginSynchronization %ls\r\n", tchBuff));
|
|
|
|
dwError = DWConnectNet(tchBuff, tzDrive, NULL, NULL, NULL, CONNECT_INTERACTIVE, NULL);
|
|
if ((dwError == WN_SUCCESS)||(dwError==WN_CONNECTED_OTHER_PASSWORD)||(dwError==WN_CONNECTED_OTHER_PASSWORD_DEFAULT))
|
|
{
|
|
fIsOnline = TRUE;
|
|
|
|
if (lpdwSpeed)
|
|
{
|
|
GetConnectionInfoForDriveBasedName(tzDrive, lpdwSpeed);
|
|
}
|
|
|
|
if (dwError==WN_CONNECTED_OTHER_PASSWORD || dwError==WN_CONNECTED_OTHER_PASSWORD_DEFAULT)
|
|
{
|
|
ReintKdPrint(API, (" CSCBeginSynchronization: Explicit Credentials\r\n"));
|
|
fExplicitCredentials = TRUE;
|
|
|
|
dwError = DoNetUseAddForAgent(tchBuff, NULL, NULL, NULL, NULL, 0, &fIsDfs);
|
|
if (dwError != WN_SUCCESS && dwError!=WN_CONNECTED_OTHER_PASSWORD_DEFAULT)
|
|
{
|
|
fIsOnline = FALSE;
|
|
ReintKdPrint(API, (" CSCBeginSynchronization: Failed extra reference %d\r\n", dwError));
|
|
}
|
|
}
|
|
|
|
DWDisconnectDriveMappedNet(tzDrive, TRUE);
|
|
}
|
|
|
|
if (!fIsOnline)
|
|
{
|
|
ReintKdPrint(ALWAYS, (" CSCBeginSynchronization: Failed %d\r\n", dwError));
|
|
SetLastError(dwError);
|
|
}
|
|
else
|
|
{
|
|
*lpdwContext = fExplicitCredentials;
|
|
}
|
|
|
|
return(fIsOnline);
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCEndSynchronizationW(
|
|
IN LPCTSTR lpszShareName,
|
|
DWORD dwContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
|
|
--*/
|
|
{
|
|
_TCHAR tchBuff[MAX_SERVER_SHARE_NAME_FOR_CSC], tzDrive[4];
|
|
BOOL fIsOnline = FALSE, fDone, fExplicitCredentials=FALSE;
|
|
DWORD dwError;
|
|
|
|
if (lstrlen(lpszShareName) >= MAX_SERVER_SHARE_NAME_FOR_CSC)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
lstrcpy(tchBuff, lpszShareName);
|
|
|
|
if (!LpBreakPath(tchBuff, TRUE, &fDone) && !fDone)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
if (dwContext != 0)
|
|
{
|
|
WNetCancelConnection2(tchBuff, 0, TRUE);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#if 0
|
|
BOOL
|
|
WINAPI
|
|
CSCEncryptDecryptFileW(
|
|
IN LPCTSTR lpszFileName,
|
|
IN BOOL fEncrypt
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
Notes:
|
|
|
|
|
|
--*/
|
|
{
|
|
WIN32_FIND_DATA sFind32;
|
|
SHADOWINFO sSI;
|
|
BOOL fRet = FALSE;
|
|
DWORD dwError = ERROR_GEN_FAILURE;
|
|
|
|
//
|
|
if(FindCreateShadowFromPath(lpszFileName, FALSE, &sFind32, &sSI, NULL))
|
|
{
|
|
fRet = RecreateShadow(INVALID_HANDLE_VALUE, sSI.hDir, sSI.hShadow, (fEncrypt)?FILE_ATTRIBUTE_ENCRYPTED:0);
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
#endif
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCQueryDatabaseStatus(
|
|
ULONG *pulStatus,
|
|
ULONG *pulErrors
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Allows caller to query the database status.
|
|
|
|
Arguments:
|
|
|
|
pulStatus Current status. Encryption status is the most interesting
|
|
|
|
pulErrors If the database has any errors, one or more bits will be set
|
|
|
|
Returns:
|
|
|
|
TRUE if the API succeeded
|
|
|
|
Notes:
|
|
|
|
|
|
--*/
|
|
{
|
|
GLOBALSTATUS sGS;
|
|
|
|
if(!GetGlobalStatus(INVALID_HANDLE_VALUE, &sGS))
|
|
{
|
|
return FALSE;
|
|
}
|
|
*pulStatus = sGS.sST.uFlags;
|
|
*pulErrors = sGS.uDatabaseErrorFlags;
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCEncryptDecryptDatabase(
|
|
IN BOOL fEncrypt,
|
|
IN LPCSCPROCW lpfnEnumProgress,
|
|
IN DWORD_PTR dwContext
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used to encrypt/decrypt the entire database in system context. The routine checks that
|
|
the CSC database is hosted on a filesystem that allows encryption. Only admins can do the conversion
|
|
|
|
|
|
Arguments:
|
|
|
|
fEncrypt if TRUE, we encrypt the database else we decrypt.
|
|
|
|
LPCSCPROCW callback proc. The usual set of CSCPROC_REASON_BEGIN, CSCPROC_REASON_MORE_DATA, CSC_PROC_END
|
|
are sent when the conversion actually begins. Conversion can fail if a file is open or for
|
|
some other reason, in which case the second to last parameter in the callback with
|
|
CSCPROC_REASON_MORE_DATA has the error code. The third to last parameter indicates whether
|
|
the conversion was complete or not. Incomplete conversion is not an error condition.
|
|
|
|
dwContext callback context
|
|
|
|
Returns:
|
|
|
|
TRUE if no errors encountered.
|
|
|
|
Notes:
|
|
|
|
|
|
Theory of operations:
|
|
|
|
The CSC database encryption code encrypts all the inodes represented by remote files.
|
|
Who: Only user in admingroup can do encryption/decryption. This is checked in kernel
|
|
Which context: Files are encrypted in system context. This allows files to be shared
|
|
while still being encrypted. This solution protects from a stolen laptop case.
|
|
|
|
The database can have the following status set on it based on the four encryption states:
|
|
|
|
a) FLAG_DATABASESTATUS_UNENCRYPTED b) FLAG_DATABASESTATUS_PARTIALLY_UNENCRYPTED
|
|
c) FLAG_DATABASESTATUS_ENCRYPTED d) FLAG_DATABASESTATUS_PARTIALLY_ENCRYPTED
|
|
|
|
In states a) and b) new files are created unencrypted. In states c) and d) new files are created encrypted.
|
|
|
|
At the beginning of the conversion, the database stats is marked to the appropriate XX_PARTIAL_XX
|
|
state. At the end, if all goes well, it is transitioned to the final state.
|
|
At the time of enabling CSC, if the database state is XX_PARTIAL_XX, the kernel code tries to
|
|
complete the conversion to the appropriate final state.
|
|
|
|
|
|
|
|
|
|
--*/
|
|
{
|
|
BOOL fRet = FALSE, fComplete = FALSE;
|
|
HANDLE hShadowDB = INVALID_HANDLE_VALUE;
|
|
SHADOWSTORE sST;
|
|
DWORD dwRet, dwError=0, dwStartigNameSpaceVersion;
|
|
ULONG uT;
|
|
WIN32_FIND_DATA sFind32;
|
|
ENCRYPT_DECRYPT_SUBTREE sEDS;
|
|
SHADOWINFO sSI;
|
|
HANDLE ulEnumCookie;
|
|
|
|
// we have begun
|
|
if (lpfnEnumProgress)
|
|
{
|
|
dwRet = (*lpfnEnumProgress)(NULL, 0, 0, 0, NULL, CSCPROC_REASON_BEGIN, fEncrypt, 0, dwContext);
|
|
|
|
if (dwRet != CSCPROC_RETURN_CONTINUE )
|
|
{
|
|
goto bailout;
|
|
}
|
|
}
|
|
|
|
if (GetShadowDatabaseLocation(INVALID_HANDLE_VALUE, &sFind32))
|
|
{
|
|
|
|
// Set NULL after the root backslash so that this API works correctly
|
|
sFind32.cFileName[3] = 0;
|
|
|
|
if(!GetVolumeInformation(sFind32.cFileName, NULL, 0, NULL, &dwRet, &dwError, NULL, 0))
|
|
{
|
|
ReintKdPrint(BADERRORS, ("failed to get volume info for %ls Error=%d\r\n", sFind32.cFileName, GetLastError()));
|
|
goto bailout;
|
|
|
|
}
|
|
if (!(dwError & FILE_SUPPORTS_ENCRYPTION))
|
|
{
|
|
ReintKdPrint(BADERRORS, ("volume doesn't support replication \r\n"));
|
|
SetLastError(ERROR_NOT_SUPPORTED);
|
|
goto bailout;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
ReintKdPrint(BADERRORS, ("failed to get database location Error=%d\r\n", GetLastError()));
|
|
goto bailout;
|
|
}
|
|
|
|
if ((hShadowDB = OpenShadowDatabaseIO())==INVALID_HANDLE_VALUE)
|
|
{
|
|
goto bailout;
|
|
}
|
|
|
|
// let us see whether we need to do anything
|
|
if(!GetSpaceStats(hShadowDB, &sST))
|
|
{
|
|
goto bailout;
|
|
}
|
|
|
|
sST.uFlags &= FLAG_DATABASESTATUS_ENCRYPTION_MASK;
|
|
|
|
// the database is already in the state desired, succeed and quit
|
|
if ((fEncrypt && (sST.uFlags == FLAG_DATABASESTATUS_ENCRYPTED))||
|
|
(!fEncrypt && (sST.uFlags == FLAG_DATABASESTATUS_UNENCRYPTED)))
|
|
{
|
|
fRet = TRUE;
|
|
goto bailout;
|
|
}
|
|
|
|
|
|
sST.uFlags = (fEncrypt)? FLAG_DATABASESTATUS_PARTIALLY_ENCRYPTED : FLAG_DATABASESTATUS_PARTIALLY_UNENCRYPTED;
|
|
|
|
// mark the database in appropriate transient state
|
|
// once this is marked, any new file that is created is in correct encryption state
|
|
if (!SetDatabaseStatus(hShadowDB, sST.uFlags, FLAG_DATABASESTATUS_ENCRYPTION_MASK))
|
|
{
|
|
goto bailout;
|
|
}
|
|
|
|
|
|
memset(&sEDS, 0, sizeof(sEDS));
|
|
memset(&sFind32, 0, sizeof(sFind32));
|
|
lstrcpy(sFind32.cFileName, _TEXT("*"));
|
|
|
|
if(!FindOpenShadow( hShadowDB, 0, FINDOPEN_SHADOWINFO_ALL,
|
|
&sFind32, &sSI))
|
|
{
|
|
// The database is empty, so set the state to fully encrypted (or decrypted)
|
|
sST.uFlags = (fEncrypt)? FLAG_DATABASESTATUS_ENCRYPTED : FLAG_DATABASESTATUS_UNENCRYPTED;
|
|
SetDatabaseStatus(hShadowDB, sST.uFlags, FLAG_DATABASESTATUS_ENCRYPTION_MASK);
|
|
goto bailout;
|
|
}
|
|
|
|
dwStartigNameSpaceVersion = sSI.dwNameSpaceVersion;
|
|
ulEnumCookie = sSI.uEnumCookie;
|
|
|
|
sEDS.dwContext = dwContext;
|
|
sEDS.lpfnEnumProgress = lpfnEnumProgress;
|
|
sEDS.fEncrypt = fEncrypt;
|
|
|
|
ReintKdPrint(ALWAYS, ("Starting NameSpaceVersion %x \n", dwStartigNameSpaceVersion));
|
|
do {
|
|
|
|
if(TraverseOneDirectory(hShadowDB, NULL, sSI.hDir, sSI.hShadow, sFind32.cFileName, EncryptDecryptSubtree, &sEDS)==TOD_ABORT)
|
|
{
|
|
break;
|
|
}
|
|
|
|
}while(FindNextShadow(hShadowDB, ulEnumCookie, &sFind32, &sSI));
|
|
|
|
FindCloseShadow(hShadowDB, ulEnumCookie);
|
|
|
|
ReintKdPrint(ALWAYS, ("Ending NameSpaceVersion %x \n", sEDS.dwEndingNameSpaceVersion));
|
|
|
|
if (!(sEDS.dwFlags & EDS_FLAG_ERROR_ENCOUNTERED) &&
|
|
(dwStartigNameSpaceVersion == sEDS.dwEndingNameSpaceVersion))
|
|
{
|
|
sST.uFlags = (fEncrypt)? FLAG_DATABASESTATUS_ENCRYPTED : FLAG_DATABASESTATUS_UNENCRYPTED;
|
|
|
|
if (!SetDatabaseStatus(hShadowDB, sST.uFlags, FLAG_DATABASESTATUS_ENCRYPTION_MASK))
|
|
{
|
|
goto bailout;
|
|
}
|
|
|
|
fComplete = TRUE;
|
|
|
|
}
|
|
|
|
dwError = NO_ERROR;
|
|
fRet = TRUE;
|
|
|
|
|
|
bailout:
|
|
|
|
if (!fRet)
|
|
{
|
|
dwError = GetLastError();
|
|
}
|
|
|
|
if (hShadowDB != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseShadowDatabaseIO(hShadowDB);
|
|
}
|
|
|
|
if (lpfnEnumProgress)
|
|
{
|
|
dwRet = (*lpfnEnumProgress)(NULL, 0, 0, 0, NULL, CSCPROC_REASON_END, fComplete, dwError, dwContext);
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
int
|
|
EncryptDecryptSubtree(
|
|
HANDLE hShadowDB,
|
|
LPSECURITYINFO pShareSecurityInfo,
|
|
LPTSTR lptzFullPath,
|
|
DWORD dwCallbackReason,
|
|
WIN32_FIND_DATA *lpFind32,
|
|
SHADOWINFO *lpSI,
|
|
LPENCRYPT_DECRYPT_SUBTREE lpEds
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is a callback routine to TraverseOneDirectory. It encrypts or decrypts files in the subtree
|
|
|
|
Arguments:
|
|
|
|
hShadowDB Handle to issue ioctls to the redir
|
|
|
|
lptzFullPath fully qualified path to the item
|
|
|
|
dwCallbackReason TOD_CALLBACK_REASON_XXX (BEGIN, NEXT_ITEM or END)
|
|
|
|
lpFind32 local win32info
|
|
|
|
lpSI other info such as priority, pincount etc.
|
|
|
|
lpEds ENCRYPT_DECRYPT_SUBTREE structure which contains the relevant info such
|
|
as encrypt-or-decrypt, callback function, context, error flag
|
|
|
|
|
|
Returns:
|
|
|
|
return code, whether continue, cancel etc.
|
|
|
|
Notes:
|
|
|
|
|
|
--*/
|
|
{
|
|
BOOL fRet;
|
|
DWORD dwError, dwRet;
|
|
int iRet = TOD_CONTINUE;
|
|
|
|
|
|
//Bug: 581224
|
|
// Should return TOD_CONTINUE for TOD_CALLBACK_REASON_BEGIN
|
|
if (dwCallbackReason == TOD_CALLBACK_REASON_BEGIN) {
|
|
return iRet;
|
|
}
|
|
|
|
|
|
// save the last known version number, the calling routine will
|
|
// compare it against the first one
|
|
if(dwCallbackReason == TOD_CALLBACK_REASON_NEXT_ITEM)
|
|
{
|
|
lpEds->dwEndingNameSpaceVersion = lpSI->dwNameSpaceVersion;
|
|
}
|
|
|
|
// operate only on files
|
|
if (lpSI->uStatus & SHADOW_IS_FILE)
|
|
{
|
|
|
|
ReintKdPrint(ALWAYS, ("Processing file %ls \n", lptzFullPath));
|
|
|
|
do
|
|
{
|
|
dwError = 0;
|
|
|
|
// try conversion. If we fail, not in the EDS structure so
|
|
// the caller knows
|
|
if(!RecreateShadow(hShadowDB, lpSI->hDir, lpSI->hShadow, (lpEds->fEncrypt)?FILE_ATTRIBUTE_ENCRYPTED:0))
|
|
{
|
|
dwError = GetLastError();
|
|
}
|
|
|
|
if (lpEds->lpfnEnumProgress)
|
|
{
|
|
dwRet = (*(lpEds->lpfnEnumProgress))(lptzFullPath, 0, 0, 0, lpFind32, CSCPROC_REASON_MORE_DATA, 0, dwError, lpEds->dwContext);
|
|
|
|
if (dwRet == CSCPROC_RETURN_RETRY)
|
|
{
|
|
continue;
|
|
}
|
|
// abort if the callback wants to
|
|
if (dwRet != CSCPROC_RETURN_CONTINUE )
|
|
{
|
|
iRet = TOD_ABORT;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
while (TRUE);
|
|
if (dwError != ERROR_SUCCESS)
|
|
{
|
|
lpEds->dwFlags |= EDS_FLAG_ERROR_ENCOUNTERED;
|
|
}
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
BOOL
|
|
CSCPurgeUnpinnedFiles(
|
|
ULONG Timeout,
|
|
PULONG pnFiles,
|
|
PULONG pnYoungFiles)
|
|
{
|
|
BOOL iRet;
|
|
|
|
iRet = PurgeUnpinnedFiles(
|
|
INVALID_HANDLE_VALUE,
|
|
Timeout,
|
|
pnFiles,
|
|
pnYoungFiles);
|
|
|
|
// DbgPrint("CSCPurgeUnpinnedFiles(Timeout=%d nFiles=%d nYoungFiles=%d)\n",
|
|
// Timeout,
|
|
// *pnFiles,
|
|
// *pnYoungFiles);
|
|
|
|
return iRet;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
CSCShareIdToShareName(
|
|
ULONG ShareId,
|
|
PBYTE Buffer,
|
|
PDWORD pBufSize)
|
|
{
|
|
|
|
BOOL iRet;
|
|
|
|
iRet = ShareIdToShareName(
|
|
INVALID_HANDLE_VALUE,
|
|
ShareId,
|
|
Buffer,
|
|
pBufSize);
|
|
|
|
return iRet;
|
|
}
|
|
|
|
BOOL
|
|
IsPersonal(VOID)
|
|
{
|
|
OSVERSIONINFOEX Osvi;
|
|
DWORD TypeMask;
|
|
DWORDLONG ConditionMask;
|
|
|
|
memset(&Osvi, 0, sizeof(OSVERSIONINFOEX));
|
|
Osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
|
Osvi.wSuiteMask = VER_SUITE_PERSONAL;
|
|
TypeMask = VER_SUITENAME;
|
|
ConditionMask = 0;
|
|
VER_SET_CONDITION(ConditionMask, VER_SUITENAME, VER_OR);
|
|
return(VerifyVersionInfo(&Osvi, TypeMask, ConditionMask));
|
|
}
|