Leaked source code of windows server 2003
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.

681 lines
17 KiB

  1. /***************************************************************************
  2. **
  3. ** File: dmnd2.c
  4. ** Purpose: CallBack functions to be passed to the Diamond
  5. ** FDI (File Decompression Interface) module.
  6. ** Notes:
  7. **
  8. ****************************************************************************/
  9. #define DMND2_C
  10. #include <windows.h>
  11. #include <stdlib.h> /* malloc */
  12. #include <malloc.h> /* malloc, _halloc */
  13. #include <stdio.h> /* _tempnam */
  14. #include <fcntl.h>
  15. #include <io.h> /* _open, _read, _write, _write, _lseek, _mktemp */
  16. #include <sys\stat.h> /* _S_IWRITE, _S_IREAD */
  17. #include "stdtypes.h"
  18. #include "setup.h"
  19. #include <fdi.h>
  20. typedef struct _fud /* Fdi User Data block used in FDICopy */
  21. {
  22. char * szDstDir;
  23. char * szSrcs;
  24. char * szDsts;
  25. char * szSrcBuf;
  26. char * szDstBuf;
  27. BOOL * rgfSrcFilesCopied;
  28. int cFilesCopied;
  29. int cSrcFiles;
  30. int cCabNum; /* Current cabinet number (starts at 1) */
  31. HWND hWnd; /* Window handle used to display dialogs */
  32. HFDI hfdi;
  33. ERF erf;
  34. BRC brc;
  35. char rgchSpillFileName[cchFullPathMax];
  36. int hfSpillFile;
  37. } FUD;
  38. typedef FUD * PFUD; /* Ptr to Fdi User Data block */
  39. #define pfudNull ((PFUD)NULL)
  40. #define hfdiNull ((HFDI)NULL)
  41. #define szSpillFilePrefix "sf"
  42. #define szSpillFileTemplate "sfXXXXXX"
  43. /* FDI Callback Routines
  44. */
  45. FNFDINOTIFY ( FnFdiNotifyCB );
  46. FNALLOC ( FnFdiAllocCB );
  47. FNFREE ( FnFdiFreeCB );
  48. INT_PTR FAR DIAMONDAPI FnFdiOpenCB ( char FAR *szFile, int oflag, int pmode );
  49. UINT FAR DIAMONDAPI FnFdiReadCB ( INT_PTR hf, void FAR *pv, UINT cb );
  50. UINT FAR DIAMONDAPI FnFdiWriteCB ( INT_PTR hf, void FAR *pv, UINT cb );
  51. int FAR DIAMONDAPI FnFdiCloseCB ( INT_PTR hf );
  52. long FAR DIAMONDAPI FnFdiSeekCB ( INT_PTR hf, long dist, int seektype );
  53. /* Private Functions
  54. */
  55. static int FhHandleCopyFileMsgInNotify ( PFUD pfud, char * szFName );
  56. static BOOL FHandleCloseFileMsgInNotify ( PFUD pfud, INT_PTR hf );
  57. static BOOL FHandleNextCabMsgInNotify ( PFUD pfud, char * szCabFName,
  58. char * szDiskLabel, char * szSrcDir, FDIERROR fdie );
  59. static BOOL FModifyCabinetName(char * szSrcDir, int cCabNum);
  60. static BOOL FEnsureCabinetFileIsPresent(HWND hWnd, char * szSrcDir,
  61. char * szCabinet, int cCabNum);
  62. static int HfOpenSpillFile ( PFDISPILLFILE pfdisf, int oflag, int pmode );
  63. static VOID InitFud (PFUD pfud, char * szDstDir, char * szSrcs,
  64. char * szDsts, char * szSrcBuf, char * szDstBuf,
  65. BOOL * rgfSrcFilesCopied, int cSrcFiles, HWND hWnd );
  66. /* KLUDGE - so pfud->brc can be found in callbacks */
  67. static PFUD pfudG = pfudNull;
  68. #ifndef DEBUG_TEST /* Turn on for create/skip file messages. */
  69. #define DebugMsgSz(sz1, sz2)
  70. #else /* DEBUG */
  71. static VOID DebugMsgSz ( char * szPattern, char * szArgument );
  72. /*
  73. ************************************************************************/
  74. static VOID DebugMsgSz ( char * szPattern, char * szArgument )
  75. {
  76. char rgch[128];
  77. wsprintf(rgch, szPattern, szArgument);
  78. DebugMsg(rgch);
  79. }
  80. #endif /* DEBUG */
  81. /*
  82. ** Purpose:
  83. ** This function is passed as a callback to the FDI library.
  84. ** Arguments:
  85. ** fdint - type of notification
  86. ** pfdin - data for notification
  87. ** Returns:
  88. ** varies with fdint
  89. **
  90. *************************************************************************/
  91. FNFDINOTIFY ( FnFdiNotifyCB )
  92. {
  93. switch (fdint)
  94. {
  95. default:
  96. DebugMsg("Unexpected message passed to FnFdiNotifyCB().");
  97. ((PFUD)(pfdin->pv))->brc = brcGen;
  98. return (0);
  99. case fdintCABINET_INFO:
  100. /* do nothing */
  101. return (0);
  102. case fdintCOPY_FILE:
  103. return (FhHandleCopyFileMsgInNotify(pfdin->pv, pfdin->psz1));
  104. case fdintCLOSE_FILE_INFO:
  105. return (FHandleCloseFileMsgInNotify(pfdin->pv, pfdin->hf) ? TRUE
  106. : -1);
  107. case fdintPARTIAL_FILE:
  108. /* do nothing */
  109. return (0);
  110. case fdintNEXT_CABINET:
  111. return (FHandleNextCabMsgInNotify(pfdin->pv, pfdin->psz1,
  112. pfdin->psz2, pfdin->psz3, pfdin->fdie) ? 0 : -1);
  113. }
  114. }
  115. /*
  116. ** returns:
  117. ** 0 == skip this file
  118. ** -1 == abort FDICopy()
  119. ** else a legitimate DOS file handle
  120. *************************************************************************/
  121. static int FhHandleCopyFileMsgInNotify ( PFUD pfud, char * szFName )
  122. {
  123. SZ szSrcs = pfud->szSrcs;
  124. SZ szDsts = pfud->szDsts;
  125. int iFile;
  126. struct _stat stat;
  127. for (iFile = 0; *szSrcs; iFile++)
  128. {
  129. if (*szSrcs == '@' && !lstrcmpi(szSrcs+1, szFName))
  130. {
  131. int hfRet;
  132. lstrcpy(pfud->szDstBuf, pfud->szDstDir);
  133. lstrcat(pfud->szDstBuf, "\\");
  134. lstrcat(pfud->szDstBuf, szDsts);
  135. DebugMsgSz("Creating Dest File: %s", pfud->szDstBuf);
  136. /* If file exists, try to remove it.
  137. */
  138. if (_stat(pfud->szDstBuf, &stat) != -1)
  139. {
  140. /* NOTE: Ignore error return values here since
  141. * _open should catch any errors anyway.
  142. */
  143. if (!(stat.st_mode & _S_IWRITE))
  144. _chmod(pfud->szDstBuf, _S_IREAD | _S_IWRITE);
  145. _unlink(pfudG->szDstBuf);
  146. }
  147. hfRet = _open(pfud->szDstBuf,
  148. _O_BINARY | _O_CREAT | _O_RDWR | _O_TRUNC,
  149. _S_IREAD | _S_IWRITE);
  150. if (hfRet == -1)
  151. pfud->brc = brcMemDS;
  152. if (iFile < pfud->cSrcFiles)
  153. (pfud->rgfSrcFilesCopied)[iFile] = TRUE;
  154. // We will have copied one more file
  155. pfud->cFilesCopied++;
  156. return (hfRet);
  157. }
  158. szSrcs += lstrlen(szSrcs) + 1;
  159. szDsts += lstrlen(szDsts) + 1;
  160. }
  161. DebugMsgSz("Skipping a cabinet file: %s", szFName);
  162. return (0);
  163. }
  164. /*
  165. *************************************************************************/
  166. static BOOL FHandleCloseFileMsgInNotify ( PFUD pfud, INT_PTR hf )
  167. {
  168. if (FnFdiCloseCB(hf) != -1)
  169. {
  170. _chmod(pfud->szDstBuf, S_IREAD);
  171. return (TRUE);
  172. }
  173. return (FALSE);
  174. }
  175. /*
  176. *************************************************************************/
  177. static BOOL FHandleNextCabMsgInNotify ( PFUD pfud, char * szCabFName,
  178. char * szDiskLabel, char * szSrcDir, FDIERROR fdie )
  179. {
  180. Unused(szDiskLabel);
  181. /* Check if diamond is calling us again because the cabinet
  182. * we specified was bad.
  183. */
  184. if (fdie == FDIERROR_WRONG_CABINET)
  185. {
  186. DebugMsg("Cabinet files are out of sequence or corrupted.");
  187. return FALSE;
  188. }
  189. lstrcpy(pfud->szSrcBuf, szSrcDir);
  190. lstrcat(pfud->szSrcBuf, szCabFName);
  191. if (!FEnsureCabinetFileIsPresent(pfud->hWnd, szSrcDir, szCabFName,
  192. pfud->cCabNum+1))
  193. {
  194. pfud->brc = brcFile;
  195. return FALSE;
  196. }
  197. return TRUE;
  198. }
  199. /*
  200. *************************************************************************/
  201. static int CFilesInSrcsInitRgf ( char * szSrcs, BOOL * rgfSrcFilesCopied )
  202. {
  203. int iFile, cFiles;
  204. for (iFile = 0; iFile < 128; iFile++)
  205. rgfSrcFilesCopied[iFile] = TRUE;
  206. cFiles = 0;
  207. while (*szSrcs)
  208. {
  209. if (*szSrcs == '@')
  210. rgfSrcFilesCopied[cFiles] = FALSE;
  211. cFiles++;
  212. szSrcs += lstrlen(szSrcs) + 1;
  213. }
  214. if (cFiles > 128)
  215. {
  216. DebugMsg("More than 128 source files in .LST file "
  217. "- will not check that all exist.");
  218. cFiles = 128;
  219. }
  220. return (cFiles);
  221. }
  222. /*
  223. ** Purpose:
  224. ** Copies all cabinet files in the specified copy list, ignoring
  225. ** any non-cabinet files in the list.
  226. ** Arguments:
  227. ** szCabinet: cabinet filename (oem).
  228. ** szSrcDir: src path with trailing backslash (ANSI).
  229. ** szDstDir: dst path with trailing backslash (oem).
  230. ** szSrcs: NULL separated list of src filenames (oem).
  231. ** szDsts: NULL separated list of dst filenames (oem).
  232. ** szSrcBuf: buffer to hold src path for error msgs.
  233. ** szDstBuf: buffer to hold dst path for error msgs.
  234. ** Returns:
  235. ** brcOkay if completed without error, brcXX otherwise.
  236. **
  237. *************************************************************************/
  238. extern BRC BrcHandleCabinetFiles ( HWND hWnd, char * szCabinet,
  239. int cFirstCabinetNum, int cLastCabinetNum, char *szSrcDir,
  240. char * szDstDir, char * szSrcs, char * szDsts,
  241. char * szSrcBuf, char * szDstBuf )
  242. {
  243. FUD fud;
  244. BRC brcRet = brcOkay;
  245. BOOL rgfSrcFilesCopied[128];
  246. int cSrcFiles = CFilesInSrcsInitRgf(szSrcs, rgfSrcFilesCopied);
  247. int cpuType = cpuUNKNOWN;
  248. InitFud(&fud, szDstDir, szSrcs, szDsts, szSrcBuf, szDstBuf,
  249. rgfSrcFilesCopied, cSrcFiles, hWnd);
  250. pfudG = &fud;
  251. #if 0
  252. /* NOTE: Get CPU type ourselves, since FDI's CPU detection may
  253. * not work correctly for 16-bit Windows applications.
  254. */
  255. cpuType = (GetWinFlags() & WF_CPU286) ? cpu80286 : cpu80386;
  256. #endif
  257. if ((fud.hfdi = FDICreate(FnFdiAllocCB, FnFdiFreeCB, FnFdiOpenCB,
  258. FnFdiReadCB, FnFdiWriteCB, FnFdiCloseCB,
  259. FnFdiSeekCB, cpuType,
  260. &(fud.erf) )) == hfdiNull)
  261. {
  262. return (brcMem);
  263. }
  264. /*
  265. * Process cabinets as long as we have more files to copy.
  266. * i is the current cabinet number (starting at 1).
  267. */
  268. for (fud.cCabNum=cFirstCabinetNum;
  269. fud.cFilesCopied < fud.cSrcFiles && fud.cCabNum<=cLastCabinetNum;
  270. fud.cCabNum++)
  271. {
  272. /* Modify the cabinet name depending on the current cabinet number */
  273. if (!FModifyCabinetName(szCabinet, fud.cCabNum))
  274. {
  275. brcRet = brcFile;
  276. break;
  277. }
  278. lstrcpy(szSrcBuf, szSrcDir);
  279. lstrcat(szSrcBuf, szCabinet);
  280. if (!FEnsureCabinetFileIsPresent(fud.hWnd, szSrcDir, szCabinet,
  281. fud.cCabNum))
  282. {
  283. brcRet = brcFile;
  284. break;
  285. }
  286. if (!FDICopy(fud.hfdi, szCabinet, szSrcDir, 0, FnFdiNotifyCB, NULL,
  287. &fud))
  288. {
  289. brcRet = (fud.brc == brcOkay) ? brcGen : fud.brc;
  290. break;
  291. }
  292. }
  293. if (brcRet == brcOkay)
  294. {
  295. int iFile;
  296. /* Check if we got all the files we want */
  297. for (iFile = 0; iFile < cSrcFiles; iFile++)
  298. {
  299. if (!(rgfSrcFilesCopied[iFile]))
  300. {
  301. lstrcat(szSrcBuf, " : ");
  302. lstrcat(szSrcBuf, szSrcs + 1);
  303. brcRet = brcFile;
  304. }
  305. szSrcs += lstrlen(szSrcs) + 1;
  306. }
  307. }
  308. FDIDestroy(fud.hfdi);
  309. /* Ensure that the spill file is deleted.
  310. */
  311. Assert(pfudG != pfudNull);
  312. if (pfudG->hfSpillFile != -1)
  313. FnFdiCloseCB(pfudG->hfSpillFile);
  314. return (brcRet);
  315. }
  316. /*
  317. *************************************************************************/
  318. static VOID InitFud (PFUD pfud, char * szDstDir, char * szSrcs,
  319. char * szDsts, char * szSrcBuf, char * szDstBuf,
  320. BOOL * rgfSrcFilesCopied, int cSrcFiles, HWND hWnd )
  321. {
  322. pfud->erf.fError = fFalse;
  323. pfud->szDstDir = szDstDir;
  324. pfud->szSrcs = szSrcs;
  325. pfud->szDsts = szDsts;
  326. pfud->szSrcBuf = szSrcBuf;
  327. pfud->szDstBuf = szDstBuf;
  328. pfud->rgfSrcFilesCopied = rgfSrcFilesCopied;
  329. pfud->cSrcFiles = cSrcFiles;
  330. pfud->cFilesCopied = 0;
  331. pfud->hWnd = hWnd;
  332. pfud->brc = brcOkay;
  333. *(pfud->rgchSpillFileName) = chEos;
  334. pfud->hfSpillFile = -1;
  335. }
  336. static BOOL FModifyCabinetName(char * szSrcDir, int cCabNum)
  337. {
  338. char *pch = szSrcDir + lstrlen(szSrcDir);
  339. if (cCabNum < 1 || cCabNum > 9)
  340. return FALSE;
  341. /* Leave the name unchabged for the first cabinet */
  342. if (cCabNum == 1)
  343. return TRUE;
  344. /* Look for the dot, starting backward */
  345. for (; *pch != '.'; pch--)
  346. {
  347. /* Error if we can't find a dot before we find a slash */
  348. if (pch<=szSrcDir+1 || *pch == '\\')
  349. return FALSE;
  350. }
  351. /* Point to the character before the dot */
  352. pch--;
  353. /* Replace the last character before the dot by the cabinet number */
  354. *pch = (char)(cCabNum + '0');
  355. return TRUE;
  356. }
  357. static BOOL FEnsureCabinetFileIsPresent(HWND hWnd, char * szSrcDir,
  358. char * szCabinet, int cCabNum)
  359. {
  360. char rgchFileName[cchFullPathMax], rgchCabNum[32];
  361. OFSTRUCT ofs;
  362. HFILE hFile;
  363. BOOL fFirst = TRUE;
  364. Unused(hWnd);
  365. lstrcpy(rgchFileName, szSrcDir);
  366. lstrcat(rgchFileName, szCabinet);
  367. for (;;)
  368. {
  369. hFile = OpenFile(rgchFileName, &ofs, OF_EXIST);
  370. if (hFile != HFILE_ERROR)
  371. break;
  372. _itoa(cCabNum, rgchCabNum, 10);
  373. if (fFirst)
  374. {
  375. if (DispErrBrc(brcInsDisk, FALSE, MB_ICONEXCLAMATION|MB_OKCANCEL,
  376. rgchCabNum, NULL, NULL) != IDOK)
  377. {
  378. return FALSE;
  379. }
  380. fFirst = FALSE;
  381. }
  382. else
  383. {
  384. if (DispErrBrc(brcInsDisk2, FALSE, MB_ICONEXCLAMATION|MB_OKCANCEL,
  385. rgchFileName, rgchCabNum, NULL) != IDOK)
  386. {
  387. return FALSE;
  388. }
  389. }
  390. }
  391. return TRUE;
  392. }
  393. /*
  394. ** Purpose:
  395. ** Memory allocator for FDI.
  396. ** Arguments:
  397. ** cb - size of block to allocate
  398. ** Returns:
  399. ** Non-NULL pointer to block of size at least cb,
  400. ** or NULL for failure.
  401. **
  402. *************************************************************************/
  403. FNALLOC ( FnFdiAllocCB )
  404. {
  405. #ifdef _WIN32
  406. void HUGE * pvRet = malloc(cb);
  407. #else
  408. void HUGE * pvRet = _halloc(cb,1);
  409. #endif
  410. if (pvRet == NULL && pfudG->brc == brcOkay)
  411. pfudG->brc = brcMem;
  412. return (pvRet);
  413. }
  414. /*
  415. ** Purpose:
  416. ** Memory free function for FDI.
  417. ** Arguments:
  418. ** pv - memory allocated by FnFdiAllocCB to be freed
  419. ** Returns:
  420. ** None.
  421. **
  422. *************************************************************************/
  423. FNFREE ( FnFdiFreeCB )
  424. {
  425. #ifdef _WIN32
  426. free(pv);
  427. #else
  428. _hfree(pv);
  429. #endif
  430. }
  431. /*
  432. *************************************************************************/
  433. INT_PTR FAR DIAMONDAPI FnFdiOpenCB ( char FAR *szFile, int oflag, int pmode )
  434. {
  435. INT_PTR hfRet;
  436. if (*szFile == '*')
  437. return (HfOpenSpillFile((PFDISPILLFILE)szFile, oflag, pmode));
  438. hfRet = _open(szFile, oflag, pmode);
  439. if (hfRet == -1 && pfudG->brc == brcOkay)
  440. pfudG->brc = brcFile;
  441. return (hfRet);
  442. }
  443. /*
  444. *************************************************************************/
  445. static int HfOpenSpillFile ( PFDISPILLFILE pfdisf, int oflag, int pmode )
  446. {
  447. SZ szTmp;
  448. CHAR rgchSize[20];
  449. BOOL fTryAgain = fTrue;
  450. Assert(pfdisf != (PFDISPILLFILE)NULL);
  451. Assert(*(pfdisf->ach) == '*');
  452. Assert(pfudG != pfudNull);
  453. Assert(pfudG->hfSpillFile == -1); /* Only one at a time */
  454. Assert(*(pfudG->rgchSpillFileName) == chEos);
  455. if ((szTmp = _tempnam("", szSpillFilePrefix)) == szNull)
  456. {
  457. DebugMsg("Unable to get spill file name.");
  458. goto LNoSpillFile;
  459. }
  460. Assert(lstrlen(szTmp) < sizeof(pfudG->rgchSpillFileName));
  461. lstrcpy(pfudG->rgchSpillFileName, szTmp);
  462. free(szTmp);
  463. LOpenSpillFile:
  464. oflag = _O_CREAT | _O_BINARY | _O_RDWR; /* Force open mode */
  465. if ((pfudG->hfSpillFile = _open(pfudG->rgchSpillFileName, oflag, pmode))
  466. == -1)
  467. {
  468. DebugMsg("Unable to open spill file.");
  469. goto LNoSpillFile;
  470. }
  471. if (pfdisf->cbFile > 0)
  472. {
  473. /* Size file by writing one byte at size - 1.
  474. */
  475. if (FnFdiSeekCB(pfudG->hfSpillFile, pfdisf->cbFile - 1, SEEK_SET) == -1
  476. || FnFdiWriteCB(pfudG->hfSpillFile, "b", 1) != 1)
  477. {
  478. DebugMsg("Unable to set spill file size.");
  479. goto LNoSpillFile;
  480. }
  481. }
  482. return (pfudG->hfSpillFile);
  483. LNoSpillFile:
  484. if (pfudG->hfSpillFile != -1)
  485. FnFdiCloseCB(pfudG->hfSpillFile);
  486. if (fTryAgain)
  487. {
  488. /* Try again with bootstrap temp dir.
  489. *
  490. * (REVIEW: We could do another search here, checking for size.)
  491. */
  492. fTryAgain = fFalse;
  493. Assert(lstrlen(pfudG->szDstBuf) + lstrlen(szSpillFileTemplate) <
  494. sizeof(pfudG->rgchSpillFileName));
  495. lstrcpy(pfudG->rgchSpillFileName, pfudG->szDstDir);
  496. lstrcat(pfudG->rgchSpillFileName, szDirSep);
  497. lstrcat(pfudG->rgchSpillFileName, szSpillFileTemplate);
  498. if (_mktemp(pfudG->rgchSpillFileName) != NULL)
  499. goto LOpenSpillFile;
  500. }
  501. _ltoa((pfdisf->cbFile + 1023) / 1024, rgchSize, 10);
  502. DispErrBrc(brcNoSpill, fTrue, MB_OK | MB_ICONSTOP, rgchSize, szNull, szNull);
  503. *(pfudG->rgchSpillFileName) = chEos;
  504. pfudG->brc = brcNoSpill;
  505. return (-1);
  506. }
  507. /*
  508. *************************************************************************/
  509. UINT FAR DIAMONDAPI FnFdiReadCB ( INT_PTR hf, void FAR *pv, UINT cb )
  510. {
  511. UINT cbRet = _read((int)hf, pv, cb);
  512. if (cbRet != cb && pfudG->brc == brcOkay)
  513. pfudG->brc = brcMemDS;
  514. return (cbRet);
  515. }
  516. /*
  517. *************************************************************************/
  518. UINT FAR DIAMONDAPI FnFdiWriteCB ( INT_PTR hf, void FAR *pv, UINT cb )
  519. {
  520. UINT cbRet = _write((int)hf, pv, cb);
  521. FYield();
  522. if (cbRet != cb && pfudG->brc == brcOkay)
  523. pfudG->brc = brcDS;
  524. return (cbRet);
  525. }
  526. /*
  527. *************************************************************************/
  528. int FAR DIAMONDAPI FnFdiCloseCB ( INT_PTR hf )
  529. {
  530. int iRet = _close((int)hf);
  531. if (iRet == -1 && pfudG->brc == brcOkay)
  532. pfudG->brc = brcDS;
  533. /* If we're closing the spill file, delete it.
  534. */
  535. if (hf == pfudG->hfSpillFile)
  536. {
  537. _unlink(pfudG->rgchSpillFileName); /* Delete spill file */
  538. *(pfudG->rgchSpillFileName) = chEos; /* Empty path */
  539. pfudG->hfSpillFile = -1; /* Mark as closed */
  540. }
  541. return (iRet);
  542. }
  543. /*
  544. *************************************************************************/
  545. long FAR DIAMONDAPI FnFdiSeekCB ( INT_PTR hf, long dist, int seektype )
  546. {
  547. long lRet = _lseek((int)hf, dist, seektype);
  548. if (lRet == -1L && pfudG->brc == brcOkay)
  549. {
  550. DebugMsg("Seek Operation failed in Cabinet");
  551. pfudG->brc = brcGen;
  552. }
  553. return (lRet);
  554. }