ZIPフォルダ内をIShellFolder2で列挙してみた。
HRESULT teExtract2(IShellFolder2 *pSF2, LPWSTR lpszFolderPath) { LPITEMIDLIST pidl; IEnumIDList *pEnumIDList; ULONG celtFetched; STRRET strret; ULONG dwAttributes; FILETIME mtime; SYSTEMTIME SysTime; SHCOLUMNID scid; scid.fmtid = FMTID_Storage; scid.pid = 14; VARIANT v; CreateDirectory(lpszFolderPath, NULL); HRESULT hr = pSF2->EnumObjects(NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &pEnumIDList); if FAILED(hr) { return hr; } while (pEnumIDList->Next(1, &pidl, &celtFetched) == S_OK) { if SUCCEEDED(pSF2->GetDisplayNameOf(pidl, SHGDN_NORMAL, &strret)) { BSTR bs; if SUCCEEDED(StrRetToBSTR(&strret, pidl, &bs)) { WCHAR *lpszPath = new WCHAR[lstrlen(lpszFolderPath) + ::SysStringLen(bs) + 2]; PathCombine(lpszPath, lpszFolderPath, bs); dwAttributes = SFGAO_FOLDER; pSF2->GetAttributesOf(1, const_cast
(&pidl), &dwAttributes); if (dwAttributes & SFGAO_FOLDER) { IShellFolder2 *pSF2New; pSF2->BindToObject(pidl, NULL, IID_PPV_ARGS(&pSF2New)); teExtract2(pSF2New, lpszPath); pSF2New->Release(); } else { IStream *pStream; ULONG uRead; DWORD dwWriteByte; hr = pSF2->BindToStorage(pidl, NULL, IID_PPV_ARGS(&pStream)); if SUCCEEDED(hr) { LPBYTE lpData = (LPBYTE)CoTaskMemAlloc(SIZE_BUFF); if (lpData) { HANDLE hFile = CreateFile(lpszPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile) { while (SUCCEEDED(pStream->Read(lpData, SIZE_BUFF, &uRead)) && uRead) { WriteFile(hFile, lpData, uRead, &dwWriteByte, NULL); } VariantInit(&v); if SUCCEEDED(pSF2->GetDetailsEx(pidl, &scid, &v) && v.vt == VT_DATE) { if (::VariantTimeToSystemTime(v.date, &SysTime)) { ::SystemTimeToFileTime(&SysTime, &mtime); } } VariantClear(&v); SetFileTime(hFile, NULL, NULL, &mtime); CloseHandle(hFile); hr = S_OK; } else { hr = E_ACCESSDENIED; } teCoTaskMemFree(lpData); } else { hr = E_OUTOFMEMORY; } pStream->Release(); } } ::SysFreeString(bs); delete [] lpszPath; } } teCoTaskMemFree(pidl); } pEnumIDList->Release(); return hr; }