スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
 

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

スポンサーサイト
 

コメント

コメントの投稿

  • URL
  • コメント内容
  • password
  • 秘密
  • 管理者にだけ表示を許可する

トラックバック

トラックバックURL: http://gakana.blog34.fc2.com/tb.php/74-cbcd61c5
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。