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.

946 lines
20 KiB

  1. #include <windows.h>
  2. #include <fcntl.h>
  3. //
  4. // lz headers
  5. //
  6. #include "lz_common.h"
  7. #include "lz_buffers.h"
  8. #include "lz_header.h"
  9. //
  10. // diamond headers
  11. //
  12. #include <diamondd.h>
  13. #include "mydiam.h"
  14. HFDI FdiContext;
  15. ERF FdiError;
  16. INT DiamondLastIoError;
  17. BOOL
  18. PatternMatch(
  19. IN PCSTR pszString,
  20. IN PCSTR pszPattern,
  21. IN BOOL fImplyDotAtEnd
  22. );
  23. INT_PTR
  24. DIAMONDAPI
  25. SpdFdiOpen(
  26. IN PSTR FileName,
  27. IN int oflag,
  28. IN int pmode
  29. );
  30. int
  31. DIAMONDAPI
  32. SpdFdiClose(
  33. IN INT_PTR Handle
  34. );
  35. typedef struct _DIAMOND_INFO {
  36. //
  37. // A read handle to the source file.
  38. //
  39. INT_PTR SourceFileHandle;
  40. //
  41. // File names.
  42. //
  43. PSTR SourceFileName;
  44. PSTR TargetFileName;
  45. //
  46. // Flag indicating whether to rename the target file.
  47. //
  48. BOOL RenameTargetFile;
  49. //
  50. // Pointer to LZ information structure.
  51. // We'll fill in some of the fields to fool expand.
  52. //
  53. PLZINFO pLZI;
  54. //
  55. // Expand callback/notification.
  56. //
  57. NOTIFYPROC ExpandNotify;
  58. //
  59. // Selective extraction file spec, ie, "aic*.sys" or NULL
  60. //
  61. PSTR SelectiveFilesSpec;
  62. } DIAMOND_INFO, *PDIAMOND_INFO;
  63. PTSTR
  64. StringRevChar(
  65. IN PTSTR String,
  66. IN TCHAR Char
  67. )
  68. {
  69. //
  70. // Although not the most efficient possible algoeithm in each case,
  71. // this algorithm is correct for unicode, sbcs, or dbcs.
  72. //
  73. PTCHAR Occurrence,Next;
  74. //
  75. // Check each character in the string and remember
  76. // the most recently encountered occurrence of the desired char.
  77. //
  78. for(Occurrence=NULL,Next=CharNext(String); *String; ) {
  79. if(!memcmp(String,&Char,(int)((PUCHAR)Next-(PUCHAR)String))) {
  80. Occurrence = String;
  81. }
  82. String = Next;
  83. Next = CharNext(Next);
  84. }
  85. //
  86. // Return address of final occurrence of the character
  87. // (will be NULL if not found at all).
  88. //
  89. return(Occurrence);
  90. }
  91. #define WILDCARD '*' /* zero or more of any character */
  92. #define WILDCHAR '?' /* one of any character (does not match END) */
  93. #define END '\0' /* terminal character */
  94. #define DOT '.' /* may be implied at end ("hosts" matches "*.") */
  95. static int __inline Lower(c)
  96. {
  97. if ((c >= 'A') && (c <= 'Z'))
  98. {
  99. return(c + ('a' - 'A'));
  100. }
  101. else
  102. {
  103. return(c);
  104. }
  105. }
  106. static int __inline CharacterMatch(char chCharacter, char chPattern)
  107. {
  108. if (Lower(chCharacter) == Lower(chPattern))
  109. {
  110. return(TRUE);
  111. }
  112. else
  113. {
  114. return(FALSE);
  115. }
  116. }
  117. BOOL
  118. PatternMatch(
  119. PCSTR pszString,
  120. PCSTR pszPattern,
  121. IN BOOL fImplyDotAtEnd
  122. )
  123. {
  124. /* RECURSIVE */
  125. //
  126. // This function does not deal with 8.3 conventions which might
  127. // be expected for filename comparisons. (In an 8.3 environment,
  128. // "alongfilename.html" would match "alongfil.htm")
  129. //
  130. // This code is NOT MBCS-enabled
  131. //
  132. for ( ; ; )
  133. {
  134. switch (*pszPattern)
  135. {
  136. case END:
  137. //
  138. // Reached end of pattern, so we're done. Matched if
  139. // end of string, no match if more string remains.
  140. //
  141. return(*pszString == END);
  142. case WILDCHAR:
  143. //
  144. // Next in pattern is a wild character, which matches
  145. // anything except end of string. If we reach the end
  146. // of the string, the implied DOT would also match.
  147. //
  148. if (*pszString == END)
  149. {
  150. if (fImplyDotAtEnd == TRUE)
  151. {
  152. fImplyDotAtEnd = FALSE;
  153. }
  154. else
  155. {
  156. return(FALSE);
  157. }
  158. }
  159. else
  160. {
  161. pszString++;
  162. }
  163. pszPattern++;
  164. break;
  165. case WILDCARD:
  166. //
  167. // Next in pattern is a wildcard, which matches anything.
  168. // Find the required character that follows the wildcard,
  169. // and search the string for it. At each occurence of the
  170. // required character, try to match the remaining pattern.
  171. //
  172. // There are numerous equivalent patterns in which multiple
  173. // WILDCARD and WILDCHAR are adjacent. We deal with these
  174. // before our search for the required character.
  175. //
  176. // Each WILDCHAR burns one non-END from the string. An END
  177. // means we have a match. Additional WILDCARDs are ignored.
  178. //
  179. for ( ; ; )
  180. {
  181. pszPattern++;
  182. if (*pszPattern == END)
  183. {
  184. return(TRUE);
  185. }
  186. else if (*pszPattern == WILDCHAR)
  187. {
  188. if (*pszString == END)
  189. {
  190. if (fImplyDotAtEnd == TRUE)
  191. {
  192. fImplyDotAtEnd = FALSE;
  193. }
  194. else
  195. {
  196. return(FALSE);
  197. }
  198. }
  199. else
  200. {
  201. pszString++;
  202. }
  203. }
  204. else if (*pszPattern != WILDCARD)
  205. {
  206. break;
  207. }
  208. }
  209. //
  210. // Now we have a regular character to search the string for.
  211. //
  212. while (*pszString != END)
  213. {
  214. //
  215. // For each match, use recursion to see if the remainder
  216. // of the pattern accepts the remainder of the string.
  217. // If it does not, continue looking for other matches.
  218. //
  219. if (CharacterMatch(*pszString, *pszPattern) == TRUE)
  220. {
  221. if (PatternMatch(pszString + 1, pszPattern + 1, fImplyDotAtEnd) == TRUE)
  222. {
  223. return(TRUE);
  224. }
  225. }
  226. pszString++;
  227. }
  228. //
  229. // Reached end of string without finding required character
  230. // which followed the WILDCARD. If the required character
  231. // is a DOT, consider matching the implied DOT.
  232. //
  233. // Since the remaining string is empty, the only pattern which
  234. // could match after the DOT would be zero or more WILDCARDs,
  235. // so don't bother with recursion.
  236. //
  237. if ((*pszPattern == DOT) && (fImplyDotAtEnd == TRUE))
  238. {
  239. pszPattern++;
  240. while (*pszPattern != END)
  241. {
  242. if (*pszPattern != WILDCARD)
  243. {
  244. return(FALSE);
  245. }
  246. pszPattern++;
  247. }
  248. return(TRUE);
  249. }
  250. //
  251. // Reached end of the string without finding required character.
  252. //
  253. return(FALSE);
  254. break;
  255. default:
  256. //
  257. // Nothing special about the pattern character, so it
  258. // must match source character.
  259. //
  260. if (CharacterMatch(*pszString, *pszPattern) == FALSE)
  261. {
  262. if ((*pszPattern == DOT) &&
  263. (*pszString == END) &&
  264. (fImplyDotAtEnd == TRUE))
  265. {
  266. fImplyDotAtEnd = FALSE;
  267. }
  268. else
  269. {
  270. return(FALSE);
  271. }
  272. }
  273. if (*pszString != END)
  274. {
  275. pszString++;
  276. }
  277. pszPattern++;
  278. }
  279. }
  280. }
  281. INT_PTR
  282. DIAMONDAPI
  283. DiamondNotifyFunction(
  284. IN FDINOTIFICATIONTYPE Operation,
  285. IN PFDINOTIFICATION Parameters
  286. )
  287. {
  288. switch(Operation) {
  289. case fdintCABINET_INFO:
  290. case fdintPARTIAL_FILE:
  291. default:
  292. //
  293. // Cabinet management functions which we don't use.
  294. // Return success.
  295. //
  296. return(0);
  297. case fdintNEXT_CABINET:
  298. return (-1); // We don't support multiple cabinets.
  299. case fdintCOPY_FILE:
  300. //
  301. // Diamond is asking us whether we want to copy the file.
  302. //
  303. {
  304. PDIAMOND_INFO Info = (PDIAMOND_INFO)Parameters->pv;
  305. HFILE h;
  306. //
  307. // If we were given a filespec, see if the name matches.
  308. //
  309. if (Info->SelectiveFilesSpec != NULL) {
  310. //
  311. // Call PatternMatch(), fAllowImpliedDot TRUE if
  312. // there is no '.' in the file's base name.
  313. //
  314. BOOL fAllowImpliedDot = TRUE;
  315. PSTR p;
  316. for (p = Parameters->psz1; *p != '\0'; p++) {
  317. if (*p == '.') {
  318. fAllowImpliedDot = FALSE;
  319. } else if (*p == '\\') {
  320. fAllowImpliedDot = TRUE;
  321. }
  322. }
  323. if (PatternMatch(
  324. Parameters->psz1,
  325. Info->SelectiveFilesSpec,
  326. fAllowImpliedDot) == FALSE) {
  327. return(0); // skip this file
  328. }
  329. }
  330. //
  331. // If we need to rename the target file, do that here.
  332. // The name stored in the cabinet file will be used as
  333. // the uncompressed name.
  334. //
  335. if(Info->RenameTargetFile) {
  336. PSTR p,q;
  337. //
  338. // Find the start of the filename part of the target.
  339. //
  340. if(p = StringRevChar(Info->TargetFileName,'\\')) {
  341. p++;
  342. } else {
  343. p = Info->TargetFileName;
  344. }
  345. //
  346. // Find the start of the filename part of the name in the cabinet.
  347. //
  348. if(q = StringRevChar(Parameters->psz1,'\\')) {
  349. q++;
  350. } else {
  351. q = Parameters->psz1;
  352. }
  353. //
  354. // Copy the filename part of the name in the cabinet over
  355. // the filename part of the name in the target spec.
  356. //
  357. lstrcpy(p,q);
  358. }
  359. //
  360. // Inform the expand callback what we are doing.
  361. //
  362. if(!Info->ExpandNotify(Info->SourceFileName,Info->TargetFileName,NOTIFY_START_EXPAND)) {
  363. return(0); // skip this file.
  364. }
  365. //
  366. // Remember the uncompressed size and open the file.
  367. // Returns -1 if an error occurs opening the file.
  368. //
  369. Info->pLZI->cblOutSize += Parameters->cb;
  370. h = _lcreat(Info->TargetFileName,0);
  371. if(h == HFILE_ERROR) {
  372. DiamondLastIoError = LZERROR_BADOUTHANDLE;
  373. return(-1);
  374. }
  375. return(h);
  376. }
  377. case fdintCLOSE_FILE_INFO:
  378. //
  379. // Diamond is done with the target file and wants us to close it.
  380. // (ie, this is the counterpart to fdint_COPY_FILE).
  381. //
  382. {
  383. PDIAMOND_INFO Info = (PDIAMOND_INFO)Parameters->pv;
  384. HANDLE TargetFileHandle;
  385. FILETIME ftLocal, ftUTC;
  386. _lclose((HFILE)Parameters->hf);
  387. //
  388. // Set the target file's date/time stamp from the value inside
  389. // the CAB.
  390. //
  391. TargetFileHandle = CreateFile(Info->TargetFileName,
  392. GENERIC_READ | GENERIC_WRITE,
  393. 0,
  394. NULL,
  395. OPEN_EXISTING,
  396. 0,
  397. NULL);
  398. if (TargetFileHandle != INVALID_HANDLE_VALUE)
  399. {
  400. if (DosDateTimeToFileTime(Parameters->date, Parameters->time, &ftLocal) &&
  401. LocalFileTimeToFileTime(&ftLocal, &ftUTC))
  402. {
  403. SetFileTime(TargetFileHandle, NULL, NULL, &ftUTC);
  404. }
  405. CloseHandle(TargetFileHandle);
  406. }
  407. }
  408. return(TRUE);
  409. }
  410. }
  411. PVOID
  412. DIAMONDAPI
  413. SpdFdiAlloc(
  414. IN ULONG NumberOfBytes
  415. )
  416. /*++
  417. Routine Description:
  418. Callback used by FDICopy to allocate memory.
  419. Arguments:
  420. NumberOfBytes - supplies desired size of block.
  421. Return Value:
  422. Returns pointer to a block of memory or NULL
  423. if memory cannot be allocated.
  424. --*/
  425. {
  426. return((PVOID)LocalAlloc(LMEM_FIXED,NumberOfBytes));
  427. }
  428. VOID
  429. DIAMONDAPI
  430. SpdFdiFree(
  431. IN PVOID Block
  432. )
  433. /*++
  434. Routine Description:
  435. Callback used by FDICopy to free a memory block.
  436. The block must have been allocated with SpdFdiAlloc().
  437. Arguments:
  438. Block - supplies pointer to block of memory to be freed.
  439. Return Value:
  440. None.
  441. --*/
  442. {
  443. LocalFree((HLOCAL)Block);
  444. }
  445. INT_PTR
  446. DIAMONDAPI
  447. SpdFdiOpen(
  448. IN PSTR FileName,
  449. IN int oflag,
  450. IN int pmode
  451. )
  452. /*++
  453. Routine Description:
  454. Callback used by FDICopy to open files.
  455. Arguments:
  456. FileName - supplies name of file to be opened.
  457. oflag - supplies flags for open.
  458. pmode - supplies additional flags for open.
  459. Return Value:
  460. Handle to open file or -1 if error occurs.
  461. --*/
  462. {
  463. HFILE h;
  464. int OpenMode;
  465. if(oflag & _O_WRONLY) {
  466. OpenMode = OF_WRITE;
  467. } else {
  468. if(oflag & _O_RDWR) {
  469. OpenMode = OF_READWRITE;
  470. } else {
  471. OpenMode = OF_READ;
  472. }
  473. }
  474. h = _lopen(FileName,OpenMode | OF_SHARE_DENY_WRITE);
  475. if(h == HFILE_ERROR) {
  476. DiamondLastIoError = LZERROR_BADINHANDLE;
  477. return(-1);
  478. }
  479. return((INT_PTR)h);
  480. }
  481. UINT
  482. DIAMONDAPI
  483. SpdFdiRead(
  484. IN INT_PTR Handle,
  485. OUT PVOID pv,
  486. IN UINT ByteCount
  487. )
  488. /*++
  489. Routine Description:
  490. Callback used by FDICopy to read from a file.
  491. Arguments:
  492. Handle - supplies handle to open file to be read from.
  493. pv - supplies pointer to buffer to receive bytes we read.
  494. ByteCount - supplies number of bytes to read.
  495. Return Value:
  496. Number of bytes read (ByteCount) or -1 if an error occurs.
  497. --*/
  498. {
  499. UINT rc;
  500. rc = _lread((HFILE)Handle,pv,ByteCount);
  501. if(rc == HFILE_ERROR) {
  502. rc = (UINT)(-1);
  503. DiamondLastIoError = LZERROR_READ;
  504. }
  505. return(rc);
  506. }
  507. UINT
  508. DIAMONDAPI
  509. SpdFdiWrite(
  510. IN INT_PTR Handle,
  511. IN PVOID pv,
  512. IN UINT ByteCount
  513. )
  514. /*++
  515. Routine Description:
  516. Callback used by FDICopy to write to a file.
  517. Arguments:
  518. Handle - supplies handle to open file to be written to.
  519. pv - supplies pointer to buffer containing bytes to write.
  520. ByteCount - supplies number of bytes to write.
  521. Return Value:
  522. Number of bytes written (ByteCount) or -1 if an error occurs.
  523. --*/
  524. {
  525. UINT rc;
  526. rc = _lwrite((HFILE)Handle,pv,ByteCount);
  527. if(rc == HFILE_ERROR) {
  528. DiamondLastIoError = (GetLastError() == ERROR_DISK_FULL) ? LZERROR_WRITE : LZERROR_BADOUTHANDLE;
  529. } else {
  530. if(rc != ByteCount) {
  531. //
  532. // let caller interpret return value but record last error just in case
  533. //
  534. DiamondLastIoError = LZERROR_WRITE;
  535. }
  536. }
  537. return(rc);
  538. }
  539. int
  540. DIAMONDAPI
  541. SpdFdiClose(
  542. IN INT_PTR Handle
  543. )
  544. /*++
  545. Routine Description:
  546. Callback used by FDICopy to close files.
  547. Arguments:
  548. Handle - handle of file to close.
  549. Return Value:
  550. 0 (success).
  551. --*/
  552. {
  553. _lclose((HFILE)Handle);
  554. return(0);
  555. }
  556. LONG
  557. DIAMONDAPI
  558. SpdFdiSeek(
  559. IN INT_PTR Handle,
  560. IN long Distance,
  561. IN int SeekType
  562. )
  563. /*++
  564. Routine Description:
  565. Callback used by FDICopy to seek files.
  566. Arguments:
  567. Handle - handle of file to close.
  568. Distance - supplies distance to seek. Interpretation of this
  569. parameter depends on the value of SeekType.
  570. SeekType - supplies a value indicating how Distance is to be
  571. interpreted; one of SEEK_SET, SEEK_CUR, SEEK_END.
  572. Return Value:
  573. New file offset or -1 if an error occurs.
  574. --*/
  575. {
  576. LONG rc;
  577. rc = _llseek((HFILE)Handle,Distance,SeekType);
  578. if(rc == HFILE_ERROR) {
  579. DiamondLastIoError = LZERROR_BADINHANDLE;
  580. rc = -1L;
  581. }
  582. return(rc);
  583. }
  584. INT
  585. ExpandDiamondFile(
  586. IN NOTIFYPROC ExpandNotify,
  587. IN PSTR SourceFileName,
  588. IN PSTR TargetFileName,
  589. IN BOOL RenameTarget,
  590. IN PSTR SelectiveFilesSpec,
  591. OUT PLZINFO pLZI
  592. )
  593. {
  594. BOOL b;
  595. INT rc;
  596. INT_PTR h;
  597. DIAMOND_INFO DiamondInfo;
  598. if(!FdiContext) {
  599. return(LZERROR_BADVALUE);
  600. }
  601. DiamondLastIoError = TRUE;
  602. //
  603. // Get a handle to the source to use to
  604. // copy the date and time stamp.
  605. //
  606. h = SpdFdiOpen(SourceFileName,_O_RDONLY,0);
  607. if(h == -1) {
  608. return(LZERROR_BADINHANDLE);
  609. }
  610. pLZI->cblInSize = GetFileSize((HANDLE)h,NULL);
  611. if(pLZI->cblInSize == -1) {
  612. SpdFdiClose(h);
  613. return(LZERROR_BADINHANDLE);
  614. }
  615. DiamondInfo.SourceFileHandle = h;
  616. DiamondInfo.SourceFileName = SourceFileName;
  617. DiamondInfo.TargetFileName = TargetFileName;
  618. DiamondInfo.RenameTargetFile = RenameTarget;
  619. DiamondInfo.ExpandNotify = ExpandNotify;
  620. DiamondInfo.SelectiveFilesSpec = SelectiveFilesSpec;
  621. DiamondInfo.pLZI = pLZI;
  622. b = FDICopy(
  623. FdiContext,
  624. SourceFileName, // pass the whole path as the name
  625. "", // don't bother with the path part
  626. 0, // flags
  627. DiamondNotifyFunction,
  628. NULL, // no decryption
  629. &DiamondInfo
  630. );
  631. if(b) {
  632. rc = TRUE;
  633. } else {
  634. switch(FdiError.erfOper) {
  635. case FDIERROR_CORRUPT_CABINET:
  636. case FDIERROR_UNKNOWN_CABINET_VERSION:
  637. case FDIERROR_BAD_COMPR_TYPE:
  638. rc = LZERROR_READ; // causes SID_FORMAT_ERROR message
  639. break;
  640. case FDIERROR_ALLOC_FAIL:
  641. rc = LZERROR_GLOBALLOC;
  642. break;
  643. case FDIERROR_TARGET_FILE:
  644. case FDIERROR_USER_ABORT:
  645. rc = DiamondLastIoError;
  646. break;
  647. default:
  648. //
  649. // The rest of the errors are not handled specially.
  650. //
  651. rc = LZERROR_BADVALUE;
  652. break;
  653. }
  654. //
  655. // Remove the partial target file.
  656. //
  657. DeleteFile(TargetFileName);
  658. }
  659. SpdFdiClose(h);
  660. return(rc);
  661. }
  662. BOOL
  663. IsDiamondFile(
  664. IN PSTR FileName,
  665. OUT PBOOL ContainsMultipleFiles
  666. )
  667. {
  668. FDICABINETINFO CabinetInfo;
  669. BOOL b;
  670. INT_PTR h;
  671. *ContainsMultipleFiles = FALSE;
  672. if(!FdiContext) {
  673. return(FALSE);
  674. }
  675. //
  676. // Open the file such that the handle is valid for use
  677. // in the diamond context (ie, seek, read routines above).
  678. //
  679. h = SpdFdiOpen(FileName,_O_RDONLY,0);
  680. if(h == -1) {
  681. return(FALSE);
  682. }
  683. b = FDIIsCabinet(FdiContext,h,&CabinetInfo);
  684. SpdFdiClose(h);
  685. if (b && (CabinetInfo.cFiles > 1)) {
  686. *ContainsMultipleFiles = TRUE;
  687. }
  688. return(b);
  689. }
  690. BOOL
  691. InitDiamond(
  692. VOID
  693. )
  694. {
  695. if(FdiContext == NULL) {
  696. FdiContext = FDICreate(
  697. SpdFdiAlloc,
  698. SpdFdiFree,
  699. SpdFdiOpen,
  700. SpdFdiRead,
  701. SpdFdiWrite,
  702. SpdFdiClose,
  703. SpdFdiSeek,
  704. cpuUNKNOWN,
  705. &FdiError
  706. );
  707. }
  708. return(FdiContext != NULL);
  709. }
  710. VOID
  711. TermDiamond(
  712. VOID
  713. )
  714. {
  715. if(FdiContext) {
  716. FDIDestroy(FdiContext);
  717. FdiContext = NULL;
  718. }
  719. }