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.

821 lines
18 KiB

  1. /*++
  2. Copyright (c) 1991-1999, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. diamond.c
  5. Abstract:
  6. Implement File Decompression Interface -FDI- for Cabinet files.
  7. Revision History:
  8. 04-20-1999 SamerA Created.
  9. --*/
  10. #include "muisetup.h"
  11. #include <io.h>
  12. #include <fcntl.h>
  13. #include <dos.h>
  14. #include <sys/stat.h>
  15. //
  16. // Module Global Variables
  17. //
  18. //
  19. // Cabinet DLL handle
  20. HINSTANCE hCabinetDll;
  21. HFDI ghfdi; // diamond FDI context
  22. //
  23. // DLL Function pointers
  24. //
  25. typedef HFDI (DIAMONDAPI *PFNFDICREATE)(
  26. PFNALLOC pfnalloc,
  27. PFNFREE pfnfree,
  28. PFNOPEN pfnopen,
  29. PFNREAD pfnread,
  30. PFNWRITE pfnwrite,
  31. PFNCLOSE pfnclose,
  32. PFNSEEK pfnseek,
  33. int cpuType,
  34. PERF perf);
  35. typedef BOOL (DIAMONDAPI *PFNFDIISCABINET)(
  36. HFDI hfdi,
  37. INT_PTR hf,
  38. PFDICABINETINFO pfdici);
  39. typedef BOOL (DIAMONDAPI *PFNFDICOPY)(
  40. HFDI hfdi,
  41. char *pszCabinet,
  42. char *pszCabPath,
  43. int flags,
  44. PFNFDINOTIFY pfnfdin,
  45. PFNFDIDECRYPT pfnfdid,
  46. void *pvUser);
  47. typedef BOOL (DIAMONDAPI *PFNFDIDESTROY)(
  48. HFDI hfdi);
  49. PFNFDICREATE pfnFDICreate;
  50. PFNFDICOPY pfnFDICopy;
  51. PFNFDIISCABINET pfnFDIIsCabinet;
  52. PFNFDIDESTROY pfnFDIDestroy;
  53. //-------------------------------------------------------------------------//
  54. // FDI EXTERNAL ROUTINES //
  55. //-------------------------------------------------------------------------//
  56. ////////////////////////////////////////////////////////////////////////////
  57. //
  58. // FDICreate
  59. //
  60. // Tries to create an FDI context. Will load cabinet.dll and hook necessary
  61. // function pointers.
  62. //
  63. // 04-20-99 SamerA Created.
  64. ////////////////////////////////////////////////////////////////////////////
  65. HFDI DIAMONDAPI FDICreate(
  66. PFNALLOC pfnalloc,
  67. PFNFREE pfnfree,
  68. PFNOPEN pfnopen,
  69. PFNREAD pfnread,
  70. PFNWRITE pfnwrite,
  71. PFNCLOSE pfnclose,
  72. PFNSEEK pfnseek,
  73. int cpuType,
  74. PERF perf)
  75. {
  76. HFDI hfdi;
  77. //
  78. // Load cabinet DLL
  79. //
  80. hCabinetDll = LoadLibrary(TEXT("CABINET.DLL"));
  81. if (hCabinetDll == NULL)
  82. {
  83. return NULL;
  84. }
  85. //
  86. // Hook function pointers
  87. //
  88. pfnFDICreate = (PFNFDICREATE) GetProcAddress(hCabinetDll, "FDICreate");
  89. pfnFDICopy = (PFNFDICOPY) GetProcAddress(hCabinetDll, "FDICopy");
  90. pfnFDIIsCabinet = (PFNFDIISCABINET) GetProcAddress(hCabinetDll, "FDIIsCabinet");
  91. pfnFDIDestroy = (PFNFDIDESTROY) GetProcAddress(hCabinetDll, "FDIDestroy");
  92. if ((pfnFDICreate == NULL) ||
  93. (pfnFDICopy == NULL) ||
  94. (pfnFDIIsCabinet == NULL) ||
  95. (pfnFDIDestroy == NULL))
  96. {
  97. FreeLibrary( hCabinetDll );
  98. return NULL;
  99. }
  100. //
  101. // Try to create an FDI context
  102. //
  103. hfdi = pfnFDICreate( pfnalloc,
  104. pfnfree,
  105. pfnopen,
  106. pfnread,
  107. pfnwrite,
  108. pfnclose,
  109. pfnseek,
  110. cpuType,
  111. perf);
  112. if (hfdi == NULL)
  113. {
  114. FreeLibrary(hCabinetDll);
  115. }
  116. return hfdi;
  117. }
  118. ////////////////////////////////////////////////////////////////////////////
  119. //
  120. // FDIIsCabinet
  121. //
  122. // Determines if file is a cabinet, returns info if it is
  123. //
  124. // 04-20-99 SamerA Created.
  125. ////////////////////////////////////////////////////////////////////////////
  126. BOOL DIAMONDAPI FDIIsCabinet(
  127. HFDI hfdi,
  128. INT_PTR hf,
  129. PFDICABINETINFO pfdici)
  130. {
  131. if (pfnFDIIsCabinet == NULL)
  132. {
  133. return FALSE;
  134. }
  135. return (pfnFDIIsCabinet(hfdi,hf,pfdici));
  136. }
  137. ////////////////////////////////////////////////////////////////////////////
  138. //
  139. // FDICopy
  140. //
  141. // Extracts files from a cabinet
  142. //
  143. // 04-20-99 SamerA Created.
  144. ////////////////////////////////////////////////////////////////////////////
  145. BOOL DIAMONDAPI FDICopy(
  146. HFDI hfdi,
  147. char *pszCabinet,
  148. char *pszCabPath,
  149. int flags,
  150. PFNFDINOTIFY pfnfdin,
  151. PFNFDIDECRYPT pfnfdid,
  152. void *pvUser)
  153. {
  154. if (pfnFDICopy == NULL)
  155. {
  156. return FALSE;
  157. }
  158. return (pfnFDICopy(hfdi,pszCabinet,pszCabPath,flags,pfnfdin,pfnfdid,pvUser));
  159. }
  160. ////////////////////////////////////////////////////////////////////////////
  161. //
  162. // FDIDestroy
  163. //
  164. // Destroy an FDI context. Should be called when you're done with the HFDI.
  165. //
  166. // 04-20-99 SamerA Created.
  167. ////////////////////////////////////////////////////////////////////////////
  168. BOOL DIAMONDAPI FDIDestroy(
  169. HFDI hfdi)
  170. {
  171. BOOL bRet;
  172. if (pfnFDIDestroy == NULL)
  173. {
  174. return FALSE;
  175. }
  176. bRet = pfnFDIDestroy( hfdi );
  177. if (bRet == TRUE)
  178. {
  179. FreeLibrary(hCabinetDll);
  180. }
  181. return bRet;
  182. }
  183. //-------------------------------------------------------------------------//
  184. // FDI SUPPORT ROUTINES //
  185. //-------------------------------------------------------------------------//
  186. PVOID
  187. DIAMONDAPI
  188. DiamondMemAlloc(
  189. IN ULONG NumberOfBytes
  190. )
  191. {
  192. return ((PVOID)LocalAlloc(LMEM_FIXED, NumberOfBytes));
  193. }
  194. VOID
  195. DIAMONDAPI
  196. DiamondMemFree(
  197. IN PVOID Block
  198. )
  199. {
  200. LocalFree( (HLOCAL)Block );
  201. }
  202. INT_PTR
  203. DIAMONDAPI
  204. DiamondFileOpen(
  205. IN PSTR FileName,
  206. IN int oflag,
  207. IN int pmode
  208. )
  209. {
  210. HFILE h;
  211. int OpenMode;
  212. if (oflag & _O_WRONLY)
  213. {
  214. OpenMode = OF_WRITE;
  215. } else
  216. {
  217. if (oflag & _O_RDWR)
  218. {
  219. OpenMode = OF_READWRITE;
  220. } else
  221. {
  222. OpenMode = OF_READ;
  223. }
  224. }
  225. h = _lopen(FileName, OpenMode | OF_SHARE_DENY_WRITE);
  226. if (h == HFILE_ERROR)
  227. {
  228. return -1;
  229. }
  230. return ((INT_PTR) h);
  231. }
  232. UINT
  233. DIAMONDAPI
  234. DiamondFileRead(
  235. IN INT_PTR Handle,
  236. OUT PVOID pv,
  237. IN UINT ByteCount
  238. )
  239. {
  240. UINT rc;
  241. rc = _lread((HFILE)Handle, pv, ByteCount);
  242. if (rc == HFILE_ERROR)
  243. {
  244. rc = (UINT)(-1);
  245. }
  246. return rc;
  247. }
  248. UINT
  249. DIAMONDAPI
  250. DiamondFileWrite(
  251. IN INT_PTR Handle,
  252. IN PVOID pv,
  253. IN UINT ByteCount
  254. )
  255. {
  256. UINT rc;
  257. rc = _lwrite((HFILE)Handle, (LPCSTR)pv, ByteCount);
  258. return rc;
  259. }
  260. int
  261. DIAMONDAPI
  262. DiamondFileClose(
  263. IN INT_PTR Handle
  264. )
  265. {
  266. _lclose( (HFILE)Handle );
  267. return 0;
  268. }
  269. LONG
  270. DIAMONDAPI
  271. DiamondFileSeek(
  272. IN INT_PTR Handle,
  273. IN long Distance,
  274. IN int SeekType
  275. )
  276. {
  277. LONG rc;
  278. rc = _llseek((HFILE)Handle, Distance, SeekType);
  279. if (rc == HFILE_ERROR)
  280. {
  281. rc = -1L;
  282. }
  283. return rc;
  284. }
  285. INT_PTR
  286. DIAMONDAPI
  287. DiamondNotifyFunction(
  288. IN FDINOTIFICATIONTYPE Operation,
  289. IN PFDINOTIFICATION Parameters
  290. )
  291. {
  292. switch (Operation)
  293. {
  294. case fdintCABINET_INFO: // general information about the cabinet
  295. return 0;
  296. break;
  297. case fdintPARTIAL_FILE: // first file in cabinet is continuation
  298. return 0;
  299. break;
  300. case fdintCOPY_FILE: // file to be copied
  301. {
  302. HFILE handle;
  303. char destination[256];
  304. PDIAMOND_PACKET pDiamond = (PDIAMOND_PACKET) Parameters->pv;
  305. //
  306. // Check to see if we just want the original file name
  307. //
  308. if (pDiamond->flags & DIAMOND_GET_DEST_FILE_NAME)
  309. {
  310. strcpy( pDiamond->szDestFilePath,
  311. Parameters->psz1 );
  312. return 0;
  313. }
  314. sprintf( destination,
  315. "%s%s",
  316. pDiamond->szDestFilePath,
  317. Parameters->psz1
  318. );
  319. handle = _lcreat(destination, 0);
  320. if (handle == HFILE_ERROR)
  321. {
  322. return -1;
  323. }
  324. return handle;
  325. }
  326. break;
  327. case fdintCLOSE_FILE_INFO: // close the file, set relevant info
  328. {
  329. HANDLE handle;
  330. DWORD attrs;
  331. char destination[256];
  332. PDIAMOND_PACKET pDiamond = (PDIAMOND_PACKET) Parameters->pv;
  333. if (pDiamond->flags & DIAMOND_GET_DEST_FILE_NAME)
  334. {
  335. return 0;
  336. }
  337. sprintf( destination,
  338. "%s%s",
  339. pDiamond->szDestFilePath,
  340. Parameters->psz1
  341. );
  342. _lclose( (HFILE)Parameters->hf );
  343. //
  344. // Set date/time
  345. //
  346. // Need Win32 type handle for to set date/time
  347. //
  348. handle = CreateFileA( destination,
  349. GENERIC_READ | GENERIC_WRITE,
  350. FILE_SHARE_READ,
  351. NULL,
  352. OPEN_EXISTING,
  353. FILE_ATTRIBUTE_NORMAL,
  354. NULL
  355. );
  356. if (handle != INVALID_HANDLE_VALUE)
  357. {
  358. FILETIME datetime;
  359. if (TRUE == DosDateTimeToFileTime( Parameters->date,
  360. Parameters->time,
  361. &datetime))
  362. {
  363. FILETIME local_filetime;
  364. if (TRUE == LocalFileTimeToFileTime( &datetime,
  365. &local_filetime))
  366. {
  367. SetFileTime( handle,
  368. &local_filetime,
  369. NULL,
  370. &local_filetime
  371. );
  372. }
  373. }
  374. CloseHandle(handle);
  375. }
  376. //
  377. // Mask out attribute bits other than readonly,
  378. // hidden, system, and archive, since the other
  379. // attribute bits are reserved for use by
  380. // the cabinet format.
  381. //
  382. attrs = Parameters->attribs;
  383. attrs &= (_A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH);
  384. SetFileAttributesA( destination,
  385. attrs
  386. );
  387. return TRUE;
  388. }
  389. break;
  390. case fdintNEXT_CABINET: // file continued to next cabinet
  391. return 0;
  392. break;
  393. }
  394. return 0;
  395. }
  396. //-------------------------------------------------------------------------//
  397. // MUISETUP-SUPPORT ROUTINES //
  398. //-------------------------------------------------------------------------//
  399. ////////////////////////////////////////////////////////////////////////////
  400. //
  401. // Muisetup_InitDiamond
  402. //
  403. // Initialize diamond DLL.
  404. //
  405. // 04-23-99 SamerA Created.
  406. ////////////////////////////////////////////////////////////////////////////
  407. HFDI Muisetup_InitDiamond()
  408. {
  409. ERF erf;
  410. if (!ghfdi)
  411. {
  412. ghfdi = FDICreate( DiamondMemAlloc,
  413. DiamondMemFree,
  414. DiamondFileOpen,
  415. DiamondFileRead,
  416. DiamondFileWrite,
  417. DiamondFileClose,
  418. DiamondFileSeek,
  419. cpuUNKNOWN,
  420. &erf );
  421. }
  422. return ghfdi;
  423. }
  424. ////////////////////////////////////////////////////////////////////////////
  425. //
  426. // Muisetup_FreeDiamond
  427. //
  428. // Free diamond dll. Should be called at application shutdown.
  429. //
  430. // 04-23-99 SamerA Created.
  431. ////////////////////////////////////////////////////////////////////////////
  432. BOOL Muisetup_FreeDiamond()
  433. {
  434. BOOL bRet = TRUE;
  435. if (ghfdi)
  436. {
  437. bRet = FDIDestroy(ghfdi);
  438. }
  439. return bRet;
  440. }
  441. ////////////////////////////////////////////////////////////////////////////
  442. //
  443. // Muisetup_DiamondReset
  444. //
  445. // Should be called at the start of processing a file to copy.
  446. //
  447. // 04-23-99 SamerA Created.
  448. ////////////////////////////////////////////////////////////////////////////
  449. void Muisetup_DiamondReset(
  450. PDIAMOND_PACKET pDiamond)
  451. {
  452. pDiamond->flags = DIAMOND_NONE;
  453. return;
  454. }
  455. ////////////////////////////////////////////////////////////////////////////
  456. //
  457. // Muisetup_IsDiamondFile
  458. //
  459. // Determines if a file is a diamond file, and if so, returns its original
  460. // name.
  461. //
  462. // 04-23-99 SamerA Created.
  463. ////////////////////////////////////////////////////////////////////////////
  464. BOOL Muisetup_IsDiamondFile(
  465. PWSTR pwszFileName,
  466. PWSTR pwszOriginalName,
  467. INT nSize,
  468. PDIAMOND_PACKET pDiamond)
  469. {
  470. INT_PTR hf;
  471. BOOL bRet;
  472. int nCount;
  473. char *p;
  474. FDICABINETINFO fdici;
  475. HFDI hfdi = ghfdi;
  476. if (!hfdi)
  477. {
  478. #if SAMER_DBG
  479. OutputDebugStringA("Muisetup_IsDiamondFile : No HFDI context\n");
  480. #endif
  481. return FALSE;
  482. }
  483. //
  484. // Init the diamond packet
  485. //
  486. pDiamond->flags = DIAMOND_NONE;
  487. if ((nCount = WideCharToMultiByte( CP_ACP,
  488. 0,
  489. pwszFileName,
  490. -1,
  491. pDiamond->szSrcFilePath,
  492. sizeof( pDiamond->szSrcFilePath ),
  493. NULL,
  494. NULL )) == 0)
  495. {
  496. #if SAMER_DBG
  497. OutputDebugStringA("Muisetup_IsDiamondFile : WideCharToMultiByte failed\n");
  498. #endif
  499. return FALSE;
  500. }
  501. pDiamond->szSrcFilePath[ nCount ] = '\0';
  502. hf = DiamondFileOpen( pDiamond->szSrcFilePath,
  503. _O_BINARY | _O_RDONLY | _O_SEQUENTIAL,
  504. 0
  505. );
  506. if (hf == -1)
  507. {
  508. #if SAMER_DBG
  509. OutputDebugStringA("Muisetup_IsDiamondFile : file_open failed\n");
  510. #endif
  511. return FALSE;
  512. }
  513. bRet = FDIIsCabinet( hfdi,
  514. hf,
  515. &fdici
  516. );
  517. DiamondFileClose( hf );
  518. //
  519. // If succeeded, then let's setup everything else
  520. // to get the correct original file name
  521. //
  522. if (bRet)
  523. {
  524. pDiamond->flags |= DIAMOND_GET_DEST_FILE_NAME;
  525. p = strrchr(pDiamond->szSrcFilePath, '\\');
  526. if (p == NULL)
  527. {
  528. strcpy(pDiamond->szSrcFileName, pDiamond->szSrcFilePath);
  529. strcpy(pDiamond->szSrcFilePath, "");
  530. }
  531. else
  532. {
  533. strcpy(pDiamond->szSrcFileName, p+1);
  534. p[ 1 ] = '\0';
  535. }
  536. strcpy( pDiamond->szDestFilePath,
  537. "c:\\samer\\" );
  538. if (Muisetup_CopyDiamondFile( pDiamond,
  539. NULL))
  540. {
  541. //
  542. // Convert the original file name back to Unicode
  543. //
  544. nCount = MultiByteToWideChar( CP_ACP,
  545. 0,
  546. pDiamond->szDestFilePath,
  547. -1,
  548. pwszOriginalName,
  549. nSize
  550. );
  551. if (!nCount)
  552. {
  553. return FALSE;
  554. }
  555. pwszOriginalName[ nCount ] = UNICODE_NULL;
  556. pDiamond->flags = DIAMOND_FILE;
  557. #if SAMER_DBG
  558. {
  559. BYTE byBuf[200];
  560. wsprintfA(byBuf, "SrcFile = %s%s, OriginalFileName=%s\n",
  561. pDiamond->szSrcFilePath,
  562. pDiamond->szSrcFileName,
  563. pDiamond->szDestFilePath);
  564. OutputDebugStringA(byBuf);
  565. }
  566. #endif
  567. }
  568. pDiamond->flags &= ~DIAMOND_GET_DEST_FILE_NAME;
  569. }
  570. return bRet;
  571. }
  572. ////////////////////////////////////////////////////////////////////////////
  573. //
  574. // Muisetup_CopyDiamondFile
  575. //
  576. // Copies and expands a diamond file.
  577. //
  578. // 04-23-99 SamerA Created.
  579. ////////////////////////////////////////////////////////////////////////////
  580. BOOL Muisetup_CopyDiamondFile(
  581. PDIAMOND_PACKET pDiamond,
  582. PWSTR pwszCopyTo)
  583. {
  584. char szDestPath[ MAX_PATH + 1];
  585. char *p;
  586. int nCount;
  587. BOOL bRet;
  588. HFDI hfdi = ghfdi;
  589. //
  590. // Validate that this is a diamond file
  591. //
  592. if ((!hfdi) ||
  593. (pDiamond->flags == DIAMOND_NONE))
  594. {
  595. return FALSE;
  596. }
  597. //
  598. // Validate flags
  599. //
  600. if (!(pDiamond->flags & (DIAMOND_FILE | DIAMOND_GET_DEST_FILE_NAME)))
  601. {
  602. return FALSE;
  603. }
  604. #if SAMER_DBG
  605. {
  606. BYTE byBuf[100];
  607. wsprintfA(byBuf, "DiamondCopy called for %s, flags = %lx\n", pDiamond->szSrcFileName, pDiamond->flags);
  608. OutputDebugStringA(byBuf);
  609. }
  610. #endif
  611. if (!(pDiamond->flags & DIAMOND_GET_DEST_FILE_NAME))
  612. {
  613. if ((nCount = WideCharToMultiByte( CP_ACP,
  614. 0,
  615. pwszCopyTo,
  616. -1,
  617. szDestPath,
  618. sizeof( szDestPath ),
  619. NULL,
  620. NULL )) == 0)
  621. {
  622. return FALSE;
  623. }
  624. szDestPath[ nCount ] = '\0';
  625. p = strrchr(szDestPath, '\\');
  626. if (p)
  627. {
  628. p[1] = '\0';
  629. }
  630. else
  631. {
  632. szDestPath[ nCount ] = '\\';
  633. szDestPath[ nCount + 1 ] = '\0';
  634. }
  635. strcpy( pDiamond->szDestFilePath,
  636. szDestPath );
  637. }
  638. bRet = FDICopy( hfdi,
  639. pDiamond->szSrcFileName,
  640. pDiamond->szSrcFilePath,
  641. 0,
  642. DiamondNotifyFunction,
  643. NULL,
  644. pDiamond);
  645. #if SAMER_DBG
  646. {
  647. BYTE byBuf[200];
  648. wsprintfA(byBuf, "SrcFile = %s%s, DestPath=%s, Status=%lx\n",
  649. pDiamond->szSrcFilePath,
  650. pDiamond->szSrcFileName,
  651. pDiamond->szDestFilePath,
  652. bRet);
  653. OutputDebugStringA(byBuf);
  654. }
  655. #endif
  656. return bRet;
  657. }