ReactOS 0.4.15-dev-7942-gd23573b
cabinet.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS text-mode setup
4 * FILE: base/setup/usetup/cabinet.c
5 * PURPOSE: Cabinet routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 15/08-2003 Created
9 */
10
11#ifndef _USETUP_PCH_
12#include "usetup.h"
13#endif
14
15#define Z_SOLO
16#include <zlib.h>
17
18#define NDEBUG
19#include <debug.h>
20
21
22/* DEFINITIONS **************************************************************/
23
24/* File management definitions */
25
26#define SEEK_BEGIN 0
27#define SEEK_CURRENT 1
28#ifndef SEEK_END
29#define SEEK_END 2
30#endif
31
32typedef struct _DOSTIME
33{
38
39typedef struct _DOSDATE
40{
45
46
47/* Cabinet constants */
48
49#define CAB_SIGNATURE 0x4643534D // "MSCF"
50#define CAB_VERSION 0x0103
51#define CAB_BLOCKSIZE 32768
52
53#define CAB_COMP_MASK 0x00FF
54#define CAB_COMP_NONE 0x0000
55#define CAB_COMP_MSZIP 0x0001
56#define CAB_COMP_QUANTUM 0x0002
57#define CAB_COMP_LZX 0x0003
58
59#define CAB_FLAG_HASPREV 0x0001
60#define CAB_FLAG_HASNEXT 0x0002
61#define CAB_FLAG_RESERVE 0x0004
62
63#define CAB_ATTRIB_READONLY 0x0001
64#define CAB_ATTRIB_HIDDEN 0x0002
65#define CAB_ATTRIB_SYSTEM 0x0004
66#define CAB_ATTRIB_VOLUME 0x0008
67#define CAB_ATTRIB_DIRECTORY 0x0010
68#define CAB_ATTRIB_ARCHIVE 0x0020
69#define CAB_ATTRIB_EXECUTE 0x0040
70#define CAB_ATTRIB_UTF_NAME 0x0080
71
72#define CAB_FILE_MAX_FOLDER 0xFFFC
73#define CAB_FILE_CONTINUED 0xFFFD
74#define CAB_FILE_SPLIT 0xFFFE
75#define CAB_FILE_PREV_NEXT 0xFFFF
76
77
78/* Cabinet structures */
79
80typedef struct _CFHEADER
81{
82 ULONG Signature; // File signature 'MSCF' (CAB_SIGNATURE)
83 ULONG Reserved1; // Reserved field
84 ULONG CabinetSize; // Cabinet file size
85 ULONG Reserved2; // Reserved field
86 ULONG FileTableOffset; // Offset of first CFFILE
87 ULONG Reserved3; // Reserved field
88 USHORT Version; // Cabinet version (CAB_VERSION)
89 USHORT FolderCount; // Number of folders
90 USHORT FileCount; // Number of files
91 USHORT Flags; // Cabinet flags (CAB_FLAG_*)
92 USHORT SetID; // Cabinet set id
93 USHORT CabinetNumber; // Zero-based cabinet number
94/* Optional fields (depends on Flags)
95 USHORT CabinetResSize // Per-cabinet reserved area size
96 CHAR FolderResSize // Per-folder reserved area size
97 CHAR FileResSize // Per-file reserved area size
98 CHAR CabinetReserved[] // Per-cabinet reserved area
99 CHAR CabinetPrev[] // Name of previous cabinet file
100 CHAR DiskPrev[] // Name of previous disk
101 CHAR CabinetNext[] // Name of next cabinet file
102 CHAR DiskNext[] // Name of next disk
103 */
105
106typedef struct _CFFOLDER
107{
108 ULONG DataOffset; // Absolute offset of first CFDATA block in this folder
109 USHORT DataBlockCount; // Number of CFDATA blocks in this folder in this cabinet
110 USHORT CompressionType; // Type of compression used for all CFDATA blocks in this folder
111/* Optional fields (depends on Flags)
112 CHAR FolderReserved[] // Per-folder reserved area
113 */
115
116typedef struct _CFFILE
117{
118 ULONG FileSize; // Uncompressed file size in bytes
119 ULONG FileOffset; // Uncompressed offset of file in the folder
120 USHORT FolderIndex; // Index number of the folder that contains this file
121 USHORT FileDate; // File date stamp, as used by DOS
122 USHORT FileTime; // File time stamp, as used by DOS
123 USHORT Attributes; // File attributes (CAB_ATTRIB_*)
125 /* After this is the NULL terminated filename */
127
128typedef struct _CFDATA
129{
130 ULONG Checksum; // Checksum of CFDATA entry
131 USHORT CompSize; // Number of compressed bytes in this block
132 USHORT UncompSize; // Number of uncompressed bytes in this block
133/* Optional fields (depends on Flags)
134 CHAR DataReserved[] // Per-datablock reserved area
135 */
137
138
139/* FUNCTIONS ****************************************************************/
140
141#if !defined(_INC_MALLOC) && !defined(_INC_STDLIB)
142
143/* Needed by zlib, but we don't want the dependency on the CRT */
144void *__cdecl
146{
148}
149
150void __cdecl
151free(void *ptr)
152{
154}
155
156void *__cdecl
157calloc(size_t nmemb, size_t size)
158{
159 return (void *)RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, nmemb * size);
160}
161
162#endif // !_INC_MALLOC && !_INC_STDLIB
163
164
165/* Codecs */
166
167/* Uncompresses a data block */
169 IN struct _CAB_CODEC* Codec,
172 IN OUT PLONG InputLength,
173 IN OUT PLONG OutputLength);
174
175typedef struct _CAB_CODEC
176{
179 // Other CODEC-related structures
181
182
183/* RAW codec */
184
185/*
186 * FUNCTION: Uncompresses data in a buffer
187 * ARGUMENTS:
188 * OutputBuffer = Pointer to buffer to place uncompressed data
189 * InputBuffer = Pointer to buffer with data to be uncompressed
190 * InputLength = Length of input buffer before, and amount consumed after
191 * Negative to indicate that this is not the start of a new block
192 * OutputLength = Length of output buffer before, amount filled after
193 * Negative to indicate that this is not the end of the block
194 */
195ULONG
197 IN OUT PCAB_CODEC Codec,
200 IN OUT PLONG InputLength,
201 IN OUT PLONG OutputLength)
202{
203 LONG Len = min(abs(*InputLength), abs(*OutputLength));
204
206 *InputLength = *OutputLength = Len;
207
208 return CS_SUCCESS;
209}
210
212{
214};
215
216/* MSZIP codec */
217
218#define MSZIP_MAGIC 0x4B43
219
220/*
221 * FUNCTION: Uncompresses data in a buffer
222 * ARGUMENTS:
223 * OutputBuffer = Pointer to buffer to place uncompressed data
224 * InputBuffer = Pointer to buffer with data to be uncompressed
225 * InputLength = Length of input buffer before, and amount consumed after
226 * Negative to indicate that this is not the start of a new block
227 * OutputLength = Length of output buffer before, amount filled after
228 * Negative to indicate that this is not the end of the block
229 */
230ULONG
232 IN OUT PCAB_CODEC Codec,
235 IN OUT PLONG InputLength,
236 IN OUT PLONG OutputLength)
237{
238 USHORT Magic;
239 INT Status;
240
241 DPRINT("MSZipCodecUncompress(OutputBuffer = %x, InputBuffer = %x, "
242 "InputLength = %d, OutputLength = %d)\n", OutputBuffer,
243 InputBuffer, *InputLength, *OutputLength);
244
245 if (*InputLength > 0)
246 {
247 Magic = *(PUSHORT)InputBuffer;
248
249 if (Magic != MSZIP_MAGIC)
250 {
251 DPRINT("Bad MSZIP block header magic (0x%X)\n", Magic);
252 return CS_BADSTREAM;
253 }
254
255 Codec->ZStream.next_in = (PUCHAR)InputBuffer + 2;
256 Codec->ZStream.avail_in = *InputLength - 2;
257 Codec->ZStream.next_out = (PUCHAR)OutputBuffer;
258 Codec->ZStream.avail_out = abs(*OutputLength);
259
260 /* WindowBits is passed < 0 to tell that there is no zlib header.
261 * Note that in this case inflate *requires* an extra "dummy" byte
262 * after the compressed stream in order to complete decompression and
263 * return Z_STREAM_END.
264 */
265 Status = inflateInit2(&Codec->ZStream, -MAX_WBITS);
266 if (Status != Z_OK)
267 {
268 DPRINT("inflateInit2() returned (%d)\n", Status);
269 return CS_BADSTREAM;
270 }
271 Codec->ZStream.total_in = 2;
272 }
273 else
274 {
275 Codec->ZStream.avail_in = -*InputLength;
276 Codec->ZStream.next_in = (PUCHAR)InputBuffer;
277 Codec->ZStream.next_out = (PUCHAR)OutputBuffer;
278 Codec->ZStream.avail_out = abs(*OutputLength);
279 Codec->ZStream.total_in = 0;
280 }
281
282 Codec->ZStream.total_out = 0;
283 Status = inflate(&Codec->ZStream, Z_SYNC_FLUSH);
284 if (Status != Z_OK && Status != Z_STREAM_END)
285 {
286 DPRINT("inflate() returned (%d) (%s)\n", Status, Codec->ZStream.msg);
287 if (Status == Z_MEM_ERROR)
288 return CS_NOMEMORY;
289 return CS_BADSTREAM;
290 }
291
292 if (*OutputLength > 0)
293 {
294 Status = inflateEnd(&Codec->ZStream);
295 if (Status != Z_OK)
296 {
297 DPRINT("inflateEnd() returned (%d)\n", Status);
298 return CS_BADSTREAM;
299 }
300 }
301
302 *InputLength = Codec->ZStream.total_in;
303 *OutputLength = Codec->ZStream.total_out;
304
305 return CS_SUCCESS;
306}
307
309{
311};
312
313
314/* Memory functions */
315
316voidpf
318{
320}
321
322void
324{
326}
327
328static BOOL
330 LPFILETIME lpFileTime)
331{
333 LARGE_INTEGER liTime;
334
335 TimeFields.Year = lpSystemTime->wYear;
336 TimeFields.Month = lpSystemTime->wMonth;
337 TimeFields.Day = lpSystemTime->wDay;
338 TimeFields.Hour = lpSystemTime->wHour;
339 TimeFields.Minute = lpSystemTime->wMinute;
340 TimeFields.Second = lpSystemTime->wSecond;
341 TimeFields.Milliseconds = lpSystemTime->wMilliseconds;
342
343 if (RtlTimeFieldsToTime(&TimeFields, &liTime))
344 {
345 lpFileTime->dwLowDateTime = liTime.u.LowPart;
346 lpFileTime->dwHighDateTime = liTime.u.HighPart;
347 return TRUE;
348 }
349
350 return FALSE;
351}
352
353static BOOL
355 WORD wFatTime,
356 LPFILETIME lpFileTime)
357{
358 PDOSTIME pdtime = (PDOSTIME)&wFatTime;
359 PDOSDATE pddate = (PDOSDATE)&wFatDate;
360 SYSTEMTIME SystemTime;
361
362 if (lpFileTime == NULL)
363 return FALSE;
364
365 SystemTime.wMilliseconds = 0;
366 SystemTime.wSecond = pdtime->Second;
367 SystemTime.wMinute = pdtime->Minute;
368 SystemTime.wHour = pdtime->Hour;
369
370 SystemTime.wDay = pddate->Day;
371 SystemTime.wMonth = pddate->Month;
372 SystemTime.wYear = 1980 + pddate->Year;
373
374 ConvertSystemTimeToFileTime(&SystemTime, lpFileTime);
375
376 return TRUE;
377}
378
379/*
380 * FUNCTION: Returns a pointer to file name
381 * ARGUMENTS:
382 * Path = Pointer to string with pathname
383 * RETURNS:
384 * Pointer to filename
385 */
386static PWCHAR
388{
389 ULONG i, j;
390
391 j = i = 0;
392
393 while (Path[i++])
394 {
395 if (Path[i - 1] == L'\\')
396 j = i;
397 }
398
399 return Path + j;
400}
401
402/*
403 * FUNCTION: Removes a file name from a path
404 * ARGUMENTS:
405 * Path = Pointer to string with path
406 */
407static VOID
409{
411 DWORD i;
412
413 i = 0;
415
416 if (FileName != Path + i && FileName[-1] == L'\\')
417 FileName--;
418
419 if (FileName == Path + i && FileName[0] == L'\\')
420 FileName++;
421
422 FileName[0] = 0;
423}
424
425/*
426 * FUNCTION: Sets attributes on a file
427 * ARGUMENTS:
428 * File = Pointer to CFFILE node for file
429 * RETURNS:
430 * Status of operation
431 */
432static BOOL
435{
436 FILE_BASIC_INFORMATION FileBasic;
438 NTSTATUS NtStatus;
439 ULONG Attributes = 0;
440
441 if (File->Attributes & CAB_ATTRIB_READONLY)
443
444 if (File->Attributes & CAB_ATTRIB_HIDDEN)
446
447 if (File->Attributes & CAB_ATTRIB_SYSTEM)
449
450 if (File->Attributes & CAB_ATTRIB_DIRECTORY)
452
453 if (File->Attributes & CAB_ATTRIB_ARCHIVE)
455
456 NtStatus = NtQueryInformationFile(hFile,
458 &FileBasic,
461 if (!NT_SUCCESS(NtStatus))
462 {
463 DPRINT("NtQueryInformationFile() failed (%x)\n", NtStatus);
464 }
465 else
466 {
467 FileBasic.FileAttributes = Attributes;
468
469 NtStatus = NtSetInformationFile(hFile,
471 &FileBasic,
474 if (!NT_SUCCESS(NtStatus))
475 {
476 DPRINT("NtSetInformationFile() failed (%x)\n", NtStatus);
477 }
478 }
479
480 return NT_SUCCESS(NtStatus);
481}
482
483/*
484 * FUNCTION: Closes the current cabinet
485 * RETURNS:
486 * Status of operation
487 */
488static ULONG
490 IN PCABINET_CONTEXT CabinetContext)
491{
492 if (CabinetContext->FileBuffer)
493 {
494 NtUnmapViewOfSection(NtCurrentProcess(), CabinetContext->FileBuffer);
495 NtClose(CabinetContext->FileSectionHandle);
496 NtClose(CabinetContext->FileHandle);
497 CabinetContext->FileBuffer = NULL;
498 }
499
500 return 0;
501}
502
503/*
504 * FUNCTION: Initialize archiver
505 */
506VOID
508 IN OUT PCABINET_CONTEXT CabinetContext)
509{
510 RtlZeroMemory(CabinetContext, sizeof(*CabinetContext));
511
512 CabinetContext->FileOpen = FALSE;
513 wcscpy(CabinetContext->DestPath, L"");
514
515 CabinetContext->CodecSelected = FALSE;
516 CabinetSelectCodec(CabinetContext, CAB_CODEC_RAW);
517
518 CabinetContext->OverwriteHandler = NULL;
519 CabinetContext->ExtractHandler = NULL;
520 CabinetContext->DiskChangeHandler = NULL;
521
522 CabinetContext->FolderUncompSize = 0;
523 CabinetContext->BytesLeftInBlock = 0;
524 CabinetContext->CabinetReserved = 0;
525 CabinetContext->FolderReserved = 0;
526 CabinetContext->DataReserved = 0;
527 CabinetContext->CabinetReservedArea = NULL;
528 CabinetContext->LastFileOffset = 0;
529}
530
531/*
532 * FUNCTION: Cleanup archiver
533 */
534VOID
536 IN OUT PCABINET_CONTEXT CabinetContext)
537{
538 CabinetClose(CabinetContext);
539}
540
541/*
542 * FUNCTION: Normalizes a path
543 * ARGUMENTS:
544 * Path = Pointer to string with pathname
545 * Length = Number of characters in Path
546 * RETURNS:
547 * TRUE if there was enough room in Path, or FALSE
548 */
549static BOOL
552{
553 ULONG n;
554 BOOL Ok;
555
556 n = wcslen(Path);
557 Ok = (n + 1) < Length;
558
559 if (n != 0 && Path[n - 1] != L'\\' && Ok)
560 {
561 Path[n] = L'\\';
562 Path[n + 1] = 0;
563 }
564
565 return Ok;
566}
567
568/*
569 * FUNCTION: Returns pointer to cabinet file name
570 * RETURNS:
571 * Pointer to string with name of cabinet
572 */
573PCWSTR
575 IN PCABINET_CONTEXT CabinetContext)
576{
577 return CabinetContext->CabinetName;
578}
579
580/*
581 * FUNCTION: Sets cabinet file name
582 * ARGUMENTS:
583 * FileName = Pointer to string with name of cabinet
584 */
585VOID
587 IN PCABINET_CONTEXT CabinetContext,
589{
590 wcscpy(CabinetContext->CabinetName, FileName);
591}
592
593/*
594 * FUNCTION: Sets destination path
595 * ARGUMENTS:
596 * DestinationPath = Pointer to string with name of destination path
597 */
598VOID
600 IN PCABINET_CONTEXT CabinetContext,
601 IN PCWSTR DestinationPath)
602{
603 wcscpy(CabinetContext->DestPath, DestinationPath);
604
605 if (wcslen(CabinetContext->DestPath) > 0)
606 CabinetNormalizePath(CabinetContext->DestPath, MAX_PATH);
607}
608
609/*
610 * FUNCTION: Returns destination path
611 * RETURNS:
612 * Pointer to string with name of destination path
613 */
614PCWSTR
616 IN PCABINET_CONTEXT CabinetContext)
617{
618 return CabinetContext->DestPath;
619}
620
621/*
622 * FUNCTION: Opens a cabinet file
623 * RETURNS:
624 * Status of operation
625 */
626ULONG
628 IN OUT PCABINET_CONTEXT CabinetContext)
629{
632 ANSI_STRING astring;
633
637 USHORT StringLength;
638 NTSTATUS NtStatus;
639
640 if (CabinetContext->FileOpen)
641 {
642 /* Cabinet file already opened */
643 DPRINT("CabinetOpen returning SUCCESS\n");
644 return CAB_STATUS_SUCCESS;
645 }
646
647 RtlInitUnicodeString(&FileName, CabinetContext->CabinetName);
648
650 &FileName,
652 NULL, NULL);
653
654 NtStatus = NtOpenFile(&CabinetContext->FileHandle,
660
661 if (!NT_SUCCESS(NtStatus))
662 {
663 DPRINT1("Cannot open file (%S) (%x)\n", CabinetContext->CabinetName, NtStatus);
665 }
666
667 CabinetContext->FileOpen = TRUE;
668
669 NtStatus = NtCreateSection(&CabinetContext->FileSectionHandle,
671 0, 0,
674 CabinetContext->FileHandle);
675
676 if (!NT_SUCCESS(NtStatus))
677 {
678 DPRINT1("NtCreateSection failed for %ls: %x\n", CabinetContext->CabinetName, NtStatus);
679 return CAB_STATUS_NOMEMORY;
680 }
681
682 CabinetContext->FileBuffer = 0;
683 CabinetContext->FileSize = 0;
684
685 NtStatus = NtMapViewOfSection(CabinetContext->FileSectionHandle,
687 (PVOID*)&CabinetContext->FileBuffer,
688 0, 0, 0,
689 &CabinetContext->FileSize,
690 ViewUnmap,
691 0,
693
694 if (!NT_SUCCESS(NtStatus))
695 {
696 DPRINT1("NtMapViewOfSection failed: %x\n", NtStatus);
697 return CAB_STATUS_NOMEMORY;
698 }
699
700 DPRINT("Cabinet file %S opened and mapped to %x\n",
701 CabinetContext->CabinetName, CabinetContext->FileBuffer);
702 CabinetContext->PCABHeader = (PCFHEADER)CabinetContext->FileBuffer;
703
704 /* Check header */
705 if (CabinetContext->FileSize <= sizeof(CFHEADER) ||
706 CabinetContext->PCABHeader->Signature != CAB_SIGNATURE ||
707 CabinetContext->PCABHeader->Version != CAB_VERSION ||
708 CabinetContext->PCABHeader->FolderCount == 0 ||
709 CabinetContext->PCABHeader->FileCount == 0 ||
710 CabinetContext->PCABHeader->FileTableOffset < sizeof(CFHEADER))
711 {
712 CloseCabinet(CabinetContext);
713 DPRINT1("File has invalid header\n");
715 }
716
717 Buffer = (PUCHAR)(CabinetContext->PCABHeader + 1);
718
719 /* Read/skip any reserved bytes */
720 if (CabinetContext->PCABHeader->Flags & CAB_FLAG_RESERVE)
721 {
722 CabinetContext->CabinetReserved = *(PUSHORT)Buffer;
723 Buffer += 2;
724 CabinetContext->FolderReserved = *Buffer;
725 Buffer++;
726 CabinetContext->DataReserved = *Buffer;
727 Buffer++;
728
729 if (CabinetContext->CabinetReserved > 0)
730 {
731 CabinetContext->CabinetReservedArea = Buffer;
732 Buffer += CabinetContext->CabinetReserved;
733 }
734 }
735
736 if (CabinetContext->PCABHeader->Flags & CAB_FLAG_HASPREV)
737 {
738 /* The previous cabinet file is in
739 the same directory as the current */
740 wcscpy(CabinetContext->CabinetPrev, CabinetContext->CabinetName);
741 RemoveFileName(CabinetContext->CabinetPrev);
742 CabinetNormalizePath(CabinetContext->CabinetPrev, sizeof(CabinetContext->CabinetPrev));
743 RtlInitAnsiString(&astring, (LPSTR)Buffer);
744
745 /* Initialize ustring with the remaining buffer */
746 StringLength = (USHORT)wcslen(CabinetContext->CabinetPrev) * sizeof(WCHAR);
747 ustring.Buffer = CabinetContext->CabinetPrev + StringLength;
748 ustring.MaximumLength = sizeof(CabinetContext->CabinetPrev) - StringLength;
749 ustring.Length = 0;
751 Buffer += astring.Length + 1;
752
753 /* Read label of prev disk */
754 RtlInitAnsiString(&astring, (LPSTR)Buffer);
755 ustring.Length = 0;
756 ustring.Buffer = CabinetContext->DiskPrev;
757 ustring.MaximumLength = sizeof(CabinetContext->DiskPrev);
759 Buffer += astring.Length + 1;
760 }
761 else
762 {
763 wcscpy(CabinetContext->CabinetPrev, L"");
764 wcscpy(CabinetContext->DiskPrev, L"");
765 }
766
767 if (CabinetContext->PCABHeader->Flags & CAB_FLAG_HASNEXT)
768 {
769 /* The next cabinet file is in
770 the same directory as the previous */
771 wcscpy(CabinetContext->CabinetNext, CabinetContext->CabinetName);
772 RemoveFileName(CabinetContext->CabinetNext);
773 CabinetNormalizePath(CabinetContext->CabinetNext, 256);
774 RtlInitAnsiString(&astring, (LPSTR)Buffer);
775
776 /* Initialize ustring with the remaining buffer */
777 StringLength = (USHORT)wcslen(CabinetContext->CabinetNext) * sizeof(WCHAR);
778 ustring.Buffer = CabinetContext->CabinetNext + StringLength;
779 ustring.MaximumLength = sizeof(CabinetContext->CabinetNext) - StringLength;
780 ustring.Length = 0;
782 Buffer += astring.Length + 1;
783
784 /* Read label of next disk */
785 RtlInitAnsiString(&astring, (LPSTR)Buffer);
786 ustring.Length = 0;
787 ustring.Buffer = CabinetContext->DiskNext;
788 ustring.MaximumLength = sizeof(CabinetContext->DiskNext);
790 Buffer += astring.Length + 1;
791 }
792 else
793 {
794 wcscpy(CabinetContext->CabinetNext, L"");
795 wcscpy(CabinetContext->DiskNext, L"");
796 }
797 CabinetContext->CabinetFolders = (PCFFOLDER)Buffer;
798
799 DPRINT("CabinetOpen returning SUCCESS\n");
800 return CAB_STATUS_SUCCESS;
801}
802
803/*
804 * FUNCTION: Closes the cabinet file
805 */
806VOID
808 IN OUT PCABINET_CONTEXT CabinetContext)
809{
810 if (!CabinetContext->FileOpen)
811 return;
812
813 CloseCabinet(CabinetContext);
814 CabinetContext->FileOpen = FALSE;
815}
816
817/*
818 * FUNCTION: Finds the first file in the cabinet that matches a search criteria
819 * ARGUMENTS:
820 * FileName = Pointer to search criteria
821 * Search = Pointer to search structure
822 * RETURNS:
823 * Status of operation
824 */
825ULONG
827 IN PCABINET_CONTEXT CabinetContext,
829 IN OUT PCAB_SEARCH Search)
830{
831 DPRINT("CabinetFindFirst(FileName = %S)\n", FileName);
832 wcsncpy(Search->Search, FileName, MAX_PATH);
833 wcsncpy(Search->Cabinet, CabinetContext->CabinetName, MAX_PATH);
834 Search->File = 0;
835 return CabinetFindNext(CabinetContext, Search);
836}
837
838/*
839 * FUNCTION: Finds next file in the cabinet that matches a search criteria
840 * ARGUMENTS:
841 * Search = Pointer to search structure
842 * RETURNS:
843 * Status of operation
844 */
845ULONG
847 IN PCABINET_CONTEXT CabinetContext,
848 IN OUT PCAB_SEARCH Search)
849{
850 PCFFILE Prev;
854
855 if (wcscmp(Search->Cabinet, CabinetContext->CabinetName) != 0)
856 {
857 /* restart search of cabinet has changed since last find */
858 Search->File = 0;
859 }
860
861 if (!Search->File)
862 {
863 /* starting new search or cabinet */
864 Search->File = (PCFFILE)(CabinetContext->FileBuffer + CabinetContext->PCABHeader->FileTableOffset);
865 Search->Index = 0;
866 Prev = 0;
867 }
868 else
869 Prev = Search->File;
870
871 while (TRUE)
872 {
873 /* look at each file in the archive and see if we found a match */
874 if (Search->File->FolderIndex == 0xFFFD ||
875 Search->File->FolderIndex == 0xFFFF)
876 {
877 /* skip files continued from previous cab */
878 DPRINT("Skipping file (%s): FileOffset (0x%X), "
879 "LastFileOffset (0x%X)\n", (char *)(Search->File + 1),
880 Search->File->FileOffset, CabinetContext->LastFileOffset);
881 }
882 else
883 {
884 // FIXME: check for match against search criteria
885 if (Search->File != Prev)
886 {
887 if (Prev == NULL || Search->File->FolderIndex != Prev->FolderIndex)
888 {
889 Search->CFData = NULL;
890 Search->Offset = 0;
891 }
892
893 /* don't match the file we started with */
894 if (wcscmp(Search->Search, L"*") == 0)
895 {
896 /* take any file */
897 break;
898 }
899 else
900 {
901 /* otherwise, try to match the exact file name */
902 RtlInitAnsiString(&AnsiString, Search->File->FileName);
903 UnicodeString.Buffer = FileName;
904 UnicodeString.Buffer[0] = 0;
905 UnicodeString.Length = 0;
906 UnicodeString.MaximumLength = sizeof(FileName);
908 if (wcscmp(Search->Search, UnicodeString.Buffer) == 0)
909 break;
910 }
911 }
912 }
913
914 /* if we make it here we found no match, so move to the next file */
915 Search->Index++;
916 if (Search->Index >= CabinetContext->PCABHeader->FileCount)
917 {
918 /* we have reached the end of this cabinet */
919 DPRINT("End of cabinet reached\n");
920 return CAB_STATUS_NOFILE;
921 }
922 else
923 Search->File = (PCFFILE)(strchr((char *)(Search->File + 1), 0) + 1);
924 }
925
926 DPRINT("Found file %s\n", Search->File->FileName);
927 return CAB_STATUS_SUCCESS;
928}
929
930/*
931 * FUNCTION: Finds the next file in the cabinet that matches a search criteria
932 * ARGUMENTS:
933 * FileName = Pointer to search criteria
934 * Search = Pointer to search structure
935 * RETURNS:
936 * Status of operation
937 */
938ULONG
940 IN PCABINET_CONTEXT CabinetContext,
942 IN OUT PCAB_SEARCH Search)
943{
944 DPRINT("CabinetFindNextFileSequential(FileName = %S)\n", FileName);
945 wcsncpy(Search->Search, FileName, MAX_PATH);
946 return CabinetFindNext(CabinetContext, Search);
947}
948
949#if 0
950int
951Validate(VOID)
952{
953 return (int)RtlValidateHeap(ProcessHeap, 0, 0);
954}
955#endif
956
957/*
958 * FUNCTION: Extracts a file from the cabinet
959 * ARGUMENTS:
960 * Search = Pointer to PCAB_SEARCH structure used to locate the file
961 * RETURNS
962 * Status of operation
963 */
964ULONG
966 IN PCABINET_CONTEXT CabinetContext,
967 IN PCAB_SEARCH Search)
968{
969 ULONG Size; // remaining file bytes to decompress
970 ULONG CurrentOffset; // current uncompressed offset within the folder
971 PUCHAR CurrentBuffer; // current pointer to compressed data in the block
972 LONG RemainingBlock; // remaining comp data in the block
973 HANDLE DestFile;
974 HANDLE DestFileSection;
975 PVOID DestFileBuffer; // mapped view of dest file
976 PVOID CurrentDestBuffer; // pointer to the current position in the dest view
977 PCFDATA CFData; // current data block
979 FILETIME FileTime;
980 WCHAR DestName[MAX_PATH];
981 NTSTATUS NtStatus;
986 FILE_BASIC_INFORMATION FileBasic;
987 PCFFOLDER CurrentFolder;
988 LARGE_INTEGER MaxDestFileSize;
989 LONG InputLength, OutputLength;
990 SIZE_T StringLength;
991 char Chunk[512];
992
993 if (wcscmp(Search->Cabinet, CabinetContext->CabinetName) != 0)
994 {
995 /* the file is not in the current cabinet */
996 DPRINT("File is not in this cabinet (%S != %S)\n",
997 Search->Cabinet, CabinetContext->CabinetName);
998 return CAB_STATUS_NOFILE;
999 }
1000
1001 /* look up the folder that the file specifies */
1002 if (Search->File->FolderIndex == 0xFFFD ||
1003 Search->File->FolderIndex == 0xFFFF)
1004 {
1005 /* folder is continued from previous cabinet,
1006 that shouldn't happen here */
1007 return CAB_STATUS_NOFILE;
1008 }
1009 else if (Search->File->FolderIndex == 0xFFFE)
1010 {
1011 /* folder is the last in this cabinet and continues into next */
1012 CurrentFolder = &CabinetContext->CabinetFolders[CabinetContext->PCABHeader->FolderCount - 1];
1013 }
1014 else
1015 {
1016 /* folder is completely contained within this cabinet */
1017 CurrentFolder = &CabinetContext->CabinetFolders[Search->File->FolderIndex];
1018 }
1019
1020 switch (CurrentFolder->CompressionType & CAB_COMP_MASK)
1021 {
1022 case CAB_COMP_NONE:
1023 CabinetSelectCodec(CabinetContext, CAB_CODEC_RAW);
1024 break;
1025 case CAB_COMP_MSZIP:
1026 CabinetSelectCodec(CabinetContext, CAB_CODEC_MSZIP);
1027 break;
1028 default:
1029 return CAB_STATUS_UNSUPPCOMP;
1030 }
1031
1032 DPRINT("Extracting file at uncompressed offset (0x%X) Size (%d bytes)\n",
1033 (UINT)Search->File->FileOffset, (UINT)Search->File->FileSize);
1034
1035 if (CabinetContext->CreateFileHandler)
1036 {
1037 /* Call create context */
1038 CurrentDestBuffer = CabinetContext->CreateFileHandler(CabinetContext, Search->File->FileSize);
1039 if (!CurrentDestBuffer)
1040 {
1041 DPRINT1("CreateFileHandler() failed\n");
1043 }
1044 }
1045 else
1046 {
1047 RtlInitAnsiString(&AnsiString, Search->File->FileName);
1048 wcscpy(DestName, CabinetContext->DestPath);
1049 StringLength = wcslen(DestName);
1050 UnicodeString.MaximumLength = sizeof(DestName) - (USHORT)StringLength * sizeof(WCHAR);
1051 UnicodeString.Buffer = DestName + StringLength;
1052 UnicodeString.Length = 0;
1054
1055 /* Create destination file, fail if it already exists */
1057
1061 NULL, NULL);
1062
1063 NtStatus = NtCreateFile(&DestFile,
1067 NULL,
1069 0,
1072 NULL, 0);
1073
1074 if (!NT_SUCCESS(NtStatus))
1075 {
1076 DPRINT("NtCreateFile() failed (%S) (%x)\n", DestName, NtStatus);
1077
1078 /* If file exists, ask to overwrite file */
1079 if (CabinetContext->OverwriteHandler == NULL ||
1080 CabinetContext->OverwriteHandler(CabinetContext, Search->File, DestName))
1081 {
1082 /* Create destination file, overwrite if it already exists */
1083 NtStatus = NtCreateFile(&DestFile,
1087 NULL,
1089 0,
1092 NULL, 0);
1093
1094 if (!NT_SUCCESS(NtStatus))
1095 {
1096 DPRINT1("NtCreateFile() failed (%S) (%x)\n", DestName, NtStatus);
1098 }
1099 }
1100 else
1101 {
1102 DPRINT1("File (%S) exists\n", DestName);
1104 }
1105 }
1106
1107 MaxDestFileSize.QuadPart = Search->File->FileSize;
1108 NtStatus = NtCreateSection(&DestFileSection,
1110 0,
1111 &MaxDestFileSize,
1113 SEC_COMMIT,
1114 DestFile);
1115
1116 if (!NT_SUCCESS(NtStatus))
1117 {
1118 DPRINT1("NtCreateSection failed for %ls: %x\n", DestName, NtStatus);
1120 goto CloseDestFile;
1121 }
1122
1123 DestFileBuffer = 0;
1124 CabinetContext->DestFileSize = 0;
1125 NtStatus = NtMapViewOfSection(DestFileSection,
1127 &DestFileBuffer,
1128 0, 0, 0,
1129 &CabinetContext->DestFileSize,
1130 ViewUnmap,
1131 0,
1133
1134 if (!NT_SUCCESS(NtStatus))
1135 {
1136 DPRINT1("NtMapViewOfSection failed: %x\n", NtStatus);
1138 goto CloseDestFileSection;
1139 }
1140
1141 CurrentDestBuffer = DestFileBuffer;
1142 if (!ConvertDosDateTimeToFileTime(Search->File->FileDate,
1143 Search->File->FileTime,
1144 &FileTime))
1145 {
1146 DPRINT1("DosDateTimeToFileTime() failed\n");
1148 goto UnmapDestFile;
1149 }
1150
1151 NtStatus = NtQueryInformationFile(DestFile,
1153 &FileBasic,
1154 sizeof(FILE_BASIC_INFORMATION),
1156 if (!NT_SUCCESS(NtStatus))
1157 {
1158 DPRINT("NtQueryInformationFile() failed (%x)\n", NtStatus);
1159 }
1160 else
1161 {
1162 memcpy(&FileBasic.LastAccessTime, &FileTime, sizeof(FILETIME));
1163
1164 NtStatus = NtSetInformationFile(DestFile,
1166 &FileBasic,
1167 sizeof(FILE_BASIC_INFORMATION),
1169 if (!NT_SUCCESS(NtStatus))
1170 {
1171 DPRINT("NtSetInformationFile() failed (%x)\n", NtStatus);
1172 }
1173 }
1174
1175 SetAttributesOnFile(Search->File, DestFile);
1176 }
1177
1178 /* Call extract event handler */
1179 if (CabinetContext->ExtractHandler != NULL)
1180 CabinetContext->ExtractHandler(CabinetContext, Search->File, DestName);
1181
1182 if (Search->CFData)
1183 CFData = Search->CFData;
1184 else
1185 CFData = (PCFDATA)(CabinetContext->CabinetFolders[Search->File->FolderIndex].DataOffset + CabinetContext->FileBuffer);
1186
1187 CurrentOffset = Search->Offset;
1188 while (CurrentOffset + CFData->UncompSize <= Search->File->FileOffset)
1189 {
1190 /* walk the data blocks until we reach
1191 the one containing the start of the file */
1192 CurrentOffset += CFData->UncompSize;
1193 CFData = (PCFDATA)((char *)(CFData + 1) + CabinetContext->DataReserved + CFData->CompSize);
1194 }
1195
1196 Search->CFData = CFData;
1197 Search->Offset = CurrentOffset;
1198
1199 /* now decompress and discard any data in
1200 the block before the start of the file */
1201
1202 /* start of comp data */
1203 CurrentBuffer = ((unsigned char *)(CFData + 1)) + CabinetContext->DataReserved;
1204 RemainingBlock = CFData->CompSize;
1205 InputLength = RemainingBlock;
1206
1207 while (CurrentOffset < Search->File->FileOffset)
1208 {
1209 /* compute remaining uncomp bytes to start
1210 of file, bounded by size of chunk */
1211 OutputLength = Search->File->FileOffset - CurrentOffset;
1212 if (OutputLength > (LONG)sizeof(Chunk))
1213 OutputLength = sizeof(Chunk);
1214
1215 /* negate to signal NOT end of block */
1216 OutputLength = -OutputLength;
1217
1218 CabinetContext->Codec->Uncompress(CabinetContext->Codec,
1219 Chunk,
1221 &InputLength,
1222 &OutputLength);
1223
1224 /* add the uncomp bytes extracted to current folder offset */
1225 CurrentOffset += OutputLength;
1226 /* add comp bytes consumed to CurrentBuffer */
1227 CurrentBuffer += InputLength;
1228 /* subtract bytes consumed from bytes remaining in block */
1229 RemainingBlock -= InputLength;
1230 /* neg for resume decompression of the same block */
1231 InputLength = -RemainingBlock;
1232 }
1233
1234 /* now CurrentBuffer points to the first comp byte
1235 of the file, so we can begin decompressing */
1236
1237 /* Size = remaining uncomp bytes of the file to decompress */
1238 Size = Search->File->FileSize;
1239 while (Size > 0)
1240 {
1241 OutputLength = Size;
1242 DPRINT("Decompressing block at %x with RemainingBlock = %d, Size = %d\n",
1243 CurrentBuffer, RemainingBlock, Size);
1244
1245 Status = CabinetContext->Codec->Uncompress(CabinetContext->Codec,
1246 CurrentDestBuffer,
1248 &InputLength,
1249 &OutputLength);
1250 if (Status != CS_SUCCESS)
1251 {
1252 DPRINT("Cannot uncompress block\n");
1253 if (Status == CS_NOMEMORY)
1256 goto UnmapDestFile;
1257 }
1258
1259 /* advance dest buffer by bytes produced */
1260 CurrentDestBuffer = (PVOID)((ULONG_PTR)CurrentDestBuffer + OutputLength);
1261 /* advance src buffer by bytes consumed */
1262 CurrentBuffer += InputLength;
1263 /* reduce remaining file bytes by bytes produced */
1264 Size -= OutputLength;
1265 /* reduce remaining block size by bytes consumed */
1266 RemainingBlock -= InputLength;
1267 if (Size > 0 && RemainingBlock == 0)
1268 {
1269 /* used up this block, move on to the next */
1270 DPRINT("Out of block data\n");
1271 CFData = (PCFDATA)CurrentBuffer;
1272 RemainingBlock = CFData->CompSize;
1273 CurrentBuffer = (unsigned char *)(CFData + 1) + CabinetContext->DataReserved;
1274 InputLength = RemainingBlock;
1275 }
1276 }
1277
1279
1280UnmapDestFile:
1281 if (!CabinetContext->CreateFileHandler)
1282 NtUnmapViewOfSection(NtCurrentProcess(), DestFileBuffer);
1283
1284CloseDestFileSection:
1285 if (!CabinetContext->CreateFileHandler)
1286 NtClose(DestFileSection);
1287
1288CloseDestFile:
1289 if (!CabinetContext->CreateFileHandler)
1290 NtClose(DestFile);
1291
1292 return Status;
1293}
1294
1295/*
1296 * FUNCTION: Selects codec engine to use
1297 * ARGUMENTS:
1298 * Id = Codec identifier
1299 */
1300VOID
1302 IN PCABINET_CONTEXT CabinetContext,
1303 IN ULONG Id)
1304{
1305 if (CabinetContext->CodecSelected)
1306 {
1307 if (Id == CabinetContext->CodecId)
1308 return;
1309
1310 CabinetContext->CodecSelected = FALSE;
1311 }
1312
1313 switch (Id)
1314 {
1315 case CAB_CODEC_RAW:
1316 {
1317 CabinetContext->Codec = &RawCodec;
1318 break;
1319 }
1320
1321 case CAB_CODEC_MSZIP:
1322 {
1323 CabinetContext->Codec = &MSZipCodec;
1324 CabinetContext->Codec->ZStream.zalloc = MSZipAlloc;
1325 CabinetContext->Codec->ZStream.zfree = MSZipFree;
1326 CabinetContext->Codec->ZStream.opaque = (voidpf)0;
1327 break;
1328 }
1329
1330 default:
1331 return;
1332 }
1333
1334 CabinetContext->CodecId = Id;
1335 CabinetContext->CodecSelected = TRUE;
1336}
1337
1338/*
1339 * FUNCTION: Set event handlers
1340 * ARGUMENTS:
1341 * Overwrite = Handler called when a file is to be overwritten
1342 * Extract = Handler called when a file is to be extracted
1343 * DiskChange = Handler called when changing the disk
1344 */
1345VOID
1347 IN PCABINET_CONTEXT CabinetContext,
1348 IN PCABINET_OVERWRITE Overwrite,
1350 IN PCABINET_DISK_CHANGE DiskChange,
1352{
1353 CabinetContext->OverwriteHandler = Overwrite;
1354 CabinetContext->ExtractHandler = Extract;
1355 CabinetContext->DiskChangeHandler = DiskChange;
1356 CabinetContext->CreateFileHandler = CreateFile;
1357}
1358
1359/*
1360 * FUNCTION: Get pointer to cabinet reserved area. NULL if none
1361 */
1362PVOID
1364 IN PCABINET_CONTEXT CabinetContext,
1365 OUT PULONG Size)
1366{
1367 if (CabinetContext->CabinetReservedArea != NULL)
1368 {
1369 if (Size != NULL)
1370 {
1371 *Size = CabinetContext->CabinetReserved;
1372 }
1373
1374 return CabinetContext->CabinetReservedArea;
1375 }
1376 else
1377 {
1378 if (Size != NULL)
1379 {
1380 *Size = 0;
1381 }
1382
1383 return NULL;
1384 }
1385}
NTSTATUS NTAPI NtUnmapViewOfSection(IN HANDLE ProcessHandle, IN PVOID BaseAddress)
Definition: section.c:3848
NTSTATUS NTAPI NtCreateSection(OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN PLARGE_INTEGER MaximumSize OPTIONAL, IN ULONG SectionPageProtection OPTIONAL, IN ULONG AllocationAttributes, IN HANDLE FileHandle OPTIONAL)
Definition: section.c:3441
NTSTATUS NTAPI NtMapViewOfSection(IN HANDLE SectionHandle, IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, IN OUT PSIZE_T ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect)
Definition: section.c:3622
static ACPI_BUFFER CurrentBuffer
DWORD Id
PRTL_UNICODE_STRING_BUFFER Path
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define __cdecl
Definition: accygwin.h:79
LONG NTSTATUS
Definition: precomp.h:26
HANDLE ProcessHeap
Definition: servman.c:15
#define DPRINT1
Definition: precomp.h:8
#define CAB_STATUS_NOFILE
Definition: cabinet.h:32
#define CAB_STATUS_CANNOT_OPEN
Definition: cabinet.h:26
#define CAB_CODEC_MSZIP
Definition: cabinet.h:48
#define CAB_STATUS_UNSUPPCOMP
Definition: cabinet.h:33
#define CAB_STATUS_FILE_EXISTS
Definition: cabinet.h:30
VOID(* PCABINET_DISK_CHANGE)(IN struct _CABINET_CONTEXT *CabinetContext, IN PCWSTR CabinetName, IN PCWSTR DiskLabel)
Definition: cabinet.h:63
#define CS_NOMEMORY
Definition: cabinet.h:42
#define CS_SUCCESS
Definition: cabinet.h:41
VOID(* PCABINET_EXTRACT)(IN struct _CABINET_CONTEXT *CabinetContext, IN PCFFILE File, IN PCWSTR FileName)
Definition: cabinet.h:58
#define CAB_STATUS_NOMEMORY
Definition: cabinet.h:25
#define CAB_CODEC_RAW
Definition: cabinet.h:46
#define CAB_STATUS_CANNOT_CREATE
Definition: cabinet.h:27
#define CAB_STATUS_SUCCESS
Definition: cabinet.h:23
#define CAB_STATUS_CANNOT_WRITE
Definition: cabinet.h:29
#define CS_BADSTREAM
Definition: cabinet.h:43
BOOL(* PCABINET_OVERWRITE)(IN struct _CABINET_CONTEXT *CabinetContext, IN PCFFILE File, IN PCWSTR FileName)
Definition: cabinet.h:53
PVOID(* PCABINET_CREATE_FILE)(IN struct _CABINET_CONTEXT *CabinetContext, IN ULONG FileSize)
Definition: cabinet.h:68
#define CAB_STATUS_INVALID_CAB
Definition: cabinet.h:31
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
static BOOL SetAttributesOnFile(PCFFILE File, HANDLE hFile)
Definition: cabinet.c:433
struct _DOSTIME * PDOSTIME
ULONG CabinetOpen(IN OUT PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:627
struct _CFFOLDER * PCFFOLDER
static BOOL ConvertDosDateTimeToFileTime(WORD wFatDate, WORD wFatTime, LPFILETIME lpFileTime)
Definition: cabinet.c:354
struct _CFHEADER CFHEADER
struct _CFDATA * PCFDATA
ULONG RawCodecUncompress(IN OUT PCAB_CODEC Codec, OUT PVOID OutputBuffer, IN PVOID InputBuffer, IN OUT PLONG InputLength, IN OUT PLONG OutputLength)
Definition: cabinet.c:196
#define CAB_ATTRIB_HIDDEN
Definition: cabinet.c:64
PCWSTR CabinetGetDestinationPath(IN PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:615
voidpf MSZipAlloc(voidpf opaque, uInt items, uInt size)
Definition: cabinet.c:317
#define CAB_ATTRIB_READONLY
Definition: cabinet.c:63
#define CAB_ATTRIB_DIRECTORY
Definition: cabinet.c:67
static BOOL ConvertSystemTimeToFileTime(CONST SYSTEMTIME *lpSystemTime, LPFILETIME lpFileTime)
Definition: cabinet.c:329
struct _CAB_CODEC CAB_CODEC
#define CAB_COMP_MASK
Definition: cabinet.c:53
ULONG CabinetFindFirst(IN PCABINET_CONTEXT CabinetContext, IN PCWSTR FileName, IN OUT PCAB_SEARCH Search)
Definition: cabinet.c:826
ULONG(* PCABINET_CODEC_UNCOMPRESS)(IN struct _CAB_CODEC *Codec, OUT PVOID OutputBuffer, IN PVOID InputBuffer, IN OUT PLONG InputLength, IN OUT PLONG OutputLength)
Definition: cabinet.c:168
#define CAB_VERSION
Definition: cabinet.c:50
struct _CFFOLDER CFFOLDER
struct _CFDATA CFDATA
static CAB_CODEC RawCodec
Definition: cabinet.c:211
#define MSZIP_MAGIC
Definition: cabinet.c:218
VOID CabinetClose(IN OUT PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:807
#define CAB_ATTRIB_SYSTEM
Definition: cabinet.c:65
ULONG CabinetFindNext(IN PCABINET_CONTEXT CabinetContext, IN OUT PCAB_SEARCH Search)
Definition: cabinet.c:846
#define CAB_SIGNATURE
Definition: cabinet.c:49
void MSZipFree(voidpf opaque, voidpf address)
Definition: cabinet.c:323
struct _DOSDATE * PDOSDATE
static PWCHAR GetFileName(PWCHAR Path)
Definition: cabinet.c:387
struct _DOSTIME DOSTIME
#define CAB_COMP_NONE
Definition: cabinet.c:54
static BOOL CabinetNormalizePath(PWCHAR Path, ULONG Length)
Definition: cabinet.c:550
PCWSTR CabinetGetCabinetName(IN PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:574
VOID CabinetSelectCodec(IN PCABINET_CONTEXT CabinetContext, IN ULONG Id)
Definition: cabinet.c:1301
ULONG MSZipCodecUncompress(IN OUT PCAB_CODEC Codec, OUT PVOID OutputBuffer, IN PVOID InputBuffer, IN OUT PLONG InputLength, IN OUT PLONG OutputLength)
Definition: cabinet.c:231
PVOID CabinetGetCabinetReservedArea(IN PCABINET_CONTEXT CabinetContext, OUT PULONG Size)
Definition: cabinet.c:1363
#define CAB_FLAG_HASNEXT
Definition: cabinet.c:60
struct _CAB_CODEC * PCAB_CODEC
ULONG CabinetExtractFile(IN PCABINET_CONTEXT CabinetContext, IN PCAB_SEARCH Search)
Definition: cabinet.c:965
#define CAB_FLAG_RESERVE
Definition: cabinet.c:61
#define CAB_ATTRIB_ARCHIVE
Definition: cabinet.c:68
static CAB_CODEC MSZipCodec
Definition: cabinet.c:308
#define CAB_FLAG_HASPREV
Definition: cabinet.c:59
struct _CFHEADER * PCFHEADER
struct _CFFILE CFFILE
#define CAB_COMP_MSZIP
Definition: cabinet.c:55
struct _DOSDATE DOSDATE
struct _CFFILE * PCFFILE
static VOID RemoveFileName(PWCHAR Path)
Definition: cabinet.c:408
VOID CabinetSetEventHandlers(IN PCABINET_CONTEXT CabinetContext, IN PCABINET_OVERWRITE Overwrite, IN PCABINET_EXTRACT Extract, IN PCABINET_DISK_CHANGE DiskChange, IN PCABINET_CREATE_FILE CreateFile)
Definition: cabinet.c:1346
VOID CabinetInitialize(IN OUT PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:507
static ULONG CloseCabinet(IN PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:489
VOID CabinetCleanup(IN OUT PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:535
VOID CabinetSetCabinetName(IN PCABINET_CONTEXT CabinetContext, IN PCWSTR FileName)
Definition: cabinet.c:586
VOID CabinetSetDestinationPath(IN PCABINET_CONTEXT CabinetContext, IN PCWSTR DestinationPath)
Definition: cabinet.c:599
ULONG CabinetFindNextFileSequential(IN PCABINET_CONTEXT CabinetContext, IN PCWSTR FileName, IN OUT PCAB_SEARCH Search)
Definition: cabinet.c:939
HRESULT WINAPI Extract(SESSION *dest, LPCSTR szCabName)
Definition: cabinet_main.c:328
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
Definition: bufpool.h:45
Definition: File.h:16
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define Len
Definition: deflate.h:82
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define PAGE_READONLY
Definition: compat.h:138
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define FILE_SHARE_READ
Definition: compat.h:136
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
int inflate(z_streamp strm, int flush)
Definition: inflate.c:1257
int inflateEnd(z_streamp strm)
Definition: inflate.c:1910
void FAR * voidpf
Definition: zlib.h:42
#define Z_STREAM_END
Definition: zlib.h:115
unsigned int uInt
Definition: zlib.h:38
#define Z_OK
Definition: zlib.h:114
#define Z_SYNC_FLUSH
Definition: zlib.h:107
#define MAX_WBITS
Definition: zlib.h:151
#define Z_MEM_ERROR
Definition: zlib.h:120
@ AnsiString
Definition: dnslib.h:19
BOOLEAN RtlTimeFieldsToTime(IN PTIME_FIELDS TimeFields, IN PLARGE_INTEGER Time)
#define abs(i)
Definition: fconv.c:206
struct _FileName FileName
Definition: fatprocs.h:896
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
@ FileBasicInformation
Definition: from_kernel.h:65
#define FILE_CREATE
Definition: from_kernel.h:55
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
#define FILE_OVERWRITE
Definition: from_kernel.h:57
#define FILE_SYNCHRONOUS_IO_ALERT
Definition: from_kernel.h:30
Status
Definition: gdiplustypes.h:25
@ Ok
Definition: gdiplustypes.h:26
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLuint address
Definition: glext.h:9393
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI BOOLEAN WINAPI RtlValidateHeap(HANDLE, ULONG, LPCVOID)
if(dx< 0)
Definition: linetemp.h:194
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static PVOID ptr
Definition: dispmode.c:27
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
static PTIME_FIELDS TimeFields
Definition: time.c:104
#define min(a, b)
Definition: monoChain.cc:55
_In_ HANDLE hFile
Definition: mswsock.h:90
unsigned int UINT
Definition: ndis.h:50
#define SEC_COMMIT
Definition: mmtypes.h:100
NTSYSAPI NTSTATUS NTAPI NtOpenFile(OUT PHANDLE phFile, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG ShareMode, IN ULONG OpenMode)
Definition: file.c:3952
#define SYNCHRONIZE
Definition: nt_native.h:61
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define SECTION_ALL_ACCESS
Definition: nt_native.h:1293
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define NtCurrentProcess()
Definition: nt_native.h:1657
NTSYSAPI NTSTATUS NTAPI NtSetInformationFile(IN HANDLE hFile, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass)
Definition: iofunc.c:3096
NTSYSAPI NTSTATUS NTAPI NtQueryInformationFile(IN HANDLE hFile, OUT PIO_STATUS_BLOCK pIoStatusBlock, OUT PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass)
@ ViewUnmap
Definition: nt_native.h:1279
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define FILE_ATTRIBUTE_ARCHIVE
Definition: nt_native.h:706
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
NTSTATUS NTAPI NtCreateFile(OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength)
#define GENERIC_WRITE
Definition: nt_native.h:90
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define L(x)
Definition: ntvdm.h:50
static TCHAR * items[]
Definition: page1.c:45
#define CONST
Definition: pedump.c:81
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define calloc
Definition: rosglue.h:14
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
_CRTIMP wchar_t *__cdecl wcsncpy(wchar_t *_Dest, const wchar_t *_Source, size_t _Count)
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define inflateInit2(strm, windowBits)
Definition: zlib.h:1817
#define DPRINT
Definition: sndvol32.h:71
Definition: fci.c:65
PCABINET_CODEC_UNCOMPRESS Uncompress
Definition: cabinet.c:177
z_stream ZStream
Definition: cabinet.c:178
USHORT CompSize
Definition: cabinet.c:131
USHORT UncompSize
Definition: cabinet.c:132
ULONG Checksum
Definition: cabinet.c:130
USHORT FolderIndex
Definition: cabinet.c:120
ULONG FileSize
Definition: cabinet.c:118
USHORT FileTime
Definition: cabinet.c:122
ULONG FileOffset
Definition: cabinet.c:119
USHORT FileDate
Definition: cabinet.c:121
USHORT Attributes
Definition: cabinet.c:123
USHORT DataBlockCount
Definition: cabinet.c:109
USHORT CompressionType
Definition: cabinet.c:110
ULONG DataOffset
Definition: cabinet.c:108
USHORT Version
Definition: cabinet.c:88
USHORT SetID
Definition: cabinet.c:92
ULONG Reserved3
Definition: cabinet.c:87
ULONG Reserved1
Definition: cabinet.c:83
ULONG CabinetSize
Definition: cabinet.c:84
ULONG FileTableOffset
Definition: cabinet.c:86
USHORT FileCount
Definition: cabinet.c:90
USHORT FolderCount
Definition: cabinet.c:89
USHORT Flags
Definition: cabinet.c:91
USHORT CabinetNumber
Definition: cabinet.c:93
ULONG Signature
Definition: cabinet.c:82
ULONG Reserved2
Definition: cabinet.c:85
WORD Month
Definition: cabinet.c:42
WORD Year
Definition: cabinet.c:43
WORD Day
Definition: cabinet.c:41
WORD Second
Definition: cabinet.c:34
WORD Minute
Definition: cabinet.c:35
WORD Hour
Definition: cabinet.c:36
DWORD dwHighDateTime
Definition: mapidefs.h:66
DWORD dwLowDateTime
Definition: mapidefs.h:65
LARGE_INTEGER LastAccessTime
Definition: nt_native.h:940
WORD wYear
Definition: winbase.h:905
WORD wMilliseconds
Definition: winbase.h:912
WORD wMonth
Definition: winbase.h:906
WORD wHour
Definition: winbase.h:909
WORD wSecond
Definition: winbase.h:911
WORD wMinute
Definition: winbase.h:910
WORD wDay
Definition: winbase.h:908
USHORT Milliseconds
Definition: env_spec_w32.h:717
Definition: config.c:19
DWORD Length
Definition: config.c:20
DWORD MaximumLength
Definition: config.c:21
unsigned char * Buffer
Definition: config.c:22
alloc_func zalloc
Definition: zlib.h:70
uint32_t * PULONG
Definition: typedefs.h:59
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define ANYSIZE_ARRAY
Definition: typedefs.h:46
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
uint16_t * PUSHORT
Definition: typedefs.h:56
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
uint16_t * PWCHAR
Definition: typedefs.h:56
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
LONGLONG QuadPart
Definition: typedefs.h:114
struct _LARGE_INTEGER::@2295 u
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:863
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:953
#define CreateFile
Definition: winbase.h:3749
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175