Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
3.1 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. extract.c
  5. Abstract:
  6. This module contains the code to extract
  7. a file from a cab file.
  8. Author:
  9. Wesley Witt (wesw) 29-Sept-1998
  10. Revision History:
  11. --*/
  12. #include <ntcabp.h>
  13. #pragma hdrstop
  14. PCAB_DIR_ENTRY
  15. FindFileInCab(
  16. IN PCAB_INSTANCE_DATA CabInst,
  17. IN PCWSTR FileName
  18. )
  19. {
  20. PLIST_ENTRY Next;
  21. PCAB_DIR_ENTRY CabDir;
  22. BOOL Found = FALSE;
  23. Next = CabInst->CabDir.Flink;
  24. while ((ULONG_PTR)Next != (ULONG_PTR)&CabInst->CabDir) {
  25. CabDir = CONTAINING_RECORD( Next, CAB_DIR_ENTRY, Next );
  26. Next = CabDir->Next.Flink;
  27. if (_wcsicmp( CabDir->FileName, FileName ) == 0) {
  28. Found = TRUE;
  29. break;
  30. }
  31. }
  32. if (Found) {
  33. return CabDir;
  34. }
  35. return NULL;
  36. }
  37. BOOL
  38. NtCabExtractOneFile(
  39. IN PCAB_INSTANCE_DATA CabInst,
  40. IN PCWSTR FileName,
  41. IN PCWSTR OutputFileName
  42. )
  43. {
  44. HANDLE hFile;
  45. ULONG i;
  46. BOOL rVal;
  47. DWORD Bytes = 0;
  48. DWORD BytesRead;
  49. NTSTATUS Status;
  50. PCAB_DIR_ENTRY CabDir;
  51. WCHAR ShortFileName[32];
  52. //if (GetShortPathName( FileName, ShortFileName, sizeof(ShortFileName)/sizeof(WCHAR) ) == 0) {
  53. // return FALSE;
  54. //}
  55. wcscpy(ShortFileName,FileName);
  56. CabDir = FindFileInCab( CabInst, ShortFileName );
  57. if (CabDir == NULL) {
  58. return FALSE;
  59. }
  60. if (SetFilePointer( CabInst->hCab, CabDir->Offset, NULL, FILE_BEGIN ) == 0xffffffff) {
  61. return FALSE;
  62. }
  63. if (OutputFileName == NULL) {
  64. OutputFileName = ShortFileName;
  65. }
  66. hFile = CreateFile(
  67. OutputFileName,
  68. GENERIC_WRITE,
  69. 0,
  70. NULL,
  71. CREATE_ALWAYS,
  72. FILE_ATTRIBUTE_NORMAL,
  73. NULL
  74. );
  75. if (hFile == INVALID_HANDLE_VALUE) {
  76. return FALSE;
  77. }
  78. for (i=0; i<CabDir->Segments; i++) {
  79. BytesRead = CabDir->Segment[i];
  80. rVal = ReadFile(
  81. CabInst->hCab,
  82. CabInst->CompressBuf,
  83. BytesRead,
  84. &BytesRead,
  85. NULL
  86. );
  87. if (!rVal) {
  88. CloseHandle( hFile );
  89. return FALSE;
  90. }
  91. Bytes += BytesRead;
  92. Status = RtlDecompressBuffer (
  93. COMPRESSION_FORMAT_LZNT1,
  94. CabInst->ReadBuf,
  95. CabInst->ReadBufSize,
  96. CabInst->CompressBuf,
  97. BytesRead,
  98. &BytesRead
  99. );
  100. if (Status != STATUS_SUCCESS) {
  101. CloseHandle( hFile );
  102. return FALSE;
  103. }
  104. rVal = WriteFile(
  105. hFile,
  106. CabInst->ReadBuf,
  107. BytesRead,
  108. &BytesRead,
  109. NULL
  110. );
  111. }
  112. SetFileTime(
  113. hFile,
  114. &CabDir->CreationTime,
  115. &CabDir->LastAccessTime,
  116. &CabDir->LastWriteTime
  117. );
  118. CloseHandle( hFile );
  119. if (CabDir->ChkSum != 0) {
  120. if (MapFileAndCheckSum( (PWSTR)OutputFileName, &i, &Bytes ) != CHECKSUM_SUCCESS) {
  121. Bytes = 0;
  122. }
  123. if (Bytes != CabDir->ChkSum) {
  124. DeleteFile( OutputFileName );
  125. SetLastError( ERROR_INVALID_DATA );
  126. return FALSE;
  127. }
  128. }
  129. return TRUE;
  130. }