Leaked source code of windows server 2003
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.
 
 
 
 
 
 

780 lines
17 KiB

#define DEFINED_UNICODE
#include "pch.h"
#ifdef CSC_ON_NT
#pragma hdrstop
#include <winioctl.h>
#endif //CSC_ON_NT
#include "shdcom.h"
#include "shdsys.h"
#include "reint.h"
#include "lib3.h"
#include "strings.h"
#include "oslayeru.h"
#include "record.h"
#include "utils.h"
#define MAX_SHADOW_DIR_NAME 16
typedef unsigned long ulong;
typedef unsigned short ushort;
typedef VOID (*PRINTPROC)(LPSTR);
typedef struct tagRBA
{
unsigned ulidShadow; // Inode which is represented by this structure
GENERICHEADER sGH; // it's header
CSCHFILE hf; // open handle to the file
DWORD cntRBE; // count of buffer entries in the array
DWORD cntRecsPerRBE; // #of records per buffer entry
DWORD cbRBE; // size in bytes of each buffer entry
LPBYTE rgRBE[]; // buffer entry array
}
RBA, *LPRBA; // stands for RecordBuffArray
#define MAX_RECBUFF_ENTRY_SIZE (0x10000-0x100)
#define MAX_RBES_EXPECTED 1024
#define INODE_NULL 0L
#define UPDATE_REC 1
#define FIND_REC 2
#define DELETE_REC 3
#define ALLOC_REC 4
#define SHADOW_FILE_NAME_SIZE 8
extern BOOL vfCSCEnabled;
extern DWORD vdwAgentThreadId;
extern char vszDBDir[MAX_PATH];
static char szBackslash[] = "\\";
static const char vszWorstCaseDefDir[] ="c:\\csc\\";
// directory name where the CSC database lives
// subdirectories under CSC directory
char szStarDotStar[]="*.*";
char vchBuff[256], vchPrintBuff[1024];
extern DWORD vdwDBCapacity, vdwClusterSize;
#define RecFromInode(hShadow) ((hShadow & 0x7fffffff) - (ULID_FIRST_USER_DIR-1))
AssertData;
AssertError;
int DoDBMaintenance(VOID);
int CALLBACK CheckDBProc(
int cntDrives,
DWORD dwCookie
);
int PUBLIC CheckPQ(VOID);
int CountProc(HANDLE hf, LPQHEADER lpQH, LPQREC lpQR, unsigned *lpcnt);
BOOL
FindCreateDBDir(
BOOL *lpfCreated,
BOOL fCleanup // empty the directory if found
);
BOOL
DeleteDirectoryFiles(
LPCSTR lpszDir
);
int ClearShadowCache();
int CALLBACK ReinitShadowDBProc(
int cntDrives,
DWORD dwCookie
);
BOOL IsValidName(LPSTR lpName);
int SetDefaultSpace(LPSTR lpShadowDir);
VOID
PrintShareHeader(
LPSHAREHEADER lpSH,
PRINTPROC lpfnPrintProc
);
VOID
PrintPQHeader(
LPQHEADER lpQH,
PRINTPROC lpfnPrintProc
);
VOID
PrintFileHeader(
LPFILEHEADER lpFH,
unsigned ulSpaces,
PRINTPROC lpfnPrintProc
);
VOID PrintShareRec(
unsigned ulRec,
LPSHAREREC lpSR,
PRINTPROC lpfnPrintProc
);
VOID PrintFilerec(
unsigned ulRec,
LPFILERECEXT lpFR,
unsigned ulSpaces,
PRINTPROC lpfnPrintProc
);
VOID
PrintPQrec(
unsigned ulRec,
LPQREC lpQrec,
PRINTPROC lpfnPrintProc
);
int
PrintSpaces(
LPSTR lpBuff,
unsigned ulSpaces
);
#ifdef CSC_ON_NT
BOOL
PUBLIC
CheckCSCShare(
USHORT *lptzShare,
LPCSCPROC lpfnMergeProgress,
DWORD dwContext
);
#else
BOOL
PUBLIC
CheckCSCShare(
LPSTR lptzShare,
LPCSCPROC lpfnMergeProgress,
DWORD dwContext
);
#endif
#ifndef CSC_ON_NT
BOOL
CheckCSCDatabaseVersion(
BOOL *lpfWasDirty
)
{
char *lpszName = NULL;
SHAREHEADER sSH;
PRIQHEADER sPQ;
CSCHFILE hfShare = 0, hfPQ=0;
BOOL fOK = FALSE;
DWORD dwErrorShare=NO_ERROR, dwErrorPQ=NO_ERROR;
// OutputDebugStringA("Checking version...\r\n");
lpszName = FormNameString(vszDBDir, ULID_SHARE);
if (!lpszName)
{
return FALSE;
}
if(!(hfShare = OpenFileLocal(lpszName)))
{
dwErrorShare = GetLastError();
}
FreeNameString(lpszName);
lpszName = FormNameString(vszDBDir, ULID_PQ);
if (!lpszName)
{
goto bailout;
}
if(!(hfPQ = OpenFileLocal(lpszName)))
{
dwErrorPQ = GetLastError();
}
FreeNameString(lpszName);
lpszName = NULL;
if ((dwErrorShare == NO_ERROR)&&(dwErrorPQ==NO_ERROR))
{
if(ReadFileLocal(hfShare, 0, &sSH, sizeof(SHAREHEADER))!=sizeof(SHAREHEADER))
{
//error message
goto bailout;
}
if (sSH.ulVersion != CSC_DATABASE_VERSION)
{
goto bailout;
}
if (lpfWasDirty)
{
*lpfWasDirty = ((sSH.uFlags & FLAG_SHAREHEADER_DATABASE_OPEN) != 0);
}
// reset the database open flag
sSH.uFlags &= ~FLAG_SHAREHEADER_DATABASE_OPEN;
// don't worry about any errors here
WriteFileLocal(hfShare, 0, &sSH, sizeof(SHAREHEADER));
if(ReadFileLocal(hfPQ, 0, &sPQ, sizeof(PRIQHEADER))!=sizeof(PRIQHEADER))
{
//error message
goto bailout;
}
if (sPQ.ulVersion != CSC_DATABASE_VERSION)
{
goto bailout;
}
fOK = TRUE;
}
else
{
if (((dwErrorShare == ERROR_FILE_NOT_FOUND)&&(dwErrorPQ==ERROR_FILE_NOT_FOUND))||
((dwErrorShare == ERROR_PATH_NOT_FOUND)&&(dwErrorPQ==ERROR_PATH_NOT_FOUND)))
{
fOK = TRUE;
}
}
bailout:
if (lpszName)
{
FreeNameString(lpszName);
}
if (hfShare)
{
CloseFileLocal(hfShare);
}
if (hfPQ)
{
CloseFileLocal(hfPQ);
}
return (fOK);
}
BOOL
UpgradeCSCDatabase(
LPSTR lpszDir
)
{
BOOL fCreated;
return (FindCreateDBDir(&fCreated, TRUE)); // cleanup dirs if exist
}
BOOL
FindCreateDBDirEx(
BOOL *lpfCreated,
BOOL *lpfIncorrectSubdirs,
BOOL fCleanup // empty the directory if found
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
DWORD dwAttr;
BOOL fRet = FALSE;
char buff[MAX_PATH+1];
int i;
UINT lenDir;
*lpfIncorrectSubdirs = *lpfCreated = FALSE;
Assert(vszDBDir[0]);
DEBUG_PRINT(("InbCreateDir: looking for %s \r\n", vszDBDir));
if ((dwAttr = GetFileAttributesA(vszDBDir)) == 0xffffffff)
{
DEBUG_PRINT(("InbCreateDir: didnt' find the CSC directory trying to create one \r\n"));
if(CreateDirectoryA(vszDBDir, NULL))
{
*lpfCreated = TRUE;
}
else
{
goto bailout;
}
}
else
{
if (dwAttr & FILE_ATTRIBUTE_DIRECTORY)
{
if (fCleanup && !DeleteDirectoryFiles(vszDBDir))
{
goto bailout;
}
}
else
{
goto bailout;
}
}
strcpy(buff, vszDBDir);
lenDir = strlen(buff);
buff[lenDir++] = '\\';
buff[lenDir++] = CSCDbSubdirFirstChar();
buff[lenDir++] = '1';
buff[lenDir] = 0;
for (i=0; i<CSCDB_SUBDIR_COUNT; ++i)
{
if ((dwAttr = GetFileAttributesA(buff)) == 0xffffffff)
{
*lpfIncorrectSubdirs = TRUE;
DEBUG_PRINT(("InbCreateDir: didnt' find the CSC directory trying to create one \r\n"));
if(!CreateDirectoryA(buff, NULL))
{
goto bailout;
}
}
else
{
if (!(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
{
goto bailout;
}
if (fCleanup && !DeleteDirectoryFiles(buff))
{
goto bailout;
}
}
buff[lenDir-1]++;
}
fRet = TRUE;
bailout:
return (fRet);
}
BOOL
FindCreateDBDir(
BOOL *lpfCreated,
BOOL fCleanup // empty the directory if found
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
BOOL fIncorrectSubdirs = FALSE, fRet;
if (fRet = FindCreateDBDirEx(lpfCreated, &fIncorrectSubdirs, fCleanup))
{
// if the root directory wasn't created and there in correct subdirs
// then we need to recreate the database.
if (!*lpfCreated && fIncorrectSubdirs)
{
fRet = FindCreateDBDirEx(lpfCreated, &fIncorrectSubdirs, TRUE);
}
}
return fRet;
}
BOOL
DeleteDirectoryFiles(
LPCSTR lpszDir
)
{
WIN32_FIND_DATAA sFind32;
char buff[MAX_PATH+32];
HANDLE hFind;
int lenDir;
BOOL fOK = TRUE;
lstrcpyA(buff, lpszDir);
lenDir = lstrlenA(buff);
if (!lenDir)
{
return (FALSE);
}
if (buff[lenDir-1] != '\\')
{
buff[lenDir++] ='\\';
buff[lenDir]=0;
}
lstrcatA(buff, szStarDotStar);
if ((hFind = FindFirstFileA(buff, &sFind32))!=INVALID_HANDLE_VALUE)
{
do
{
buff[lenDir] = 0;
if (!(sFind32.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
&& IsValidName(sFind32.cFileName))
{
lstrcatA(buff, sFind32.cFileName);
fOK = DeleteFileA(buff);
if (!fOK)
{
break;
}
}
}
while(FindNextFileA(hFind, &sFind32));
FindClose(hFind);
}
return (fOK);
}
BOOL IsValidName(LPSTR lpName)
{
int len = strlen(lpName), ch, i=0;
if (len != INODE_STRING_LENGTH)
{
return FALSE;
}
while (len--)
{
++i;
ch = *lpName++;
if (!(((ch>='0') && (ch <='9'))||
((ch>='A') && (ch <='F'))||
((ch>='a') && (ch <='f'))))
{
return FALSE;
}
}
if (i != INODE_STRING_LENGTH)
{
return FALSE;
}
return (TRUE);
}
#endif
BOOL WINAPI CheckCSCEx(
LPSTR lpszShare,
LPCSCPROC lpfnProgress,
DWORD dwContext,
DWORD dwType
)
{
#ifdef DEBUG
#ifdef CSC_ON_NT
USHORT uBuff[MAX_PATH];
memset(uBuff, 0, sizeof(uBuff));
if (MultiByteToWideChar(CP_ACP, 0, lpszShare, strlen(lpszShare), uBuff, sizeof(uBuff)))
{
return(CheckCSCShare(uBuff, lpfnProgress, dwContext));
}
#else
return(CheckCSCShare(lpszShare, lpfnProgress, dwContext));
#endif
#else
return FALSE;
#endif
return FALSE;
}
BOOL
WINAPI
CheckCSC(
LPSTR lpszDBDir,
BOOL fFix
)
{
LPVOID lpdbID = NULL;
BOOL fRet = FALSE;
char szDBDir[MAX_PATH+1];
DWORD dwDBCapacity;
DWORD dwClusterSize;
ULONG ulDatabaseStatus;
// if we are the agent and CSC is enabled then bailout;
if (vdwAgentThreadId)
{
if (vfCSCEnabled)
{
DEBUG_PRINT(("CheckCSC: CSC is enabled, cannot do database check\r\n"));
return FALSE;
}
}
else
{
unsigned ulSwitch = SHADOW_SWITCH_SHADOWING;
if(ShadowSwitches(INVALID_HANDLE_VALUE, &ulSwitch, SHADOW_SWITCH_GET_STATE))
{
if((ulSwitch & SHADOW_SWITCH_SHADOWING)!=0)
{
DEBUG_PRINT(("CheckCSC: CSC is enabled, cannot do database check\r\n"));
return FALSE;
}
}
}
if (InitValues(szDBDir, sizeof(szDBDir), &dwDBCapacity, &dwClusterSize))
{
if (!(lpdbID = OpenRecDB((lpszDBDir)?lpszDBDir:szDBDir, "Test", 0, dwDBCapacity, dwClusterSize, FALSE, NULL, &ulDatabaseStatus)))
{
DEBUG_PRINT(("CheckCSC: failed to open record database at %s\r\n", (lpszDBDir)?lpszDBDir:szDBDir));
goto bailout;
}
fRet = TraverseHierarchy(lpdbID, fFix);
}
bailout:
if (lpdbID)
{
CloseRecDB(lpdbID);
}
return (fRet);
}
VOID
PrintShareHeader(
LPSHAREHEADER lpSH,
PRINTPROC lpfnPrintProc
)
{
int iRet=0;
if (lpfnPrintProc)
{
iRet += wsprintfA(vchPrintBuff,"****ShareHeader****\r\n" );
iRet+=wsprintfA(vchPrintBuff+iRet,"Header: Flags=%xh Version=%lxh Records=%ld Size=%d \r\n",
lpSH->uchFlags, lpSH->ulVersion, lpSH->ulRecords, lpSH->uRecSize);
iRet+=wsprintfA(vchPrintBuff+iRet,"Store: Max=%ld Current=%ld \r\n", lpSH->sMax.ulSize, lpSH->sCur.ulSize);
iRet+=wsprintfA(vchPrintBuff+iRet,"\r\n");
(lpfnPrintProc)(vchPrintBuff);
}
}
VOID
PrintPQHeader(
LPQHEADER lpQH,
PRINTPROC lpfnPrintProc
)
{
int iRet=0;
if (lpfnPrintProc)
{
iRet += wsprintfA(vchPrintBuff+iRet,"****PQHeader****\r\n" );
iRet += wsprintfA(vchPrintBuff+iRet,"Flags=%xh Version=%lxh Records=%ld Size=%d head=%ld tail=%ld\r\n",
lpQH->uchFlags, lpQH->ulVersion, lpQH->ulRecords, lpQH->uRecSize, lpQH->ulrecHead, lpQH->ulrecTail);
iRet += wsprintfA(vchPrintBuff+iRet,"\r\n");
(lpfnPrintProc)(vchPrintBuff);
}
}
VOID
PrintFileHeader(
LPFILEHEADER lpFH,
unsigned ulSpaces,
PRINTPROC lpfnPrintProc
)
{
int iRet=0;
if (lpfnPrintProc)
{
iRet += PrintSpaces(vchPrintBuff+iRet, ulSpaces);
iRet += wsprintfA(vchPrintBuff+iRet,"****FileHeader****\r\n" );
iRet += PrintSpaces(vchPrintBuff+iRet, ulSpaces);
iRet += wsprintfA(vchPrintBuff+iRet,"Flags=%xh Version=%lxh Records=%ld Size=%d\r\n",
lpFH->uchFlags, lpFH->ulVersion, lpFH->ulRecords, lpFH->uRecSize);
iRet += PrintSpaces(vchPrintBuff+iRet, ulSpaces);
iRet += wsprintfA(vchPrintBuff+iRet,"bytes=%ld entries=%d Share=%xh Dir=%xh\r\n",
lpFH->ulsizeShadow, lpFH->ucShadows, lpFH->ulidShare, lpFH->ulidDir);
iRet += wsprintfA(vchPrintBuff+iRet,"\r\n");
(lpfnPrintProc)(vchPrintBuff);
}
}
VOID
PrintPQrec(
unsigned ulRec,
LPQREC lpQrec,
PRINTPROC lpfnPrintProc
)
{
int iRet=0;
if (lpfnPrintProc)
{
iRet += wsprintfA(vchPrintBuff+iRet,"rec=%xh: Srvr=%xh dir=%xh shd=%xh prev=%xh next=%xh Stts=%xh, RfPr=%d PnCnt=%x PnFlgs=%xh DrEntr=%d\r\n"
,ulRec
, lpQrec->ulidShare
, lpQrec->ulidDir
, lpQrec->ulidShadow
, lpQrec->ulrecPrev
, lpQrec->ulrecNext
, (unsigned long)(lpQrec->usStatus)
, (unsigned long)(lpQrec->uchRefPri)
, (unsigned long)(lpQrec->uchHintPri)
, (unsigned long)(lpQrec->uchHintFlags)
, lpQrec->ulrecDirEntry
);
(lpfnPrintProc)(vchPrintBuff);
}
}
VOID PrintShareRec(
unsigned ulRec,
LPSHAREREC lpSR,
PRINTPROC lpfnPrintProc
)
{
int iRet=0;
if (lpfnPrintProc)
{
iRet += wsprintfA(vchPrintBuff+iRet,"Type=%c Flags=%xh hShare=%lxh Root=%0lxh status=%xh Share=%s \r\n"
, lpSR->uchType, (unsigned)lpSR->uchFlags, ulRec, lpSR->ulidShadow
, lpSR->uStatus, lpSR->rgPath);
iRet += wsprintfA(vchPrintBuff+iRet,"Hint: HintFlags=%xh\r\n",
(unsigned)(lpSR->uchHintFlags));
iRet += wsprintfA(vchPrintBuff+iRet, "\r\n");
(lpfnPrintProc)(vchPrintBuff+iRet);
}
}
VOID PrintFilerec(
unsigned ulRec,
LPFILERECEXT lpFR,
unsigned ulSpaces,
PRINTPROC lpfnPrintProc
)
{
int i;
int iRet=0;
if (lpfnPrintProc)
{
iRet += PrintSpaces(vchPrintBuff+iRet, ulSpaces);
iRet += wsprintfA(vchPrintBuff+iRet,"Type=%c Flags=%xh Inode=%0lxh status=%xh 83Name=%ls size=%ld attrib=%lxh \r\n",
lpFR->sFR.uchType, (unsigned)lpFR->sFR.uchFlags, lpFR->sFR.ulidShadow,
lpFR->sFR.uStatus, lpFR->sFR.rgw83Name, lpFR->sFR.ulFileSize, lpFR->sFR.dwFileAttrib);
iRet += PrintSpaces(vchPrintBuff+iRet, ulSpaces);
iRet += wsprintfA(vchPrintBuff+iRet,"time: hi=%lxh lo=%lxh orgtime: hi=%lxh lo=%lxh\r\n"
, lpFR->sFR.ftLastWriteTime.dwHighDateTime,lpFR->sFR.ftLastWriteTime.dwLowDateTime
, lpFR->sFR.ftOrgTime.dwHighDateTime,lpFR->sFR.ftOrgTime.dwLowDateTime);
iRet += PrintSpaces(vchPrintBuff+iRet, ulSpaces);
iRet += wsprintfA(vchPrintBuff+iRet,"Hint: HintFlags=%xh, RefPri=%d, HintPri=%d AliasInode=%0lxh \r\n",
(unsigned)(lpFR->sFR.uchHintFlags)
, (int)(lpFR->sFR.uchRefPri)
, (int)(lpFR->sFR.uchHintPri)
, lpFR->sFR.ulidShadowOrg);
iRet += PrintSpaces(vchPrintBuff+iRet, ulSpaces);
iRet += wsprintfA(vchPrintBuff+iRet,"LFN=%-14ls", lpFR->sFR.rgwName);
for(i = 0; i < OvfCount(lpFR); ++i)
{
iRet += wsprintfA(vchPrintBuff+iRet,"%-74s", &(lpFR->sFR.ulidShadow));
}
iRet += wsprintfA(vchPrintBuff+iRet,"\r\n");
(lpfnPrintProc)(vchPrintBuff);
}
}
int
PrintSpaces(
LPSTR lpBuff,
unsigned ulSpaces
)
{
unsigned i;
int iRet=0;
for (i=0; i< ulSpaces; ++i)
{
iRet += wsprintfA(lpBuff+iRet," ");
}
return iRet;
}