OSDN Git Service

Add Expand Different Subfolders menu item (#1964)
[winmerge-jp/winmerge-jp.git] / Src / Merge7zFormatShellImpl.cpp
1 /** 
2  * @file  Merge7zFormatShellImpl.cpp
3  *
4  * @brief Implementation file for Merge7zFormatShellImpl class
5  */
6 #include "pch.h"
7 #include "Merge7zFormatShellImpl.h"
8 #pragma warning (push)                  // prevent "warning C4091: 'typedef ': ignored on left of 'tagGPFIDL_FLAGS' when no variable is declared"
9 #pragma warning (disable:4091)  // VC bug when using XP enabled toolsets.
10 #include <shlobj.h>
11 #pragma warning (pop)
12 #include <ShObjIdl.h>
13 #include <comip.h>
14 #include <vector>
15 #include "unicoder.h"
16 #include "Merge7zFormatRegister.h"
17 #include "paths.h"
18
19 typedef _com_ptr_t<_com_IIID<IFileOperation, &__uuidof(IFileOperation)>> IFileOperationPtr;
20 typedef _com_ptr_t<_com_IIID<IShellItem, &__uuidof(IShellItem)>> IShellItemPtr;
21 typedef _com_ptr_t<_com_IIID<IEnumShellItems, &__uuidof(IEnumShellItems)>> IEnumShellItemsPtr;
22
23 static Merge7zFormatRegister g_autoregister(&Merge7zFormatShellImpl::GuessFormat);
24 static Merge7zFormatShellImpl g_shellformat;
25
26 static HRESULT MySHCreateShellItemFromPath(PCWSTR pszPath, IShellItem **ppShellItem)
27 {
28         PIDLIST_ABSOLUTE pidl;
29         HRESULT hr = SHParseDisplayName(pszPath, nullptr, &pidl, 0, nullptr);
30         if (FAILED(hr))
31                 return hr;
32         hr = SHCreateShellItem(nullptr, nullptr, pidl, ppShellItem);
33         ILFree(pidl);
34         return hr;
35 }
36
37 struct IEnumShellItems;
38
39 static HRESULT MySHCreateEnumShellItemsFromPath(PCWSTR pszPath, IEnumShellItems **ppEnumShellItems)
40 {
41         IShellItemPtr pShellItem;
42         HRESULT hr = MySHCreateShellItemFromPath(pszPath, &pShellItem);
43         if (FAILED(hr))
44                 return hr;
45         return pShellItem->BindToHandler(nullptr, BHID_EnumItems, IID_PPV_ARGS(ppEnumShellItems));
46 }
47
48 Merge7z::Format *Merge7zFormatShellImpl::GuessFormat(const String& path)
49 {
50         if (!paths::IsURL(path))
51         {
52                 int i;
53                 static const tchar_t *exts[] = {_T(".zip"), _T(".lzh"), _T("::{")};
54                 for (i = 0; i < sizeof(exts) / sizeof(exts[0]); ++i)
55                 {
56                         if (path.find(exts[i]) != String::npos)
57                                 break;
58                 }
59                 if (i == sizeof(exts)/sizeof(exts[0]))
60                         return nullptr;
61         }
62         else
63         {
64                 if (path.find(_T("ftp://")) == String::npos)
65                         return nullptr;
66         }
67         IEnumShellItemsPtr pEnumShellItems;
68         if (FAILED(MySHCreateEnumShellItemsFromPath(ucr::toUTF16(path).c_str(), &pEnumShellItems)))
69                 return nullptr;
70         return &g_shellformat;
71 }
72
73 HRESULT Merge7zFormatShellImpl::DeCompressArchive(HWND, LPCTSTR path, LPCTSTR folder)
74 {
75         IFileOperationPtr pFileOperation;
76         HRESULT hr = pFileOperation.CreateInstance(CLSID_FileOperation, nullptr, CLSCTX_ALL);
77         if (FAILED(hr))
78                 return hr;
79
80         pFileOperation->SetOperationFlags(0);
81
82         IShellItemPtr pShellItemDest, pShellItem;
83         IEnumShellItemsPtr pEnumShellItems;
84         ULONG ulRetNo;
85
86         hr = MySHCreateShellItemFromPath(ucr::toUTF16(folder).c_str(), &pShellItemDest);
87         if (FAILED(hr))
88                 return hr;
89         hr = MySHCreateEnumShellItemsFromPath(ucr::toUTF16(path).c_str(), &pEnumShellItems);
90         if (FAILED(hr))
91                 return hr;
92
93         while ((hr = pEnumShellItems->Next(1, &pShellItem, &ulRetNo)) == NOERROR)
94         {
95                 pFileOperation->CopyItem(pShellItem, pShellItemDest, nullptr, nullptr);
96                 pShellItem.Release();
97         }
98         if (FAILED(hr))
99                 return hr;
100
101         return pFileOperation->PerformOperations();
102 }
103
104 HRESULT Merge7zFormatShellImpl::CompressArchive(HWND, LPCTSTR path, Merge7z::DirItemEnumerator *)
105 {
106         return E_FAIL;
107 }
108
109 Merge7z::Format::Inspector *Merge7zFormatShellImpl::Open(HWND, LPCTSTR) { return nullptr; }
110 Merge7z::Format::Updater *Merge7zFormatShellImpl::Update(HWND, LPCTSTR) { return nullptr; }
111 HRESULT Merge7zFormatShellImpl::GetHandlerProperty(HWND, PROPID, PROPVARIANT *, VARTYPE) { return E_FAIL; }
112 BSTR Merge7zFormatShellImpl::GetHandlerName(HWND) { return nullptr; }
113 BSTR Merge7zFormatShellImpl::GetHandlerClassID(HWND) { return nullptr; }
114 BSTR Merge7zFormatShellImpl::GetHandlerExtension(HWND) { return nullptr; }
115 BSTR Merge7zFormatShellImpl::GetHandlerAddExtension(HWND) { return nullptr; }
116 VARIANT_BOOL Merge7zFormatShellImpl::GetHandlerUpdate(HWND) { return VARIANT_FALSE; }
117 VARIANT_BOOL Merge7zFormatShellImpl::GetHandlerKeepName(HWND) { return VARIANT_FALSE; }
118
119 BSTR Merge7zFormatShellImpl::GetDefaultName(HWND, LPCTSTR path)
120 {
121         return SysAllocString(L"");
122 }