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.

999 lines
22 KiB

  1. /*
  2. * EXTRACT.C borrowed from TWEX\wextract.c
  3. *
  4. * Has the CAB extraction capabilty for Code Downloader; uses FDI.LIB
  5. */
  6. #include <urlmon.h>
  7. #include <io.h>
  8. #include <stdio.h>
  9. #include <fcntl.h>
  10. #include "cdl.h"
  11. #ifdef unix
  12. #include "unixfile.h"
  13. #endif /* unix */
  14. //
  15. // single theaded access to the FDI lib
  16. static BOOL fCritCreated = FALSE;
  17. CRITICAL_SECTION g_mxsFDI;
  18. /*
  19. * W i n 3 2 O p e n ( )
  20. *
  21. * Routine: Win32Open()
  22. *
  23. * Purpose: Translate a C-Runtime _open() call into appropriate Win32
  24. * CreateFile()
  25. *
  26. * Returns: Handle to file on success
  27. * INVALID_HANDLE_VALUE on failure
  28. *
  29. *
  30. * BUGBUG: Doesn't fully implement C-Runtime _open() capability but it
  31. * BUGBUG: currently supports all callbacks that FDI will give us
  32. */
  33. HANDLE
  34. Win32Open(char *pszFile, int oflag, int pmode )
  35. {
  36. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  37. BOOL fExists = FALSE;
  38. DWORD fAccess;
  39. DWORD fCreate;
  40. ASSERT( pszFile );
  41. // BUGBUG: No Append Mode Support
  42. if (oflag & _O_APPEND)
  43. return( INVALID_HANDLE_VALUE );
  44. // Set Read-Write Access
  45. if ((oflag & _O_RDWR) || (oflag & _O_WRONLY))
  46. fAccess = GENERIC_WRITE;
  47. else
  48. fAccess = GENERIC_READ;
  49. // Set Create Flags
  50. if (oflag & _O_CREAT) {
  51. if (oflag & _O_EXCL)
  52. fCreate = CREATE_NEW;
  53. else if (oflag & _O_TRUNC)
  54. fCreate = CREATE_ALWAYS;
  55. else
  56. fCreate = OPEN_ALWAYS;
  57. } else {
  58. if (oflag & _O_TRUNC)
  59. fCreate = TRUNCATE_EXISTING;
  60. else
  61. fCreate = OPEN_EXISTING;
  62. }
  63. #ifdef unix
  64. UnixEnsureDir(pszFile);
  65. #endif /* unix */
  66. //BUGBUG: seterrormode to no crit errors and then catch sharing violations
  67. // and access denied
  68. // Call Win32
  69. FileHandle = CreateFile(
  70. pszFile, fAccess, FILE_SHARE_READ, NULL, fCreate,
  71. FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE
  72. );
  73. if (FileHandle == INVALID_HANDLE_VALUE &&
  74. SetFileAttributes(pszFile, FILE_ATTRIBUTE_NORMAL))
  75. FileHandle = CreateFile(
  76. pszFile, fAccess, FILE_SHARE_READ, NULL, fCreate,
  77. FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE
  78. );
  79. return( FileHandle );
  80. }
  81. /*
  82. * O p e n F u n c ( )
  83. *
  84. * Routine: OpenFunc()
  85. *
  86. * Purpose: Open File Callback from FDI
  87. *
  88. * Returns: File Handle (small integer index into file table)
  89. * -1 on failure
  90. *
  91. */
  92. int FAR DIAMONDAPI openfunc(char FAR *pszFile, int oflag, int pmode )
  93. {
  94. int rc;
  95. HANDLE hf;
  96. ASSERT( pszFile );
  97. //BUGBUG Spill File Support for Quantum?
  98. if ((*pszFile == '*') && (*(pszFile+1) != 'M')) {
  99. DEBUGTRAP("Spill File Support for Quantum Not Supported");
  100. }
  101. hf = Win32Open(pszFile, oflag, pmode );
  102. if (hf != INVALID_HANDLE_VALUE) {
  103. // SUNDOWN: typecast problem
  104. rc = PtrToLong(hf);
  105. } else {
  106. rc = -1;
  107. }
  108. return( rc );
  109. }
  110. /*
  111. * R E A D F U N C ( )
  112. *
  113. * Routine: readfunc()
  114. *
  115. * Purpose: FDI read() callback
  116. *
  117. */
  118. UINT FAR DIAMONDAPI readfunc(INT_PTR hf, void FAR *pv, UINT cb)
  119. {
  120. int rc;
  121. ASSERT( pv );
  122. if (! ReadFile((HANDLE)hf, pv, cb, (DWORD *) &cb, NULL))
  123. rc = -1;
  124. else
  125. rc = cb;
  126. return( rc );
  127. }
  128. /*
  129. * W r i t e F u n c ( )
  130. *
  131. * Routine: WriteFunc()
  132. *
  133. * Purpose: FDI Write() callback
  134. *
  135. */
  136. UINT FAR DIAMONDAPI
  137. writefunc(INT_PTR hf, void FAR *pv, UINT cb)
  138. {
  139. int rc;
  140. ASSERT( pv );
  141. if (! WriteFile((HANDLE)hf, pv, cb, (DWORD *) &cb, NULL))
  142. rc = -1;
  143. else
  144. rc = cb;
  145. // BUGBUG: implement OnProgress notification
  146. return( rc );
  147. }
  148. /*
  149. * C l o s e F u n c ( )
  150. *
  151. * Routine: CloseFunc()
  152. *
  153. * Purpose: FDI Close File Callback
  154. *
  155. */
  156. int FAR DIAMONDAPI closefunc( INT_PTR hf )
  157. {
  158. int rc;
  159. if (CloseHandle( (HANDLE)hf )) {
  160. rc = 0;
  161. } else {
  162. rc = -1;
  163. }
  164. return( rc );
  165. }
  166. /*
  167. * S e e k F u n c ( )
  168. *
  169. * Routine: seekfunc()
  170. *
  171. * Purpose: FDI Seek Callback
  172. */
  173. long FAR DIAMONDAPI seekfunc( INT_PTR hf, long dist, int seektype )
  174. {
  175. long rc;
  176. DWORD W32seektype;
  177. switch (seektype) {
  178. case SEEK_SET:
  179. W32seektype = FILE_BEGIN;
  180. break;
  181. case SEEK_CUR:
  182. W32seektype = FILE_CURRENT;
  183. break;
  184. case SEEK_END:
  185. W32seektype = FILE_END;
  186. break;
  187. }
  188. rc = SetFilePointer((HANDLE)hf, dist, NULL, W32seektype);
  189. if (rc == 0xffffffff)
  190. rc = -1;
  191. return( rc );
  192. }
  193. /*
  194. * A d j u s t F i l e T i m e ( )
  195. *
  196. * Routine: AdjustFileTime()
  197. *
  198. * Purpose: Change the time info for a file
  199. */
  200. BOOL
  201. AdjustFileTime(INT_PTR hf, USHORT date, USHORT time )
  202. {
  203. FILETIME ft;
  204. FILETIME ftUTC;
  205. if (! DosDateTimeToFileTime( date, time, &ft ))
  206. return( FALSE );
  207. if (! LocalFileTimeToFileTime(&ft, &ftUTC))
  208. return( FALSE );
  209. if (! SetFileTime((HANDLE)hf,&ftUTC,&ftUTC,&ftUTC))
  210. return( FALSE );
  211. return( TRUE );
  212. }
  213. /*
  214. * A t t r 3 2 F r o m A t t r F A T ( )
  215. *
  216. * Translate FAT attributes to Win32 Attributes
  217. */
  218. DWORD Attr32FromAttrFAT(WORD attrMSDOS)
  219. {
  220. //** Quick out for normal file special case
  221. if (attrMSDOS == _A_NORMAL) {
  222. return FILE_ATTRIBUTE_NORMAL;
  223. }
  224. //** Otherwise, mask off read-only, hidden, system, and archive bits
  225. // NOTE: These bits are in the same places in MS-DOS and Win32!
  226. //
  227. return attrMSDOS & ~(_A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH);
  228. }
  229. /*
  230. * A l l o c F u n c ( )
  231. *
  232. * FDI Memory Allocation Callback
  233. */
  234. FNALLOC(allocfunc)
  235. {
  236. void *pv;
  237. pv = (void *) CoTaskMemAlloc( cb );
  238. DEBUGMSG("%d = ALLOC( %d )", (DWORD_PTR) pv, cb );
  239. return( pv );
  240. }
  241. /*
  242. * F r e e F u n c ( )
  243. *
  244. * FDI Memory Deallocation Callback
  245. * XXX Return Value?
  246. */
  247. FNFREE(freefunc)
  248. {
  249. ASSERT(pv);
  250. DEBUGMSG("FREE( %d )", pv );
  251. CoTaskMemFree( pv );
  252. }
  253. /*
  254. * D O G E T N E X T C A B ( )
  255. *
  256. * Routine: doGetNextCab()
  257. *
  258. * Purpose: Get Next Cabinet in chain
  259. *
  260. * Returns: -1
  261. *
  262. * BUGBUG: CLEANUP: STUB THIS OUT
  263. * BUGBUG: STUBBED OUT IN WEXTRACT - CHAINED CABINETS NOT SUPPORTED
  264. */
  265. FNFDINOTIFY(doGetNextCab)
  266. {
  267. return( -1 );
  268. }
  269. /*** updateCabinetInfo - update history of cabinets seen
  270. *
  271. * Entry:
  272. * psess - Session
  273. * pfdin - FDI info structurue
  274. *
  275. * Exit:
  276. * Returns 0;
  277. */
  278. int updateCabinetInfo(PSESSION psess, PFDINOTIFICATION pfdin)
  279. {
  280. ASSERT(psess);
  281. // Don't need any of this!
  282. //** Save cabinet info
  283. //lstrcpy(psess->acab.achCabPath ,pfdin->psz3);
  284. //lstrcpy(psess->acab.achCabFilename ,pfdin->psz1);
  285. //lstrcpy(psess->acab.achDiskName ,pfdin->psz2);
  286. //psess->acab.setID = pfdin->setID;
  287. //psess->acab.iCabinet = pfdin->iCabinet;
  288. return 0;
  289. }
  290. /*
  291. * A P P E N D P A T H S E P A R A T O R ( )
  292. *
  293. * Routine: appendPathSeparator()
  294. *
  295. * Purpose: Append a path separator only if necessary
  296. *
  297. * Returns: TRUE - Path Separator Added
  298. * FALSE No Path Separator added
  299. */
  300. BOOL
  301. appendPathSeparator(char *pszPathEnd)
  302. {
  303. //** Add path separator if necessary
  304. if ((*pszPathEnd != '\0') && // Path is not empty
  305. (*pszPathEnd != chPATH_SEP1) && // Not a path separator
  306. (*pszPathEnd != chPATH_SEP2) && // Not a path separator
  307. (*pszPathEnd != chDRIVE_SEP) ) { // Not a drive separator
  308. #ifdef unix
  309. *(++pszPathEnd) = chPATH_SEP2; // Add Unix path separator
  310. #else
  311. *(++pszPathEnd) = chPATH_SEP1; // Add path separator
  312. #endif /* !unix */
  313. *(++pszPathEnd) = '\0'; // Terminate path
  314. return TRUE; // Account for path separator
  315. }
  316. //** No separator added
  317. return FALSE;
  318. }
  319. /*
  320. * C A T D I R A N D F I L E ( )
  321. *
  322. * Routine: catDirAndFile()
  323. *
  324. * Purpose: Concatenate a directory with a filename!
  325. *
  326. */
  327. BOOL
  328. catDirAndFile( char *pszResult,
  329. int cbResult,
  330. char *pszDir,
  331. char *pszFile
  332. )
  333. {
  334. int cch = 0;
  335. //** Handle directory
  336. if (!cbResult)
  337. return FALSE;
  338. pszResult[0] = '\0'; // No filespec, yet
  339. if (pszDir)
  340. cch = lstrlen(pszDir); // Get length of dir
  341. if (cch != 0) { // Have to concatenate path
  342. cbResult -= cch; // Account for dir
  343. if (cbResult <= 1)
  344. {
  345. //this check also accounts for the next one byte that could be added.
  346. return FALSE;
  347. }
  348. lstrcpy(pszResult,pszDir); // Copy destination dir to buffer
  349. //** Add path separator if necessary, adjust remaining size
  350. cbResult -= appendPathSeparator(&(pszResult[cch-1]));
  351. if (cbResult <= 0)
  352. {
  353. return FALSE;
  354. }
  355. }
  356. //** Append file name, using default if primary one not supplied
  357. if (*pszFile == '\0') {
  358. return( FALSE );
  359. }
  360. cbResult -= lstrlen(pszFile); // Update remaining size
  361. if (cbResult <= 0) {
  362. return FALSE;
  363. }
  364. lstrcat(pszResult,pszFile); // Append file name
  365. //** Success
  366. return TRUE;
  367. }
  368. /*
  369. * IsExtracted
  370. *
  371. * Look for pszName in psess->pFileList and see if extracted
  372. *
  373. * Returns:
  374. * Success: TRUE, failure: FALSE
  375. */
  376. static
  377. BOOL
  378. IsExtracted( PSESSION ps, LPCSTR pszName)
  379. {
  380. PFNAME CurName = ps->pFileList;
  381. ASSERT(pszName);
  382. ASSERT(CurName); // atleast one file needed
  383. // search for filename in list of files in this CAB
  384. do {
  385. if (lstrcmpi(pszName, CurName->pszFilename) == 0) {
  386. if (CurName->status == SFNAME_EXTRACTED)
  387. return TRUE;
  388. else
  389. return FALSE;
  390. }
  391. } while (CurName = CurName->pNextName);
  392. ASSERT(TRUE); // if here not found in list!
  393. return FALSE;
  394. }
  395. /*
  396. * NeedFile
  397. *
  398. * search for pszName in psess->pFilesToExtract (list of PFNAMEs)
  399. * Returns:
  400. * TRUE - need file, extract it
  401. * FALSE - don't need file, skip it
  402. *
  403. */
  404. static
  405. BOOL
  406. NeedFile( PSESSION ps, LPCSTR pszName)
  407. {
  408. PFNAME CurName;
  409. ASSERT(pszName);
  410. if (IsExtracted(ps, pszName) )
  411. return FALSE;
  412. if ( ps->flags & SESSION_FLAG_EXTRACT_ALL )
  413. return TRUE;
  414. // search for filename in list of files needed
  415. for (CurName = ps->pFilesToExtract; CurName; CurName = CurName->pNextName){
  416. ASSERT(CurName->pszFilename);
  417. if (lstrcmpi(CurName->pszFilename, pszName) == 0)
  418. return TRUE;
  419. }
  420. return FALSE;
  421. }
  422. /*
  423. * MarkExtracted
  424. *
  425. * Look for pszName in psess->pFileList and mark status = status_passed_in
  426. * really can be use to mark status as anything else as well (not just
  427. * extracted.)
  428. *
  429. * Returns:
  430. * Success: TRUE, failure: FALSE
  431. */
  432. static
  433. BOOL
  434. MarkExtracted( PSESSION ps, LPCSTR pszName , DWORD status)
  435. {
  436. PFNAME CurName = ps->pFileList;
  437. ASSERT(pszName);
  438. ASSERT(CurName); // atleast one file needed
  439. // search for filename in list of files in this CAB
  440. do {
  441. if (lstrcmpi(pszName, CurName->pszFilename) == 0) {
  442. CurName->status = status;
  443. return TRUE;
  444. }
  445. } while (CurName = CurName->pNextName);
  446. ASSERT(TRUE); // if here not found in list!
  447. return FALSE;
  448. }
  449. /*
  450. * A d d F i l e ( )
  451. *
  452. * Add a file to the list of files we have in the CAB file
  453. *
  454. * Singly linked list - items added at front
  455. */
  456. static
  457. BOOL
  458. AddFile( PSESSION ps, LPCSTR pszName , long cb)
  459. {
  460. PFNAME NewName;
  461. ASSERT(pszName);
  462. if (!(ps->flags & SESSION_FLAG_ENUMERATE))
  463. return TRUE;
  464. // Allocate Node
  465. NewName = (PFNAME) CoTaskMemAlloc(sizeof(FNAME) );
  466. if (NewName == NULL) {
  467. DEBUGMSG("AddFile(): Memory Allocation of structure failed");
  468. return( FALSE );
  469. }
  470. // Allocate String Space
  471. NewName->pszFilename = (LPSTR) CoTaskMemAlloc(lstrlen(pszName) + 1);
  472. if (NewName->pszFilename == NULL) {
  473. DEBUGMSG("AddFile(): Memory Allocation of name failed");
  474. CoTaskMemFree(NewName);
  475. return( FALSE );
  476. }
  477. NewName->status = SFNAME_INIT;
  478. // Copy Filename
  479. lstrcpy( (char *)NewName->pszFilename, pszName );
  480. // Link into list
  481. NewName->pNextName = ps->pFileList;
  482. ps->pFileList = NewName;
  483. ps->cFiles++;
  484. ps->cbCabSize += cb;
  485. return( TRUE );
  486. }
  487. /*
  488. * f d i N o t i f y E x t r a c t()
  489. *
  490. * Routine: fdiNotifyExtract()
  491. *
  492. * Purpose: Principle FDI Callback in file extraction
  493. *
  494. *
  495. */
  496. FNFDINOTIFY(fdiNotifyExtract)
  497. {
  498. int fh;
  499. PSESSION psess;
  500. psess = (PSESSION) pfdin->pv;
  501. switch (fdint) {
  502. case fdintCABINET_INFO:
  503. return updateCabinetInfo(psess,pfdin);
  504. case fdintCOPY_FILE:
  505. // BUGBUG: implement OnProgress?
  506. #ifdef unix
  507. UnixifyFileName(pfdin->psz1);
  508. #endif /* unix */
  509. if (!catDirAndFile(psess->achFile, // Buffer for output filespec
  510. sizeof(psess->achFile), // Size of output buffer
  511. psess->achLocation, // Output directory
  512. pfdin->psz1)) {
  513. return -1; // Abort with error;
  514. }
  515. // always add the file (enumeration)
  516. if (! AddFile(psess, pfdin->psz1, pfdin->cb))
  517. return( -1 );
  518. // check if this is the file we are looking for if any
  519. if (!NeedFile(psess, pfdin->psz1))
  520. return( 0 );
  521. if (StrStrA(pfdin->psz1, "\\")) {
  522. // cab contains dir struct for this file
  523. // create struct on dest dir as well.
  524. char *pBaseFileName = NULL;
  525. char szDir[MAX_PATH];
  526. LPSTR pchStart;
  527. LPSTR pchSlash = NULL;
  528. lstrcpy(szDir, psess->achFile);
  529. pchStart = szDir + lstrlen(psess->achLocation) + 1;
  530. while (*pchStart && (pchSlash = StrStrA(pchStart, "\\"))) {
  531. *pchSlash = '\0';
  532. // don't care if this fails. may even already exist!
  533. CreateDirectory(szDir, NULL);
  534. *pchSlash = '\\';
  535. pchStart = pchSlash +1;
  536. }
  537. }
  538. //** Do overwrite processing
  539. fh = openfunc( psess->achFile, _O_BINARY | _O_TRUNC | _O_RDWR |
  540. _O_CREAT, 0 );
  541. return(fh); // -1 if error on open
  542. case fdintCLOSE_FILE_INFO:
  543. if (!catDirAndFile(psess->achFile, // Buffer for output filespec
  544. sizeof(psess->achFile), // Size of output buffer
  545. psess->achLocation, // Output directory
  546. pfdin->psz1)) {
  547. return -1; // Abort with error;
  548. }
  549. if (! AdjustFileTime( pfdin->hf, pfdin->date, pfdin->time )) {
  550. return( -1 );
  551. }
  552. closefunc( (int) pfdin->hf );
  553. if (! SetFileAttributes(psess->achFile, Attr32FromAttrFAT(pfdin->attribs)))
  554. return( -1 );
  555. MarkExtracted(psess, pfdin->psz1, SFNAME_EXTRACTED);
  556. return(TRUE);
  557. case fdintPARTIAL_FILE:
  558. return( 0 );
  559. case fdintNEXT_CABINET:
  560. return doGetNextCab(fdint,pfdin);
  561. default:
  562. DEBUGTRAP("fdiNotifyExtract(): Unknown Callback Type");
  563. break;
  564. }
  565. return( 0 );
  566. }
  567. #ifdef DEBUG
  568. /*
  569. * V E R I F Y C A B I N E T ( )
  570. *
  571. * Routine: VerifyCabinet()
  572. *
  573. * Purpose: Check that cabinet is properly formed
  574. *
  575. * Returns: TRUE - Cabinet OK
  576. * FALSE - Cabinet invalid
  577. */
  578. BOOL
  579. VerifyCabinet( PSESSION psess, LPCSTR lpCabName )
  580. {
  581. HFDI hfdi;
  582. ERF erf;
  583. FDICABINETINFO cabinfo;
  584. INT fh;
  585. hfdi = FDICreate(allocfunc,freefunc,openfunc,readfunc,writefunc,closefunc,seekfunc,cpu80386,&erf);
  586. if (hfdi == NULL) {
  587. DEBUGMSG("VerifyCabinet(): FDICreate() Failed");
  588. //BUGBUG Error Handling?
  589. return( FALSE );
  590. }
  591. fh = openfunc((char FAR *)lpCabName, _O_BINARY | _O_RDONLY, 0 );
  592. if (fh == -1) {
  593. DEBUGMSG("VerifyCabinet(): Open of Memory File Failed");
  594. return( FALSE );
  595. }
  596. if (FDIIsCabinet(hfdi, fh, &cabinfo ) == FALSE) {
  597. DEBUGMSG("VerifyCabinet(): FDIIsCabinet() Returned FALSE");
  598. return( FALSE );
  599. }
  600. if (cabinfo.cbCabinet != (long) psess->cbCabSize) {
  601. DEBUGMSG("VerifyCabinet(): cabinfo.cbCabinet != cbCabSize");
  602. return( FALSE );
  603. }
  604. if (cabinfo.hasprev || cabinfo.hasnext) {
  605. DEBUGMSG("VerifyCabinet(): Cabinet is chained");
  606. return( FALSE );
  607. }
  608. if (closefunc( fh ) == -1) {
  609. DEBUGMSG("VerifyCabinet(): Closefunc() Failed");
  610. return( FALSE );
  611. }
  612. if (FDIDestroy(hfdi) == FALSE) {
  613. DEBUGMSG("VerifyCabinet(): FDIDestroy() Failed");
  614. return( FALSE );
  615. }
  616. return( TRUE );
  617. }
  618. #endif /* DEBUG */
  619. /*
  620. * E X T R A C T ( )
  621. *
  622. * Routine: Extract()
  623. *
  624. * Parameters:
  625. *
  626. * PSESSION ps = session information tied to this extract session
  627. *
  628. * IN params
  629. * ps->pFilesToExtract = linked list of PFNAMEs that point to
  630. * upper case filenames that need extraction
  631. *
  632. * ps->flags SESSION_FLAG_ENUMERATE = whether need to enumerate
  633. * files in CAB (ie. create a pFileList
  634. * ps->flags SESSION_FLAG_EXTRACTALL = all
  635. *
  636. * OUT params
  637. * ps->pFileList = global alloced list of files in CAB
  638. * caller needs to call DeleteExtractedFiles
  639. * to free memory and temp files
  640. *
  641. *
  642. * LPCSTR lpCabName = name of cab file
  643. *
  644. *
  645. * Returns:
  646. * S_OK: sucesss
  647. *
  648. *
  649. */
  650. HRESULT
  651. Extract(PSESSION ps, LPCSTR lpCabName )
  652. {
  653. HFDI hfdi;
  654. BOOL fExtractResult = FALSE;
  655. HRESULT hr = S_OK;
  656. if (ps->flags & SESSION_FLAG_EXTRACTED_ALL) {
  657. // already extracted all files in this CAB
  658. // nothing to do!
  659. return S_OK;
  660. }
  661. memset(&(ps->erf), 0, sizeof(ERF));
  662. if (ps->flags & SESSION_FLAG_ENUMERATE) {
  663. ps->cbCabSize = 0;
  664. }
  665. // don't enumerate when pFileList already pre-populated
  666. ASSERT( (!(ps->flags & SESSION_FLAG_ENUMERATE)) || (!ps->pFileList));
  667. {
  668. HRESULT hrOut = NOERROR;
  669. if (fCritCreated == FALSE)
  670. {
  671. fCritCreated = TRUE;
  672. InitializeCriticalSection(&g_mxsFDI);
  673. }
  674. EnterCriticalSection(&g_mxsFDI);
  675. // Extract the files
  676. hfdi = FDICreate(allocfunc,freefunc,openfunc,readfunc,writefunc,closefunc,seekfunc,cpu80386, &(ps->erf));
  677. if (hfdi == NULL) {
  678. // Error value will be retrieved from ps->erf
  679. hrOut = STG_E_UNKNOWN;
  680. goto done;
  681. }
  682. fExtractResult = FDICopy(hfdi, (char FAR *)lpCabName, "", 0, fdiNotifyExtract, NULL, (void *) ps );
  683. if (FDIDestroy(hfdi) == FALSE) {
  684. // Error value will be retrieved from ps->erf
  685. hrOut = STG_E_UNKNOWN;
  686. }
  687. done:
  688. LeaveCriticalSection(&g_mxsFDI);
  689. // leave now if this failed!
  690. if (hrOut != NOERROR)
  691. {
  692. return hrOut;
  693. }
  694. }
  695. if (fExtractResult && (!ps->erf.fError))
  696. return S_OK;
  697. hr = HRESULT_FROM_WIN32(GetLastError());
  698. if (SUCCEEDED(hr)) {
  699. // not a win32 failure but a cabinet failure
  700. // convert CABINET failure to disk full or STG_E_UNKNOWN.
  701. // On win95 writefile failing with disk full is not
  702. // setting the last error correctly
  703. if (ps->erf.fError && (ps->erf.erfOper == FDIERROR_TARGET_FILE))
  704. hr = HRESULT_FROM_WIN32(ERROR_DISK_FULL);
  705. else
  706. hr = STG_E_UNKNOWN;
  707. }
  708. return hr;
  709. }
  710. /*
  711. * D E L E T E E X T R A C T E D F I L E S ( )
  712. *
  713. * Routine: DeleteExtractedFiles()
  714. *
  715. * Purpose: Delete the files that were extracted
  716. * into the temporary directory
  717. * FREE all the memory in pFileList
  718. * make pFileList = NULL.
  719. *
  720. * Paramaters:
  721. * psess - Pointer to Session Structure containing
  722. * all state about this extraction session
  723. *
  724. * Returns: None
  725. */
  726. VOID
  727. DeleteExtractedFiles(PSESSION psess)
  728. {
  729. PFNAME rover = psess->pFileList;
  730. PFNAME roverprev;
  731. char szBuf[MAX_PATH];
  732. ASSERT(psess);
  733. DEBUGMSG("Deleting Extracted Files");
  734. while (rover != NULL) {
  735. // skip if this is not a tmp file
  736. if ( rover->status == SFNAME_EXTRACTED) {
  737. // Get full filename
  738. if (catDirAndFile(szBuf, MAX_PATH, psess->achLocation,
  739. rover->pszFilename)) {
  740. if (SetFileAttributes(szBuf, FILE_ATTRIBUTE_NORMAL))
  741. DeleteFile(szBuf);
  742. }
  743. }
  744. CoTaskMemFree(rover->pszFilename);
  745. roverprev = rover; // save for free'ing current rover below
  746. rover = rover->pNextName;
  747. CoTaskMemFree(roverprev);
  748. }
  749. psess->pFileList = NULL; // prevent use after deletion!
  750. }