forked from reactos/reactos
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[CABVIEW] Add CabView shell extension (reactos#7494)
CORE-14616
- Loading branch information
Showing
31 changed files
with
2,118 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
|
||
spec2def(cabview.dll cabview.spec) | ||
|
||
list(APPEND SOURCE | ||
cabview.cpp | ||
extract.cpp | ||
folder.cpp | ||
resource.h) | ||
|
||
add_library(cabview MODULE | ||
${SOURCE} | ||
cabview.spec | ||
cabview.rc | ||
${CMAKE_CURRENT_BINARY_DIR}/cabview.def) | ||
|
||
set_module_type(cabview win32dll UNICODE) | ||
target_link_libraries(cabview uuid cpprt atl_classes) | ||
set_target_cpp_properties(cabview WITH_EXCEPTIONS) | ||
add_importlibs(cabview cabinet oleaut32 ole32 shlwapi comctl32 shell32 user32 advapi32 msvcrt kernel32 ntdll) | ||
add_pch(cabview precomp.h SOURCE) | ||
add_cd_file(TARGET cabview DESTINATION reactos/system32 FOR all) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* | ||
* PROJECT: ReactOS CabView Shell Extension | ||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) | ||
* PURPOSE: DLL entry point | ||
* COPYRIGHT: Copyright 2024 Whindmar Saksit <[email protected]> | ||
*/ | ||
|
||
#include "cabview.h" | ||
|
||
#include <initguid.h> | ||
DEFINE_GUID(CLSID_CabFolder, 0x0CD7A5C0,0x9F37,0x11CE,0xAE,0x65,0x08,0x00,0x2B,0x2E,0x12,0x62); | ||
|
||
CComModule g_Module; | ||
|
||
BEGIN_OBJECT_MAP(ObjectMap) | ||
OBJECT_ENTRY(CLSID_CabFolder, CCabFolder) | ||
END_OBJECT_MAP() | ||
|
||
EXTERN_C BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) | ||
{ | ||
switch (dwReason) | ||
{ | ||
case DLL_PROCESS_ATTACH: | ||
DisableThreadLibraryCalls(hInstance); | ||
g_Module.Init(ObjectMap, hInstance, NULL); | ||
break; | ||
} | ||
|
||
return TRUE; | ||
} | ||
|
||
STDAPI DllCanUnloadNow() | ||
{ | ||
return g_Module.DllCanUnloadNow(); | ||
} | ||
|
||
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) | ||
{ | ||
return g_Module.DllGetClassObject(rclsid, riid, ppv); | ||
} | ||
|
||
STDAPI DllRegisterServer() | ||
{ | ||
HRESULT hr; | ||
|
||
hr = g_Module.DllRegisterServer(FALSE); | ||
if (FAILED_UNEXPECTEDLY(hr)) | ||
return hr; | ||
|
||
hr = g_Module.UpdateRegistryFromResource(IDR_FOLDER, TRUE, NULL); | ||
if (FAILED(hr)) | ||
return hr; | ||
|
||
return S_OK; | ||
} | ||
|
||
STDAPI DllUnregisterServer() | ||
{ | ||
HRESULT hr1 = g_Module.DllUnregisterServer(FALSE); | ||
HRESULT hr2 = g_Module.UpdateRegistryFromResource(IDR_FOLDER, FALSE, NULL); | ||
if (FAILED_UNEXPECTEDLY(hr1)) | ||
return hr1; | ||
if (FAILED_UNEXPECTEDLY(hr2)) | ||
return hr2; | ||
return S_OK; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,240 @@ | ||
/* | ||
* PROJECT: ReactOS CabView Shell Extension | ||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) | ||
* PURPOSE: Main header file | ||
* COPYRIGHT: Copyright 2024 Whindmar Saksit <[email protected]> | ||
*/ | ||
|
||
#pragma once | ||
#include "precomp.h" | ||
#include "resource.h" | ||
|
||
#define FLATFOLDER TRUE | ||
|
||
EXTERN_C const GUID CLSID_CabFolder; | ||
|
||
enum EXTRACTCALLBACKMSG { ECM_BEGIN, ECM_FILE, ECM_PREPAREPATH, ECM_ERROR }; | ||
struct EXTRACTCALLBACKDATA | ||
{ | ||
LPCWSTR Path; | ||
const FDINOTIFICATION *pfdin; | ||
HRESULT hr; | ||
}; | ||
typedef HRESULT (CALLBACK*EXTRACTCALLBACK)(EXTRACTCALLBACKMSG msg, const EXTRACTCALLBACKDATA &data, LPVOID cookie); | ||
HRESULT ExtractCabinet(LPCWSTR cab, LPCWSTR destination, EXTRACTCALLBACK callback, LPVOID cookie); | ||
|
||
class CEnumIDList : | ||
public CComObjectRootEx<CComMultiThreadModelNoCS>, | ||
public IEnumIDList | ||
{ | ||
protected: | ||
HDPA m_Items; | ||
ULONG m_Pos; | ||
|
||
public: | ||
static int CALLBACK DPADestroyCallback(void *pidl, void *pData) | ||
{ | ||
SHFree(pidl); | ||
return TRUE; | ||
} | ||
|
||
CEnumIDList() : m_Pos(0) | ||
{ | ||
m_Items = DPA_Create(0); | ||
} | ||
|
||
virtual ~CEnumIDList() | ||
{ | ||
DPA_DestroyCallback(m_Items, DPADestroyCallback, NULL); | ||
} | ||
|
||
int FindNamedItem(PCUITEMID_CHILD pidl) const; | ||
HRESULT Fill(LPCWSTR path, HWND hwnd = NULL, SHCONTF contf = 0); | ||
HRESULT Fill(PCIDLIST_ABSOLUTE pidl, HWND hwnd = NULL, SHCONTF contf = 0); | ||
|
||
HRESULT Append(LPCITEMIDLIST pidl) | ||
{ | ||
return DPA_AppendPtr(m_Items, (void*)pidl) != DPA_ERR ? S_OK : E_OUTOFMEMORY; | ||
} | ||
|
||
UINT GetCount() const { return m_Items ? DPA_GetPtrCount(m_Items) : 0; } | ||
|
||
// IEnumIDList | ||
IFACEMETHODIMP Next(ULONG celt, PITEMID_CHILD *rgelt, ULONG *pceltFetched) | ||
{ | ||
if (!rgelt) | ||
return E_INVALIDARG; | ||
HRESULT hr = S_FALSE; | ||
UINT count = GetCount(), fetched = 0; | ||
if (m_Pos < count && fetched < celt) | ||
{ | ||
if (SUCCEEDED(hr = SHILClone(DPA_FastGetPtr(m_Items, m_Pos), &rgelt[fetched]))) | ||
fetched++; | ||
} | ||
if (pceltFetched) | ||
*pceltFetched = fetched; | ||
m_Pos += fetched; | ||
return FAILED(hr) ? hr : (celt == fetched && fetched) ? S_OK : S_FALSE; | ||
} | ||
|
||
IFACEMETHODIMP Reset() | ||
{ | ||
m_Pos = 0; | ||
return S_OK; | ||
} | ||
|
||
IFACEMETHODIMP Skip(ULONG celt) | ||
{ | ||
UINT count = GetCount(), newpos = m_Pos + celt; | ||
if (celt > count || newpos >= count) | ||
return E_INVALIDARG; | ||
m_Pos = newpos; | ||
return S_OK; | ||
} | ||
|
||
IFACEMETHODIMP Clone(IEnumIDList **ppenum) | ||
{ | ||
UNIMPLEMENTED; | ||
*ppenum = NULL; | ||
return E_NOTIMPL; | ||
} | ||
|
||
static CEnumIDList* CreateInstance() | ||
{ | ||
CComPtr<CEnumIDList> obj; | ||
return SUCCEEDED(ShellObjectCreator(obj)) ? obj.Detach() : NULL; | ||
} | ||
|
||
DECLARE_NO_REGISTRY() | ||
DECLARE_NOT_AGGREGATABLE(CEnumIDList) | ||
|
||
BEGIN_COM_MAP(CEnumIDList) | ||
COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList) | ||
END_COM_MAP() | ||
}; | ||
|
||
class CCabFolder : | ||
public CComCoClass<CCabFolder, &CLSID_CabFolder>, | ||
public CComObjectRootEx<CComMultiThreadModelNoCS>, | ||
public IShellFolder2, | ||
public IPersistFolder2, | ||
public IShellFolderViewCB, | ||
public IShellIcon | ||
{ | ||
protected: | ||
CComHeapPtr<ITEMIDLIST> m_CurDir; | ||
HWND m_ShellViewWindow = NULL; | ||
|
||
public: | ||
HRESULT ExtractFilesUI(HWND hWnd, IDataObject *pDO); | ||
HRESULT GetItemDetails(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd, VARIANT *pv); | ||
int MapSCIDToColumn(const SHCOLUMNID &scid); | ||
HRESULT CompareID(LPARAM lParam, PCUITEMID_CHILD pidl1, PCUITEMID_CHILD pidl2); | ||
|
||
HRESULT CreateEnum(CEnumIDList **List) | ||
{ | ||
CEnumIDList *pEIDL = CEnumIDList::CreateInstance(); | ||
*List = pEIDL; | ||
return pEIDL ? pEIDL->Fill(m_CurDir) : E_OUTOFMEMORY; | ||
} | ||
|
||
// IShellFolder2 | ||
IFACEMETHODIMP GetDefaultSearchGUID(GUID *pguid) override | ||
{ | ||
return E_NOTIMPL; | ||
} | ||
|
||
IFACEMETHODIMP EnumSearches(IEnumExtraSearch **ppenum) override | ||
{ | ||
return E_NOTIMPL; | ||
} | ||
|
||
IFACEMETHODIMP GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay) override; | ||
|
||
IFACEMETHODIMP GetDefaultColumnState(UINT iColumn, SHCOLSTATEF *pcsFlags) override; | ||
|
||
IFACEMETHODIMP GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv) override; | ||
|
||
IFACEMETHODIMP GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd) override; | ||
|
||
IFACEMETHODIMP MapColumnToSCID(UINT column, SHCOLUMNID *pscid) override; | ||
|
||
IFACEMETHODIMP ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, ULONG *pchEaten, PIDLIST_RELATIVE *ppidl, ULONG *pdwAttributes) override | ||
{ | ||
UNIMPLEMENTED; | ||
return E_NOTIMPL; | ||
} | ||
|
||
IFACEMETHODIMP EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList) override; | ||
|
||
IFACEMETHODIMP BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut) override; | ||
|
||
IFACEMETHODIMP BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut) override | ||
{ | ||
UNIMPLEMENTED; | ||
return E_NOTIMPL; | ||
} | ||
|
||
IFACEMETHODIMP CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2) override; | ||
|
||
IFACEMETHODIMP CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut) override; | ||
|
||
IFACEMETHODIMP GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, SFGAOF *rgfInOut) override; | ||
|
||
IFACEMETHODIMP GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT *prgfInOut, LPVOID *ppvOut) override; | ||
|
||
IFACEMETHODIMP GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET pName) override; | ||
|
||
IFACEMETHODIMP SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut) override | ||
{ | ||
return E_NOTIMPL; | ||
} | ||
|
||
// IPersistFolder2 | ||
IFACEMETHODIMP GetCurFolder(PIDLIST_ABSOLUTE *pidl) override | ||
{ | ||
LPITEMIDLIST curdir = (LPITEMIDLIST)m_CurDir; | ||
return curdir ? SHILClone(curdir, pidl) : E_UNEXPECTED; | ||
} | ||
|
||
IFACEMETHODIMP Initialize(PCIDLIST_ABSOLUTE pidl) override | ||
{ | ||
WCHAR path[MAX_PATH]; | ||
if (SHGetPathFromIDListW(pidl, path)) | ||
{ | ||
PIDLIST_ABSOLUTE curdir = ILClone(pidl); | ||
if (curdir) | ||
{ | ||
m_CurDir.Attach(curdir); | ||
return S_OK; | ||
} | ||
return E_OUTOFMEMORY; | ||
} | ||
return E_INVALIDARG; | ||
} | ||
|
||
IFACEMETHODIMP GetClassID(CLSID *lpClassId) override | ||
{ | ||
*lpClassId = CLSID_CabFolder; | ||
return S_OK; | ||
} | ||
|
||
// IShellFolderViewCB | ||
IFACEMETHODIMP MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam) override; | ||
|
||
// IShellIcon | ||
IFACEMETHODIMP GetIconOf(PCUITEMID_CHILD pidl, UINT flags, int *pIconIndex) override; | ||
|
||
DECLARE_NO_REGISTRY() | ||
DECLARE_NOT_AGGREGATABLE(CCabFolder) | ||
|
||
BEGIN_COM_MAP(CCabFolder) | ||
COM_INTERFACE_ENTRY_IID(IID_IShellFolder, IShellFolder) | ||
COM_INTERFACE_ENTRY_IID(IID_IShellFolder2, IShellFolder2) | ||
COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist) | ||
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder, IPersistFolder) | ||
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2) | ||
COM_INTERFACE_ENTRY_IID(IID_IShellFolderViewCB, IShellFolderViewCB) | ||
COM_INTERFACE_ENTRY_IID(IID_IShellIcon, IShellIcon) | ||
END_COM_MAP() | ||
}; |
Oops, something went wrong.