Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

1205 lines
39 KiB

#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);
BOOL 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, (DLGPROC) 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, (DLGPROC) 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);
}
BOOL 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);
}