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