/****************************************************************************** * * Copyright (c) 2000 Microsoft Corporation * * Module Name: * snappatch.cpp * * Abstract: * functions for computing snapshot patch, and reconstructing snapshot from patch * * Revision History: * Brijesh Krishnaswami (brijeshk) 03/22/2001 * created * *****************************************************************************/ #include "snapshoth.h" #include "..\service\srconfig.h" DWORD g_dwPatchWindow = 0xFFFFFFFF; // // get patch window // 0 if patching is turned off // DWORD PatchGetPatchWindow() { DWORD dwErr = ERROR_SUCCESS; HKEY hKey = NULL; tenter("PatchGetPatchWindow"); if (g_dwPatchWindow == 0xFFFFFFFF) { // uninitialized // read from the registry g_dwPatchWindow = 0; if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, s_cszSRRegKey, 0, KEY_READ, &hKey)) { RegReadDWORD(hKey, s_cszPatchWindow, &g_dwPatchWindow); RegCloseKey(hKey); } trace(0, "Initializing g_dwPatchWindow = %ld", g_dwPatchWindow); } tleave(); return g_dwPatchWindow; } // // get reference rp for a given rp // RP1-RP10 -> reference is RP1 // RP11-RP20 -> reference is RP11 and so on // DWORD PatchGetReferenceRpNum( DWORD dwCurrentRp) { if (PatchGetPatchWindow() == 0) return dwCurrentRp; else return (dwCurrentRp/PatchGetPatchWindow())*PatchGetPatchWindow() + 1; } DWORD PatchGetReferenceRpPath( DWORD dwCurrentRp, LPWSTR pszRefRpPath) { tenter("PatchGetReferenceRpPath"); WCHAR szRp[MAX_RP_PATH], szSys[MAX_SYS_DRIVE]=L""; DWORD dwRefRpNum = PatchGetReferenceRpNum(dwCurrentRp); DWORD dwErr = ERROR_SUCCESS; wsprintf(szRp, L"%s%ld", s_cszRPDir, dwRefRpNum); GetSystemDrive(szSys); MakeRestorePath(pszRefRpPath, szSys, szRp); if (0xFFFFFFFF == GetFileAttributes(pszRefRpPath)) { // RP directory does not exist -- it must've been fifoed // try RefRP trace(0, "Original rp does not exist -- trying RefRP"); wsprintf(szRp,L" %s%ld", s_cszReferenceDir, dwRefRpNum); MakeRestorePath(pszRefRpPath, szSys, szRp); if (0xFFFFFFFF == GetFileAttributes(pszRefRpPath)) { // this does not exist either -- something wrong trace(0, "RefRP does not exist either -- bailing"); dwErr = ERROR_NOT_FOUND; goto Err; } } trace(0, "Current Rp: %ld, Reference : %S", dwCurrentRp, pszRefRpPath); Err: tleave(); return dwErr; } // // extract rp number from path // DWORD PatchGetRpNumberFromPath( LPCWSTR pszPath, PDWORD pdwRpNum) { while (*pszPath != L'\0') { if (0 == wcsncmp(pszPath, s_cszRPDir, lstrlen(s_cszRPDir))) { pszPath += lstrlen(s_cszRPDir); *pdwRpNum = _wtol(pszPath); if (*pdwRpNum == 0) continue; else return ERROR_SUCCESS; } pszPath++; } return ERROR_NOT_FOUND; } // // compute the diff // DWORD PatchComputePatch( LPCWSTR pszCurrentDir) { tenter("PatchComputePatch"); DWORD dwErr = ERROR_SUCCESS; WCHAR szTemp[MAX_PATH], szRef[MAX_PATH]; FILE* f = NULL; DWORD dwCurRpNum; // check if patching is turned off if (PatchGetPatchWindow() == 0) { trace(0, "No patching"); goto Err; } // get the reference directory for this rp CHECKERR(PatchGetRpNumberFromPath(pszCurrentDir, &dwCurRpNum), L"PatchGetRpNumberFromPath"); CHECKERR(PatchGetReferenceRpPath(dwCurRpNum, szRef), L"PatchGetReferenceRpPath"); // check if this directory is already patched lstrcpy(szTemp, pszCurrentDir); lstrcat(szTemp, L"\\"); lstrcat(szTemp, s_cszPatchCompleteMarker); if (0xFFFFFFFF != GetFileAttributes(szTemp)) { trace(0, "%S already patched", pszCurrentDir); goto Err; } // call the library api to compute the patch // this is a blocking call till the patching completes // progress callback is used to terminate it // PlaceHolder for library call (pszCurrentDir, szRef) // check if we completed the patch successfully // if so, then write a zero-byte file inside the directory to indicate this lstrcpy(szTemp, pszCurrentDir); lstrcat(szTemp, L"\\"); lstrcat(szTemp, s_cszPatchCompleteMarker); f = (FILE *) _wfopen(szTemp, L"w"); if (!f) { dwErr = GetLastError(); trace(0, "! Cannot create %S : %ld", szTemp, dwErr); goto Err; } fclose(f); Err: tleave(); return dwErr; } // // patch progress callback // BOOL PatchContinueCallback() { tenter("PatchContinueCallback"); BOOL fRc; trace(0, "PatchContinueCallback called"); if (!g_pSRConfig) { trace(0, "g_pSRConfig = NULL -- terminating patch"); fRc = FALSE; } else if (IsStopSignalled(g_pSRConfig->m_hSRStopEvent)) { trace(0, "Stop signalled -- terminating patch"); fRc = FALSE; } else { fRc = TRUE; } tleave(); return fRc; } // // reconstruct the original // DWORD PatchReconstructOriginal( LPCWSTR pszCurrentDir, LPWSTR pszDestDir) { tenter("PatchReconstructOriginal"); DWORD dwErr = ERROR_SUCCESS; WCHAR szReferenceDir[MAX_PATH]; WCHAR szSys[MAX_SYS_DRIVE]=L""; DWORD dwCurRpNum; // check if patching is turned off if (PatchGetPatchWindow() == 0) { trace(0, "No patching"); goto Err; } CHECKERR(PatchGetRpNumberFromPath(pszCurrentDir, &dwCurRpNum), L"PatchGetRpNumberFromPath"); CHECKERR(PatchGetReferenceRpPath(dwCurRpNum, szReferenceDir), L"PatchGetReferenceRpPath"); // call the library api to reconstruct the snapshot // PlaceHolder for library call (pszCurrentDir, szReferenceDir, pszDestDir) Err: tleave(); return dwErr; }