【发布时间】:2020-03-09 23:45:28
【问题描述】:
我正在尝试用 C 语言在 Windows 文件中创建一个受保护的 ZIP。
我根据这些答案创建了以下方法:
- Creating a ZIP file on Windows (XP/2003) in C/C++ #1
- Creating a ZIP file on Windows (XP/2003) in C/C++ #2
代码如下:
#include <windows.h>
#include <shldisp.h>
#include <tlhelp32.h>
#include <stdio.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <shellapi.h>
#include <stdlib.h>
#include <objbase.h>
int main(int argc, TCHAR* argv[])
{
DWORD strlen = 0;
char szFrom[] = "C:\\Users\\dist",
szTo[] = "C:\\Users\\harrison4\\Desktop\\example.zip";
HRESULT hResult;
IShellDispatch *pISD;
Folder* pToFolder = NULL;
VARIANT vDir, vFile, vOpt;
BSTR strptr1, strptr2;
FILE* f;
fopen_s(&f, szTo, "wb");
if (!f)
return 0;
fwrite("\x50\x4B\x05\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 22, 1, f);
fclose(f);
CoInitialize(NULL);
hResult = CoCreateInstance(&CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, &IID_IShellDispatch, (void**)&pISD);
if (SUCCEEDED(hResult) && pISD != NULL)
{
strlen = MultiByteToWideChar(CP_ACP, 0, szTo, -1, 0, 0);
strptr1 = SysAllocStringLen(0, strlen);
MultiByteToWideChar(CP_ACP, 0, szTo, -1, strptr1, strlen);
VariantInit(&vDir);
vDir.vt = VT_BSTR;
vDir.bstrVal = strptr1;
hResult = pISD->NameSpace(vDir, &pToFolder);
if (SUCCEEDED(hResult))
{
strlen = MultiByteToWideChar(CP_ACP, 0, szFrom, -1, 0, 0);
strptr2 = SysAllocStringLen(0, strlen);
MultiByteToWideChar(CP_ACP, 0, szFrom, -1, strptr2, strlen);
VariantInit(&vFile);
vFile.vt = VT_BSTR;
vFile.bstrVal = strptr2;
VariantInit(&vOpt);
vOpt.vt = VT_I4;
vOpt.lVal = 4; // Do not display a progress dialog box
printf("Copying %s to %s ...\n", szFrom, szTo);
hResult = pToFolder->CopyHere(vFile, vOpt); //NOTE: this appears to always return S_OK even on error
/*
* 1) Enumerate current threads in the process using Thread32First/Thread32Next
* 2) Start the operation
* 3) Enumerate the threads again
* 4) Wait for any new threads using WaitForMultipleObjects
*
* Of course, if the operation creates any new threads that don't exit, then you have a problem.
*/
if (hResult == S_OK) {
//NOTE: hard-coded for testing - be sure not to overflow the array if > 5 threads exist
HANDLE hThrd[5];
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0); //TH32CS_SNAPMODULE, 0);
DWORD NUM_THREADS = 0;
if (h != INVALID_HANDLE_VALUE) {
THREADENTRY32 te;
te.dwSize = sizeof(te);
if (Thread32First(h, &te)) {
do {
if (te.dwSize >= (FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID))) {
//only enumerate threads that are called by this process and not the main thread
if ((te.th32OwnerProcessID == GetCurrentProcessId()) && (te.th32ThreadID != GetCurrentThreadId())) {
//printf("Process 0x%04x Thread 0x%04x\n", te.th32OwnerProcessID, te.th32ThreadID);
hThrd[NUM_THREADS] = OpenThread(SYNCHRONIZE, FALSE, te.th32ThreadID);
NUM_THREADS++;
}
}
te.dwSize = sizeof(te);
} while (Thread32Next(h, &te));
}
CloseHandle(h);
printf("waiting for all threads to exit...\n");
//Wait for all threads to exit
WaitForMultipleObjects(NUM_THREADS, hThrd, TRUE, INFINITE);
//Close All handles
for (DWORD i = 0; i < NUM_THREADS; i++) {
CloseHandle(hThrd[i]);
}
} //if invalid handle
} //if CopyHere() hResult is S_OK
SysFreeString(strptr2);
pToFolder->Release();
}
SysFreeString(strptr1);
pISD->Release();
}
CoUninitialize();
printf("Press ENTER to exit\n");
getchar();
return 0;
}
确实有效。但是,我找不到任何文档来设置文件的密码。
我还找到了the zip C library,它可以简化 ZIP 的创建,但不幸的是,它没有包含密码保护。
【问题讨论】:
-
我不确定 Windows API 是否包含加密的 zip 功能。您可以获得执行 AES 加密 zip 所需的点点滴滴,但可能一个完整的工具/库更容易。 7-zip 有一些选项,但可能对您的需要来说有点大,并且不确定构建仅包含所需存档/压缩/加密的 DLL 是否容易。
-
你能分享一下这样做的目的吗?在您提供的代码中,您可以创建一个空的 zip 文件,但这不能压缩现有文件。对于受保护的 zip 文件,我没有找到这样的 API。您可能需要使用第三方库。请参考this link
-
@StriveSun-MSFT 我发现this resource of minzip lib 也有一个更清晰的例子。我会及时通知你的。谢谢!
-
也许你应该自己写答案!可能很整洁。
-
赏金有点无意义。答案是使用第三方库,但推荐问题不在此处。