ReactOS  0.4.15-dev-1070-ge1a01de
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 
30 typedef struct _DOSTIME
31 {
35 } DOSTIME, *PDOSTIME;
36 
37 typedef struct _DOSDATE
38 {
39  WORD Day:5;
42 } DOSDATE, *PDOSDATE;
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 
78 typedef 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  */
102 } CFHEADER, *PCFHEADER;
103 
104 typedef 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  */
112 } CFFOLDER, *PCFFOLDER;
113 
114 typedef 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 */
124 } CFFILE, *PCFFILE;
125 
126 typedef 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  */
134 } CFDATA, *PCFDATA;
135 
136 
137 /* FUNCTIONS ****************************************************************/
138 
139 /* Needed by zlib, but we don't want the dependency on the CRT */
140 void *__cdecl
141 malloc(size_t size)
142 {
144 }
145 
146 void __cdecl
147 free(void *ptr)
148 {
150 }
151 
152 void *__cdecl
153 calloc(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 
169 typedef 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  */
189 ULONG
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 {
207  RawCodecUncompress, {0}
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  */
224 ULONG
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 
310 voidpf
312 {
314 }
315 
316 void
318 {
320 }
321 
322 static 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 
347 static 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  */
380 static 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  */
401 static VOID
403 {
405  DWORD i;
406 
407  i = 0;
408  FileName = GetFileName(Path + i);
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  */
426 static BOOL
428  HANDLE hFile)
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,
451  &IoStatusBlock,
452  &FileBasic,
453  sizeof(FILE_BASIC_INFORMATION),
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,
464  &IoStatusBlock,
465  &FileBasic,
466  sizeof(FILE_BASIC_INFORMATION),
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  */
482 static 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  */
500 VOID
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  */
528 VOID
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  */
543 static BOOL
545  ULONG Length)
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  */
567 PCWSTR
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  */
579 VOID
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  */
592 VOID
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  */
608 PCWSTR
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  */
620 ULONG
622  IN OUT PCABINET_CONTEXT CabinetContext)
623 {
624  PUCHAR Buffer;
626  ANSI_STRING astring;
627 
631  NTSTATUS NtStatus;
632 
633  if (CabinetContext->FileOpen)
634  {
635  /* Cabinet file already opened */
636  DPRINT("CabinetOpen returning SUCCESS\n");
637  return CAB_STATUS_SUCCESS;
638  }
639 
640  RtlInitUnicodeString(&FileName, CabinetContext->CabinetName);
641 
643  &FileName,
645  NULL, NULL);
646 
647  NtStatus = NtOpenFile(&CabinetContext->FileHandle,
650  &IoStatusBlock,
653 
654  if (!NT_SUCCESS(NtStatus))
655  {
656  DPRINT1("Cannot open file (%S) (%x)\n", CabinetContext->CabinetName, NtStatus);
657  return CAB_STATUS_CANNOT_OPEN;
658  }
659 
660  CabinetContext->FileOpen = TRUE;
661 
662  NtStatus = NtCreateSection(&CabinetContext->FileSectionHandle,
664  0, 0,
666  SEC_COMMIT,
667  CabinetContext->FileHandle);
668 
669  if (!NT_SUCCESS(NtStatus))
670  {
671  DPRINT1("NtCreateSection failed for %ls: %x\n", CabinetContext->CabinetName, NtStatus);
672  return CAB_STATUS_NOMEMORY;
673  }
674 
675  CabinetContext->FileBuffer = 0;
676  CabinetContext->FileSize = 0;
677 
678  NtStatus = NtMapViewOfSection(CabinetContext->FileSectionHandle,
680  (PVOID*)&CabinetContext->FileBuffer,
681  0, 0, 0,
682  &CabinetContext->FileSize,
683  ViewUnmap,
684  0,
685  PAGE_READONLY);
686 
687  if (!NT_SUCCESS(NtStatus))
688  {
689  DPRINT1("NtMapViewOfSection failed: %x\n", NtStatus);
690  return CAB_STATUS_NOMEMORY;
691  }
692 
693  DPRINT("Cabinet file %S opened and mapped to %x\n",
694  CabinetContext->CabinetName, CabinetContext->FileBuffer);
695  CabinetContext->PCABHeader = (PCFHEADER)CabinetContext->FileBuffer;
696 
697  /* Check header */
698  if (CabinetContext->FileSize <= sizeof(CFHEADER) ||
699  CabinetContext->PCABHeader->Signature != CAB_SIGNATURE ||
700  CabinetContext->PCABHeader->Version != CAB_VERSION ||
701  CabinetContext->PCABHeader->FolderCount == 0 ||
702  CabinetContext->PCABHeader->FileCount == 0 ||
703  CabinetContext->PCABHeader->FileTableOffset < sizeof(CFHEADER))
704  {
705  CloseCabinet(CabinetContext);
706  DPRINT1("File has invalid header\n");
707  return CAB_STATUS_INVALID_CAB;
708  }
709 
710  Buffer = (PUCHAR)(CabinetContext->PCABHeader + 1);
711 
712  /* Read/skip any reserved bytes */
713  if (CabinetContext->PCABHeader->Flags & CAB_FLAG_RESERVE)
714  {
715  CabinetContext->CabinetReserved = *(PUSHORT)Buffer;
716  Buffer += 2;
717  CabinetContext->FolderReserved = *Buffer;
718  Buffer++;
719  CabinetContext->DataReserved = *Buffer;
720  Buffer++;
721 
722  if (CabinetContext->CabinetReserved > 0)
723  {
724  CabinetContext->CabinetReservedArea = Buffer;
725  Buffer += CabinetContext->CabinetReserved;
726  }
727  }
728 
729  if (CabinetContext->PCABHeader->Flags & CAB_FLAG_HASPREV)
730  {
731  /* The previous cabinet file is in
732  the same directory as the current */
733  wcscpy(CabinetContext->CabinetPrev, CabinetContext->CabinetName);
734  RemoveFileName(CabinetContext->CabinetPrev);
735  CabinetNormalizePath(CabinetContext->CabinetPrev, 256);
736  RtlInitAnsiString(&astring, (LPSTR)Buffer);
737  ustring.Length = wcslen(CabinetContext->CabinetPrev);
738  ustring.Buffer = CabinetContext->CabinetPrev + ustring.Length;
739  ustring.MaximumLength = sizeof(CabinetContext->CabinetPrev) - ustring.Length;
741  Buffer += astring.Length + 1;
742 
743  /* Read label of prev disk */
744  RtlInitAnsiString(&astring, (LPSTR)Buffer);
745  ustring.Length = 0;
746  ustring.Buffer = CabinetContext->DiskPrev;
747  ustring.MaximumLength = sizeof(CabinetContext->DiskPrev);
749  Buffer += astring.Length + 1;
750  }
751  else
752  {
753  wcscpy(CabinetContext->CabinetPrev, L"");
754  wcscpy(CabinetContext->DiskPrev, L"");
755  }
756 
757  if (CabinetContext->PCABHeader->Flags & CAB_FLAG_HASNEXT)
758  {
759  /* The next cabinet file is in
760  the same directory as the previous */
761  wcscpy(CabinetContext->CabinetNext, CabinetContext->CabinetName);
762  RemoveFileName(CabinetContext->CabinetNext);
763  CabinetNormalizePath(CabinetContext->CabinetNext, 256);
764  RtlInitAnsiString(&astring, (LPSTR)Buffer);
765  ustring.Length = wcslen(CabinetContext->CabinetNext);
766  ustring.Buffer = CabinetContext->CabinetNext + ustring.Length;
767  ustring.MaximumLength = sizeof(CabinetContext->CabinetNext) - ustring.Length;
769  Buffer += astring.Length + 1;
770 
771  /* Read label of next disk */
772  RtlInitAnsiString(&astring, (LPSTR)Buffer);
773  ustring.Length = 0;
774  ustring.Buffer = CabinetContext->DiskNext;
775  ustring.MaximumLength = sizeof(CabinetContext->DiskNext);
777  Buffer += astring.Length + 1;
778  }
779  else
780  {
781  wcscpy(CabinetContext->CabinetNext, L"");
782  wcscpy(CabinetContext->DiskNext, L"");
783  }
784  CabinetContext->CabinetFolders = (PCFFOLDER)Buffer;
785 
786  DPRINT("CabinetOpen returning SUCCESS\n");
787  return CAB_STATUS_SUCCESS;
788 }
789 
790 /*
791  * FUNCTION: Closes the cabinet file
792  */
793 VOID
795  IN OUT PCABINET_CONTEXT CabinetContext)
796 {
797  if (!CabinetContext->FileOpen)
798  return;
799 
800  CloseCabinet(CabinetContext);
801  CabinetContext->FileOpen = FALSE;
802 }
803 
804 /*
805  * FUNCTION: Finds the first file in the cabinet that matches a search criteria
806  * ARGUMENTS:
807  * FileName = Pointer to search criteria
808  * Search = Pointer to search structure
809  * RETURNS:
810  * Status of operation
811  */
812 ULONG
814  IN PCABINET_CONTEXT CabinetContext,
816  IN OUT PCAB_SEARCH Search)
817 {
818  DPRINT("CabinetFindFirst(FileName = %S)\n", FileName);
819  wcsncpy(Search->Search, FileName, MAX_PATH);
820  wcsncpy(Search->Cabinet, CabinetContext->CabinetName, MAX_PATH);
821  Search->File = 0;
822  return CabinetFindNext(CabinetContext, Search);
823 }
824 
825 /*
826  * FUNCTION: Finds next file in the cabinet that matches a search criteria
827  * ARGUMENTS:
828  * Search = Pointer to search structure
829  * RETURNS:
830  * Status of operation
831  */
832 ULONG
834  IN PCABINET_CONTEXT CabinetContext,
835  IN OUT PCAB_SEARCH Search)
836 {
837  PCFFILE Prev;
841 
842  if (wcscmp(Search->Cabinet, CabinetContext->CabinetName) != 0)
843  {
844  /* restart search of cabinet has changed since last find */
845  Search->File = 0;
846  }
847 
848  if (!Search->File)
849  {
850  /* starting new search or cabinet */
851  Search->File = (PCFFILE)(CabinetContext->FileBuffer + CabinetContext->PCABHeader->FileTableOffset);
852  Search->Index = 0;
853  Prev = 0;
854  }
855  else
856  Prev = Search->File;
857 
858  while (TRUE)
859  {
860  /* look at each file in the archive and see if we found a match */
861  if (Search->File->FolderIndex == 0xFFFD ||
862  Search->File->FolderIndex == 0xFFFF)
863  {
864  /* skip files continued from previous cab */
865  DPRINT("Skipping file (%s): FileOffset (0x%X), "
866  "LastFileOffset (0x%X)\n", (char *)(Search->File + 1),
867  Search->File->FileOffset, CabinetContext->LastFileOffset);
868  }
869  else
870  {
871  // FIXME: check for match against search criteria
872  if (Search->File != Prev)
873  {
874  if (Prev == NULL || Search->File->FolderIndex != Prev->FolderIndex)
875  {
876  Search->CFData = NULL;
877  Search->Offset = 0;
878  }
879 
880  /* don't match the file we started with */
881  if (wcscmp(Search->Search, L"*") == 0)
882  {
883  /* take any file */
884  break;
885  }
886  else
887  {
888  /* otherwise, try to match the exact file name */
889  RtlInitAnsiString(&AnsiString, Search->File->FileName);
890  UnicodeString.Buffer = FileName;
891  UnicodeString.Buffer[0] = 0;
892  UnicodeString.Length = 0;
893  UnicodeString.MaximumLength = sizeof(FileName);
895  if (wcscmp(Search->Search, UnicodeString.Buffer) == 0)
896  break;
897  }
898  }
899  }
900 
901  /* if we make it here we found no match, so move to the next file */
902  Search->Index++;
903  if (Search->Index >= CabinetContext->PCABHeader->FileCount)
904  {
905  /* we have reached the end of this cabinet */
906  DPRINT("End of cabinet reached\n");
907  return CAB_STATUS_NOFILE;
908  }
909  else
910  Search->File = (PCFFILE)(strchr((char *)(Search->File + 1), 0) + 1);
911  }
912 
913  DPRINT("Found file %s\n", Search->File->FileName);
914  return CAB_STATUS_SUCCESS;
915 }
916 
917 /*
918  * FUNCTION: Finds the next file in the cabinet that matches a search criteria
919  * ARGUMENTS:
920  * FileName = Pointer to search criteria
921  * Search = Pointer to search structure
922  * RETURNS:
923  * Status of operation
924  */
925 ULONG
927  IN PCABINET_CONTEXT CabinetContext,
929  IN OUT PCAB_SEARCH Search)
930 {
931  DPRINT("CabinetFindNextFileSequential(FileName = %S)\n", FileName);
932  wcsncpy(Search->Search, FileName, MAX_PATH);
933  return CabinetFindNext(CabinetContext, Search);
934 }
935 
936 #if 0
937 int
938 Validate(VOID)
939 {
940  return (int)RtlValidateHeap(ProcessHeap, 0, 0);
941 }
942 #endif
943 
944 /*
945  * FUNCTION: Extracts a file from the cabinet
946  * ARGUMENTS:
947  * Search = Pointer to PCAB_SEARCH structure used to locate the file
948  * RETURNS
949  * Status of operation
950  */
951 ULONG
953  IN PCABINET_CONTEXT CabinetContext,
954  IN PCAB_SEARCH Search)
955 {
956  ULONG Size; // remaining file bytes to decompress
957  ULONG CurrentOffset; // current uncompressed offset within the folder
958  PUCHAR CurrentBuffer; // current pointer to compressed data in the block
959  LONG RemainingBlock; // remaining comp data in the block
960  HANDLE DestFile;
961  HANDLE DestFileSection;
962  PVOID DestFileBuffer; // mapped view of dest file
963  PVOID CurrentDestBuffer; // pointer to the current position in the dest view
964  PCFDATA CFData; // current data block
965  ULONG Status;
966  FILETIME FileTime;
967  WCHAR DestName[MAX_PATH];
968  NTSTATUS NtStatus;
973  FILE_BASIC_INFORMATION FileBasic;
974  PCFFOLDER CurrentFolder;
975  LARGE_INTEGER MaxDestFileSize;
976  LONG InputLength, OutputLength;
977  char Chunk[512];
978 
979  if (wcscmp(Search->Cabinet, CabinetContext->CabinetName) != 0)
980  {
981  /* the file is not in the current cabinet */
982  DPRINT("File is not in this cabinet (%S != %S)\n",
983  Search->Cabinet, CabinetContext->CabinetName);
984  return CAB_STATUS_NOFILE;
985  }
986 
987  /* look up the folder that the file specifies */
988  if (Search->File->FolderIndex == 0xFFFD ||
989  Search->File->FolderIndex == 0xFFFF)
990  {
991  /* folder is continued from previous cabinet,
992  that shouldn't happen here */
993  return CAB_STATUS_NOFILE;
994  }
995  else if (Search->File->FolderIndex == 0xFFFE)
996  {
997  /* folder is the last in this cabinet and continues into next */
998  CurrentFolder = &CabinetContext->CabinetFolders[CabinetContext->PCABHeader->FolderCount - 1];
999  }
1000  else
1001  {
1002  /* folder is completely contained within this cabinet */
1003  CurrentFolder = &CabinetContext->CabinetFolders[Search->File->FolderIndex];
1004  }
1005 
1006  switch (CurrentFolder->CompressionType & CAB_COMP_MASK)
1007  {
1008  case CAB_COMP_NONE:
1009  CabinetSelectCodec(CabinetContext, CAB_CODEC_RAW);
1010  break;
1011  case CAB_COMP_MSZIP:
1012  CabinetSelectCodec(CabinetContext, CAB_CODEC_MSZIP);
1013  break;
1014  default:
1015  return CAB_STATUS_UNSUPPCOMP;
1016  }
1017 
1018  DPRINT("Extracting file at uncompressed offset (0x%X) Size (%d bytes)\n",
1019  (UINT)Search->File->FileOffset, (UINT)Search->File->FileSize);
1020 
1021  if (CabinetContext->CreateFileHandler)
1022  {
1023  /* Call create context */
1024  CurrentDestBuffer = CabinetContext->CreateFileHandler(CabinetContext, Search->File->FileSize);
1025  if (!CurrentDestBuffer)
1026  {
1027  DPRINT1("CreateFileHandler() failed\n");
1028  return CAB_STATUS_CANNOT_CREATE;
1029  }
1030  }
1031  else
1032  {
1033  RtlInitAnsiString(&AnsiString, Search->File->FileName);
1034  wcscpy(DestName, CabinetContext->DestPath);
1035  UnicodeString.MaximumLength = sizeof(DestName) - wcslen(DestName) * sizeof(WCHAR);
1036  UnicodeString.Buffer = DestName + wcslen(DestName);
1037  UnicodeString.Length = 0;
1039 
1040  /* Create destination file, fail if it already exists */
1041  RtlInitUnicodeString(&UnicodeString, DestName);
1042 
1044  &UnicodeString,
1046  NULL, NULL);
1047 
1048  NtStatus = NtCreateFile(&DestFile,
1051  &IoStatusBlock,
1052  NULL,
1054  0,
1055  FILE_CREATE,
1057  NULL, 0);
1058 
1059  if (!NT_SUCCESS(NtStatus))
1060  {
1061  DPRINT("NtCreateFile() failed (%S) (%x)\n", DestName, NtStatus);
1062 
1063  /* If file exists, ask to overwrite file */
1064  if (CabinetContext->OverwriteHandler == NULL ||
1065  CabinetContext->OverwriteHandler(CabinetContext, Search->File, DestName))
1066  {
1067  /* Create destination file, overwrite if it already exists */
1068  NtStatus = NtCreateFile(&DestFile,
1071  &IoStatusBlock,
1072  NULL,
1074  0,
1077  NULL, 0);
1078 
1079  if (!NT_SUCCESS(NtStatus))
1080  {
1081  DPRINT1("NtCreateFile() failed (%S) (%x)\n", DestName, NtStatus);
1082  return CAB_STATUS_CANNOT_CREATE;
1083  }
1084  }
1085  else
1086  {
1087  DPRINT1("File (%S) exists\n", DestName);
1088  return CAB_STATUS_FILE_EXISTS;
1089  }
1090  }
1091 
1092  MaxDestFileSize.QuadPart = Search->File->FileSize;
1093  NtStatus = NtCreateSection(&DestFileSection,
1095  0,
1096  &MaxDestFileSize,
1098  SEC_COMMIT,
1099  DestFile);
1100 
1101  if (!NT_SUCCESS(NtStatus))
1102  {
1103  DPRINT1("NtCreateSection failed for %ls: %x\n", DestName, NtStatus);
1105  goto CloseDestFile;
1106  }
1107 
1108  DestFileBuffer = 0;
1109  CabinetContext->DestFileSize = 0;
1110  NtStatus = NtMapViewOfSection(DestFileSection,
1111  NtCurrentProcess(),
1112  &DestFileBuffer,
1113  0, 0, 0,
1114  &CabinetContext->DestFileSize,
1115  ViewUnmap,
1116  0,
1117  PAGE_READWRITE);
1118 
1119  if (!NT_SUCCESS(NtStatus))
1120  {
1121  DPRINT1("NtMapViewOfSection failed: %x\n", NtStatus);
1123  goto CloseDestFileSection;
1124  }
1125 
1126  CurrentDestBuffer = DestFileBuffer;
1127  if (!ConvertDosDateTimeToFileTime(Search->File->FileDate,
1128  Search->File->FileTime,
1129  &FileTime))
1130  {
1131  DPRINT1("DosDateTimeToFileTime() failed\n");
1133  goto UnmapDestFile;
1134  }
1135 
1136  NtStatus = NtQueryInformationFile(DestFile,
1137  &IoStatusBlock,
1138  &FileBasic,
1139  sizeof(FILE_BASIC_INFORMATION),
1141  if (!NT_SUCCESS(NtStatus))
1142  {
1143  DPRINT("NtQueryInformationFile() failed (%x)\n", NtStatus);
1144  }
1145  else
1146  {
1147  memcpy(&FileBasic.LastAccessTime, &FileTime, sizeof(FILETIME));
1148 
1149  NtStatus = NtSetInformationFile(DestFile,
1150  &IoStatusBlock,
1151  &FileBasic,
1152  sizeof(FILE_BASIC_INFORMATION),
1154  if (!NT_SUCCESS(NtStatus))
1155  {
1156  DPRINT("NtSetInformationFile() failed (%x)\n", NtStatus);
1157  }
1158  }
1159 
1160  SetAttributesOnFile(Search->File, DestFile);
1161  }
1162 
1163  /* Call extract event handler */
1164  if (CabinetContext->ExtractHandler != NULL)
1165  CabinetContext->ExtractHandler(CabinetContext, Search->File, DestName);
1166 
1167  if (Search->CFData)
1168  CFData = Search->CFData;
1169  else
1170  CFData = (PCFDATA)(CabinetContext->CabinetFolders[Search->File->FolderIndex].DataOffset + CabinetContext->FileBuffer);
1171 
1172  CurrentOffset = Search->Offset;
1173  while (CurrentOffset + CFData->UncompSize <= Search->File->FileOffset)
1174  {
1175  /* walk the data blocks until we reach
1176  the one containing the start of the file */
1177  CurrentOffset += CFData->UncompSize;
1178  CFData = (PCFDATA)((char *)(CFData + 1) + CabinetContext->DataReserved + CFData->CompSize);
1179  }
1180 
1181  Search->CFData = CFData;
1182  Search->Offset = CurrentOffset;
1183 
1184  /* now decompress and discard any data in
1185  the block before the start of the file */
1186 
1187  /* start of comp data */
1188  CurrentBuffer = ((unsigned char *)(CFData + 1)) + CabinetContext->DataReserved;
1189  RemainingBlock = CFData->CompSize;
1190  InputLength = RemainingBlock;
1191 
1192  while (CurrentOffset < Search->File->FileOffset)
1193  {
1194  /* compute remaining uncomp bytes to start
1195  of file, bounded by size of chunk */
1196  OutputLength = Search->File->FileOffset - CurrentOffset;
1197  if (OutputLength > (LONG)sizeof(Chunk))
1198  OutputLength = sizeof(Chunk);
1199 
1200  /* negate to signal NOT end of block */
1201  OutputLength = -OutputLength;
1202 
1203  CabinetContext->Codec->Uncompress(CabinetContext->Codec,
1204  Chunk,
1205  CurrentBuffer,
1206  &InputLength,
1207  &OutputLength);
1208 
1209  /* add the uncomp bytes extracted to current folder offset */
1210  CurrentOffset += OutputLength;
1211  /* add comp bytes consumed to CurrentBuffer */
1212  CurrentBuffer += InputLength;
1213  /* subtract bytes consumed from bytes remaining in block */
1214  RemainingBlock -= InputLength;
1215  /* neg for resume decompression of the same block */
1216  InputLength = -RemainingBlock;
1217  }
1218 
1219  /* now CurrentBuffer points to the first comp byte
1220  of the file, so we can begin decompressing */
1221 
1222  /* Size = remaining uncomp bytes of the file to decompress */
1223  Size = Search->File->FileSize;
1224  while (Size > 0)
1225  {
1226  OutputLength = Size;
1227  DPRINT("Decompressing block at %x with RemainingBlock = %d, Size = %d\n",
1228  CurrentBuffer, RemainingBlock, Size);
1229 
1230  Status = CabinetContext->Codec->Uncompress(CabinetContext->Codec,
1231  CurrentDestBuffer,
1232  CurrentBuffer,
1233  &InputLength,
1234  &OutputLength);
1235  if (Status != CS_SUCCESS)
1236  {
1237  DPRINT("Cannot uncompress block\n");
1238  if (Status == CS_NOMEMORY)
1241  goto UnmapDestFile;
1242  }
1243 
1244  /* advance dest buffer by bytes produced */
1245  CurrentDestBuffer = (PVOID)((ULONG_PTR)CurrentDestBuffer + OutputLength);
1246  /* advance src buffer by bytes consumed */
1247  CurrentBuffer += InputLength;
1248  /* reduce remaining file bytes by bytes produced */
1249  Size -= OutputLength;
1250  /* reduce remaining block size by bytes consumed */
1251  RemainingBlock -= InputLength;
1252  if (Size > 0 && RemainingBlock == 0)
1253  {
1254  /* used up this block, move on to the next */
1255  DPRINT("Out of block data\n");
1256  CFData = (PCFDATA)CurrentBuffer;
1257  RemainingBlock = CFData->CompSize;
1258  CurrentBuffer = (unsigned char *)(CFData + 1) + CabinetContext->DataReserved;
1259  InputLength = RemainingBlock;
1260  }
1261  }
1262 
1264 
1265 UnmapDestFile:
1266  if (!CabinetContext->CreateFileHandler)
1267  NtUnmapViewOfSection(NtCurrentProcess(), DestFileBuffer);
1268 
1269 CloseDestFileSection:
1270  if (!CabinetContext->CreateFileHandler)
1271  NtClose(DestFileSection);
1272 
1273 CloseDestFile:
1274  if (!CabinetContext->CreateFileHandler)
1275  NtClose(DestFile);
1276 
1277  return Status;
1278 }
1279 
1280 /*
1281  * FUNCTION: Selects codec engine to use
1282  * ARGUMENTS:
1283  * Id = Codec identifier
1284  */
1285 VOID
1287  IN PCABINET_CONTEXT CabinetContext,
1288  IN ULONG Id)
1289 {
1290  if (CabinetContext->CodecSelected)
1291  {
1292  if (Id == CabinetContext->CodecId)
1293  return;
1294 
1295  CabinetContext->CodecSelected = FALSE;
1296  }
1297 
1298  switch (Id)
1299  {
1300  case CAB_CODEC_RAW:
1301  {
1302  CabinetContext->Codec = &RawCodec;
1303  break;
1304  }
1305 
1306  case CAB_CODEC_MSZIP:
1307  {
1308  CabinetContext->Codec = &MSZipCodec;
1309  CabinetContext->Codec->ZStream.zalloc = MSZipAlloc;
1310  CabinetContext->Codec->ZStream.zfree = MSZipFree;
1311  CabinetContext->Codec->ZStream.opaque = (voidpf)0;
1312  break;
1313  }
1314 
1315  default:
1316  return;
1317  }
1318 
1319  CabinetContext->CodecId = Id;
1320  CabinetContext->CodecSelected = TRUE;
1321 }
1322 
1323 /*
1324  * FUNCTION: Set event handlers
1325  * ARGUMENTS:
1326  * Overwrite = Handler called when a file is to be overwritten
1327  * Extract = Handler called when a file is to be extracted
1328  * DiskChange = Handler called when changing the disk
1329  */
1330 VOID
1332  IN PCABINET_CONTEXT CabinetContext,
1333  IN PCABINET_OVERWRITE Overwrite,
1335  IN PCABINET_DISK_CHANGE DiskChange,
1337 {
1338  CabinetContext->OverwriteHandler = Overwrite;
1339  CabinetContext->ExtractHandler = Extract;
1340  CabinetContext->DiskChangeHandler = DiskChange;
1341  CabinetContext->CreateFileHandler = CreateFile;
1342 }
1343 
1344 /*
1345  * FUNCTION: Get pointer to cabinet reserved area. NULL if none
1346  */
1347 PVOID
1349  IN PCABINET_CONTEXT CabinetContext,
1350  OUT PULONG Size)
1351 {
1352  if (CabinetContext->CabinetReservedArea != NULL)
1353  {
1354  if (Size != NULL)
1355  {
1356  *Size = CabinetContext->CabinetReserved;
1357  }
1358 
1359  return CabinetContext->CabinetReservedArea;
1360  }
1361  else
1362  {
1363  if (Size != NULL)
1364  {
1365  *Size = 0;
1366  }
1367 
1368  return NULL;
1369  }
1370 }
VOID CabinetInitialize(IN OUT PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:501
static ACPI_BUFFER CurrentBuffer
#define CAB_STATUS_INVALID_CAB
Definition: cabinet.h:31
struct _CFHEADER CFHEADER
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define abs(i)
Definition: fconv.c:206
PCWSTR CabinetGetCabinetName(IN PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:568
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define IN
Definition: typedefs.h:39
VOID(* PCABINET_EXTRACT)(IN struct _CABINET_CONTEXT *CabinetContext, IN PCFFILE File, IN PCWSTR FileName)
Definition: cabinet.h:58
static ULONG CloseCabinet(IN PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:483
WORD Month
Definition: cabinet.c:40
ULONG CabinetExtractFile(IN PCABINET_CONTEXT CabinetContext, IN PCAB_SEARCH Search)
Definition: cabinet.c:952
NTSTATUS NTAPI NtUnmapViewOfSection(IN HANDLE ProcessHandle, IN PVOID BaseAddress)
Definition: section.c:3782
void __cdecl free(void *ptr)
Definition: cabinet.c:147
static CAB_CODEC MSZipCodec
Definition: cabinet.c:302
NTSTATUS NTAPI NtSetInformationFile(HANDLE hFile, PIO_STATUS_BLOCK io, PVOID ptr, ULONG len, FILE_INFORMATION_CLASS FileInformationClass)
*BytesInUnicodeString PWCH UnicodeString
Definition: rtlfuncs.h:1979
USHORT FileDate
Definition: cabinet.c:119
static BOOL ConvertSystemTimeToFileTime(CONST SYSTEMTIME *lpSystemTime, LPFILETIME lpFileTime)
Definition: cabinet.c:323
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:3373
void FAR * voidpf
Definition: zlib.h:42
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
VOID CabinetSelectCodec(IN PCABINET_CONTEXT CabinetContext, IN ULONG Id)
Definition: cabinet.c:1286
#define __cdecl
Definition: accygwin.h:79
static PWCHAR GetFileName(PWCHAR Path)
Definition: cabinet.c:381
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
WORD wMonth
Definition: winbase.h:884
#define ANYSIZE_ARRAY
Definition: typedefs.h:46
LARGE_INTEGER LastAccessTime
Definition: nt_native.h:940
#define TRUE
Definition: types.h:120
#define CAB_CODEC_RAW
Definition: cabinet.h:46
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
#define Z_OK
Definition: zlib.h:114
WORD Year
Definition: cabinet.c:41
unsigned char * PUCHAR
Definition: retypes.h:3
DWORD MaximumLength
Definition: config.c:21
char CHAR
Definition: xmlstorage.h:175
VOID CabinetClose(IN OUT PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:794
VOID(* PCABINET_DISK_CHANGE)(IN struct _CABINET_CONTEXT *CabinetContext, IN PCWSTR CabinetName, IN PCWSTR DiskLabel)
Definition: cabinet.h:63
struct _CAB_CODEC CAB_CODEC
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
#define FILE_CREATE
Definition: from_kernel.h:55
USHORT Version
Definition: cabinet.c:86
GLdouble n
Definition: glext.h:7729
z_stream ZStream
Definition: cabinet.c:172
WORD Second
Definition: cabinet.c:32
static BOOL ConvertDosDateTimeToFileTime(WORD wFatDate, WORD wFatTime, LPFILETIME lpFileTime)
Definition: cabinet.c:348
PCWSTR CabinetGetDestinationPath(IN PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:609
HRESULT WINAPI Extract(SESSION *dest, LPCSTR szCabName)
Definition: cabinet_main.c:328
#define CAB_ATTRIB_SYSTEM
Definition: cabinet.c:63
#define CAB_ATTRIB_HIDDEN
Definition: cabinet.c:62
#define FILE_OVERWRITE
Definition: from_kernel.h:57
USHORT FileTime
Definition: cabinet.c:120
ULONG Reserved3
Definition: cabinet.c:85
struct _DOSDATE * PDOSDATE
WORD Minute
Definition: cabinet.c:33
ULONG Signature
Definition: cabinet.c:80
uint16_t * PWCHAR
Definition: typedefs.h:56
#define MAX_WBITS
Definition: zlib.h:151
struct _LARGE_INTEGER::@2260 u
char * LPSTR
Definition: xmlstorage.h:182
PVOID(* PCABINET_CREATE_FILE)(IN struct _CABINET_CONTEXT *CabinetContext, IN ULONG FileSize)
Definition: cabinet.h:68
struct _CFDATA * PCFDATA
int32_t INT
Definition: typedefs.h:58
struct _CFFILE CFFILE
VOID CabinetSetCabinetName(IN PCABINET_CONTEXT CabinetContext, IN PCWSTR FileName)
Definition: cabinet.c:580
CHAR InputBuffer[80]
Definition: conmgr.c:33
#define FILE_SHARE_READ
Definition: compat.h:136
DWORD Id
struct _DOSTIME * PDOSTIME
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
uint32_t ULONG_PTR
Definition: typedefs.h:65
void *__cdecl malloc(size_t size)
Definition: cabinet.c:141
DWORD Length
Definition: config.c:20
DWORD dwHighDateTime
Definition: mapidefs.h:66
while(1)
Definition: macro.lex.yy.c:740
#define SECTION_ALL_ACCESS
Definition: nt_native.h:1293
WORD wYear
Definition: winbase.h:883
#define CAB_CODEC_MSZIP
Definition: cabinet.h:48
struct _CFFOLDER CFFOLDER
#define CAB_COMP_MSZIP
Definition: cabinet.c:53
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
#define FILE_SYNCHRONOUS_IO_ALERT
Definition: from_kernel.h:30
#define SEC_COMMIT
Definition: mmtypes.h:99
#define Z_STREAM_END
Definition: zlib.h:115
#define FALSE
Definition: types.h:117
USHORT Attributes
Definition: cabinet.c:121
#define CS_BADSTREAM
Definition: cabinet.h:43
#define CAB_VERSION
Definition: cabinet.c:48
unsigned int BOOL
Definition: ntddk_ex.h:94
ULONG Checksum
Definition: cabinet.c:128
long LONG
Definition: pedump.c:60
#define CAB_FLAG_RESERVE
Definition: cabinet.c:59
struct _CFFILE * PCFFILE
WORD Hour
Definition: cabinet.c:34
#define GENERIC_WRITE
Definition: nt_native.h:90
USHORT FileCount
Definition: cabinet.c:88
static PVOID ptr
Definition: dispmode.c:27
#define CAB_STATUS_CANNOT_WRITE
Definition: cabinet.h:29
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:3554
#define Z_SYNC_FLUSH
Definition: zlib.h:107
USHORT CompSize
Definition: cabinet.c:129
ULONG CabinetFindNext(IN PCABINET_CONTEXT CabinetContext, IN OUT PCAB_SEARCH Search)
Definition: cabinet.c:833
WORD wMinute
Definition: winbase.h:888
#define CAB_STATUS_NOMEMORY
Definition: cabinet.h:25
smooth NULL
Definition: ftsmooth.c:416
struct _DOSDATE DOSDATE
#define CAB_ATTRIB_DIRECTORY
Definition: cabinet.c:65
void DPRINT(...)
Definition: polytest.cpp:61
#define CAB_ATTRIB_READONLY
Definition: cabinet.c:61
Definition: bufpool.h:45
#define MSZIP_MAGIC
Definition: cabinet.c:212
_Must_inspect_result_ __drv_aliasesMem _In_ PDEVICE_OBJECT _In_opt_ PVOID _In_ ULONG _Out_opt_ PVOID OutputBuffer
Definition: iofuncs.h:713
void * PVOID
Definition: retypes.h:9
USHORT Milliseconds
Definition: env_spec_w32.h:717
static BOOL SetAttributesOnFile(PCFFILE File, HANDLE hFile)
Definition: cabinet.c:427
USHORT FolderCount
Definition: cabinet.c:87
USHORT CabinetNumber
Definition: cabinet.c:91
#define NtCurrentProcess()
Definition: nt_native.h:1657
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
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
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
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:3951
#define CAB_STATUS_UNSUPPCOMP
Definition: cabinet.h:33
GLsizeiptr size
Definition: glext.h:5919
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)
if(!(yy_init))
Definition: macro.lex.yy.c:714
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ULONG CabinetFindNextFileSequential(IN PCABINET_CONTEXT CabinetContext, IN PCWSTR FileName, IN OUT PCAB_SEARCH Search)
Definition: cabinet.c:926
static VOID RemoveFileName(PWCHAR Path)
Definition: cabinet.c:402
#define MAX_PATH
Definition: compat.h:34
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
alloc_func zalloc
Definition: zlib.h:70
#define CAB_STATUS_CANNOT_CREATE
Definition: cabinet.h:27
#define CAB_FLAG_HASPREV
Definition: cabinet.c:57
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
unsigned short WORD
Definition: ntddk_ex.h:93
NTSYSAPI BOOLEAN WINAPI RtlValidateHeap(HANDLE, ULONG, LPCVOID)
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint address
Definition: glext.h:9393
PCABINET_CODEC_UNCOMPRESS Uncompress
Definition: cabinet.c:171
#define Len
Definition: deflate.h:82
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:1331
void *__cdecl calloc(size_t nmemb, size_t size)
Definition: cabinet.c:153
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define CAB_SIGNATURE
Definition: cabinet.c:47
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
WORD wSecond
Definition: winbase.h:889
#define CAB_STATUS_SUCCESS
Definition: cabinet.h:23
struct _CFHEADER * PCFHEADER
USHORT CompressionType
Definition: cabinet.c:108
USHORT SetID
Definition: cabinet.c:90
WORD wMilliseconds
Definition: winbase.h:890
#define FILE_ATTRIBUTE_ARCHIVE
Definition: nt_native.h:706
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
int inflateEnd(z_streamp strm)
Definition: inflate.c:1910
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
Status
Definition: gdiplustypes.h:24
ULONG Reserved1
Definition: cabinet.c:81
struct _DOSTIME DOSTIME
static const WCHAR L[]
Definition: oid.c:1250
USHORT DataBlockCount
Definition: cabinet.c:107
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define GENERIC_READ
Definition: compat.h:135
#define CAB_FLAG_HASNEXT
Definition: cabinet.c:58
ULONG CabinetOpen(IN OUT PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:621
ULONG FileOffset
Definition: cabinet.c:117
NTSTATUS NTAPI NtQueryInformationFile(HANDLE hFile, PIO_STATUS_BLOCK io, PVOID ptr, ULONG len, FILE_INFORMATION_CLASS FileInformationClass)
struct _CFDATA CFDATA
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
#define SYNCHRONIZE
Definition: nt_native.h:61
_In_ HANDLE hFile
Definition: mswsock.h:90
USHORT Flags
Definition: cabinet.c:89
HANDLE ProcessHeap
Definition: servman.c:15
USHORT FolderIndex
Definition: cabinet.c:118
void MSZipFree(voidpf opaque, voidpf address)
Definition: cabinet.c:317
#define CS_NOMEMORY
Definition: cabinet.h:42
WORD wDay
Definition: winbase.h:886
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
struct _FileName FileName
Definition: fatprocs.h:893
_Must_inspect_result_ _In_ USHORT _In_ PHIDP_PREPARSED_DATA _Out_writes_to_ LengthAttributes PHIDP_EXTENDED_ATTRIBUTES Attributes
Definition: hidpi.h:348
unsigned int uInt
Definition: zlib.h:38
PRTL_UNICODE_STRING_BUFFER Path
_CRTIMP wchar_t *__cdecl wcsncpy(wchar_t *_Dest, const wchar_t *_Source, size_t _Count)
#define CAB_ATTRIB_ARCHIVE
Definition: cabinet.c:66
IN OUT PVCB OUT PDIRENT OUT PBCB IN BOOLEAN CreateFile
Definition: fatprocs.h:913
unsigned short USHORT
Definition: pedump.c:61
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
#define CAB_COMP_MASK
Definition: cabinet.c:51
WORD wHour
Definition: winbase.h:887
ULONG CabinetSize
Definition: cabinet.c:82
ULONG CabinetFindFirst(IN PCABINET_CONTEXT CabinetContext, IN PCWSTR FileName, IN OUT PCAB_SEARCH Search)
Definition: cabinet.c:813
static BOOL CabinetNormalizePath(PWCHAR Path, ULONG Length)
Definition: cabinet.c:544
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
unsigned int * PULONG
Definition: retypes.h:1
Definition: config.c:18
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
#define PAGE_READONLY
Definition: compat.h:138
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
Definition: fci.c:65
#define inflateInit2(strm, windowBits)
Definition: zlib.h:1800
USHORT UncompSize
Definition: cabinet.c:130
#define Z_MEM_ERROR
Definition: zlib.h:120
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define DPRINT1
Definition: precomp.h:8
WORD Day
Definition: cabinet.c:39
PVOID CabinetGetCabinetReservedArea(IN PCABINET_CONTEXT CabinetContext, OUT PULONG Size)
Definition: cabinet.c:1348
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
struct _CFFOLDER * PCFFOLDER
#define CAB_STATUS_FILE_EXISTS
Definition: cabinet.h:30
#define OUT
Definition: typedefs.h:40
voidpf MSZipAlloc(voidpf opaque, uInt items, uInt size)
Definition: cabinet.c:311
VOID CabinetSetDestinationPath(IN PCABINET_CONTEXT CabinetContext, IN PCWSTR DestinationPath)
Definition: cabinet.c:593
unsigned int ULONG
Definition: retypes.h:1
static CAB_CODEC RawCodec
Definition: cabinet.c:205
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define CAB_STATUS_CANNOT_OPEN
Definition: cabinet.h:26
int inflate(z_streamp strm, int flush)
Definition: inflate.c:1257
ULONG FileSize
Definition: cabinet.c:116
Definition: File.h:15
#define CAB_COMP_NONE
Definition: cabinet.c:52
#define CS_SUCCESS
Definition: cabinet.h:41
ULONG FileTableOffset
Definition: cabinet.c:84
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
BOOLEAN RtlTimeFieldsToTime(IN PTIME_FIELDS TimeFields, IN PLARGE_INTEGER Time)
static PTIME_FIELDS TimeFields
Definition: time.c:104
static TCHAR * items[]
Definition: page1.c:45
signed int * PLONG
Definition: retypes.h:5
BOOL(* PCABINET_OVERWRITE)(IN struct _CABINET_CONTEXT *CabinetContext, IN PCFFILE File, IN PCWSTR FileName)
Definition: cabinet.h:53
VOID CabinetCleanup(IN OUT PCABINET_CONTEXT CabinetContext)
Definition: cabinet.c:529
struct _CAB_CODEC * PCAB_CODEC
#define CAB_STATUS_NOFILE
Definition: cabinet.h:32
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
unsigned short * PUSHORT
Definition: retypes.h:2
#define CONST
Definition: pedump.c:81
DWORD dwLowDateTime
Definition: mapidefs.h:65
unsigned char * Buffer
Definition: config.c:22
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG Reserved2
Definition: cabinet.c:83
ULONG DataOffset
Definition: cabinet.c:106
#define PAGE_READWRITE
Definition: nt_native.h:1304