@@ -17,12 +17,9 @@ limitations under the License.
1717#ifdef WIN32
1818
1919#include " install_windbg.h"
20+ #include " minizip_extract.h"
2021#include < windows.h>
2122#include < urlmon.h>
22- #include < shlobj.h>
23- #include < objbase.h>
24- #include < shldisp.h>
25- #include < comdef.h>
2623#include < filesystem>
2724#include < fstream>
2825#include < iostream>
@@ -34,9 +31,6 @@ limitations under the License.
3431#include < binaryninjaapi.h>
3532
3633#pragma comment(lib, "urlmon.lib")
37- #pragma comment(lib, "shell32.lib")
38- #pragma comment(lib, "ole32.lib")
39- #pragma comment(lib, "oleaut32.lib")
4034
4135using namespace BinaryNinja ;
4236using namespace std ;
@@ -80,278 +74,25 @@ namespace BinaryNinjaDebugger
8074 }
8175 }
8276
83- // / Extract a ZIP archive using Windows Shell COM interface (secure)
77+ // / Extract a ZIP archive using our custom ZIP extractor
8478 // / @param zipPath Path to the ZIP file
8579 // / @param extractPath Directory where to extract contents
8680 // / @return true if extraction was successful, false otherwise
8781 bool ExtractZip (const std::string& zipPath, const std::string& extractPath)
8882 {
8983 LogInfo (" Extracting %s to %s" , zipPath.c_str (), extractPath.c_str ());
90-
91- // Create destination directory if it doesn't exist
92- std::error_code ec;
93- fs::create_directories (extractPath, ec);
94- if (ec)
95- {
96- LogError (" Failed to create extract directory: %s" , ec.message ().c_str ());
97- return false ;
98- }
99-
100- // Initialize COM
101- HRESULT hr = CoInitialize (nullptr );
102- if (FAILED (hr))
103- {
104- LogError (" Failed to initialize COM: 0x%08x" , hr);
105- return false ;
106- }
107-
108- bool success = false ;
109- try
110- {
111- // Create Shell Application object
112- IShellDispatch* pShellApp = nullptr ;
113- hr = CoCreateInstance (CLSID_Shell, nullptr , CLSCTX_INPROC_SERVER, IID_IShellDispatch, (void **)&pShellApp);
114- if (FAILED (hr))
115- {
116- LogError (" Failed to create Shell Application: 0x%08x" , hr);
117- CoUninitialize ();
118- return false ;
119- }
120-
121- // Convert paths to BSTRs and then to VARIANTs
122- _bstr_t bstrZipPath (zipPath.c_str ());
123- _bstr_t bstrExtractPath (extractPath.c_str ());
124-
125- VARIANT vZipPath, vExtractPath;
126- vZipPath.vt = VT_BSTR;
127- vZipPath.bstrVal = bstrZipPath.Detach ();
128- vExtractPath.vt = VT_BSTR;
129- vExtractPath.bstrVal = bstrExtractPath.Detach ();
130-
131- // Get folder objects
132- Folder* pZipFolder = nullptr ;
133- Folder* pDestFolder = nullptr ;
134-
135- hr = pShellApp->NameSpace (vZipPath, &pZipFolder);
136- if (SUCCEEDED (hr) && pZipFolder)
137- {
138- hr = pShellApp->NameSpace (vExtractPath, &pDestFolder);
139- if (SUCCEEDED (hr) && pDestFolder)
140- {
141- // Get items from zip folder
142- FolderItems* pItems = nullptr ;
143- hr = pZipFolder->Items (&pItems);
144- if (SUCCEEDED (hr) && pItems)
145- {
146- // Copy items with no progress dialog and overwrite existing
147- VARIANT vOptions;
148- vOptions.vt = VT_I4;
149- vOptions.lVal = 0x14 ; // FOF_NOCONFIRMATION | FOF_NOERRORUI
150-
151- hr = pDestFolder->CopyHere (_variant_t (pItems), vOptions);
152- if (SUCCEEDED (hr))
153- {
154- LogInfo (" Successfully extracted ZIP archive using Shell API" );
155- success = true ;
156- }
157- else
158- {
159- LogError (" Shell CopyHere failed: 0x%08x" , hr);
160- }
161-
162- pItems->Release ();
163- }
164- else
165- {
166- LogError (" Failed to get items from zip folder: 0x%08x" , hr);
167- }
168-
169- pDestFolder->Release ();
170- }
171- else
172- {
173- LogError (" Failed to get destination folder: 0x%08x" , hr);
174- }
175-
176- pZipFolder->Release ();
177- }
178- else
179- {
180- LogError (" Failed to open zip file as folder: 0x%08x" , hr);
181- }
182-
183- // Clean up VARIANTs
184- VariantClear (&vZipPath);
185- VariantClear (&vExtractPath);
186-
187- pShellApp->Release ();
188- }
189- catch (...)
190- {
191- LogError (" Exception during ZIP extraction" );
192- }
193-
194- CoUninitialize ();
195- return success;
84+ return ZipExtractor::ExtractAll (zipPath, extractPath);
19685 }
19786
198- // / Extract a specific file from a ZIP archive using Windows Shell COM interface (secure)
87+ // / Extract a specific file from a ZIP archive using our custom ZIP extractor
19988 // / @param zipPath Path to the ZIP file
20089 // / @param fileName Name of file to extract
20190 // / @param extractDir Directory where to extract the file
20291 // / @return Path to extracted file, or empty string if extraction failed
20392 std::string ExtractFileFromZip (const std::string& zipPath, const std::string& fileName, const std::string& extractDir)
20493 {
20594 LogInfo (" Extracting %s from %s" , fileName.c_str (), zipPath.c_str ());
206-
207- // Create destination directory if it doesn't exist
208- std::error_code ec;
209- fs::create_directories (extractDir, ec);
210- if (ec)
211- {
212- LogError (" Failed to create extract directory: %s" , ec.message ().c_str ());
213- return " " ;
214- }
215-
216- // Initialize COM
217- HRESULT hr = CoInitialize (nullptr );
218- if (FAILED (hr))
219- {
220- LogError (" Failed to initialize COM: 0x%08x" , hr);
221- return " " ;
222- }
223-
224- std::string outputPath;
225- try
226- {
227- // Create Shell Application object
228- IShellDispatch* pShellApp = nullptr ;
229- hr = CoCreateInstance (CLSID_Shell, nullptr , CLSCTX_INPROC_SERVER, IID_IShellDispatch, (void **)&pShellApp);
230- if (FAILED (hr))
231- {
232- LogError (" Failed to create Shell Application: 0x%08x" , hr);
233- CoUninitialize ();
234- return " " ;
235- }
236-
237- // Convert paths to BSTRs and then to VARIANTs
238- _bstr_t bstrZipPath (zipPath.c_str ());
239- _bstr_t bstrExtractPath (extractDir.c_str ());
240-
241- VARIANT vZipPath, vExtractPath;
242- vZipPath.vt = VT_BSTR;
243- vZipPath.bstrVal = bstrZipPath.Detach ();
244- vExtractPath.vt = VT_BSTR;
245- vExtractPath.bstrVal = bstrExtractPath.Detach ();
246-
247- // Get folder objects
248- Folder* pZipFolder = nullptr ;
249- Folder* pDestFolder = nullptr ;
250-
251- hr = pShellApp->NameSpace (vZipPath, &pZipFolder);
252- if (SUCCEEDED (hr) && pZipFolder)
253- {
254- hr = pShellApp->NameSpace (vExtractPath, &pDestFolder);
255- if (SUCCEEDED (hr) && pDestFolder)
256- {
257- // Get items from zip folder
258- FolderItems* pItems = nullptr ;
259- hr = pZipFolder->Items (&pItems);
260- if (SUCCEEDED (hr) && pItems)
261- {
262- // Look for specific file
263- long itemCount = 0 ;
264- pItems->get_Count (&itemCount);
265-
266- for (long i = 0 ; i < itemCount; i++)
267- {
268- VARIANT vIndex;
269- vIndex.vt = VT_I4;
270- vIndex.lVal = i;
271-
272- FolderItem* pItem = nullptr ;
273- hr = pItems->Item (vIndex, &pItem);
274- if (SUCCEEDED (hr) && pItem)
275- {
276- BSTR bstrName = nullptr ;
277- hr = pItem->get_Name (&bstrName);
278- if (SUCCEEDED (hr) && bstrName)
279- {
280- _bstr_t itemName (bstrName, false ); // Don't copy, take ownership
281-
282- if (_stricmp (itemName, fileName.c_str ()) == 0 )
283- {
284- // Found the file, extract it
285- VARIANT vOptions;
286- vOptions.vt = VT_I4;
287- vOptions.lVal = 0x14 ; // FOF_NOCONFIRMATION | FOF_NOERRORUI
288-
289- hr = pDestFolder->CopyHere (_variant_t (pItem), vOptions);
290- if (SUCCEEDED (hr))
291- {
292- outputPath = extractDir + " \\ " + fileName;
293- LogInfo (" Successfully extracted %s" , fileName.c_str ());
294- }
295- else
296- {
297- LogError (" Failed to extract file: 0x%08x" , hr);
298- }
299-
300- pItem->Release ();
301- break ;
302- }
303- }
304-
305- pItem->Release ();
306- }
307- }
308-
309- if (outputPath.empty ())
310- {
311- LogError (" File %s not found in ZIP archive" , fileName.c_str ());
312- }
313-
314- pItems->Release ();
315- }
316- else
317- {
318- LogError (" Failed to get items from zip folder: 0x%08x" , hr);
319- }
320-
321- pDestFolder->Release ();
322- }
323- else
324- {
325- LogError (" Failed to get destination folder: 0x%08x" , hr);
326- }
327-
328- pZipFolder->Release ();
329- }
330- else
331- {
332- LogError (" Failed to open zip file as folder: 0x%08x" , hr);
333- }
334-
335- // Clean up VARIANTs
336- VariantClear (&vZipPath);
337- VariantClear (&vExtractPath);
338-
339- pShellApp->Release ();
340- }
341- catch (...)
342- {
343- LogError (" Exception during file extraction" );
344- }
345-
346- CoUninitialize ();
347-
348- // Verify the file exists before returning
349- if (!outputPath.empty () && fs::exists (outputPath))
350- {
351- return outputPath;
352- }
353-
354- return " " ;
95+ return ZipExtractor::ExtractFile (zipPath, fileName, extractDir);
35596 }
35697
35798 // / Get a temporary file path
0 commit comments