タブファイラー開発ブログ

Tablacus ExplorerやX-Finderの作者のブログ

ZIPフォルダ内をIShellFolder2で列挙してみた。

前回はIStorageでの列挙でしたが、今回はIShellFolder2→IEnumIDListで列挙できるか試してみました。 IStreamの取得もIShellFolder2->BindToStorageでできました。 ItemIDListからファイル名に変換する場合はIStorageでの列挙の方が簡単ですね。 そして、IShellFolderとIStorageって両方使える場合が多そうな感じがします。 ファイル名や更新日時しか取得しないのであれば、普通のフォルダもIShellFolderの代わりにIStorageで列挙したほうが簡単かも。 IStorage版はTablacus ExploerのソースのteExtractをご覧ください。

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; }