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.

596 lines
11 KiB

  1. #include "pch.h"
  2. #include <fdi.h>
  3. #include <io.h>
  4. #include <fcntl.h>
  5. #include <sys\stat.h>
  6. #include <malloc.h>
  7. #include <lzexpand.h>
  8. #ifdef __cplusplus
  9. extern "C" {
  10. #endif
  11. BOOL
  12. UncompressFile(
  13. IN LPCSTR CompressedFileName,
  14. IN LPCSTR UncompressedFileName
  15. );
  16. DWORD
  17. UncompressLZFile(
  18. IN LPCSTR CompressedFileName,
  19. IN LPCSTR UncompressedFileName
  20. );
  21. #ifdef __cplusplus
  22. }
  23. #endif
  24. typedef struct
  25. {
  26. LPCSTR TargetFileName; // pathname of file to create
  27. LPCSTR SymbolFileName; // name of file to uncompress
  28. DWORD FileSize; // expected file size
  29. DWORD LastError; // completion code
  30. } OPCONTEXT;
  31. DWORD
  32. ExtractSingleFileFromCabinet(
  33. IN LPCSTR CabinetFileName,
  34. IN LPCSTR TargetFileName,
  35. IN LPCSTR FileNameInCabinet
  36. );
  37. INT_PTR
  38. DIAMONDAPI
  39. FdiNotification(
  40. FDINOTIFICATIONTYPE fdint,
  41. PFDINOTIFICATION pfdin
  42. );
  43. void HUGE *
  44. FAR DIAMONDAPI
  45. FdiAlloc(
  46. ULONG cb
  47. );
  48. void
  49. FAR DIAMONDAPI
  50. FdiFree(
  51. void HUGE *pv
  52. );
  53. INT_PTR
  54. FAR DIAMONDAPI
  55. FdiOpen(
  56. char FAR *pszFile,
  57. int oflag,
  58. int pmode
  59. );
  60. UINT
  61. FAR DIAMONDAPI
  62. FdiRead(
  63. INT_PTR hf,
  64. void FAR *pv,
  65. UINT cb
  66. );
  67. UINT
  68. FAR DIAMONDAPI
  69. FdiWrite(
  70. INT_PTR hf,
  71. void FAR *pv,
  72. UINT cb
  73. );
  74. long
  75. FAR DIAMONDAPI
  76. FdiSeek(
  77. INT_PTR hf,
  78. long dist,
  79. int seektype
  80. );
  81. int
  82. FAR DIAMONDAPI
  83. FdiClose(
  84. INT_PTR hf
  85. );
  86. DWORD
  87. GetLastErrorWithDefault(
  88. DWORD DefaultError
  89. );
  90. #ifdef STANDALONE
  91. int __cdecl main( int argc, char * argv[] )
  92. {
  93. BOOL rc;
  94. printf( "UncompressFile( \"%s\", \"%s\" )\n", argv[ 1 ], argv[ 2 ] );
  95. rc = UncompressFile( argv[1], argv[2] );
  96. if ( rc == TRUE )
  97. {
  98. printf( "Expanded \"%s\" to \"%s\"\n", argv[1], argv[2] );
  99. }
  100. else
  101. {
  102. printf( "Failed to expand, GLE=%u\n", GetLastError());
  103. }
  104. return rc;
  105. }
  106. #endif
  107. BOOL
  108. UncompressFile(
  109. IN LPCSTR CompressedFileName,
  110. IN LPCSTR UncompressedFileName
  111. )
  112. {
  113. DWORD rc;
  114. LPCSTR FileNameInCabinet;
  115. // Assume the name to be extracted from the
  116. // compressed file is the same as the base
  117. // name of the specified target file.
  118. FileNameInCabinet = strrchr( UncompressedFileName, '\\' );
  119. if ( FileNameInCabinet == NULL )
  120. {
  121. FileNameInCabinet = UncompressedFileName;
  122. }
  123. else
  124. {
  125. FileNameInCabinet++;
  126. }
  127. __try
  128. {
  129. rc = ExtractSingleFileFromCabinet(
  130. CompressedFileName,
  131. UncompressedFileName,
  132. FileNameInCabinet
  133. );
  134. //
  135. // If the file is not a cabinet, it might be an LZExpand file
  136. //
  137. if ( rc == ERROR_FILE_CORRUPT )
  138. {
  139. rc = UncompressLZFile(
  140. CompressedFileName,
  141. UncompressedFileName
  142. );
  143. }
  144. }
  145. __except ( EXCEPTION_EXECUTE_HANDLER )
  146. {
  147. rc = GetExceptionCode();
  148. if ( rc == ERROR_SUCCESS )
  149. {
  150. rc = E_UNEXPECTED;
  151. }
  152. }
  153. if ( rc != ERROR_SUCCESS )
  154. {
  155. SetLastError( rc );
  156. return( FALSE );
  157. }
  158. return( TRUE );
  159. }
  160. DWORD
  161. ExtractSingleFileFromCabinet(
  162. IN LPCSTR CabinetFileName,
  163. IN LPCSTR TargetFileName,
  164. IN LPCSTR FileNameInCabinet
  165. )
  166. {
  167. HFDI hFDI;
  168. OPCONTEXT Context;
  169. ERF Erf;
  170. DWORD rc;
  171. memset( &Context, 0, sizeof( Context ));
  172. Context.TargetFileName = TargetFileName;
  173. Context.SymbolFileName = FileNameInCabinet;
  174. Context.LastError = ERROR_FILE_NOT_FOUND;
  175. memset( &Erf, 0, sizeof( Erf ));
  176. hFDI = FDICreate(
  177. FdiAlloc,
  178. FdiFree,
  179. FdiOpen,
  180. FdiRead,
  181. FdiWrite,
  182. FdiClose,
  183. FdiSeek,
  184. cpuUNKNOWN,
  185. &Erf
  186. );
  187. if ( hFDI == NULL )
  188. {
  189. Context.LastError = GetLastErrorWithDefault( ERROR_NOT_ENOUGH_MEMORY );
  190. }
  191. else
  192. {
  193. rc = FDICopy(
  194. hFDI,
  195. "",
  196. (char *) CabinetFileName,
  197. 0,
  198. FdiNotification,
  199. NULL,
  200. &Context
  201. );
  202. FDIDestroy( hFDI );
  203. if (( rc == FALSE ) &&
  204. ( Context.LastError == ERROR_FILE_NOT_FOUND ))
  205. {
  206. switch ( Erf.erfOper )
  207. {
  208. case FDIERROR_NOT_A_CABINET:
  209. case FDIERROR_UNKNOWN_CABINET_VERSION:
  210. case FDIERROR_CORRUPT_CABINET:
  211. case FDIERROR_BAD_COMPR_TYPE:
  212. case FDIERROR_MDI_FAIL:
  213. Context.LastError = ERROR_FILE_CORRUPT;
  214. }
  215. }
  216. }
  217. return( Context.LastError );
  218. }
  219. DWORD
  220. UncompressLZFile(
  221. IN LPCSTR CompressedFileName,
  222. IN LPCSTR UncompressedFileName
  223. )
  224. {
  225. INT_PTR hSource;
  226. int hSrc, hDst;
  227. OFSTRUCT ofSrc, ofDst;
  228. long l;
  229. static unsigned char Signature[] = { 'S', 'Z', 'D', 'D', 0x88, 0xF0, 0x27, 0x33 };
  230. unsigned char SignatureBuffer[ sizeof( Signature ) ];
  231. //
  232. // Make sure it really is an LZExpand file
  233. //
  234. memset( SignatureBuffer, 0xFF, sizeof( Signature ));
  235. hSource = FdiOpen(
  236. (char *) CompressedFileName,
  237. _O_BINARY,
  238. 0
  239. );
  240. if ( hSource != -1 )
  241. {
  242. FdiRead( hSource, SignatureBuffer, sizeof( Signature ));
  243. FdiClose( hSource );
  244. }
  245. if ( memcmp( Signature, SignatureBuffer, sizeof( Signature )))
  246. {
  247. return ERROR_FILE_CORRUPT;
  248. }
  249. //
  250. // Use LZ32.DLL functions to decompress
  251. //
  252. hSrc = LZOpenFile(
  253. (char *) CompressedFileName,
  254. &ofSrc,
  255. OF_READ | OF_SHARE_DENY_WRITE
  256. );
  257. if ( hSrc >= 0 )
  258. {
  259. hDst = LZOpenFile(
  260. (char *) UncompressedFileName,
  261. &ofDst,
  262. OF_CREATE | OF_WRITE | OF_SHARE_EXCLUSIVE
  263. );
  264. if ( hDst >= 0 )
  265. {
  266. l = LZCopy( hSrc, hDst );
  267. if ( l >= 0 )
  268. {
  269. l = 0;
  270. }
  271. LZClose( hDst );
  272. }
  273. else
  274. {
  275. l = hDst;
  276. }
  277. LZClose( hSrc );
  278. }
  279. else
  280. {
  281. l = hSrc;
  282. }
  283. switch( l )
  284. {
  285. case NO_ERROR:
  286. return( NO_ERROR );
  287. case LZERROR_BADINHANDLE:
  288. case LZERROR_READ:
  289. return( ERROR_READ_FAULT );
  290. case LZERROR_BADOUTHANDLE:
  291. case LZERROR_WRITE:
  292. return( ERROR_WRITE_FAULT );
  293. case LZERROR_GLOBALLOC:
  294. case LZERROR_GLOBLOCK:
  295. return( ERROR_NOT_ENOUGH_MEMORY );
  296. case LZERROR_BADVALUE:
  297. case LZERROR_UNKNOWNALG:
  298. return( ERROR_INVALID_DATA );
  299. default:
  300. return( ERROR_INVALID_FUNCTION );
  301. }
  302. }
  303. DWORD
  304. GetLastErrorWithDefault(
  305. DWORD DefaultError
  306. )
  307. {
  308. DWORD LastError;
  309. LastError = GetLastError();
  310. if ( LastError == ERROR_SUCCESS )
  311. {
  312. LastError = DefaultError;
  313. }
  314. return( LastError );
  315. }
  316. INT_PTR
  317. DIAMONDAPI
  318. FdiNotification(
  319. FDINOTIFICATIONTYPE fdint,
  320. PFDINOTIFICATION pfdin
  321. )
  322. {
  323. OPCONTEXT * Context = (OPCONTEXT *) pfdin->pv;
  324. FILETIME LocalTime;
  325. FILETIME FileTime;
  326. INT_PTR hFile;
  327. switch ( fdint )
  328. {
  329. case fdintCOPY_FILE:
  330. hFile = 0;
  331. if ( _stricmp( pfdin->psz1, Context->SymbolFileName ) == 0 )
  332. {
  333. Context->FileSize = pfdin->cb;
  334. hFile = FdiOpen(
  335. (char *) Context->TargetFileName,
  336. _O_CREAT,
  337. 0
  338. );
  339. if ( hFile == -1 )
  340. {
  341. Context->LastError = GetLastErrorWithDefault( ERROR_CANNOT_MAKE );
  342. }
  343. }
  344. return( hFile ); // 0 = skip, -1 = abort, other = handle
  345. case fdintCLOSE_FILE_INFO:
  346. if ( DosDateTimeToFileTime( pfdin->date, pfdin->time, &LocalTime ) &&
  347. LocalFileTimeToFileTime( &LocalTime, &FileTime ))
  348. {
  349. SetFileTime(
  350. (HANDLE) pfdin->hf,
  351. NULL,
  352. NULL,
  353. &FileTime // last-modified date/time
  354. );
  355. }
  356. if ( GetFileSize( (HANDLE) pfdin->hf, NULL ) == Context->FileSize )
  357. {
  358. Context->LastError = ERROR_SUCCESS;
  359. }
  360. FdiClose( pfdin->hf );
  361. return 0;
  362. case fdintNEXT_CABINET:
  363. return -1; // multi-part cabinets not supported
  364. default:
  365. return 0; // disregard any other messages
  366. }
  367. }
  368. //
  369. // FDI I/O callback functions
  370. //
  371. void HUGE *
  372. FAR DIAMONDAPI
  373. FdiAlloc(
  374. ULONG cb
  375. )
  376. {
  377. void HUGE * pv;
  378. pv = LocalAlloc(LPTR, cb);
  379. return( pv );
  380. }
  381. void
  382. FAR DIAMONDAPI
  383. FdiFree(
  384. void HUGE *pv
  385. )
  386. {
  387. LocalFree( pv );
  388. }
  389. INT_PTR
  390. FAR DIAMONDAPI
  391. FdiOpen(
  392. char FAR *pszFile,
  393. int oflag,
  394. int pmode
  395. )
  396. {
  397. HANDLE Handle;
  398. BOOL Create = ( oflag & _O_CREAT );
  399. Handle = CreateFile(
  400. pszFile,
  401. Create ? GENERIC_WRITE : GENERIC_READ,
  402. Create ? 0 : FILE_SHARE_READ,
  403. NULL,
  404. Create ? CREATE_ALWAYS : OPEN_EXISTING,
  405. FILE_ATTRIBUTE_NORMAL,
  406. NULL
  407. );
  408. if ( Handle == INVALID_HANDLE_VALUE )
  409. {
  410. return( -1 );
  411. }
  412. return( (INT_PTR) Handle );
  413. }
  414. UINT
  415. FAR DIAMONDAPI
  416. FdiRead(
  417. INT_PTR hf,
  418. void FAR *pv,
  419. UINT cb
  420. )
  421. {
  422. BOOL rc;
  423. DWORD cbActual;
  424. rc = ReadFile((HANDLE)hf,
  425. pv,
  426. cb,
  427. &cbActual,
  428. NULL);
  429. return rc ? cbActual : 0;
  430. }
  431. UINT
  432. FAR DIAMONDAPI
  433. FdiWrite(
  434. INT_PTR hf,
  435. void FAR *pv,
  436. UINT cb
  437. )
  438. {
  439. DWORD cbActual = 0;
  440. WriteFile((HANDLE)hf,
  441. pv,
  442. cb,
  443. &cbActual,
  444. NULL);
  445. return cbActual;
  446. }
  447. long
  448. FAR DIAMONDAPI
  449. FdiSeek(
  450. INT_PTR hf,
  451. long dist,
  452. int seektype
  453. )
  454. {
  455. long result;
  456. DWORD NewPosition;
  457. NewPosition = SetFilePointer(
  458. (HANDLE) hf,
  459. dist,
  460. NULL,
  461. (DWORD) seektype
  462. );
  463. if ( NewPosition == INVALID_SET_FILE_POINTER )
  464. {
  465. return( -1 );
  466. }
  467. return( (long) NewPosition );
  468. }
  469. int
  470. FAR DIAMONDAPI
  471. FdiClose(
  472. INT_PTR hf
  473. )
  474. {
  475. if ( ! CloseHandle( (HANDLE) hf ))
  476. {
  477. return( -1 );
  478. }
  479. return( 0 );
  480. }