NTSTATUS SetupExtractFile( PWCHAR CabinetFileName, PWCHAR SourceFileName, PWCHAR DestinationPathName) { ULONG CabStatus; DPRINT("SetupExtractFile(CabinetFileName %S, SourceFileName %S, DestinationPathName %S)\n", CabinetFileName, SourceFileName, DestinationPathName); if (HasCurrentCabinet) { DPRINT("CurrentCabinetName: %S\n", CurrentCabinetName); } if ((HasCurrentCabinet) && (wcscmp(CabinetFileName, CurrentCabinetName) == 0)) { DPRINT("Using same cabinet as last time\n"); /* Use our last location because the files should be sequential */ CabStatus = CabinetFindNextFileSequential(SourceFileName, &Search); if (CabStatus != CAB_STATUS_SUCCESS) { DPRINT("Sequential miss on file: %S\n", SourceFileName); /* Looks like we got unlucky */ CabStatus = CabinetFindFirst(SourceFileName, &Search); } } else { DPRINT("Using new cabinet\n"); if (HasCurrentCabinet) { CabinetCleanup(); } wcscpy(CurrentCabinetName, CabinetFileName); CabinetInitialize(); CabinetSetEventHandlers(NULL, NULL, NULL); CabinetSetCabinetName(CabinetFileName); CabStatus = CabinetOpen(); if (CabStatus == CAB_STATUS_SUCCESS) { DPRINT("Opened cabinet %S\n", CabinetGetCabinetName()); HasCurrentCabinet = TRUE; } else { DPRINT("Cannot open cabinet (%d)\n", CabStatus); return STATUS_UNSUCCESSFUL; } /* We have to start at the beginning here */ CabStatus = CabinetFindFirst(SourceFileName, &Search); } if (CabStatus != CAB_STATUS_SUCCESS) { DPRINT1("Unable to find '%S' in cabinet '%S'\n", SourceFileName, CabinetGetCabinetName()); return STATUS_UNSUCCESSFUL; } CabinetSetDestinationPath(DestinationPathName); CabStatus = CabinetExtractFile(&Search); if (CabStatus != CAB_STATUS_SUCCESS) { DPRINT("Cannot extract file %S (%d)\n", SourceFileName, CabStatus); return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; }
/* * FUNCTION: Finds next file in the cabinet that matches a search criteria * ARGUMENTS: * Search = Pointer to search structure * RETURNS: * Status of operation */ ULONG CabinetFindNext(PCAB_SEARCH Search) { ULONG Status; PCFFILE Prev; ANSI_STRING AnsiString; UNICODE_STRING UnicodeString; WCHAR FileName[MAX_PATH]; if (wcscmp(Search->Cabinet, CabinetName) != 0) { /* restart search of cabinet has changed since last find */ Search->File = 0; } if (!Search->File) { /* starting new search or cabinet */ Search->File = (PCFFILE)(FileBuffer + PCABHeader->FileTableOffset); Search->Index = 0; Prev = 0; } else Prev = Search->File; while (TRUE) { /* 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.Buffer[0] = 0; 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); wcscpy(Search->Cabinet, CabinetName); if (DiskChangeHandler != NULL) { DiskChangeHandler(CabinetNext, DiskNext); } Status = CabinetOpen(); if (Status != CAB_STATUS_SUCCESS) return Status; } else { return CAB_STATUS_NOFILE; } /* starting new search or cabinet */ Search->File = (PCFFILE)(FileBuffer + PCABHeader->FileTableOffset); Search->Index = 0; Prev = 0; } else Search->File = (PCFFILE)(strchr((char *)(Search->File + 1), 0) + 1); } DPRINT("Found file %s\n", Search->File->FileName); return CAB_STATUS_SUCCESS; }