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

  1. #define STRICT
  2. #include <windows.h>
  3. #include <windowsx.h>
  4. #include <stdio.h>
  5. #include <wchar.h>
  6. #include <stdlib.h>
  7. #include <limits.h>
  8. #include <commdlg.h>
  9. #include "setupapi.h"
  10. #include "resource.h"
  11. #include "advpack.h"
  12. #include "uninstal.h"
  13. #include "globals.h"
  14. #include "mrcicode.h"
  15. #include "crc32.h"
  16. #include <advpub.h>
  17. #include <regstr.h>
  18. #define MAX_STR_LEN 1024
  19. #define SEC_RENAME "Rename"
  20. #define MAX_IOSIZE 32768
  21. #define DAT_FILESIG 0x504A4743
  22. #define OK 0
  23. #define CR 13
  24. const char c_szREGKEY_SHAREDLL[] = REGSTR_PATH_SETUP "\\SharedDlls";
  25. const char c_szExtINI[] = ".INI";
  26. const char c_szExtDAT[] = ".DAT";
  27. //const char c_szIE4SECTIONNAME[] = "backup";
  28. const char c_szNoFileLine[] = "-1,0,0,0,0,0,-1";
  29. int RestoreSingleFile(FILELIST *filelist, LPSTR lpszBakFile, HANDLE hDatFile);
  30. extern const char c_szNoFileLine[];
  31. void MySetUninstallFileAttrib(LPSTR lpszPath, LPCSTR lpszBasename);
  32. BOOL UninstallInfoInit(PBAKDATA pbd, LPCSTR lpszPath, LPCSTR lpszBasename, BOOL bBackup);
  33. HRESULT BackupFiles( HWND hDlg, LPSTR lpFileList, LPSTR lpDir, LPSTR lpBaseName, DWORD dwFlags);
  34. HRESULT RestoreFiles( HWND hDlg, LPSTR lpFileList, LPSTR lpDir, LPSTR lpBaseName, DWORD dwFlags);
  35. void FillBackupInfo(LPCSTR lpINIFile, FILELIST *pFileList);
  36. void initcopy(const char * StfWinDir, char * from, char * to);
  37. unsigned long Mystrtoul (const char *nptr, char **endptr, int ibase);
  38. BOOL CALLBACK SaveRestoreProgressDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  39. void GetListFromIniFile(LPSTR lpDir, LPSTR lpBaseName, LPSTR *lplpFileList);
  40. void CreateFullPathForFile(LPSTR lpszBakFile);
  41. DWORD GetRefCountFrReg( LPSTR lpFile );
  42. HRESULT UpdateRefCount( HWND hDlg, LPSTR lpFileList, LPSTR lpDir, LPSTR lpBaseName, DWORD dwFlags );
  43. HRESULT WINAPI FileSaveRestore( HWND hDlg, LPSTR lpFileList, LPSTR lpDir, LPSTR lpBaseName, DWORD dwFlags)
  44. {
  45. char szTitle[MAX_STR_LEN];
  46. LPSTR lpszOldTitle = ctx.lpszTitle;
  47. HRESULT hr;
  48. if (!CheckOSVersion())
  49. return E_FAIL;
  50. ctx.lpszTitle = szTitle; // Do we have to do this??
  51. if ( hDlg && !IsWindow(hDlg))
  52. dwFlags |= IE4_NOMESSAGES | IE4_NOPROGRESS;
  53. if (dwFlags & IE4_RESTORE)
  54. {
  55. LoadString(g_hInst, IDS_FILERESTORE_TITLE, szTitle, sizeof(szTitle));
  56. hr = RestoreFiles( hDlg, lpFileList, lpDir, lpBaseName, dwFlags);
  57. }
  58. else if ( dwFlags & AFSR_UPDREFCNT )
  59. {
  60. hr = UpdateRefCount( hDlg, lpFileList, lpDir, lpBaseName, dwFlags );
  61. }
  62. else
  63. {
  64. LoadString(g_hInst, IDS_FILEBACKUP_TITLE, szTitle, sizeof(szTitle));
  65. hr = BackupFiles( hDlg, lpFileList, lpDir, lpBaseName, dwFlags);
  66. }
  67. ctx.lpszTitle = lpszOldTitle;
  68. return hr;
  69. }
  70. HRESULT UpdateRefCount( HWND hDlg, LPSTR lpFileList, LPSTR lpDir, LPSTR lpBaseName, DWORD dwFlags )
  71. {
  72. char szIniFile[MAX_PATH];
  73. char szLine[MAX_STR_LEN];
  74. char szBuf[MAX_PATH];
  75. DWORD dwRefCount = -1;
  76. DWORD dwOldAttr;
  77. LPSTR lpFile;
  78. if ( !lpFileList || !*lpFileList )
  79. return S_OK;
  80. lpFile = lpFileList;
  81. BuildPath( szIniFile, lpDir, lpBaseName );
  82. lstrcat( szIniFile, c_szExtINI );
  83. if ( FileExists( szIniFile ) )
  84. {
  85. dwOldAttr = GetFileAttributes( szIniFile );
  86. SetFileAttributes( szIniFile, FILE_ATTRIBUTE_NORMAL );
  87. while ( *lpFile )
  88. {
  89. if ( GetPrivateProfileString( c_szIE4SECTIONNAME, lpFile, "", szLine, sizeof(szLine), szIniFile) )
  90. {
  91. LPSTR lpszComma;
  92. int i, j;
  93. if ( GetFieldString(szLine, 6, szBuf, sizeof(szBuf)) ) // For the Attribute
  94. {
  95. dwRefCount = My_atol( szBuf );
  96. if ( dwRefCount == (DWORD)-1 )
  97. {
  98. dwRefCount = GetRefCountFrReg( lpFile );
  99. }
  100. else if ( dwFlags & AFSR_EXTRAINCREFCNT )
  101. dwRefCount++;
  102. }
  103. else
  104. {
  105. dwRefCount = GetRefCountFrReg( lpFile );
  106. }
  107. // re-write the updated INI line
  108. lpszComma = szLine;
  109. for ( i=0; i<6; i++ )
  110. {
  111. lpszComma = ANSIStrChr(lpszComma, ',');
  112. if ( !lpszComma )
  113. break;
  114. else
  115. lpszComma = CharNext(lpszComma);
  116. }
  117. if ( !lpszComma )
  118. {
  119. for ( j=i; j<6; j++ )
  120. {
  121. lstrcat( szLine, "," );
  122. }
  123. }
  124. else
  125. *(++lpszComma) = '0';
  126. ULtoA( dwRefCount, szBuf, 10 );
  127. lstrcat( szLine, szBuf );
  128. WritePrivateProfileString( c_szIE4SECTIONNAME, lpFile, szLine, szIniFile );
  129. }
  130. lpFile += lstrlen(lpFile) + 1;
  131. }
  132. SetFileAttributes( szIniFile, dwOldAttr );
  133. }
  134. return S_OK;
  135. }
  136. DWORD GetRefCountFrReg( LPSTR lpFile )
  137. {
  138. HKEY hKey;
  139. DWORD dwRefCount = 0;
  140. DWORD dwType;
  141. DWORD dwSize;
  142. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, c_szREGKEY_SHAREDLL, (ULONG)0, KEY_READ, &hKey ) == ERROR_SUCCESS )
  143. {
  144. dwSize = sizeof(DWORD);
  145. if ( RegQueryValueEx( hKey, lpFile, NULL, &dwType, (LPBYTE)&dwRefCount, &dwSize ) != ERROR_SUCCESS )
  146. {
  147. dwRefCount = 0;
  148. }
  149. RegCloseKey( hKey );
  150. }
  151. return dwRefCount;
  152. }
  153. HRESULT BackupFiles( HWND hDlg, LPSTR lpFileList, LPSTR lpDir, LPSTR lpBaseName, DWORD dwFlags)
  154. {
  155. HRESULT hr = S_OK;
  156. BAKDATA bd;
  157. FILELIST FileList;
  158. LPSTR lpFile;
  159. char szLine[MAX_STR_LEN];
  160. char szValue[MAX_PATH];
  161. DWORD dwItems = 0;
  162. HWND hProgressDlg = NULL;
  163. if ((lpFileList) && (*lpFileList))
  164. {
  165. if (SUCCEEDED(CreateFullPath(lpDir, TRUE)) && UninstallInfoInit(&bd, lpDir, lpBaseName, TRUE))
  166. {
  167. if (!(dwFlags & IE4_NOPROGRESS))
  168. {
  169. hProgressDlg = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_SAVERESTOREDLG), hDlg, (DLGPROC) SaveRestoreProgressDlgProc, TRUE);
  170. ShowWindow(hProgressDlg, SW_SHOWNORMAL);
  171. lpFile = lpFileList;
  172. while (*lpFile)
  173. {
  174. dwItems++;
  175. lpFile += lstrlen(lpFile) + 1;
  176. }
  177. UpdateWindow(hProgressDlg);
  178. SendMessage(GetDlgItem(hProgressDlg, IDC_SAVERESTORE_PROGRESS), PBM_SETRANGE, 0, MAKELONG(0, dwItems));
  179. SendMessage(GetDlgItem(hProgressDlg, IDC_SAVERESTORE_PROGRESS), PBM_SETSTEP, 1, 0L);
  180. }
  181. lpFile = lpFileList;
  182. while ((hr == S_OK) && (*lpFile))
  183. {
  184. if (GetPrivateProfileString(c_szIE4SECTIONNAME, lpFile, "", szLine, sizeof(szLine), bd.szIniFileName) == 0)
  185. {
  186. FileList.bak_attribute = GetFileAttributes( lpFile );
  187. FileList.bak_exists = 0;
  188. }
  189. else
  190. {
  191. FileList.bak_exists = 1;
  192. FileList.bak_attribute = (DWORD)NO_FILE;
  193. if (GetFieldString(szLine, 0, szValue, sizeof(szValue))) // For the Attribute
  194. FileList.bak_attribute = (DWORD)Mystrtoul((const char*)szValue, NULL, 16);
  195. // If the file was in the list of files to backup the last time, but did not exist on the user machine
  196. // but this time around it exists, only backup the file if the user specifies IE4_BACKUPNEW
  197. if ((FileList.bak_attribute == (DWORD)NO_FILE) && (dwFlags & IE4_BACKNEW) )
  198. {
  199. FileList.bak_attribute = GetFileAttributes( lpFile );
  200. FileList.bak_exists = 0;
  201. }
  202. else
  203. {
  204. // the existing INI fields: Attri[Filed0],size[Filed1],date-time(low)[Filed2], date-time(high)[Field3],offset[Field4],CRC[Field5]
  205. // we are going to add the extra colume of reference count if not there already
  206. if ( !GetFieldString(szLine, 6, szValue, sizeof(szValue)) ) // For the Ref-count field
  207. {
  208. lstrcat( szLine, ",-1" );
  209. WritePrivateProfileString( c_szIE4SECTIONNAME, lpFile, szLine, bd.szIniFileName );
  210. }
  211. }
  212. }
  213. if (FileList.bak_exists == 0)
  214. {
  215. if (FileList.bak_attribute != (DWORD)NO_FILE)
  216. {
  217. FileList.name = lpFile;
  218. if (!BackupSingleFile(&FileList, &bd))
  219. { // If something went wrong, Sorry backup failed.
  220. if (!(dwFlags & IE4_NOMESSAGES))
  221. {
  222. if (MsgBox1Param( hDlg, IDS_FILEBACKUP_ERROR, lpFile, MB_ICONEXCLAMATION, MB_YESNO) == IDNO)
  223. {
  224. hr = E_FAIL;
  225. break;
  226. }
  227. }
  228. }
  229. }
  230. else
  231. {
  232. // File does not exist, nothing to backup, report this in the INI file.
  233. WritePrivateProfileString(c_szIE4SECTIONNAME, lpFile, c_szNoFileLine, bd.szIniFileName);
  234. }
  235. }
  236. // else we did already backup this file the previous install
  237. if (!(dwFlags & IE4_NOPROGRESS))
  238. {
  239. UpdateWindow(hProgressDlg);
  240. SendMessage(GetDlgItem(hProgressDlg, IDC_SAVERESTORE_PROGRESS), PBM_STEPIT, 0, 0L);
  241. }
  242. lpFile += lstrlen(lpFile) + 1;
  243. }
  244. if (bd.hDatFile != INVALID_HANDLE_VALUE)
  245. CloseHandle(bd.hDatFile);
  246. WritePrivateProfileString( NULL, NULL, NULL, bd.szIniFileName); // to make sure the ie4bak.ini file gets flushed
  247. }
  248. else
  249. {
  250. if (!(dwFlags & IE4_NOMESSAGES))
  251. {
  252. if (MsgBox( hDlg, IDS_BACKUPINIT_ERROR, MB_ICONEXCLAMATION , MB_YESNO) == IDNO)
  253. hr = E_FAIL;
  254. }
  255. }
  256. }
  257. if (hProgressDlg)
  258. DestroyWindow(hProgressDlg);
  259. MySetUninstallFileAttrib(lpDir, lpBaseName);
  260. return hr;
  261. }
  262. BOOL UninstallInfoInit(PBAKDATA pbd, LPCSTR lpszPath, LPCSTR lpszBasename, BOOL bBackup)
  263. {
  264. pbd->hDatFile = INVALID_HANDLE_VALUE;
  265. lstrcpy(pbd->szFinalDir, lpszPath);
  266. // the dat file and ini file are made on the first call to backup single file.
  267. if(pbd->hDatFile == INVALID_HANDLE_VALUE )
  268. {
  269. char szTmp[MAX_PATH];
  270. BuildPath(szTmp, pbd->szFinalDir, lpszBasename);
  271. lstrcat(szTmp, c_szExtDAT);
  272. SetFileAttributes(szTmp, FILE_ATTRIBUTE_NORMAL);
  273. pbd->hDatFile = CreateFile(szTmp, GENERIC_READ|GENERIC_WRITE, 0, NULL,
  274. (bBackup ? OPEN_ALWAYS : OPEN_EXISTING) , FILE_ATTRIBUTE_NORMAL, NULL);
  275. if(pbd->hDatFile == INVALID_HANDLE_VALUE)
  276. return FALSE;
  277. pbd->dwDatOffset = SetFilePointer(pbd->hDatFile, 0, NULL, FILE_END);
  278. BuildPath(pbd->szIniFileName, pbd->szFinalDir, lpszBasename);
  279. lstrcat(pbd->szIniFileName, c_szExtINI);
  280. SetFileAttributes(pbd->szIniFileName, FILE_ATTRIBUTE_NORMAL);
  281. }
  282. return TRUE;
  283. }
  284. void MySetUninstallFileAttrib(LPSTR lpszPath, LPCSTR lpszBasename)
  285. {
  286. char szTmp[MAX_PATH];
  287. BuildPath(szTmp, lpszPath, lpszBasename);
  288. lstrcat(szTmp, c_szExtDAT);
  289. SetFileAttributes(szTmp, FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_READONLY);
  290. BuildPath(szTmp, lpszPath, lpszBasename);
  291. lstrcat(szTmp, c_szExtINI);
  292. SetFileAttributes(szTmp, FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_READONLY);
  293. return;
  294. }
  295. HRESULT RestoreFiles( HWND hDlg, LPSTR lpFileList, LPSTR lpDir, LPSTR lpBaseName, DWORD dwFlags)
  296. {
  297. HRESULT hr = S_OK;
  298. int iErr = 0;
  299. BAKDATA bd;
  300. char szFile[MAX_PATH];
  301. char szWinDir[MAX_PATH];
  302. DWORD dwItems = 0;
  303. HWND hProgressDlg = NULL;
  304. LPSTR lpFile;
  305. FILELIST FileList;
  306. BOOL bGotListFromIniFile = FALSE;
  307. if (lpFileList == NULL)
  308. {
  309. GetListFromIniFile(lpDir, lpBaseName, &lpFileList);
  310. bGotListFromIniFile = TRUE;
  311. }
  312. if ((lpFileList == NULL) || !(*lpFileList))
  313. return hr; // Nothing to restore.
  314. if (!UninstallInfoInit(&bd, lpDir, lpBaseName, FALSE))
  315. {
  316. if (!(dwFlags & IE4_NOMESSAGES))
  317. MsgBox( NULL, IDS_BACKUPDAT_ERROR, MB_ICONEXCLAMATION, MB_OK);
  318. if (bGotListFromIniFile)
  319. {
  320. LocalFree(lpFileList);
  321. lpFileList = NULL;
  322. }
  323. return E_FAIL;
  324. }
  325. if (!(dwFlags & IE4_NOPROGRESS))
  326. {
  327. hProgressDlg = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_SAVERESTOREDLG), hDlg, (DLGPROC) SaveRestoreProgressDlgProc, FALSE);
  328. ShowWindow(hProgressDlg, SW_SHOWNORMAL);
  329. lpFile = lpFileList;
  330. while (*lpFile)
  331. {
  332. dwItems++;
  333. lpFile += lstrlen(lpFile) + 1;
  334. }
  335. UpdateWindow(hProgressDlg);
  336. SendMessage(GetDlgItem(hProgressDlg, IDC_SAVERESTORE_PROGRESS), PBM_SETRANGE, 0, MAKELONG(0, dwItems));
  337. SendMessage(GetDlgItem(hProgressDlg, IDC_SAVERESTORE_PROGRESS), PBM_SETSTEP, 1, 0L);
  338. }
  339. GetWindowsDirectory(szWinDir, sizeof(szWinDir));
  340. lpFile = lpFileList;
  341. while ((hr == S_OK) && (*lpFile))
  342. {
  343. FileList.name = lpFile;
  344. FileList.dwSize = 0;
  345. FileList.dwDatOffset = (DWORD)-1;
  346. FillBackupInfo(bd.szIniFileName, &FileList);
  347. if ( (FileList.bak_attribute != NO_FILE) &&
  348. (FileList.dwSize > 0) && (FileList.dwDatOffset != (DWORD)-1))
  349. {
  350. if (!MakeBakName(FileList.name, szFile))
  351. {
  352. if (!(dwFlags & IE4_NOMESSAGES))
  353. {
  354. if (MsgBox1Param( hDlg, IDS_RESTORE_ERROR2, FileList.name, MB_ICONEXCLAMATION, MB_YESNO) == IDNO)
  355. {
  356. // error creating a temp file for file to restore.
  357. hr = E_FAIL;
  358. break;
  359. }
  360. }
  361. goto NextFile;
  362. }
  363. // if need to use the reg count, we only do it for those files have real ref count to begin with
  364. if ( (dwFlags & AFSR_USEREFCNT) && (FileList.dwRefCount!=(DWORD)-1) )
  365. {
  366. DWORD dwRefCntInReg;
  367. dwRefCntInReg = GetRefCountFrReg( FileList.name );
  368. if ( dwRefCntInReg > FileList.dwRefCount )
  369. goto NextFile;
  370. }
  371. iErr = RestoreSingleFile(&FileList, szFile, bd.hDatFile);
  372. if (iErr != 0)
  373. {
  374. if (!(dwFlags & IE4_NOMESSAGES))
  375. {
  376. wsprintf(szFile, "%d", iErr); // reuse szFile, it is set on every call in MakeBakName
  377. if (MsgBox2Param( hDlg, IDS_RESTORE_ERROR, FileList.name, szFile, MB_ICONEXCLAMATION, MB_YESNO) == IDNO)
  378. hr = E_FAIL;
  379. }
  380. }
  381. else
  382. {
  383. SetFileAttributes( szFile, FileList.bak_attribute );
  384. if ( CopyFileA(szFile, FileList.name, FALSE))
  385. {
  386. SetFileAttributes( szFile, FILE_ATTRIBUTE_NORMAL );
  387. DeleteFile( szFile );
  388. }
  389. else
  390. initcopy(szWinDir, szFile, FileList.name);
  391. }
  392. }
  393. else
  394. {
  395. // the file was never backed up, delete it if the caller want's us to
  396. if (!(dwFlags & IE4_NODELETENEW) )
  397. {
  398. if ( (!DeleteFile(lpFile)) && (GetFileAttributes(lpFile) != (DWORD)-1))
  399. initcopy(szWinDir, lpFile, "NUL"); // If we could not delete the file. Add to reboot delete
  400. }
  401. }
  402. NextFile:
  403. lpFile += lstrlen(lpFile) + 1;
  404. if (!(dwFlags & IE4_NOPROGRESS))
  405. {
  406. UpdateWindow(hProgressDlg);
  407. SendMessage(GetDlgItem(hProgressDlg, IDC_SAVERESTORE_PROGRESS), PBM_STEPIT, 0, 0L);
  408. }
  409. }
  410. if (hProgressDlg)
  411. DestroyWindow(hProgressDlg);
  412. if (bd.hDatFile != INVALID_HANDLE_VALUE)
  413. CloseHandle(bd.hDatFile);
  414. if (bGotListFromIniFile)
  415. {
  416. LocalFree(lpFileList);
  417. lpFileList = NULL;
  418. }
  419. return hr;
  420. }
  421. void FillBackupInfo(LPCSTR lpINIFile, FILELIST *pFileList)
  422. {
  423. char szLine[MAX_STR_LEN];
  424. char szValue[MAX_PATH];
  425. pFileList->dwDatOffset = (DWORD)-1;
  426. pFileList->dwRefCount = (DWORD)-1;
  427. if (GetPrivateProfileString(c_szIE4SECTIONNAME, pFileList->name, "", szLine, sizeof(szLine), lpINIFile) != 0)
  428. {
  429. if (GetFieldString(szLine, 0, szValue, sizeof(szValue))) // For the Attribute
  430. pFileList->bak_attribute = (DWORD)Mystrtoul((const char*)szValue, NULL, 16);
  431. if (pFileList->bak_attribute != (DWORD)NO_FILE)
  432. {
  433. pFileList->bak_exists = 1;
  434. if (GetFieldString(szLine, 1, szValue, sizeof(szValue))) // For the size
  435. pFileList->dwSize = (DWORD)Mystrtoul((const char*)szValue, NULL, 16);
  436. if (GetFieldString(szLine, 2, szValue, sizeof(szValue))) // For the time/date
  437. pFileList->FileTime.dwLowDateTime = (DWORD)Mystrtoul((const char*)szValue, NULL, 16);
  438. if (GetFieldString(szLine, 3, szValue, sizeof(szValue))) // For the time/date
  439. pFileList->FileTime.dwHighDateTime = (DWORD)Mystrtoul((const char*)szValue, NULL, 16);
  440. if (GetFieldString(szLine, 4, szValue, sizeof(szValue))) // For the Offset
  441. pFileList->dwDatOffset = (DWORD)Mystrtoul((const char*)szValue, NULL, 16);
  442. if (GetFieldString(szLine, 5, szValue, sizeof(szValue))) // For the CRC
  443. pFileList->dwFileCRC = (DWORD)Mystrtoul((const char*)szValue, NULL, 16);
  444. if (GetFieldString(szLine, 6, szValue, sizeof(szValue))) // For the CRC
  445. pFileList->dwRefCount = (DWORD)Mystrtoul((const char*)szValue, NULL, 16);
  446. }
  447. else
  448. pFileList->bak_exists = 0;
  449. }
  450. else
  451. pFileList->bak_exists = 0;
  452. return;
  453. }
  454. BOOL MakeBakName(LPSTR lpszName, LPSTR szBakName)
  455. {
  456. static int iNum = 0;
  457. BOOL bOK = FALSE;
  458. LPSTR lpTmp;
  459. char szFilename[14];
  460. lstrcpy(szBakName, lpszName);
  461. lpTmp = CharPrev( szBakName, szBakName+lstrlen(szBakName));
  462. // chop filename off
  463. //
  464. while ( (lpTmp > szBakName) && *lpTmp && (*lpTmp != '\\') )
  465. lpTmp = CharPrev( szBakName, lpTmp );
  466. if ( *CharPrev( szBakName, lpTmp ) == ':' )
  467. {
  468. lpTmp = CharNext(lpTmp) ;
  469. }
  470. *lpTmp = '\0';
  471. while ((iNum < 1000) && !bOK)
  472. {
  473. *lpTmp = '\0';
  474. wsprintf(szFilename, "IEBAK%03d.TMP", iNum++);
  475. AddPath(szBakName, szFilename);
  476. bOK = (GetFileAttributes(szBakName) == 0xFFFFFFFF); // File does not exist, then OK
  477. }
  478. if (!bOK)
  479. {
  480. // If we could not get a tempfile name with the above methode, try GetTempFileName
  481. // Retry once, if it does not work fail.
  482. *lpTmp = '\0';
  483. CreateFullPath(lpszName, FALSE); // If directory does not exist GetTempFileName() fails.
  484. bOK = GetTempFileName(szBakName, "IE4", 0, szBakName);
  485. }
  486. return bOK;
  487. }
  488. // copy files by, adding them to wininit.ini
  489. void initcopy(const char * StfWinDir, char * from, char * to)
  490. {
  491. char * wininitpath;
  492. char * wininitname = {"wininit.ini"};
  493. LPTSTR lpBuf = NULL;
  494. LPTSTR lpTmp;
  495. static DWORD dwBufSize = MAX_STR_LEN*3;
  496. DWORD dwBytes;
  497. if (ctx.wOSVer == _OSVER_WIN95)
  498. {
  499. // 16 is just for padding
  500. wininitpath = (char*) LocalAlloc(LPTR, lstrlen(StfWinDir) + lstrlen(wininitname) + 2 + 16);
  501. if (wininitpath)
  502. {
  503. lstrcpy(wininitpath, StfWinDir);
  504. AddPath(wininitpath, wininitname);
  505. while (TRUE)
  506. {
  507. lpBuf = (LPTSTR)LocalAlloc( LPTR, (UINT)dwBufSize );
  508. if (lpBuf)
  509. {
  510. dwBytes = GetPrivateProfileSection( SEC_RENAME, lpBuf, dwBufSize, wininitname );
  511. //The 16 below is just padding (all we probably need is only 3 or so)...
  512. if ( (dwBytes >= (dwBufSize - 2)) || (dwBytes+lstrlen(to)+lstrlen(from)+16) > dwBufSize )
  513. {
  514. // not enough buf size
  515. dwBufSize += MAX_STR_LEN;
  516. LocalFree( lpBuf );
  517. }
  518. else
  519. {
  520. lpTmp = lpBuf+dwBytes;
  521. if (lstrcmpi(to, "NUL") == 0)
  522. lstrcpy(lpTmp, to);
  523. else
  524. GetShortPathName( to, lpTmp, (dwBufSize - dwBytes) );
  525. lstrcat( lpTmp, "=" );
  526. GetShortPathName( from, lpTmp + lstrlen(lpTmp), (dwBufSize - dwBytes - lstrlen(lpTmp)) );
  527. // MessageBox(NULL, lpTmp, wininitname, MB_OK);
  528. lpTmp += lstrlen(lpTmp);
  529. lpTmp++; //jump over the first '\0'
  530. *lpTmp = '\0';
  531. WritePrivateProfileSection( SEC_RENAME, lpBuf, wininitname );
  532. break;
  533. }
  534. }
  535. else
  536. break;
  537. }
  538. if (lpBuf)
  539. {
  540. LocalFree( lpBuf );
  541. lpBuf = NULL;
  542. }
  543. LocalFree(wininitpath);
  544. }
  545. }
  546. else
  547. {
  548. if (lstrcmpi(to, "NUL") == 0)
  549. MoveFileEx(from, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); // delete the file
  550. else
  551. MoveFileEx(from, to, MOVEFILE_DELAY_UNTIL_REBOOT | MOVEFILE_REPLACE_EXISTING); // rename the file
  552. }
  553. }
  554. BOOL BackupSingleFile(FILELIST * filelist, PBAKDATA pbd)
  555. {
  556. HANDLE hFile;
  557. BOOL bErr=FALSE;
  558. DWORD cbRead;
  559. DWORD cbComp;
  560. LPBYTE lpBuff;
  561. LPBYTE lpBuffComp;
  562. DWORD dwFileSig = DAT_FILESIG;
  563. DWORD dwOrigDatOffset = pbd->dwDatOffset;
  564. DWORD dwBytesWritten = 0;
  565. DWORD dwFileSize;
  566. ULONG ulCRC = CRC32_INITIAL_VALUE;
  567. FILETIME FileTime = {0, 0};
  568. BOOL bRet=TRUE;
  569. cbRead = (DWORD)MAX_IOSIZE;
  570. lpBuff = LocalAlloc(LPTR, cbRead + 32 );
  571. lpBuffComp = LocalAlloc(LPTR, cbRead + 32);
  572. if (!lpBuff || !lpBuffComp)
  573. {
  574. bRet=FALSE;
  575. }
  576. else
  577. {
  578. hFile = CreateFile(filelist->name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  579. if (hFile==INVALID_HANDLE_VALUE)
  580. {
  581. bRet=FALSE;
  582. }
  583. else
  584. {
  585. GetFileTime(hFile, NULL, NULL, &FileTime);
  586. dwFileSize = GetFileSize(hFile, NULL);
  587. if (!WriteFile(pbd->hDatFile, &dwFileSig, sizeof(dwFileSig), &dwBytesWritten, NULL))
  588. {
  589. cbRead = 0; // prevent the loop from executing
  590. bRet=FALSE;
  591. }
  592. else
  593. pbd->dwDatOffset += sizeof(dwFileSig);
  594. while (cbRead == MAX_IOSIZE)
  595. {
  596. if (!ReadFile (hFile, lpBuff, (DWORD)MAX_IOSIZE, &cbRead, NULL))
  597. {
  598. bRet=FALSE;
  599. break;
  600. }
  601. if (cbRead == 0) // no more data, time to leave
  602. break;
  603. ulCRC = CRC32Compute(lpBuff, cbRead, ulCRC);
  604. cbComp = Mrci1MaxCompress(lpBuff, cbRead, lpBuffComp, (DWORD)MAX_IOSIZE);
  605. if ((cbComp == (DWORD) -1) || (cbComp >= cbRead))
  606. {
  607. cbComp = 0;
  608. }
  609. // We want to write out lpBuff if cbComp is ZERO, or
  610. // lpBuffComp is cbComp is NON-ZERO. In any case, we
  611. // precede every chunk with two words: cbRead and cbComp.
  612. dwFileSig = cbRead | ((DWORD)cbComp << 16);
  613. if (!WriteFile(pbd->hDatFile, &dwFileSig, sizeof(dwFileSig), &dwBytesWritten, NULL))
  614. {
  615. bRet=FALSE;
  616. break;
  617. }
  618. pbd->dwDatOffset += sizeof(dwFileSig);
  619. if (!cbComp)
  620. {
  621. bErr = !WriteFile(pbd->hDatFile, lpBuff, cbRead, &dwBytesWritten, NULL);
  622. }
  623. else
  624. {
  625. bErr = !WriteFile(pbd->hDatFile, lpBuffComp, cbComp, &dwBytesWritten, NULL);
  626. }
  627. if (bErr)
  628. {
  629. bRet=FALSE;
  630. break;
  631. }
  632. pbd->dwDatOffset += dwBytesWritten;
  633. }
  634. CloseHandle(hFile);
  635. // Write out size/date/time etc to ini file
  636. if (!bErr)
  637. {
  638. DosPrintf(pbd, filelist,
  639. dwFileSize,
  640. FileTime,
  641. dwOrigDatOffset,
  642. ulCRC);
  643. }
  644. }
  645. }
  646. if (lpBuffComp)
  647. LocalFree(lpBuffComp);
  648. if (lpBuff)
  649. LocalFree(lpBuff);
  650. return bRet;
  651. }
  652. int DosPrintf(PBAKDATA pbd, FILELIST *filelist, DWORD dwFileSize,
  653. FILETIME FileTime, DWORD dwDatOffset, DWORD dwCRC)
  654. {
  655. WORD cb;
  656. char szTmp[MAX_STR_LEN];
  657. // BUGBUG: if we rewrite the line, we lose the ref count and becomes -1 again.
  658. // UpdateRefCnt() will not get a chance to increase the count based on the original data.
  659. //
  660. cb = (WORD)wsprintf(szTmp, "%lx,%lx,%lx,%lx,%lx,%lx,%d",
  661. filelist->bak_attribute,
  662. dwFileSize,
  663. FileTime.dwLowDateTime,
  664. FileTime.dwHighDateTime,
  665. dwDatOffset, dwCRC, -1);
  666. WritePrivateProfileString(c_szIE4SECTIONNAME, filelist->name, szTmp, pbd->szIniFileName);
  667. return cb;
  668. }
  669. //
  670. // Copied from Windows 95 unistal.exe cfg.c function CfgGetField
  671. BOOL GetFieldString(LPSTR lpszLine, int iField, LPSTR lpszField, int cbSize)
  672. {
  673. int cbField;
  674. LPSTR lpszChar, lpszEnd;
  675. // Find the field we are looking for
  676. lpszChar = lpszLine;
  677. // Each time we see a separator, decrement iField
  678. while (iField > 0 && (BYTE)*lpszChar > CR) {
  679. if (*lpszChar == '=' || *lpszChar == ',' || *lpszChar == ' ' ) {
  680. iField--;
  681. while (*lpszChar == '=' || *lpszChar== ',' || *lpszChar == ' ' && (BYTE)*lpszChar > 13)
  682. lpszChar++;
  683. }
  684. else
  685. lpszChar++;
  686. }
  687. // If we still have fields remaining then something went wrong
  688. if (iField)
  689. return FALSE;
  690. // Now find the end of this field
  691. lpszEnd = lpszChar;
  692. while (*lpszEnd != '=' && *lpszEnd != ',' && *lpszEnd != ' ' && (BYTE)*lpszEnd > CR)
  693. lpszEnd++;
  694. // Find the length of this field - make sure it'll fit in the buffer
  695. cbField = (int)((lpszEnd - lpszChar) + 1);
  696. if (cbField > cbSize) { // I return an error if the requested
  697. //cbField = cbSize; // data won't fit, rather than truncating
  698. return FALSE; // it at some random point! -JTP
  699. }
  700. // Note that the C runtime treats cbField as the number of characters
  701. // to copy from the source, and if that doesn't happen to transfer a NULL,
  702. // too bad. The Windows implementation of _lstrcpyn treats cbField as
  703. // the number of characters that can be stored in the destination, and
  704. // always copies a NULL (even if it means copying only cbField-1 characters
  705. // from the source).
  706. // The C runtime also pads the destination with NULLs if a NULL in the
  707. // source is found before cbField is exhausted. _lstrcpyn essentially quits
  708. // after copying a NULL.
  709. lstrcpyn(lpszField, lpszChar, cbField);
  710. return TRUE;
  711. }
  712. int RestoreSingleFile(FILELIST *filelist, LPSTR lpszBakFile, HANDLE hDatFile)
  713. {
  714. LPBYTE lpBuff;
  715. LPBYTE lpBuffDecomp;
  716. LPBYTE lpWrite;
  717. HANDLE hFile;
  718. DWORD dwFileSig;
  719. DWORD dwByteRead;
  720. DWORD dwByteDecomp;
  721. DWORD dwBytesWritten;
  722. ULONG ulCRC = CRC32_INITIAL_VALUE;
  723. int iErr = OK;
  724. LONG lSize = (LONG)filelist->dwSize;
  725. WORD wComp;
  726. WORD wRead;
  727. lpBuff = LocalAlloc(LPTR, MAX_IOSIZE);
  728. lpBuffDecomp = LocalAlloc(LPTR, MAX_IOSIZE);
  729. if ((lpBuff) && (lpBuffDecomp))
  730. {
  731. hFile= CreateFile(lpszBakFile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  732. if (hFile == INVALID_HANDLE_VALUE)
  733. {
  734. CreateFullPathForFile(lpszBakFile);
  735. hFile= CreateFile(lpszBakFile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  736. }
  737. if (hFile != INVALID_HANDLE_VALUE)
  738. {
  739. if (SetFilePointer(hDatFile, filelist->dwDatOffset, NULL, FILE_BEGIN) != (DWORD)-1)
  740. {
  741. if (ReadFile (hDatFile, (LPVOID)&dwFileSig, (DWORD)sizeof(dwFileSig), &dwByteRead, NULL))
  742. {
  743. if (dwFileSig != DAT_FILESIG)
  744. iErr = MYERROR_BAD_SIG;
  745. }
  746. else
  747. iErr = MYERROR_READ;
  748. }
  749. else
  750. iErr = MYERROR_UNKNOWN;
  751. while ((iErr == OK) && (lSize > 0))
  752. {
  753. if (!ReadFile (hDatFile, (LPVOID)&dwFileSig, (DWORD)sizeof(dwFileSig), &dwByteRead, NULL))
  754. {
  755. iErr = MYERROR_READ;
  756. break;
  757. }
  758. wComp = (WORD)(dwFileSig >> 16);
  759. wRead = (WORD)(dwFileSig & 0xffff);
  760. lpWrite = lpBuff;
  761. dwByteDecomp = (DWORD)wRead;
  762. if ((wComp > MAX_IOSIZE) || (wRead > MAX_IOSIZE))
  763. {
  764. iErr = MYERROR_BAD_DATA;
  765. }
  766. else if (wComp == 0)
  767. {
  768. if (!ReadFile (hDatFile, lpBuff, wRead, &dwByteDecomp, NULL))
  769. {
  770. iErr = MYERROR_READ;
  771. }
  772. }
  773. else
  774. {
  775. lpWrite = lpBuffDecomp;
  776. if (!ReadFile (hDatFile, lpBuff, wComp, &dwByteRead, NULL))
  777. {
  778. iErr = MYERROR_READ;
  779. }
  780. else
  781. {
  782. dwByteDecomp = Mrci1Decompress(lpBuff, wComp, lpBuffDecomp, wRead);
  783. if (dwByteDecomp != (DWORD)wRead)
  784. iErr = MYERROR_DECOMP_FAILURE;
  785. }
  786. }
  787. if (iErr != OK)
  788. {
  789. break;
  790. }
  791. ulCRC = CRC32Compute(lpWrite, dwByteDecomp, ulCRC);
  792. if (!WriteFile(hFile, lpWrite, dwByteDecomp, &dwBytesWritten, NULL))
  793. {
  794. iErr = MYERROR_WRITE;
  795. break;
  796. }
  797. lSize -= (LONG)dwBytesWritten;
  798. } // while
  799. SetFileTime(hFile, NULL, NULL, &filelist->FileTime);
  800. CloseHandle(hFile);
  801. if (ulCRC != filelist->dwFileCRC)
  802. {
  803. iErr = MYERROR_BAD_CRC;
  804. }
  805. if (iErr != OK)
  806. {
  807. DeleteFile(lpszBakFile);
  808. }
  809. }
  810. else
  811. {
  812. // Could not create backup file
  813. iErr = MYERROR_BAD_BAK;
  814. }
  815. }
  816. else
  817. {
  818. // Alloc failed
  819. iErr = MYERROR_OUTOFMEMORY;
  820. }
  821. if (lpBuff)
  822. LocalFree(lpBuff);
  823. if (lpBuffDecomp)
  824. LocalFree(lpBuffDecomp);
  825. return iErr;
  826. }
  827. #define IsSpace(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n' || (c) == '\v' || (c) == '\f')
  828. /* flag values */
  829. #define FL_UNSIGNED 1 /* strtoul called */
  830. #define FL_NEG 2 /* negative sign found */
  831. #define FL_OVERFLOW 4 /* overflow occured */
  832. #define FL_READDIGIT 8 /* we've read at least one correct digit */
  833. unsigned long Mystrtoxl (
  834. const char *nptr,
  835. const char **endptr,
  836. int ibase,
  837. int flags
  838. )
  839. {
  840. const char *p;
  841. char c;
  842. unsigned long number;
  843. unsigned digval;
  844. unsigned long maxval;
  845. p = nptr; /* p is our scanning pointer */
  846. number = 0; /* start with zero */
  847. c = *p++; /* read char */
  848. while ( IsSpace((int)(unsigned char)c) )
  849. c = *p++; /* skip whitespace */
  850. if (c == '-') {
  851. flags |= FL_NEG; /* remember minus sign */
  852. c = *p++;
  853. }
  854. else if (c == '+')
  855. c = *p++; /* skip sign */
  856. if (ibase < 0 || ibase == 1 || ibase > 36) {
  857. /* bad base! */
  858. if (endptr)
  859. /* store beginning of string in endptr */
  860. *endptr = nptr;
  861. return 0L; /* return 0 */
  862. }
  863. else if (ibase == 0) {
  864. /* determine base free-lance, based on first two chars of
  865. string */
  866. if (c != '0')
  867. ibase = 10;
  868. else if (*p == 'x' || *p == 'X')
  869. ibase = 16;
  870. else
  871. ibase = 8;
  872. }
  873. if (ibase == 16) {
  874. /* we might have 0x in front of number; remove if there */
  875. if (c == '0' && (*p == 'x' || *p == 'X')) {
  876. ++p;
  877. c = *p++; /* advance past prefix */
  878. }
  879. }
  880. /* if our number exceeds this, we will overflow on multiply */
  881. maxval = ULONG_MAX / ibase;
  882. for (;;) { /* exit in middle of loop */
  883. /* convert c to value */
  884. if ( c >= '0' && c <= '9' ) // isdigit
  885. digval = c - '0';
  886. else if ( ( c >= 'A' && c <= 'Z' ) || ( c >= 'a' && c <= 'z' ))
  887. // if ( isalpha((int)(unsigned char)c) )
  888. digval = (unsigned)(ULONG_PTR)CharUpper((LPSTR)c) - 'A' + 10;
  889. else
  890. break;
  891. if (digval >= (unsigned)ibase)
  892. break; /* exit loop if bad digit found */
  893. /* record the fact we have read one digit */
  894. flags |= FL_READDIGIT;
  895. /* we now need to compute number = number * base + digval,
  896. but we need to know if overflow occured. This requires
  897. a tricky pre-check. */
  898. if (number < maxval || (number == maxval &&
  899. (unsigned long)digval <= ULONG_MAX % ibase)) {
  900. /* we won't overflow, go ahead and multiply */
  901. number = number * ibase + digval;
  902. }
  903. else {
  904. /* we would have overflowed -- set the overflow flag */
  905. flags |= FL_OVERFLOW;
  906. }
  907. c = *p++; /* read next digit */
  908. }
  909. --p; /* point to place that stopped scan */
  910. if (!(flags & FL_READDIGIT)) {
  911. /* no number there; return 0 and point to beginning of
  912. string */
  913. if (endptr)
  914. /* store beginning of string in endptr later on */
  915. p = nptr;
  916. number = 0L; /* return 0 */
  917. }
  918. else if ( (flags & FL_OVERFLOW) ||
  919. ( !(flags & FL_UNSIGNED) &&
  920. ( ( (flags & FL_NEG) && (number > -LONG_MIN) ) ||
  921. ( !(flags & FL_NEG) && (number > LONG_MAX) ) ) ) )
  922. {
  923. /* overflow or signed overflow occurred */
  924. //errno = 34; // 34 is the define of ERANGE from errno.h
  925. if ( flags & FL_UNSIGNED )
  926. number = ULONG_MAX;
  927. else if ( flags & FL_NEG )
  928. number = (unsigned long)(-LONG_MIN);
  929. else
  930. number = LONG_MAX;
  931. }
  932. if (endptr != NULL)
  933. /* store pointer to char that stopped the scan */
  934. *endptr = p;
  935. if (flags & FL_NEG)
  936. /* negate result if there was a neg sign */
  937. number = (unsigned long)(-(long)number);
  938. return number; /* done. */
  939. }
  940. unsigned long Mystrtoul (
  941. const char *nptr,
  942. char **endptr,
  943. int ibase
  944. )
  945. {
  946. return Mystrtoxl(nptr, endptr, ibase, FL_UNSIGNED);
  947. }
  948. BOOL CALLBACK SaveRestoreProgressDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  949. {
  950. switch( uMsg )
  951. {
  952. case WM_INITDIALOG:
  953. ShowWindow(GetDlgItem(hwndDlg, IDS_SAVEINFO_TEXT), lParam? SW_SHOW : SW_HIDE);
  954. ShowWindow(GetDlgItem(hwndDlg, IDS_RESTOREINFO_TEXT), lParam? SW_HIDE : SW_SHOW );
  955. CenterWindow( hwndDlg, GetDesktopWindow());
  956. ShowWindow(hwndDlg, SW_SHOWNORMAL);
  957. break;
  958. default: // For MSG switch
  959. return(FALSE);
  960. }
  961. return(TRUE);
  962. }
  963. //
  964. // Creates the path for the full qualified file name.
  965. // We have to get rid of the filename first, before we
  966. // can attempt to create the path.
  967. void CreateFullPathForFile(LPSTR lpszBakFile)
  968. {
  969. char szDir[MAX_PATH];
  970. lstrcpy(szDir, lpszBakFile);
  971. GetParentDir(szDir);
  972. CreateFullPath(szDir, FALSE);
  973. }
  974. void GetListFromIniFile(LPSTR lpDir, LPSTR lpBaseName, LPSTR *lplpFileList)
  975. {
  976. char szINI[MAX_PATH];
  977. WIN32_FIND_DATA FindFileData;
  978. HANDLE hFind;
  979. LPSTR lpTmp;
  980. BuildPath(szINI, lpDir, lpBaseName);
  981. lstrcat(szINI, c_szExtINI);
  982. if ((hFind = FindFirstFile(szINI, &FindFileData)) != INVALID_HANDLE_VALUE)
  983. {
  984. if (lpTmp = LocalAlloc(LPTR, FindFileData.nFileSizeLow))
  985. {
  986. GetPrivateProfileString(c_szIE4SECTIONNAME, NULL, "", lpTmp, FindFileData.nFileSizeLow, szINI);
  987. if (*lpTmp)
  988. {
  989. *lplpFileList = lpTmp;
  990. }
  991. else
  992. LocalFree(lpTmp); // Nothing found in the INI file
  993. }
  994. FindClose(hFind);
  995. }
  996. }
  997. HRESULT AddDelBackupEntryHelper(LPCSTR lpcszFileList, LPCSTR lpcszBackupDir, LPCSTR lpcszBaseName, DWORD dwFlags)
  998. {
  999. HRESULT hr = S_OK;
  1000. LPCSTR lpcszFile;
  1001. char szIniFileName[MAX_PATH];
  1002. if ((lpcszFileList) && (*lpcszFileList))
  1003. {
  1004. BuildPath(szIniFileName, lpcszBackupDir, lpcszBaseName);
  1005. lstrcat(szIniFileName, c_szExtINI);
  1006. SetFileAttributes(szIniFileName, FILE_ATTRIBUTE_NORMAL);
  1007. lpcszFile = lpcszFileList;
  1008. while (*lpcszFile)
  1009. {
  1010. WritePrivateProfileString(c_szIE4SECTIONNAME, lpcszFile, (dwFlags & AADBE_ADD_ENTRY) ? c_szNoFileLine : NULL, szIniFileName);
  1011. lpcszFile += lstrlen(lpcszFile) + 1;
  1012. }
  1013. WritePrivateProfileString(NULL, NULL, NULL, szIniFileName); // flush the INI file
  1014. SetFileAttributes(szIniFileName, FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_READONLY);
  1015. }
  1016. return hr;
  1017. }
  1018. HRESULT WINAPI FileSaveMarkNotExist( LPSTR lpFileList, LPSTR lpDir, LPSTR lpBaseName)
  1019. {
  1020. return AddDelBackupEntryHelper(lpFileList, lpDir, lpBaseName, AADBE_ADD_ENTRY);
  1021. }
  1022. HRESULT WINAPI AddDelBackupEntry(LPCSTR lpcszFileList, LPCSTR lpcszBackupDir, LPCSTR lpcszBaseName, DWORD dwFlags)
  1023. {
  1024. return AddDelBackupEntryHelper(lpcszFileList, lpcszBackupDir, lpcszBaseName, dwFlags);
  1025. }