mirror of
https://github.com/reactos/reactos.git
synced 2025-08-02 15:46:52 +00:00
[IEFRAME] Implement URL PIDL (#7850)
This commit is contained in:
parent
13657fdb5b
commit
769462faaa
5 changed files with 417 additions and 0 deletions
|
@ -13,6 +13,7 @@ list(APPEND SOURCE
|
|||
ieframe_main.c
|
||||
iehtmlwnd.c
|
||||
iexplore.c
|
||||
inetfolder.c
|
||||
intshcut.c
|
||||
navigate.c
|
||||
oleobject.c
|
||||
|
|
|
@ -178,6 +178,20 @@ static const IClassFactoryVtbl CUrlHistoryFactoryVtbl = {
|
|||
|
||||
static IClassFactory CUrlHistoryFactory = { &CUrlHistoryFactoryVtbl };
|
||||
|
||||
#ifdef __REACTOS__
|
||||
extern HRESULT WINAPI CInternetFolder_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv);
|
||||
|
||||
static const IClassFactoryVtbl CInternetFolderFactoryVtbl = {
|
||||
ClassFactory_QueryInterface,
|
||||
ClassFactory_AddRef,
|
||||
ClassFactory_Release,
|
||||
CInternetFolder_CreateInstance,
|
||||
ClassFactory_LockServer
|
||||
};
|
||||
|
||||
static IClassFactory CInternetFolderFactory = { &CInternetFolderFactoryVtbl };
|
||||
#endif
|
||||
|
||||
/******************************************************************
|
||||
* DllMain (ieframe.@)
|
||||
*/
|
||||
|
@ -226,6 +240,13 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
|
|||
return IClassFactory_QueryInterface(&CUrlHistoryFactory, riid, ppv);
|
||||
}
|
||||
|
||||
#ifdef __REACTOS__
|
||||
if(IsEqualGUID(&CLSID_Internet, rclsid)) {
|
||||
TRACE("(CLSID_Internet %s %p)\n", debugstr_guid(riid), ppv);
|
||||
return IClassFactory_QueryInterface(&CInternetFolderFactory, riid, ppv);
|
||||
}
|
||||
#endif
|
||||
|
||||
FIXME("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
}
|
||||
|
|
358
dll/win32/ieframe/inetfolder.c
Normal file
358
dll/win32/ieframe/inetfolder.c
Normal file
|
@ -0,0 +1,358 @@
|
|||
/*
|
||||
* PROJECT: ReactOS ieframe
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Internet IShellFolder implementation
|
||||
* COPYRIGHT: Copyright 2025 Whindmar Saksit <whindsaks@proton.me>
|
||||
*/
|
||||
|
||||
#define NONAMELESSUNION
|
||||
|
||||
#include "ieframe.h"
|
||||
|
||||
#include "shlobj.h"
|
||||
#include "shobjidl.h"
|
||||
#include "shellapi.h"
|
||||
#include "shlwapi.h"
|
||||
#include "shlguid.h"
|
||||
#include "intshcut.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ieframe);
|
||||
|
||||
extern int WINAPI SHAnsiToUnicodeCP(UINT CodePage, LPCSTR pszSrc, LPWSTR pwszDst, int cwchBuf);
|
||||
|
||||
#define MAX_URL_LENGTH 1024
|
||||
|
||||
#define PT_INTERNET_URL 0x61
|
||||
#define IFUIF_UNICODE 0x80
|
||||
typedef struct _IFURLITEM
|
||||
{
|
||||
WORD cb;
|
||||
BYTE Type; // PT_INTERNET_URL
|
||||
BYTE Flags; // IFUIF_*
|
||||
UINT Unknown;
|
||||
WCHAR Url[ANYSIZE_ARRAY];
|
||||
} IFURLITEM;
|
||||
|
||||
static int GetSchemeCharType(WCHAR c)
|
||||
{
|
||||
if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))
|
||||
return 0;
|
||||
return c == '+' || c == '-' || c == '.' ? 1 : -1;
|
||||
}
|
||||
|
||||
static unsigned int GetSchemeLength(PCWSTR s)
|
||||
{
|
||||
if (GetSchemeCharType(s[0]) != 0) // The first character MUST be A-Z, a-z.
|
||||
return 0;
|
||||
for (unsigned int i = 0;;)
|
||||
{
|
||||
if (s[++i] == ':')
|
||||
return ++i;
|
||||
if (GetSchemeCharType(s[i]) < 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static LPITEMIDLIST CreateUrlItem(PCWSTR pszUrl)
|
||||
{
|
||||
UINT cch = lstrlenW(pszUrl) + 1;
|
||||
UINT cb = FIELD_OFFSET(IFURLITEM, Url[cch]);
|
||||
IFURLITEM *pidl = SHAlloc(cb + sizeof(WORD));
|
||||
if (!pidl)
|
||||
return (LPITEMIDLIST)pidl;
|
||||
pidl->cb = cb;
|
||||
pidl->Type = PT_INTERNET_URL;
|
||||
pidl->Flags = IFUIF_UNICODE;
|
||||
pidl->Unknown = 0;
|
||||
CopyMemory(pidl->Url, pszUrl, cch * sizeof(*pszUrl));
|
||||
ILGetNext((LPITEMIDLIST)pidl)->mkid.cb = 0;
|
||||
return (LPITEMIDLIST)pidl;
|
||||
}
|
||||
|
||||
static IFURLITEM* IsUrlItem(LPCITEMIDLIST pidl)
|
||||
{
|
||||
IFURLITEM *p = (IFURLITEM*)pidl;
|
||||
if (p && p->cb > FIELD_OFFSET(IFURLITEM, Url) && p->Type == PT_INTERNET_URL)
|
||||
return p;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PWSTR GetUrl(IFURLITEM *pUrl, PWSTR Buffer)
|
||||
{
|
||||
if (pUrl->Flags & IFUIF_UNICODE)
|
||||
return pUrl->Url;
|
||||
SHAnsiToUnicodeCP(CP_ACP, (PCSTR)pUrl->Url, Buffer, MAX_URL_LENGTH);
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
static HRESULT CreateUrlShortcut(PCWSTR Url, IUniformResourceLocatorW **ppv)
|
||||
{
|
||||
HRESULT hr = CoCreateInstance(&CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER,
|
||||
&IID_IUniformResourceLocatorW, (void**)ppv);
|
||||
if (SUCCEEDED(hr))
|
||||
hr = (*ppv)->lpVtbl->SetURL(*ppv, Url, 0);
|
||||
return hr;
|
||||
}
|
||||
|
||||
typedef struct _CInternetFolder
|
||||
{
|
||||
IShellFolder IShellFolder_iface;
|
||||
IPersistFolder IPersistFolder_iface;
|
||||
LONG refCount;
|
||||
} CInternetFolder;
|
||||
|
||||
static HRESULT Unknown_QueryInterface(CInternetFolder *This, REFIID riid, PVOID *ppvObject)
|
||||
{
|
||||
TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppvObject);
|
||||
*ppvObject = NULL;
|
||||
if (IsEqualGUID(&IID_IUnknown, riid))
|
||||
*ppvObject = &This->IShellFolder_iface;
|
||||
else if (IsEqualGUID(&IID_IShellFolder, riid))
|
||||
*ppvObject = &This->IShellFolder_iface;
|
||||
else if (IsEqualGUID(&IID_IPersist, riid) || IsEqualGUID(&IID_IPersistFolder, riid))
|
||||
*ppvObject = &This->IPersistFolder_iface;
|
||||
else
|
||||
return E_NOINTERFACE;
|
||||
IUnknown_AddRef((IUnknown*)*ppvObject);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static ULONG Unknown_AddRef(CInternetFolder *This)
|
||||
{
|
||||
return InterlockedIncrement(&This->refCount);
|
||||
}
|
||||
|
||||
static ULONG Unknown_Release(CInternetFolder *This)
|
||||
{
|
||||
const ULONG count = InterlockedDecrement(&This->refCount);
|
||||
if (count == 0)
|
||||
{
|
||||
SHFree(This);
|
||||
unlock_module();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI ShellFolder_QueryInterface(IShellFolder *This, REFIID riid, PVOID *ppvObject)
|
||||
{
|
||||
return Unknown_QueryInterface(CONTAINING_RECORD(This, CInternetFolder, IShellFolder_iface), riid, ppvObject);
|
||||
}
|
||||
|
||||
static ULONG WINAPI ShellFolder_AddRef(IShellFolder *This)
|
||||
{
|
||||
return Unknown_AddRef(CONTAINING_RECORD(This, CInternetFolder, IShellFolder_iface));
|
||||
}
|
||||
|
||||
static ULONG WINAPI ShellFolder_Release(IShellFolder *This)
|
||||
{
|
||||
return Unknown_Release(CONTAINING_RECORD(This, CInternetFolder, IShellFolder_iface));
|
||||
}
|
||||
|
||||
static HRESULT WINAPI ParseDisplayName(IShellFolder *This, HWND hwnd, IBindCtx *pbc, LPWSTR pszDisplayName, ULONG *pchEaten, PIDLIST_RELATIVE *ppidl, ULONG *pdwAttributes)
|
||||
{
|
||||
UINT len;
|
||||
|
||||
*ppidl = NULL;
|
||||
len = GetSchemeLength(pszDisplayName);
|
||||
if (len)
|
||||
{
|
||||
if (len + 1 == sizeof("shell:"))
|
||||
{
|
||||
WCHAR szBuf[100];
|
||||
lstrcpynW(szBuf, pszDisplayName, sizeof("shell:"));
|
||||
if (!lstrcmpiW(szBuf, L"shell:"))
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if ((*ppidl = CreateUrlItem(pszDisplayName)) == NULL)
|
||||
return E_OUTOFMEMORY;
|
||||
if (pchEaten)
|
||||
*pchEaten = lstrlenW(pszDisplayName);
|
||||
if (pdwAttributes)
|
||||
IShellFolder_GetAttributesOf(This, 1, (PCUITEMID_CHILD_ARRAY)ppidl, pdwAttributes);
|
||||
return S_OK;
|
||||
}
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI ShellFolder_EnumObjects(IShellFolder *This, HWND hwndOwner, SHCONTF grfFlags, IEnumIDList **ppenumIDList)
|
||||
{
|
||||
*ppenumIDList = NULL;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI BindToObject(IShellFolder *This, PCUIDLIST_RELATIVE pidl, IBindCtx *pbc, REFIID riid, void **ppvOut)
|
||||
{
|
||||
*ppvOut = NULL;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI BindToStorage(IShellFolder *This, PCUIDLIST_RELATIVE pidl, IBindCtx *pbc, REFIID riid, void **ppvOut)
|
||||
{
|
||||
*ppvOut = NULL;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI CompareIDs(IShellFolder *This, LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
|
||||
{
|
||||
IFURLITEM *pUrl1 = IsUrlItem(pidl1), *pUrl2 = IsUrlItem(pidl2);
|
||||
if (pUrl1 && pUrl2)
|
||||
{
|
||||
WCHAR szUrl1[MAX_URL_LENGTH], *pszUrl1 = GetUrl(pUrl1, szUrl1);
|
||||
WCHAR szUrl2[MAX_URL_LENGTH], *pszUrl2 = GetUrl(pUrl2, szUrl2);
|
||||
int cmp = lstrcmpiW(pszUrl1, pszUrl2);
|
||||
return cmp < 0 ? 0xffff : cmp != 0;
|
||||
}
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI CreateViewObject(IShellFolder *This, HWND hwndOwner,REFIID riid,void **ppv)
|
||||
{
|
||||
*ppv = NULL;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI GetAttributesOf(IShellFolder *This, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, SFGAOF *rgfInOut)
|
||||
{
|
||||
UINT i;
|
||||
|
||||
if (cidl == 0)
|
||||
{
|
||||
*rgfInOut &= SFGAO_FOLDER | SFGAO_CANLINK | SFGAO_STREAM; // Folder attributes
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
for (i = 0; i < cidl; ++i)
|
||||
{
|
||||
IFURLITEM *pUrl = IsUrlItem(apidl[i]);
|
||||
if (!pUrl)
|
||||
return E_FAIL;
|
||||
*rgfInOut &= SFGAO_CANLINK | SFGAO_BROWSABLE | SFGAO_STREAM;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI GetUIObjectOf(IShellFolder *This, HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT *rgfReserved, void **ppv)
|
||||
{
|
||||
IFURLITEM *pUrl;
|
||||
if (cidl == 1 && (pUrl = IsUrlItem(apidl[0])) != NULL)
|
||||
{
|
||||
if (IsEqualIID(riid, &IID_IExtractIconW) || IsEqualIID(riid, &IID_IExtractIconA) ||
|
||||
IsEqualIID(riid, &IID_IContextMenu) ||
|
||||
IsEqualIID(riid, &IID_IDataObject) ||
|
||||
IsEqualIID(riid, &IID_IQueryInfo))
|
||||
{
|
||||
IUniformResourceLocatorW *pUrlLnk;
|
||||
WCHAR szUrl[MAX_URL_LENGTH], *pszUrl = GetUrl(pUrl, szUrl);
|
||||
HRESULT hr = CreateUrlShortcut(pszUrl, &pUrlLnk);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IUnknown_QueryInterface(pUrlLnk, riid, ppv);
|
||||
IUnknown_Release(pUrlLnk);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI GetDisplayNameOf(IShellFolder *This, PCUITEMID_CHILD pidl, SHGDNF uFlags, STRRET *pSR)
|
||||
{
|
||||
IFURLITEM *pUrl = IsUrlItem(pidl);
|
||||
if (pUrl)
|
||||
{
|
||||
WCHAR szUrl[MAX_URL_LENGTH], *pszUrl = GetUrl(pUrl, szUrl);
|
||||
pSR->uType = STRRET_WSTR;
|
||||
return SHStrDupW(pszUrl, &pSR->u.pOleStr);
|
||||
}
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI SetNameOf(IShellFolder *This, HWND hwndOwner, PCUITEMID_CHILD pidl, LPCWSTR pszName, SHGDNF uFlags, PITEMID_CHILD*ppidlOut)
|
||||
{
|
||||
if (ppidlOut)
|
||||
*ppidlOut = NULL;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI PersistFolder_QueryInterface(IPersistFolder *This, REFIID riid, PVOID *ppvObject)
|
||||
{
|
||||
return Unknown_QueryInterface(CONTAINING_RECORD(This, CInternetFolder, IPersistFolder_iface), riid, ppvObject);
|
||||
}
|
||||
|
||||
static ULONG WINAPI PersistFolder_AddRef(IPersistFolder *This)
|
||||
{
|
||||
return Unknown_AddRef(CONTAINING_RECORD(This, CInternetFolder, IPersistFolder_iface));
|
||||
}
|
||||
|
||||
static ULONG WINAPI PersistFolder_Release(IPersistFolder *This)
|
||||
{
|
||||
return Unknown_Release(CONTAINING_RECORD(This, CInternetFolder, IPersistFolder_iface));
|
||||
}
|
||||
|
||||
static HRESULT WINAPI PersistFolder_GetClassID(IPersistFolder *This, CLSID *pClassID)
|
||||
{
|
||||
*pClassID = CLSID_Internet;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI PersistFolder_Initialize(IPersistFolder *This, PCIDLIST_ABSOLUTE pidl)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const IShellFolderVtbl ShellFolderVtbl = {
|
||||
ShellFolder_QueryInterface,
|
||||
ShellFolder_AddRef,
|
||||
ShellFolder_Release,
|
||||
ParseDisplayName,
|
||||
ShellFolder_EnumObjects,
|
||||
BindToObject,
|
||||
BindToStorage,
|
||||
CompareIDs,
|
||||
CreateViewObject,
|
||||
GetAttributesOf,
|
||||
GetUIObjectOf,
|
||||
GetDisplayNameOf,
|
||||
SetNameOf
|
||||
};
|
||||
|
||||
static const IPersistFolderVtbl PersistFolderVtbl = {
|
||||
PersistFolder_QueryInterface,
|
||||
PersistFolder_AddRef,
|
||||
PersistFolder_Release,
|
||||
PersistFolder_GetClassID,
|
||||
PersistFolder_Initialize
|
||||
};
|
||||
|
||||
static CInternetFolder* CreateInstance(void)
|
||||
{
|
||||
CInternetFolder *obj = SHAlloc(sizeof(CInternetFolder));
|
||||
if (obj)
|
||||
{
|
||||
obj->IShellFolder_iface.lpVtbl = &ShellFolderVtbl;
|
||||
obj->IPersistFolder_iface.lpVtbl = &PersistFolderVtbl;
|
||||
obj->refCount = 1;
|
||||
lock_module();
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
HRESULT WINAPI CInternetFolder_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
|
||||
{
|
||||
CInternetFolder *pThis;
|
||||
|
||||
*ppv = NULL;
|
||||
if (outer)
|
||||
return CLASS_E_NOAGGREGATION;
|
||||
|
||||
if ((pThis = CreateInstance()) != NULL)
|
||||
{
|
||||
HRESULT hr = Unknown_QueryInterface(pThis, riid, ppv);
|
||||
Unknown_Release(pThis);
|
||||
return hr;
|
||||
}
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
|
@ -108,12 +108,15 @@ extern "C" {
|
|||
#define PT_FOLDERTYPEMASK 0x70
|
||||
#define PT_DESKTOP_REGITEM 0x1F // => SHDID_ROOT_REGITEM
|
||||
#define PT_COMPUTER_REGITEM 0x2E // => SHDID_COMPUTER_?
|
||||
#define PT_COMPUTER_DRIVE 0x2F
|
||||
#define PT_FS 0x30 // Win95 SHSimpleIDListFromPath
|
||||
#define PT_FS_FOLDER_FLAG 0x01
|
||||
#define PT_FS_FILE_FLAG 0x02
|
||||
#define PT_FS_UNICODE_FLAG 0x04
|
||||
#define PT_FS_COMMON_FLAG 0x08
|
||||
// PT_NET_REGITEM 0x4? // => SHDID_NET_OTHER
|
||||
#define PT_INTERNET 0x60
|
||||
#define PT_INTERNET_URL 0x61
|
||||
#define PT_CONTROLS_OLDREGITEM 0x70
|
||||
#define PT_CONTROLS_NEWREGITEM 0x71
|
||||
#endif
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
enum {
|
||||
DIRBIT = 1, FILEBIT = 2,
|
||||
PT_COMPUTER_REGITEM = 0x2E,
|
||||
PT_INTERNET_URL = 0x61,
|
||||
};
|
||||
|
||||
static BYTE GetPIDLType(LPCITEMIDLIST pidl)
|
||||
|
@ -48,6 +49,15 @@ static int FileStruct_Att(LPCITEMIDLIST pidl)
|
|||
return p ? p->att : (UINT(1) << 31);
|
||||
}
|
||||
|
||||
static HRESULT GetDisplayNameOf(IShellFolder *pSF, LPCITEMIDLIST pidl, UINT Flags, PWSTR Buf, UINT Cap)
|
||||
{
|
||||
STRRET sr;
|
||||
HRESULT hr = pSF->GetDisplayNameOf(pidl, Flags, &sr);
|
||||
if (SUCCEEDED(hr))
|
||||
hr = StrRetToBufW(&sr, pidl, Buf, Cap);
|
||||
return hr;
|
||||
}
|
||||
|
||||
#define TEST_CLSID(pidl, type, offset, clsid) \
|
||||
do { \
|
||||
ok_long(GetPIDLType(pidl), (type)); \
|
||||
|
@ -195,6 +205,7 @@ START_TEST(ILCreateFromPath)
|
|||
|
||||
START_TEST(PIDL)
|
||||
{
|
||||
CCoInit ComInit;
|
||||
LPITEMIDLIST pidl;
|
||||
|
||||
pidl = SHCloneSpecialIDList(NULL, CSIDL_DRIVES, FALSE);
|
||||
|
@ -210,6 +221,29 @@ START_TEST(PIDL)
|
|||
else
|
||||
skip("?\n");
|
||||
ILFree(pidl);
|
||||
|
||||
|
||||
CComPtr<IShellFolder> pInternet;
|
||||
HRESULT hr = SHCoCreateInstance(NULL, &CLSID_Internet, NULL, IID_PPV_ARG(IShellFolder, &pInternet));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
PCWSTR pszUrl = L"http://example.com/page?query&foo=bar";
|
||||
PIDLIST_RELATIVE pidlUrl;
|
||||
hr = pInternet->ParseDisplayName(NULL, NULL, const_cast<PWSTR>(pszUrl), NULL, &pidlUrl, NULL);
|
||||
ok_long(hr, S_OK);
|
||||
if (hr == S_OK)
|
||||
{
|
||||
ok_int(pidlUrl->mkid.abID[0], PT_INTERNET_URL);
|
||||
WCHAR buf[MAX_PATH];
|
||||
hr = GetDisplayNameOf(pInternet, pidlUrl, SHGDN_FORPARSING, buf, _countof(buf));
|
||||
ok_long(hr, S_OK);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ok(!lstrcmpiW(buf, pszUrl), "FORPARSING must match URL\n");
|
||||
}
|
||||
ILFree(pidlUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(ILIsEqual)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue