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
init_zlib()46 static void init_zlib()
47 {
48 fill_win32_filefunc64W(&g_FFunc);
49 }
50
51 static BOOL
CreateEmptyFile(PCWSTR pszFile)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
CreateSendToZip(PCWSTR pszSendTo)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
GetDefaultUserSendTo(PWSTR pszPath)84 GetDefaultUserSendTo(PWSTR pszPath)
85 {
86 return SHGetFolderPathW(NULL, CSIDL_SENDTO, INVALID_HANDLE_VALUE,
87 SHGFP_TYPE_DEFAULT, pszPath);
88 }
89
GetZipCodePage(BOOL bUnZip)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
DllMain(HINSTANCE hInstance,DWORD dwReason,LPVOID lpReserved)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
DllCanUnloadNow()128 STDAPI DllCanUnloadNow()
129 {
130 if (g_ModuleRefCnt)
131 return S_FALSE;
132 return gModule.DllCanUnloadNow();
133 }
134
DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID * ppv)135 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
136 {
137 return gModule.DllGetClassObject(rclsid, riid, ppv);
138 }
139
DllRegisterServer()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
DllUnregisterServer()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
RouteTheCallW(IN HWND hWndOwner,IN HINSTANCE hInstance,IN PCWSTR lpStringArg,IN INT Show)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