xref: /reactos/dll/shellext/zipfldr/zipfldr.cpp (revision 56582812)
1 /*
2  * PROJECT:     ReactOS Zip Shell Extension
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     zipfldr entrypoint
5  * COPYRIGHT:   Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
6  *              Copyright 2023 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
7  */
8 
9 #include "precomp.h"
10 
11 HMODULE g_hModule = NULL;
12 LONG g_ModuleRefCnt = 0;
13 
14 #include <initguid.h>
15 
16 DEFINE_GUID(CLSID_ZipFolderStorageHandler, 0xe88dcce0, 0xb7b3, 0x11d1, 0xa9, 0xf0, 0x00, 0xaa, 0x00, 0x60, 0xfa, 0x31);
17 DEFINE_GUID(CLSID_ZipFolderSendTo,         0x888dca60, 0xfc0a, 0x11cf, 0x8f, 0x0f, 0x00, 0xc0, 0x4f, 0xd7, 0xd0, 0x62);
18 DEFINE_GUID(CLSID_ZipFolderContextMenu,    0xb8cdcb65, 0xb1bf, 0x4b42, 0x94, 0x28, 0x1d, 0xfd, 0xb7, 0xee, 0x92, 0xaf);
19 DEFINE_GUID(CLSID_ZipFolderRightDragHandler,0xbd472f60, 0x27fa, 0x11cf, 0xb8, 0xb4, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00);
20 DEFINE_GUID(CLSID_ZipFolderDropHandler,    0xed9d80b9, 0xd157, 0x457b, 0x91, 0x92, 0x0e, 0x72, 0x80, 0x31, 0x3b, 0xf0);
21 
22 /* IExplorerCommand: Extract All */
23 DEFINE_GUID(CLSID_ZipFolderExtractAllCommand, 0xc3d9647b, 0x8fd9, 0x4ee6, 0x8b, 0xc7, 0x82, 0x7, 0x80, 0x9, 0x10, 0x5a);
24 
25 
26 class CZipFldrModule : public CComModule
27 {
28 public:
29 };
30 
31 
32 BEGIN_OBJECT_MAP(ObjectMap)
33     OBJECT_ENTRY(CLSID_ZipFolderStorageHandler, CZipFolder)
34     OBJECT_ENTRY(CLSID_ZipFolderContextMenu, CZipFolder)
35     OBJECT_ENTRY(CLSID_ZipFolderSendTo, CSendToZip)
36 END_OBJECT_MAP()
37 
38 CZipFldrModule gModule;
39 
40 
41 #include "minizip/ioapi.h"
42 #include "minizip/iowin32.h"
43 
44 zlib_filefunc64_def g_FFunc;
45 
46 static void init_zlib()
47 {
48     fill_win32_filefunc64W(&g_FFunc);
49 }
50 
51 static BOOL
52 CreateEmptyFile(PCWSTR pszFile)
53 {
54     HANDLE hFile;
55     hFile = CreateFileW(pszFile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
56                         CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
57     if (hFile != INVALID_HANDLE_VALUE)
58     {
59         CloseHandle(hFile);
60         return TRUE;
61     }
62     return FALSE;
63 }
64 
65 static HRESULT
66 CreateSendToZip(PCWSTR pszSendTo)
67 {
68     WCHAR szTarget[MAX_PATH], szSendToFile[MAX_PATH];
69 
70     LoadStringW(g_hModule, IDS_FRIENDLYNAME, szTarget, _countof(szTarget));
71 
72     StringCbCopyW(szSendToFile, sizeof(szSendToFile), pszSendTo);
73     PathAppendW(szSendToFile, szTarget);
74     StringCbCatW(szSendToFile, sizeof(szSendToFile), L".ZFSendToTarget");
75     if (!CreateEmptyFile(szSendToFile))
76     {
77         DPRINT1("CreateEmptyFile('%ls')\n", szSendToFile);
78         return E_FAIL;
79     }
80     return S_OK;
81 }
82 
83 static HRESULT
84 GetDefaultUserSendTo(PWSTR pszPath)
85 {
86     return SHGetFolderPathW(NULL, CSIDL_SENDTO, INVALID_HANDLE_VALUE,
87                             SHGFP_TYPE_DEFAULT, pszPath);
88 }
89 
90 UINT GetZipCodePage(BOOL bUnZip)
91 {
92     WCHAR szValue[16];
93     DWORD dwType, cbValue = sizeof(szValue);
94     UINT nDefaultCodePage = (bUnZip ? CP_ACP : CP_UTF8);
95 
96     LONG error = SHGetValueW(HKEY_CURRENT_USER, L"Software\\ReactOS",
97                              (bUnZip ? L"UnZipCodePage" : L"ZipCodePage"),
98                              &dwType, szValue, &cbValue);
99     if (error != ERROR_SUCCESS)
100         return nDefaultCodePage;
101 
102     if (cbValue == sizeof(DWORD) && (dwType == REG_DWORD || dwType == REG_BINARY))
103         return *(DWORD*)szValue;
104 
105     if (dwType != REG_SZ && dwType != REG_EXPAND_SZ)
106         return nDefaultCodePage;
107 
108     szValue[_countof(szValue) - 1] = UNICODE_NULL;
109     return (UINT)wcstol(szValue, NULL, 0);
110 }
111 
112 EXTERN_C
113 BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
114 {
115     switch (dwReason)
116     {
117     case DLL_PROCESS_ATTACH:
118         DisableThreadLibraryCalls(hInstance);
119         g_hModule = hInstance;
120         gModule.Init(ObjectMap, hInstance, NULL);
121         init_zlib();
122         break;
123     }
124 
125     return TRUE;
126 }
127 
128 STDAPI DllCanUnloadNow()
129 {
130     if (g_ModuleRefCnt)
131         return S_FALSE;
132     return gModule.DllCanUnloadNow();
133 }
134 
135 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
136 {
137     return gModule.DllGetClassObject(rclsid, riid, ppv);
138 }
139 
140 STDAPI DllRegisterServer()
141 {
142     HRESULT hr;
143 
144     hr = gModule.DllRegisterServer(FALSE);
145     if (FAILED_UNEXPECTEDLY(hr))
146         return hr;
147 
148     hr = gModule.UpdateRegistryFromResource(IDR_ZIPFLDR, TRUE, NULL);
149     if (FAILED(hr))
150         return hr;
151 
152     WCHAR szSendTo[MAX_PATH];
153     hr = GetDefaultUserSendTo(szSendTo);
154     if (SUCCEEDED(hr))
155         CreateSendToZip(szSendTo);
156 
157     return S_OK;
158 }
159 
160 STDAPI DllUnregisterServer()
161 {
162     HRESULT hr;
163 
164     hr = gModule.DllUnregisterServer(FALSE);
165     if (FAILED_UNEXPECTEDLY(hr))
166         return hr;
167 
168     hr = gModule.UpdateRegistryFromResource(IDR_ZIPFLDR, FALSE, NULL);
169     if (FAILED(hr))
170         return hr;
171 
172     return S_OK;
173 }
174 
175 EXTERN_C
176 BOOL WINAPI
177 RouteTheCallW(IN HWND hWndOwner, IN HINSTANCE hInstance, IN PCWSTR lpStringArg, IN INT Show)
178 {
179     CStringW path = lpStringArg;
180     PathRemoveBlanksW(path.GetBuffer());
181     path.ReleaseBuffer();
182     path = L"\"" + path + L"\"";
183 
184     WCHAR app[MAX_PATH];
185     GetWindowsDirectoryW(app, _countof(app));
186     PathAppendW(app, L"explorer.exe");
187 
188     ShellExecuteW(NULL, L"open", app, path.GetString(), NULL, Show ? Show : SW_SHOWNORMAL);
189     return TRUE;
190 }
191