// // test_setupapi_cab.c : Testing file extraction from cabinets // using an undocumented way with SetupQueueCopy() and // SetupCommitFileQueue(). // // Copyright 2017 Hermès Bélusca-Maïto // Under GPLv2 license. // #include #include #include #include // PSP_FILE_CALLBACK UINT CALLBACK FileCopyCallback(PVOID Context, UINT Notification, UINT_PTR Param1, UINT_PTR Param2) { PFILEPATHS FilePathInfo; switch (Notification) { case SPFILENOTIFY_STARTSUBQUEUE: break; case SPFILENOTIFY_STARTCOPY: FilePathInfo = (PFILEPATHS)Param1; /* Display copy message */ wprintf(L" Copying file '%s' --> '%s'...\n", FilePathInfo->Source, FilePathInfo->Target); return FILEOP_DOIT; case SPFILENOTIFY_ENDCOPY: break; } return SetupDefaultQueueCallback(Context, Notification, Param1, Param2); } VOID ReadFromStdin(WCHAR* Buffer, SIZE_T cchBufferSize) { PWSTR ptr = Buffer; fgetws(Buffer, cchBufferSize, stdin); while (*ptr) { if (*ptr == L'\n' || *ptr == L'\r') { *ptr = 0; break; } ++ptr; } } int wmain(int argc, WCHAR* argv[]) { HSPFILEQ SetupFileQueue; PVOID Context; WCHAR ArchiveDir[MAX_PATH]; WCHAR ArchiveFileName[MAX_PATH]; WCHAR SourceFileName[MAX_PATH]; WCHAR TargetDir[MAX_PATH]; WCHAR TargetFileName[MAX_PATH]; printf("Enter the directory where the cabinet archive resides:\n"); ReadFromStdin(ArchiveDir, _countof(ArchiveDir)); printf("\n"); printf("Enter the cabinet archive file name:\n"); ReadFromStdin(ArchiveFileName, _countof(ArchiveFileName)); printf("\n"); printf("Enter the file name to be extracted from the cabinet archive:\n"); ReadFromStdin(SourceFileName, _countof(SourceFileName)); printf("\n"); printf("Enter the target directory where the file should be extracted:\n"); ReadFromStdin(TargetDir, _countof(TargetDir)); printf("\n"); printf("Enter the name of the target file to be extracted:\n"); ReadFromStdin(TargetFileName, _countof(TargetFileName)); printf("\n"); SetupFileQueue = SetupOpenFileQueue(); if (!SetupFileQueue) { printf("Unable to create setup queue, last error 0x%x\n", GetLastError()); return 1; } printf("Prepare file copying...\n"); /* * Use the undocumented way of copying files from within a given cabinet file * *ONLY IF* the files do not already exist in the same directory where * the cabinet file resides!! */ SetupQueueCopyW(SetupFileQueue, ArchiveDir, NULL, SourceFileName, L"foobar", // Undocumented on MSDN is the fact that this parameter is mandatory *IF* one wants to take the TagFile into account! ArchiveFileName, // Special behaviour: use cabinet file! The API does not check for a ".cab" extension. TargetDir, TargetFileName, SP_COPY_NOOVERWRITE /* | SP_COPY_SOURCE_ABSOLUTE | SP_COPY_SOURCEPATH_ABSOLUTE */); // We choose to decompress the archive, so do NOT specify SP_COPY_NODECOMP ! printf("Copy files...\n"); Context = SetupInitDefaultQueueCallback(NULL); SetupCommitFileQueue(NULL, SetupFileQueue, FileCopyCallback, Context); SetupTermDefaultQueueCallback(Context); printf("Closing setup queue...\n"); SetupCloseFileQueue(SetupFileQueue); printf("Press any key to quit...\n"); _getch(); return 0; }