📄 cabinet.c
字号:
return 0;
}
VOID
CabinetInitialize(VOID)
/*
* FUNCTION: Initialize archiver
*/
{
ZStream.zalloc = MSZipAlloc;
ZStream.zfree = MSZipFree;
ZStream.opaque = (voidpf)0;
FileOpen = FALSE;
wcscpy(DestPath, L"");
CodecId = CAB_CODEC_RAW;
CodecSelected = TRUE;
FolderUncompSize = 0;
BytesLeftInBlock = 0;
CabinetReserved = 0;
FolderReserved = 0;
DataReserved = 0;
CabinetReservedArea = NULL;
LastFileOffset = 0;
}
VOID
CabinetCleanup(VOID)
/*
* FUNCTION: Cleanup archiver
*/
{
CabinetClose();
}
BOOL
CabinetNormalizePath(PWCHAR Path,
ULONG Length)
/*
* FUNCTION: Normalizes a path
* ARGUMENTS:
* Path = Pointer to string with pathname
* Length = Number of characters in Path
* RETURNS:
* TRUE if there was enough room in Path, or FALSE
*/
{
ULONG n;
BOOL OK = TRUE;
if ((n = wcslen(Path)) &&
(Path[n - 1] != L'\\') &&
(OK = ((n + 1) < Length)))
{
Path[n] = L'\\';
Path[n + 1] = 0;
}
return OK;
}
PWCHAR
CabinetGetCabinetName()
/*
* FUNCTION: Returns pointer to cabinet file name
* RETURNS:
* Pointer to string with name of cabinet
*/
{
return CabinetName;
}
VOID
CabinetSetCabinetName(PWCHAR FileName)
/*
* FUNCTION: Sets cabinet file name
* ARGUMENTS:
* FileName = Pointer to string with name of cabinet
*/
{
wcscpy(CabinetName, FileName);
}
VOID
CabinetSetDestinationPath(PWCHAR DestinationPath)
/*
* FUNCTION: Sets destination path
* ARGUMENTS:
* DestinationPath = Pointer to string with name of destination path
*/
{
wcscpy(DestPath, DestinationPath);
if (wcslen(DestPath) > 0)
CabinetNormalizePath(DestPath, MAX_PATH);
}
PWCHAR
CabinetGetDestinationPath()
/*
* FUNCTION: Returns destination path
* RETURNS:
* Pointer to string with name of destination path
*/
{
return DestPath;
}
ULONG
CabinetOpen(VOID)
/*
* FUNCTION: Opens a cabinet file
* RETURNS:
* Status of operation
*/
{
PUCHAR Buffer;
UNICODE_STRING ustring;
ANSI_STRING astring;
if (!FileOpen)
{
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
UNICODE_STRING FileName;
NTSTATUS NtStatus;
ULONG Size;
RtlInitUnicodeString(&FileName,
CabinetName);
InitializeObjectAttributes(&ObjectAttributes,
&FileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
NtStatus = NtOpenFile(&FileHandle,
GENERIC_READ | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(NtStatus))
{
DPRINT("Cannot open file (%S) (%x).\n", CabinetName, NtStatus);
return CAB_STATUS_CANNOT_OPEN;
}
FileOpen = TRUE;
NtStatus = NtCreateSection(&FileSectionHandle,
SECTION_ALL_ACCESS,
0,
0,
PAGE_READONLY,
SEC_COMMIT,
FileHandle);
if(!NT_SUCCESS(NtStatus))
{
DPRINT("NtCreateSection failed: %x\n", NtStatus);
return CAB_STATUS_NOMEMORY;
}
FileBuffer = 0;
FileSize = 0;
NtStatus = NtMapViewOfSection(FileSectionHandle,
NtCurrentProcess(),
(PVOID *)&FileBuffer,
0,
0,
0,
&FileSize,
ViewUnmap,
0,
PAGE_READONLY);
if(!NT_SUCCESS(NtStatus))
{
DPRINT("NtMapViewOfSection failed: %x\n", NtStatus);
return CAB_STATUS_NOMEMORY;
}
DPRINT( "Cabinet file %S opened and mapped to %x\n", CabinetName, FileBuffer );
PCABHeader = (PCFHEADER)FileBuffer;
/* Check header */
if(FileSize <= sizeof(CFHEADER) ||
PCABHeader->Signature != CAB_SIGNATURE ||
PCABHeader->Version != CAB_VERSION ||
PCABHeader->FolderCount == 0 ||
PCABHeader->FileCount == 0 ||
PCABHeader->FileTableOffset < sizeof(CFHEADER))
{
CloseCabinet();
DPRINT("File has invalid header.\n");
return CAB_STATUS_INVALID_CAB;
}
Size = 0;
Buffer = (PUCHAR)(PCABHeader+1);
/* Read/skip any reserved bytes */
if (PCABHeader->Flags & CAB_FLAG_RESERVE)
{
CabinetReserved = *(PUSHORT)Buffer;
Buffer += 2;
FolderReserved = *Buffer;
Buffer++;
DataReserved = *Buffer;
Buffer++;
if (CabinetReserved > 0)
{
CabinetReservedArea = Buffer;
Buffer += CabinetReserved;
}
}
if (PCABHeader->Flags & CAB_FLAG_HASPREV)
{
/* The previous cabinet file is in the same directory as the current */
wcscpy(CabinetPrev, CabinetName);
RemoveFileName(CabinetPrev);
CabinetNormalizePath(CabinetPrev, 256);
RtlInitAnsiString( &astring, (LPSTR)Buffer );
ustring.Length = wcslen( CabinetPrev );
ustring.Buffer = CabinetPrev + ustring.Length;
ustring.MaximumLength = sizeof( CabinetPrev ) - ustring.Length;
RtlAnsiStringToUnicodeString( &ustring, &astring, FALSE );
Buffer += astring.Length + 1;
/* Read label of prev disk */
RtlInitAnsiString( &astring, (LPSTR)Buffer );
ustring.Length = 0;
ustring.Buffer = DiskPrev;
ustring.MaximumLength = sizeof( DiskPrev );
RtlAnsiStringToUnicodeString( &ustring, &astring, FALSE );
Buffer += astring.Length + 1;
}
else
{
wcscpy(CabinetPrev, L"");
wcscpy(DiskPrev, L"");
}
if (PCABHeader->Flags & CAB_FLAG_HASNEXT)
{
/* The next cabinet file is in the same directory as the previous */
wcscpy(CabinetNext, CabinetName);
RemoveFileName(CabinetNext);
CabinetNormalizePath(CabinetNext, 256);
RtlInitAnsiString( &astring, (LPSTR)Buffer );
ustring.Length = wcslen( CabinetNext );
ustring.Buffer = CabinetNext + ustring.Length;
ustring.MaximumLength = sizeof( CabinetNext ) - ustring.Length;
RtlAnsiStringToUnicodeString( &ustring, &astring, FALSE );
Buffer += astring.Length + 1;
/* Read label of next disk */
RtlInitAnsiString( &astring, (LPSTR)Buffer );
ustring.Length = 0;
ustring.Buffer = DiskNext;
ustring.MaximumLength = sizeof( DiskNext );
RtlAnsiStringToUnicodeString( &ustring, &astring, FALSE );
Buffer += astring.Length + 1;
}
else
{
wcscpy(CabinetNext, L"");
wcscpy(DiskNext, L"");
}
CabinetFolders = (PCFFOLDER)Buffer;
}
DPRINT( "CabinetOpen returning SUCCESS\n" );
return CAB_STATUS_SUCCESS;
}
VOID
CabinetClose(VOID)
/*
* FUNCTION: Closes the cabinet file
*/
{
if (FileOpen)
{
CloseCabinet();
FileOpen = FALSE;
}
}
ULONG
CabinetFindFirst(PWCHAR FileName,
PCAB_SEARCH Search)
/*
* FUNCTION: Finds the first file in the cabinet that matches a search criteria
* ARGUMENTS:
* FileName = Pointer to search criteria
* Search = Pointer to search structure
* RETURNS:
* Status of operation
*/
{
DPRINT( "CabinetFindFirst( FileName = %S )\n", FileName );
wcsncpy(Search->Search, FileName, MAX_PATH);
wcsncpy(Search->Cabinet, CabinetName, MAX_PATH);
Search->File = 0;
return CabinetFindNext(Search);
}
ULONG
CabinetFindNext(PCAB_SEARCH Search)
/*
* FUNCTION: Finds next file in the cabinet that matches a search criteria
* ARGUMENTS:
* Search = Pointer to search structure
* RETURNS:
* Status of operation
*/
{
ULONG Status;
PCFFILE Prev;
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
WCHAR FileName[MAX_PATH];
if( wcscmp( Search->Cabinet, CabinetName ) != 0 )
Search->File = 0; // restart search of cabinet has changed since last find
if( !Search->File )
{
// starting new search or cabinet
Search->File = (PCFFILE)(FileBuffer + PCABHeader->FileTableOffset);
Search->Index = 0;
Prev = 0;
}
else Prev = Search->File;
while(1)
{
// look at each file in the archive and see if we found a match
if( Search->File->FolderIndex == 0xFFFD || Search->File->FolderIndex == 0xFFFF )
{
// skip files continued from previous cab
DPRINT("Skipping file (%s) FileOffset (0x%X) LastFileOffset (0x%X).\n",
(char *)(Search->File + 1), Search->File->FileOffset, LastFileOffset);
}
else {
// FIXME: check for match against search criteria
if( Search->File != Prev )
{
// don't match the file we started with
if( wcscmp( Search->Search, L"*" ) == 0 )
{
// take any file
break;
}
else {
// otherwise, try to match the exact file name
RtlInitAnsiString( &AnsiString, Search->File->FileName );
UnicodeString.Buffer = FileName;
UnicodeString.Length = 0;
UnicodeString.MaximumLength = sizeof( FileName );
RtlAnsiStringToUnicodeString( &UnicodeString, &AnsiString, FALSE );
if( wcscmp( Search->Search, UnicodeString.Buffer ) == 0 )
break;
}
}
}
// if we make it here we found no match, so move to the next file
Search->Index++;
if( Search->Index >= PCABHeader->FileCount )
{
// we have reached the end of this cabinet, try to open the next
DPRINT( "End of cabinet reached\n" );
if (wcslen(DiskNext) > 0)
{
CloseCabinet();
CabinetSetCabinetName(CabinetNext);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -