|
|
#define STRICT
#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <wchar.h>
#include <stdlib.h>
#include <limits.h>
#include <commdlg.h>
#include "setupapi.h"
#include "resource.h"
#include "advpack.h"
#include "uninstal.h"
#include "globals.h"
#include "mrcicode.h"
#include "crc32.h"
#include <advpub.h>
#include <regstr.h>
#define MAX_STR_LEN 1024
#define SEC_RENAME "Rename"
#define MAX_IOSIZE 32768
#define DAT_FILESIG 0x504A4743
#define OK 0
#define CR 13
const char c_szREGKEY_SHAREDLL[] = REGSTR_PATH_SETUP "\\SharedDlls";
const char c_szExtINI[] = ".INI"; const char c_szExtDAT[] = ".DAT"; //const char c_szIE4SECTIONNAME[] = "backup";
const char c_szNoFileLine[] = "-1,0,0,0,0,0,-1";
int RestoreSingleFile(FILELIST *filelist, LPSTR lpszBakFile, HANDLE hDatFile); extern const char c_szNoFileLine[];
void MySetUninstallFileAttrib(LPSTR lpszPath, LPCSTR lpszBasename); BOOL UninstallInfoInit(PBAKDATA pbd, LPCSTR lpszPath, LPCSTR lpszBasename, BOOL bBackup); HRESULT BackupFiles( HWND hDlg, LPSTR lpFileList, LPSTR lpDir, LPSTR lpBaseName, DWORD dwFlags); HRESULT RestoreFiles( HWND hDlg, LPSTR lpFileList, LPSTR lpDir, LPSTR lpBaseName, DWORD dwFlags); void FillBackupInfo(LPCSTR lpINIFile, FILELIST *pFileList); void initcopy(const char * StfWinDir, char * from, char * to); unsigned long Mystrtoul (const char *nptr, char **endptr, int ibase); INT_PTR CALLBACK SaveRestoreProgressDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); void GetListFromIniFile(LPSTR lpDir, LPSTR lpBaseName, LPSTR *lplpFileList); void CreateFullPathForFile(LPSTR lpszBakFile); DWORD GetRefCountFrReg( LPSTR lpFile ); HRESULT UpdateRefCount( HWND hDlg, LPSTR lpFileList, LPSTR lpDir, LPSTR lpBaseName, DWORD dwFlags );
HRESULT WINAPI FileSaveRestore( HWND hDlg, LPSTR lpFileList, LPSTR lpDir, LPSTR lpBaseName, DWORD dwFlags) { char szTitle[MAX_STR_LEN]; LPSTR lpszOldTitle = ctx.lpszTitle; HRESULT hr;
if (!CheckOSVersion()) return E_FAIL;
ctx.lpszTitle = szTitle; // Do we have to do this??
if ( hDlg && !IsWindow(hDlg)) dwFlags |= IE4_NOMESSAGES | IE4_NOPROGRESS;
if (dwFlags & IE4_RESTORE) { LoadString(g_hInst, IDS_FILERESTORE_TITLE, szTitle, sizeof(szTitle)); hr = RestoreFiles( hDlg, lpFileList, lpDir, lpBaseName, dwFlags); } else if ( dwFlags & AFSR_UPDREFCNT ) { hr = UpdateRefCount( hDlg, lpFileList, lpDir, lpBaseName, dwFlags ); } else { LoadString(g_hInst, IDS_FILEBACKUP_TITLE, szTitle, sizeof(szTitle)); hr = BackupFiles( hDlg, lpFileList, lpDir, lpBaseName, dwFlags); }
ctx.lpszTitle = lpszOldTitle; return hr; }
HRESULT UpdateRefCount( HWND hDlg, LPSTR lpFileList, LPSTR lpDir, LPSTR lpBaseName, DWORD dwFlags ) { char szIniFile[MAX_PATH]; char szLine[MAX_STR_LEN]; char szBuf[MAX_PATH]; DWORD dwRefCount = -1; DWORD dwOldAttr; LPSTR lpFile;
if ( !lpFileList || !*lpFileList ) return S_OK;
lpFile = lpFileList; BuildPath( szIniFile, lpDir, lpBaseName ); lstrcat( szIniFile, c_szExtINI );
if ( FileExists( szIniFile ) ) { dwOldAttr = GetFileAttributes( szIniFile ); SetFileAttributes( szIniFile, FILE_ATTRIBUTE_NORMAL ); while ( *lpFile ) { if ( GetPrivateProfileString( c_szIE4SECTIONNAME, lpFile, "", szLine, sizeof(szLine), szIniFile) ) { LPSTR lpszComma; int i, j;
if ( GetFieldString(szLine, 6, szBuf, sizeof(szBuf)) ) // For the Attribute
{ dwRefCount = My_atol( szBuf ); if ( dwRefCount == (DWORD)-1 ) { dwRefCount = GetRefCountFrReg( lpFile ); } else if ( dwFlags & AFSR_EXTRAINCREFCNT ) dwRefCount++; } else { dwRefCount = GetRefCountFrReg( lpFile ); }
// re-write the updated INI line
lpszComma = szLine; for ( i=0; i<6; i++ ) { lpszComma = ANSIStrChr(lpszComma, ','); if ( !lpszComma ) break; else lpszComma = CharNext(lpszComma); }
if ( !lpszComma ) { for ( j=i; j<6; j++ ) { lstrcat( szLine, "," ); } } else *(++lpszComma) = '0';
ULtoA( dwRefCount, szBuf, 10 ); lstrcat( szLine, szBuf ); WritePrivateProfileString( c_szIE4SECTIONNAME, lpFile, szLine, szIniFile ); }
lpFile += lstrlen(lpFile) + 1; } SetFileAttributes( szIniFile, dwOldAttr );
} return S_OK; }
DWORD GetRefCountFrReg( LPSTR lpFile ) { HKEY hKey; DWORD dwRefCount = 0; DWORD dwType; DWORD dwSize;
if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, c_szREGKEY_SHAREDLL, (ULONG)0, KEY_READ, &hKey ) == ERROR_SUCCESS ) { dwSize = sizeof(DWORD); if ( RegQueryValueEx( hKey, lpFile, NULL, &dwType, (LPBYTE)&dwRefCount, &dwSize ) != ERROR_SUCCESS ) { dwRefCount = 0; } RegCloseKey( hKey ); } return dwRefCount; }
HRESULT BackupFiles( HWND hDlg, LPSTR lpFileList, LPSTR lpDir, LPSTR lpBaseName, DWORD dwFlags) { HRESULT hr = S_OK; BAKDATA bd; FILELIST FileList; LPSTR lpFile; char szLine[MAX_STR_LEN]; char szValue[MAX_PATH]; DWORD dwItems = 0; HWND hProgressDlg = NULL;
if ((lpFileList) && (*lpFileList)) { if (SUCCEEDED(CreateFullPath(lpDir, TRUE)) && UninstallInfoInit(&bd, lpDir, lpBaseName, TRUE)) { if (!(dwFlags & IE4_NOPROGRESS)) { hProgressDlg = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_SAVERESTOREDLG), hDlg, SaveRestoreProgressDlgProc, TRUE); ShowWindow(hProgressDlg, SW_SHOWNORMAL);
lpFile = lpFileList; while (*lpFile) { dwItems++; lpFile += lstrlen(lpFile) + 1; } UpdateWindow(hProgressDlg); SendMessage(GetDlgItem(hProgressDlg, IDC_SAVERESTORE_PROGRESS), PBM_SETRANGE, 0, MAKELONG(0, dwItems)); SendMessage(GetDlgItem(hProgressDlg, IDC_SAVERESTORE_PROGRESS), PBM_SETSTEP, 1, 0L); } lpFile = lpFileList; while ((hr == S_OK) && (*lpFile)) { if (GetPrivateProfileString(c_szIE4SECTIONNAME, lpFile, "", szLine, sizeof(szLine), bd.szIniFileName) == 0) { FileList.bak_attribute = GetFileAttributes( lpFile ); FileList.bak_exists = 0; } else { FileList.bak_exists = 1; FileList.bak_attribute = (DWORD)NO_FILE; if (GetFieldString(szLine, 0, szValue, sizeof(szValue))) // For the Attribute
FileList.bak_attribute = (DWORD)Mystrtoul((const char*)szValue, NULL, 16);
// If the file was in the list of files to backup the last time, but did not exist on the user machine
// but this time around it exists, only backup the file if the user specifies IE4_BACKUPNEW
if ((FileList.bak_attribute == (DWORD)NO_FILE) && (dwFlags & IE4_BACKNEW) ) { FileList.bak_attribute = GetFileAttributes( lpFile ); FileList.bak_exists = 0; } else { // the existing INI fields: Attri[Filed0],size[Filed1],date-time(low)[Filed2], date-time(high)[Field3],offset[Field4],CRC[Field5]
// we are going to add the extra colume of reference count if not there already
if ( !GetFieldString(szLine, 6, szValue, sizeof(szValue)) ) // For the Ref-count field
{ lstrcat( szLine, ",-1" ); WritePrivateProfileString( c_szIE4SECTIONNAME, lpFile, szLine, bd.szIniFileName ); } } }
if (FileList.bak_exists == 0) { if (FileList.bak_attribute != (DWORD)NO_FILE) { FileList.name = lpFile; if (!BackupSingleFile(&FileList, &bd)) { // If something went wrong, Sorry backup failed.
if (!(dwFlags & IE4_NOMESSAGES)) { if (MsgBox1Param( hDlg, IDS_FILEBACKUP_ERROR, lpFile, MB_ICONEXCLAMATION, MB_YESNO) == IDNO) { hr = E_FAIL; break; } } } } else { // File does not exist, nothing to backup, report this in the INI file.
WritePrivateProfileString(c_szIE4SECTIONNAME, lpFile, c_szNoFileLine, bd.szIniFileName); }
} // else we did already backup this file the previous install
if (!(dwFlags & IE4_NOPROGRESS)) { UpdateWindow(hProgressDlg); SendMessage(GetDlgItem(hProgressDlg, IDC_SAVERESTORE_PROGRESS), PBM_STEPIT, 0, 0L); }
lpFile += lstrlen(lpFile) + 1; }
if (bd.hDatFile != INVALID_HANDLE_VALUE) CloseHandle(bd.hDatFile); WritePrivateProfileString( NULL, NULL, NULL, bd.szIniFileName); // to make sure the ie4bak.ini file gets flushed
} else { if (!(dwFlags & IE4_NOMESSAGES)) { if (MsgBox( hDlg, IDS_BACKUPINIT_ERROR, MB_ICONEXCLAMATION , MB_YESNO) == IDNO) hr = E_FAIL; } } }
if (hProgressDlg) DestroyWindow(hProgressDlg);
MySetUninstallFileAttrib(lpDir, lpBaseName);
return hr; }
BOOL UninstallInfoInit(PBAKDATA pbd, LPCSTR lpszPath, LPCSTR lpszBasename, BOOL bBackup) { pbd->hDatFile = INVALID_HANDLE_VALUE; lstrcpy(pbd->szFinalDir, lpszPath);
// the dat file and ini file are made on the first call to backup single file.
if(pbd->hDatFile == INVALID_HANDLE_VALUE ) { char szTmp[MAX_PATH]; BuildPath(szTmp, pbd->szFinalDir, lpszBasename); lstrcat(szTmp, c_szExtDAT); SetFileAttributes(szTmp, FILE_ATTRIBUTE_NORMAL); pbd->hDatFile = CreateFile(szTmp, GENERIC_READ|GENERIC_WRITE, 0, NULL, (bBackup ? OPEN_ALWAYS : OPEN_EXISTING) , FILE_ATTRIBUTE_NORMAL, NULL); if(pbd->hDatFile == INVALID_HANDLE_VALUE) return FALSE;
pbd->dwDatOffset = SetFilePointer(pbd->hDatFile, 0, NULL, FILE_END);
BuildPath(pbd->szIniFileName, pbd->szFinalDir, lpszBasename); lstrcat(pbd->szIniFileName, c_szExtINI); SetFileAttributes(pbd->szIniFileName, FILE_ATTRIBUTE_NORMAL); } return TRUE; }
void MySetUninstallFileAttrib(LPSTR lpszPath, LPCSTR lpszBasename) { char szTmp[MAX_PATH]; BuildPath(szTmp, lpszPath, lpszBasename); lstrcat(szTmp, c_szExtDAT); SetFileAttributes(szTmp, FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_READONLY);
BuildPath(szTmp, lpszPath, lpszBasename); lstrcat(szTmp, c_szExtINI); SetFileAttributes(szTmp, FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_READONLY); return; }
HRESULT RestoreFiles( HWND hDlg, LPSTR lpFileList, LPSTR lpDir, LPSTR lpBaseName, DWORD dwFlags) { HRESULT hr = S_OK; int iErr = 0; BAKDATA bd; char szFile[MAX_PATH]; char szWinDir[MAX_PATH]; DWORD dwItems = 0; HWND hProgressDlg = NULL; LPSTR lpFile; FILELIST FileList; BOOL bGotListFromIniFile = FALSE;
if (lpFileList == NULL) { GetListFromIniFile(lpDir, lpBaseName, &lpFileList); bGotListFromIniFile = TRUE; }
if ((lpFileList == NULL) || !(*lpFileList)) return hr; // Nothing to restore.
if (!UninstallInfoInit(&bd, lpDir, lpBaseName, FALSE)) { if (!(dwFlags & IE4_NOMESSAGES)) MsgBox( NULL, IDS_BACKUPDAT_ERROR, MB_ICONEXCLAMATION, MB_OK); if (bGotListFromIniFile) { LocalFree(lpFileList); lpFileList = NULL; } return E_FAIL; }
if (!(dwFlags & IE4_NOPROGRESS)) { hProgressDlg = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_SAVERESTOREDLG), hDlg, SaveRestoreProgressDlgProc, FALSE); ShowWindow(hProgressDlg, SW_SHOWNORMAL);
lpFile = lpFileList; while (*lpFile) { dwItems++; lpFile += lstrlen(lpFile) + 1; } UpdateWindow(hProgressDlg); SendMessage(GetDlgItem(hProgressDlg, IDC_SAVERESTORE_PROGRESS), PBM_SETRANGE, 0, MAKELONG(0, dwItems)); SendMessage(GetDlgItem(hProgressDlg, IDC_SAVERESTORE_PROGRESS), PBM_SETSTEP, 1, 0L); } GetWindowsDirectory(szWinDir, sizeof(szWinDir));
lpFile = lpFileList; while ((hr == S_OK) && (*lpFile)) { FileList.name = lpFile; FileList.dwSize = 0; FileList.dwDatOffset = (DWORD)-1;
FillBackupInfo(bd.szIniFileName, &FileList);
if ( (FileList.bak_attribute != NO_FILE) && (FileList.dwSize > 0) && (FileList.dwDatOffset != (DWORD)-1)) { if (!MakeBakName(FileList.name, szFile)) { if (!(dwFlags & IE4_NOMESSAGES)) { if (MsgBox1Param( hDlg, IDS_RESTORE_ERROR2, FileList.name, MB_ICONEXCLAMATION, MB_YESNO) == IDNO) { // error creating a temp file for file to restore.
hr = E_FAIL; break; } } goto NextFile; }
// if need to use the reg count, we only do it for those files have real ref count to begin with
if ( (dwFlags & AFSR_USEREFCNT) && (FileList.dwRefCount!=(DWORD)-1) ) { DWORD dwRefCntInReg;
dwRefCntInReg = GetRefCountFrReg( FileList.name ); if ( dwRefCntInReg > FileList.dwRefCount ) goto NextFile; }
iErr = RestoreSingleFile(&FileList, szFile, bd.hDatFile); if (iErr != 0) { if (!(dwFlags & IE4_NOMESSAGES)) { wsprintf(szFile, "%d", iErr); // reuse szFile, it is set on every call in MakeBakName
if (MsgBox2Param( hDlg, IDS_RESTORE_ERROR, FileList.name, szFile, MB_ICONEXCLAMATION, MB_YESNO) == IDNO) hr = E_FAIL; } } else { SetFileAttributes( szFile, FileList.bak_attribute ); if ( CopyFileA(szFile, FileList.name, FALSE)) { SetFileAttributes( szFile, FILE_ATTRIBUTE_NORMAL ); DeleteFile( szFile ); } else initcopy(szWinDir, szFile, FileList.name); } } else { // the file was never backed up, delete it if the caller want's us to
if (!(dwFlags & IE4_NODELETENEW) ) { if ( (!DeleteFile(lpFile)) && (GetFileAttributes(lpFile) != (DWORD)-1)) initcopy(szWinDir, lpFile, "NUL"); // If we could not delete the file. Add to reboot delete
} }
NextFile: lpFile += lstrlen(lpFile) + 1;
if (!(dwFlags & IE4_NOPROGRESS)) { UpdateWindow(hProgressDlg); SendMessage(GetDlgItem(hProgressDlg, IDC_SAVERESTORE_PROGRESS), PBM_STEPIT, 0, 0L); }
}
if (hProgressDlg) DestroyWindow(hProgressDlg);
if (bd.hDatFile != INVALID_HANDLE_VALUE) CloseHandle(bd.hDatFile);
if (bGotListFromIniFile) { LocalFree(lpFileList); lpFileList = NULL; } return hr; }
void FillBackupInfo(LPCSTR lpINIFile, FILELIST *pFileList) { char szLine[MAX_STR_LEN]; char szValue[MAX_PATH];
pFileList->dwDatOffset = (DWORD)-1; pFileList->dwRefCount = (DWORD)-1; if (GetPrivateProfileString(c_szIE4SECTIONNAME, pFileList->name, "", szLine, sizeof(szLine), lpINIFile) != 0) { if (GetFieldString(szLine, 0, szValue, sizeof(szValue))) // For the Attribute
pFileList->bak_attribute = (DWORD)Mystrtoul((const char*)szValue, NULL, 16);
if (pFileList->bak_attribute != (DWORD)NO_FILE) { pFileList->bak_exists = 1; if (GetFieldString(szLine, 1, szValue, sizeof(szValue))) // For the size
pFileList->dwSize = (DWORD)Mystrtoul((const char*)szValue, NULL, 16);
if (GetFieldString(szLine, 2, szValue, sizeof(szValue))) // For the time/date
pFileList->FileTime.dwLowDateTime = (DWORD)Mystrtoul((const char*)szValue, NULL, 16);
if (GetFieldString(szLine, 3, szValue, sizeof(szValue))) // For the time/date
pFileList->FileTime.dwHighDateTime = (DWORD)Mystrtoul((const char*)szValue, NULL, 16);
if (GetFieldString(szLine, 4, szValue, sizeof(szValue))) // For the Offset
pFileList->dwDatOffset = (DWORD)Mystrtoul((const char*)szValue, NULL, 16);
if (GetFieldString(szLine, 5, szValue, sizeof(szValue))) // For the CRC
pFileList->dwFileCRC = (DWORD)Mystrtoul((const char*)szValue, NULL, 16);
if (GetFieldString(szLine, 6, szValue, sizeof(szValue))) // For the CRC
pFileList->dwRefCount = (DWORD)Mystrtoul((const char*)szValue, NULL, 16); } else pFileList->bak_exists = 0;
} else pFileList->bak_exists = 0;
return; }
BOOL MakeBakName(LPSTR lpszName, LPSTR szBakName) { static int iNum = 0; BOOL bOK = FALSE; LPSTR lpTmp; char szFilename[14];
lstrcpy(szBakName, lpszName); lpTmp = CharPrev( szBakName, szBakName+lstrlen(szBakName));
// chop filename off
//
while ( (lpTmp > szBakName) && *lpTmp && (*lpTmp != '\\') ) lpTmp = CharPrev( szBakName, lpTmp );
if ( *CharPrev( szBakName, lpTmp ) == ':' ) { lpTmp = CharNext(lpTmp) ; } *lpTmp = '\0';
while ((iNum < 1000) && !bOK) { *lpTmp = '\0'; wsprintf(szFilename, "IEBAK%03d.TMP", iNum++); AddPath(szBakName, szFilename); bOK = (GetFileAttributes(szBakName) == 0xFFFFFFFF); // File does not exist, then OK
}
if (!bOK) { // If we could not get a tempfile name with the above methode, try GetTempFileName
// Retry once, if it does not work fail.
*lpTmp = '\0'; CreateFullPath(lpszName, FALSE); // If directory does not exist GetTempFileName() fails.
bOK = GetTempFileName(szBakName, "IE4", 0, szBakName); } return bOK; }
// copy files by, adding them to wininit.ini
void initcopy(const char * StfWinDir, char * from, char * to) { char * wininitpath; char * wininitname = {"wininit.ini"}; LPTSTR lpBuf = NULL; LPTSTR lpTmp; static DWORD dwBufSize = MAX_STR_LEN*3; DWORD dwBytes;
if (ctx.wOSVer == _OSVER_WIN95) { // 16 is just for padding
wininitpath = (char*) LocalAlloc(LPTR, lstrlen(StfWinDir) + lstrlen(wininitname) + 2 + 16); if (wininitpath) { lstrcpy(wininitpath, StfWinDir); AddPath(wininitpath, wininitname);
while (TRUE) { lpBuf = (LPTSTR)LocalAlloc( LPTR, (UINT)dwBufSize ); if (lpBuf) { dwBytes = GetPrivateProfileSection( SEC_RENAME, lpBuf, dwBufSize, wininitname );
//The 16 below is just padding (all we probably need is only 3 or so)...
if ( (dwBytes >= (dwBufSize - 2)) || (dwBytes+lstrlen(to)+lstrlen(from)+16) > dwBufSize ) { // not enough buf size
dwBufSize += MAX_STR_LEN; LocalFree( lpBuf ); } else { lpTmp = lpBuf+dwBytes; if (lstrcmpi(to, "NUL") == 0) lstrcpy(lpTmp, to); else GetShortPathName( to, lpTmp, (dwBufSize - dwBytes) ); lstrcat( lpTmp, "=" ); GetShortPathName( from, lpTmp + lstrlen(lpTmp), (dwBufSize - dwBytes - lstrlen(lpTmp)) );
// MessageBox(NULL, lpTmp, wininitname, MB_OK);
lpTmp += lstrlen(lpTmp); lpTmp++; //jump over the first '\0'
*lpTmp = '\0';
WritePrivateProfileSection( SEC_RENAME, lpBuf, wininitname );
break; } } else break; }
if (lpBuf) { LocalFree( lpBuf ); lpBuf = NULL; }
LocalFree(wininitpath); } } else { if (lstrcmpi(to, "NUL") == 0) MoveFileEx(from, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); // delete the file
else MoveFileEx(from, to, MOVEFILE_DELAY_UNTIL_REBOOT | MOVEFILE_REPLACE_EXISTING); // rename the file
} }
BOOL BackupSingleFile(FILELIST * filelist, PBAKDATA pbd) { HANDLE hFile; BOOL bErr=FALSE; DWORD cbRead; DWORD cbComp; LPBYTE lpBuff; LPBYTE lpBuffComp; DWORD dwFileSig = DAT_FILESIG; DWORD dwOrigDatOffset = pbd->dwDatOffset; DWORD dwBytesWritten = 0; DWORD dwFileSize; ULONG ulCRC = CRC32_INITIAL_VALUE; FILETIME FileTime = {0, 0}; BOOL bRet=TRUE;
cbRead = (DWORD)MAX_IOSIZE; lpBuff = LocalAlloc(LPTR, cbRead + 32 ); lpBuffComp = LocalAlloc(LPTR, cbRead + 32);
if (!lpBuff || !lpBuffComp) { bRet=FALSE; } else { hFile = CreateFile(filelist->name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile==INVALID_HANDLE_VALUE) { bRet=FALSE; } else { GetFileTime(hFile, NULL, NULL, &FileTime); dwFileSize = GetFileSize(hFile, NULL);
if (!WriteFile(pbd->hDatFile, &dwFileSig, sizeof(dwFileSig), &dwBytesWritten, NULL)) { cbRead = 0; // prevent the loop from executing
bRet=FALSE; } else pbd->dwDatOffset += sizeof(dwFileSig);
while (cbRead == MAX_IOSIZE) { if (!ReadFile (hFile, lpBuff, (DWORD)MAX_IOSIZE, &cbRead, NULL)) { bRet=FALSE; break; } if (cbRead == 0) // no more data, time to leave
break;
ulCRC = CRC32Compute(lpBuff, cbRead, ulCRC); cbComp = Mrci1MaxCompress(lpBuff, cbRead, lpBuffComp, (DWORD)MAX_IOSIZE); if ((cbComp == (DWORD) -1) || (cbComp >= cbRead)) { cbComp = 0; }
// We want to write out lpBuff if cbComp is ZERO, or
// lpBuffComp is cbComp is NON-ZERO. In any case, we
// precede every chunk with two words: cbRead and cbComp.
dwFileSig = cbRead | ((DWORD)cbComp << 16);
if (!WriteFile(pbd->hDatFile, &dwFileSig, sizeof(dwFileSig), &dwBytesWritten, NULL)) { bRet=FALSE; break; } pbd->dwDatOffset += sizeof(dwFileSig);
if (!cbComp) { bErr = !WriteFile(pbd->hDatFile, lpBuff, cbRead, &dwBytesWritten, NULL); } else { bErr = !WriteFile(pbd->hDatFile, lpBuffComp, cbComp, &dwBytesWritten, NULL); } if (bErr) { bRet=FALSE; break; } pbd->dwDatOffset += dwBytesWritten; }
CloseHandle(hFile);
// Write out size/date/time etc to ini file
if (!bErr) { DosPrintf(pbd, filelist, dwFileSize, FileTime, dwOrigDatOffset, ulCRC); } } } if (lpBuffComp) LocalFree(lpBuffComp);
if (lpBuff) LocalFree(lpBuff);
return bRet; }
int DosPrintf(PBAKDATA pbd, FILELIST *filelist, DWORD dwFileSize, FILETIME FileTime, DWORD dwDatOffset, DWORD dwCRC) { WORD cb; char szTmp[MAX_STR_LEN];
// BUGBUG: if we rewrite the line, we lose the ref count and becomes -1 again.
// UpdateRefCnt() will not get a chance to increase the count based on the original data.
//
cb = (WORD)wsprintf(szTmp, "%lx,%lx,%lx,%lx,%lx,%lx,%d", filelist->bak_attribute, dwFileSize, FileTime.dwLowDateTime, FileTime.dwHighDateTime, dwDatOffset, dwCRC, -1); WritePrivateProfileString(c_szIE4SECTIONNAME, filelist->name, szTmp, pbd->szIniFileName); return cb; }
//
// Copied from Windows 95 unistal.exe cfg.c function CfgGetField
BOOL GetFieldString(LPSTR lpszLine, int iField, LPSTR lpszField, int cbSize) { int cbField; LPSTR lpszChar, lpszEnd; // Find the field we are looking for
lpszChar = lpszLine;
// Each time we see a separator, decrement iField
while (iField > 0 && (BYTE)*lpszChar > CR) {
if (*lpszChar == '=' || *lpszChar == ',' || *lpszChar == ' ' ) { iField--; while (*lpszChar == '=' || *lpszChar== ',' || *lpszChar == ' ' && (BYTE)*lpszChar > 13) lpszChar++; } else lpszChar++; }
// If we still have fields remaining then something went wrong
if (iField) return FALSE;
// Now find the end of this field
lpszEnd = lpszChar; while (*lpszEnd != '=' && *lpszEnd != ',' && *lpszEnd != ' ' && (BYTE)*lpszEnd > CR) lpszEnd++;
// Find the length of this field - make sure it'll fit in the buffer
cbField = (int)((lpszEnd - lpszChar) + 1);
if (cbField > cbSize) { // I return an error if the requested
//cbField = cbSize; // data won't fit, rather than truncating
return FALSE; // it at some random point! -JTP
}
// Note that the C runtime treats cbField as the number of characters
// to copy from the source, and if that doesn't happen to transfer a NULL,
// too bad. The Windows implementation of _lstrcpyn treats cbField as
// the number of characters that can be stored in the destination, and
// always copies a NULL (even if it means copying only cbField-1 characters
// from the source).
// The C runtime also pads the destination with NULLs if a NULL in the
// source is found before cbField is exhausted. _lstrcpyn essentially quits
// after copying a NULL.
lstrcpyn(lpszField, lpszChar, cbField);
return TRUE; }
int RestoreSingleFile(FILELIST *filelist, LPSTR lpszBakFile, HANDLE hDatFile) { LPBYTE lpBuff; LPBYTE lpBuffDecomp; LPBYTE lpWrite; HANDLE hFile; DWORD dwFileSig; DWORD dwByteRead; DWORD dwByteDecomp; DWORD dwBytesWritten; ULONG ulCRC = CRC32_INITIAL_VALUE; int iErr = OK; LONG lSize = (LONG)filelist->dwSize; WORD wComp; WORD wRead;
lpBuff = LocalAlloc(LPTR, MAX_IOSIZE); lpBuffDecomp = LocalAlloc(LPTR, MAX_IOSIZE); if ((lpBuff) && (lpBuffDecomp)) {
hFile= CreateFile(lpszBakFile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { CreateFullPathForFile(lpszBakFile); hFile= CreateFile(lpszBakFile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); }
if (hFile != INVALID_HANDLE_VALUE) { if (SetFilePointer(hDatFile, filelist->dwDatOffset, NULL, FILE_BEGIN) != (DWORD)-1) { if (ReadFile (hDatFile, (LPVOID)&dwFileSig, (DWORD)sizeof(dwFileSig), &dwByteRead, NULL)) { if (dwFileSig != DAT_FILESIG) iErr = MYERROR_BAD_SIG; } else iErr = MYERROR_READ;
} else iErr = MYERROR_UNKNOWN;
while ((iErr == OK) && (lSize > 0)) { if (!ReadFile (hDatFile, (LPVOID)&dwFileSig, (DWORD)sizeof(dwFileSig), &dwByteRead, NULL)) { iErr = MYERROR_READ; break; }
wComp = (WORD)(dwFileSig >> 16); wRead = (WORD)(dwFileSig & 0xffff); lpWrite = lpBuff; dwByteDecomp = (DWORD)wRead;
if ((wComp > MAX_IOSIZE) || (wRead > MAX_IOSIZE)) { iErr = MYERROR_BAD_DATA; } else if (wComp == 0) { if (!ReadFile (hDatFile, lpBuff, wRead, &dwByteDecomp, NULL)) { iErr = MYERROR_READ; } } else { lpWrite = lpBuffDecomp; if (!ReadFile (hDatFile, lpBuff, wComp, &dwByteRead, NULL)) { iErr = MYERROR_READ; } else { dwByteDecomp = Mrci1Decompress(lpBuff, wComp, lpBuffDecomp, wRead); if (dwByteDecomp != (DWORD)wRead) iErr = MYERROR_DECOMP_FAILURE; } } if (iErr != OK) { break; } ulCRC = CRC32Compute(lpWrite, dwByteDecomp, ulCRC); if (!WriteFile(hFile, lpWrite, dwByteDecomp, &dwBytesWritten, NULL)) { iErr = MYERROR_WRITE; break; } lSize -= (LONG)dwBytesWritten; } // while
SetFileTime(hFile, NULL, NULL, &filelist->FileTime); CloseHandle(hFile);
if (ulCRC != filelist->dwFileCRC) { iErr = MYERROR_BAD_CRC; }
if (iErr != OK) { DeleteFile(lpszBakFile); } } else { // Could not create backup file
iErr = MYERROR_BAD_BAK; } } else { // Alloc failed
iErr = MYERROR_OUTOFMEMORY; }
if (lpBuff) LocalFree(lpBuff); if (lpBuffDecomp) LocalFree(lpBuffDecomp);
return iErr; }
#define IsSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n' || (c) == '\v' || (c) == '\f')
/* flag values */ #define FL_UNSIGNED 1 /* strtoul called */
#define FL_NEG 2 /* negative sign found */
#define FL_OVERFLOW 4 /* overflow occured */
#define FL_READDIGIT 8 /* we've read at least one correct digit */
unsigned long Mystrtoxl ( const char *nptr, const char **endptr, int ibase, int flags ) { const char *p; char c; unsigned long number; unsigned digval; unsigned long maxval;
p = nptr; /* p is our scanning pointer */ number = 0; /* start with zero */
c = *p++; /* read char */ while ( IsSpace((int)(unsigned char)c) ) c = *p++; /* skip whitespace */
if (c == '-') { flags |= FL_NEG; /* remember minus sign */ c = *p++; } else if (c == '+') c = *p++; /* skip sign */
if (ibase < 0 || ibase == 1 || ibase > 36) { /* bad base! */ if (endptr) /* store beginning of string in endptr */ *endptr = nptr; return 0L; /* return 0 */ } else if (ibase == 0) { /* determine base free-lance, based on first two chars of
string */ if (c != '0') ibase = 10; else if (*p == 'x' || *p == 'X') ibase = 16; else ibase = 8; }
if (ibase == 16) { /* we might have 0x in front of number; remove if there */ if (c == '0' && (*p == 'x' || *p == 'X')) { ++p; c = *p++; /* advance past prefix */ } }
/* if our number exceeds this, we will overflow on multiply */ maxval = ULONG_MAX / ibase;
for (;;) { /* exit in middle of loop */ /* convert c to value */ if ( c >= '0' && c <= '9' ) // isdigit
digval = c - '0'; else if ( ( c >= 'A' && c <= 'Z' ) || ( c >= 'a' && c <= 'z' )) // if ( isalpha((int)(unsigned char)c) )
digval = (unsigned)(ULONG_PTR)CharUpper((LPSTR)c) - 'A' + 10; else break; if (digval >= (unsigned)ibase) break; /* exit loop if bad digit found */
/* record the fact we have read one digit */ flags |= FL_READDIGIT;
/* we now need to compute number = number * base + digval,
but we need to know if overflow occured. This requires a tricky pre-check. */
if (number < maxval || (number == maxval && (unsigned long)digval <= ULONG_MAX % ibase)) { /* we won't overflow, go ahead and multiply */ number = number * ibase + digval; } else { /* we would have overflowed -- set the overflow flag */ flags |= FL_OVERFLOW; }
c = *p++; /* read next digit */ }
--p; /* point to place that stopped scan */
if (!(flags & FL_READDIGIT)) { /* no number there; return 0 and point to beginning of
string */ if (endptr) /* store beginning of string in endptr later on */ p = nptr; number = 0L; /* return 0 */ } else if ( (flags & FL_OVERFLOW) || ( !(flags & FL_UNSIGNED) && ( ( (flags & FL_NEG) && (number > -LONG_MIN) ) || ( !(flags & FL_NEG) && (number > LONG_MAX) ) ) ) ) { /* overflow or signed overflow occurred */ //errno = 34; // 34 is the define of ERANGE from errno.h
if ( flags & FL_UNSIGNED ) number = ULONG_MAX; else if ( flags & FL_NEG ) number = (unsigned long)(-LONG_MIN); else number = LONG_MAX; }
if (endptr != NULL) /* store pointer to char that stopped the scan */ *endptr = p;
if (flags & FL_NEG) /* negate result if there was a neg sign */ number = (unsigned long)(-(long)number);
return number; /* done. */ }
unsigned long Mystrtoul ( const char *nptr, char **endptr, int ibase ) { return Mystrtoxl(nptr, endptr, ibase, FL_UNSIGNED); }
INT_PTR CALLBACK SaveRestoreProgressDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch( uMsg ) { case WM_INITDIALOG: ShowWindow(GetDlgItem(hwndDlg, IDS_SAVEINFO_TEXT), lParam? SW_SHOW : SW_HIDE); ShowWindow(GetDlgItem(hwndDlg, IDS_RESTOREINFO_TEXT), lParam? SW_HIDE : SW_SHOW ); CenterWindow( hwndDlg, GetDesktopWindow()); ShowWindow(hwndDlg, SW_SHOWNORMAL); break; default: // For MSG switch
return(FALSE); } return(TRUE); }
//
// Creates the path for the full qualified file name.
// We have to get rid of the filename first, before we
// can attempt to create the path.
void CreateFullPathForFile(LPSTR lpszBakFile) { char szDir[MAX_PATH]; lstrcpy(szDir, lpszBakFile); GetParentDir(szDir); CreateFullPath(szDir, FALSE); }
void GetListFromIniFile(LPSTR lpDir, LPSTR lpBaseName, LPSTR *lplpFileList) { char szINI[MAX_PATH]; WIN32_FIND_DATA FindFileData; HANDLE hFind; LPSTR lpTmp;
BuildPath(szINI, lpDir, lpBaseName); lstrcat(szINI, c_szExtINI); if ((hFind = FindFirstFile(szINI, &FindFileData)) != INVALID_HANDLE_VALUE) { if (lpTmp = LocalAlloc(LPTR, FindFileData.nFileSizeLow)) { GetPrivateProfileString(c_szIE4SECTIONNAME, NULL, "", lpTmp, FindFileData.nFileSizeLow, szINI); if (*lpTmp) { *lplpFileList = lpTmp; } else LocalFree(lpTmp); // Nothing found in the INI file
} FindClose(hFind); }
}
HRESULT AddDelBackupEntryHelper(LPCSTR lpcszFileList, LPCSTR lpcszBackupDir, LPCSTR lpcszBaseName, DWORD dwFlags) { HRESULT hr = S_OK; LPCSTR lpcszFile; char szIniFileName[MAX_PATH];
if ((lpcszFileList) && (*lpcszFileList)) { BuildPath(szIniFileName, lpcszBackupDir, lpcszBaseName); lstrcat(szIniFileName, c_szExtINI); SetFileAttributes(szIniFileName, FILE_ATTRIBUTE_NORMAL); lpcszFile = lpcszFileList; while (*lpcszFile) { WritePrivateProfileString(c_szIE4SECTIONNAME, lpcszFile, (dwFlags & AADBE_ADD_ENTRY) ? c_szNoFileLine : NULL, szIniFileName); lpcszFile += lstrlen(lpcszFile) + 1; } WritePrivateProfileString(NULL, NULL, NULL, szIniFileName); // flush the INI file
SetFileAttributes(szIniFileName, FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_READONLY); } return hr; }
HRESULT WINAPI FileSaveMarkNotExist( LPSTR lpFileList, LPSTR lpDir, LPSTR lpBaseName) { return AddDelBackupEntryHelper(lpFileList, lpDir, lpBaseName, AADBE_ADD_ENTRY); }
HRESULT WINAPI AddDelBackupEntry(LPCSTR lpcszFileList, LPCSTR lpcszBackupDir, LPCSTR lpcszBaseName, DWORD dwFlags) { return AddDelBackupEntryHelper(lpcszFileList, lpcszBackupDir, lpcszBaseName, dwFlags); }
|