#define DEFINED_UNICODE #include "pch.h" #ifdef CSC_ON_NT #pragma hdrstop #include #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='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; }