[SHELL32][SHLWAPI][SHELL32_APITEST][SDK] Support AssocCreateElement (#9215)

Prepare for CLSID_QueryAssociations.
JIRA issue: CORE-20467
- Add dll/win32/shell32/evalcmd/
  elements.cpp.
- Implement AssocCreateElement
  function in elements.cpp.
- Modify shell32.spec.
- Fix shlwapi!AssocCreate by using
  AssocCreateElement.
- Add SKGetValueW and
  SKSetValueW prototypes into
  <shlwapi_undoc.h>.
- Add AssocCreateElement
  prototype into <shlwapi_undoc.h>.
- Add some CLSIDs into
  <shlguid_undoc.h>.
- Add some resource strings into
  shlwapi.
- Add AssocGetPerceivedType
  prototype into <shlwapi.h>.
- Add AssocCreateElement
  testcase into shell32_apitest.
This commit is contained in:
Katayama Hirofumi MZ
2026-07-04 01:10:31 +09:00
committed by GitHub
parent f66f40ec43
commit 79761d88fd
41 changed files with 2495 additions and 6 deletions
+6 -2
View File
@@ -1,7 +1,11 @@
add_library(evalcmd STATIC evalcmd.cpp)
list(APPEND SOURCE
evalcmd.cpp
elements.cpp)
add_library(evalcmd STATIC ${SOURCE})
add_dependencies(evalcmd psdk)
target_link_libraries(evalcmd PRIVATE pathcch_static)
target_link_libraries(evalcmd PRIVATE wine uuid pathcch_static cppstl)
target_compile_definitions(evalcmd PRIVATE STATIC_PATHCCH)
if(DLL_EXPORT_VERSION GREATER_EQUAL 0x600)
File diff suppressed because it is too large Load Diff
+7 -3
View File
@@ -14,6 +14,10 @@
#include <strsafe.h>
#include <pathcch.h>
#include <assert.h>
#include "evalcmd.h"
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(evalcmd);
#define PATH_VALID_CHARS \
(PATH_CHAR_CLASS_DOT | PATH_CHAR_CLASS_SEMICOLON | PATH_CHAR_CLASS_COMMA | \
@@ -45,7 +49,7 @@ static PCWSTR _PathGetArgsLikeCreateProcess(PCWSTR lpString)
return &lpString[lstrlenW(lpString)];
}
static HRESULT
EXTERN_C HRESULT
_PathCopyExeAndTrimWhiteSpaces(PWSTR pszBuff, size_t cchBuff, PCWSTR pszSrc, size_t cchSrc)
{
HRESULT hr = StringCchCopyNW(pszBuff, cchBuff, pszSrc, cchSrc);
@@ -140,7 +144,7 @@ static HRESULT _PathExeExists(_In_ PCWSTR pszPath)
return S_OK;
}
static HRESULT
EXTERN_C HRESULT
_PathFindInFolder(_In_ INT csidl, _In_ PCWSTR pszSrc, _Out_ PWSTR pszPath, _In_ UINT cchPath)
{
WCHAR szDir[MAX_PATH];
@@ -155,7 +159,7 @@ _PathFindInFolder(_In_ INT csidl, _In_ PCWSTR pszSrc, _Out_ PWSTR pszPath, _In_
return _PathExeExists(pszPath);
}
static HRESULT _PathFindInSystem(_Inout_ PWSTR pszPath, _In_ UINT cchPath)
EXTERN_C HRESULT _PathFindInSystem(_Inout_ PWSTR pszPath, _In_ UINT cchPath)
{
WCHAR szPath[MAX_PATH];
HRESULT hr = _PathFindInFolder(CSIDL_SYSTEM, pszPath, szPath, _countof(szPath));
+7
View File
@@ -0,0 +1,7 @@
#pragma once
// These values must match shlwapi's ones
#define IDS_ANY_FILE 4864
#define IDS_FILE 4865
#define IDS_FOLDER 4866
+1 -1
View File
@@ -326,7 +326,7 @@
761 stub -version=0x600+ -noname SHChangeNotifyDeregisterWindow
762 stub -version=0x600+ -noname Create_IUICommandFromDef
763 stub -version=0x600+ -noname Create_IEnumUICommandFromDefArray
764 stub -version=0x600+ -noname AssocCreateElement
764 stdcall -version=0x600+ -noname AssocCreateElement(ptr ptr ptr)
766 stub -version=0x600+ -noname SHCopyStreamWithProgress
777 stub -version=0x600+ -noname SHGetAssocKeys
778 stub -version=0x600+ -noname AssocGetPropListForExt
+24
View File
@@ -28,6 +28,10 @@
#include "shlguid.h"
#include "shlobj.h"
#include "shlwapi.h"
#ifdef __REACTOS__
#include "shlwapi_undoc.h"
#include "evalcmd.h"
#endif
#include "wine/unicode.h"
#include "wine/debug.h"
@@ -43,6 +47,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell);
ASSOCF_INIT_DEFAULTTOFOLDER)
#endif
#ifdef __REACTOS__
EXTERN_C ULONG WINAPI GetProcessOsVersion(void); // FIXME: Move or delete
#endif
/*************************************************************************
* SHLWAPI_ParamAToW
*
@@ -87,9 +95,11 @@ static BOOL SHLWAPI_ParamAToW(LPCSTR lpszParam, LPWSTR lpszBuff, DWORD dwLen,
* Success: S_OK. lpInterface contains the new object.
* Failure: An HRESULT error code indicating the error.
*
#ifndef __REACTOS__ // WRONG NOTES!
* NOTES
* clsid must be equal to CLSID_QueryAssociations and
* refiid must be equal to IID_IQueryAssociations, IID_IUnknown or this function will fail
#endif
*/
HRESULT WINAPI AssocCreate(CLSID clsid, REFIID refiid, void **lpInterface)
{
@@ -99,10 +109,24 @@ HRESULT WINAPI AssocCreate(CLSID clsid, REFIID refiid, void **lpInterface)
if (!lpInterface)
return E_INVALIDARG;
#ifdef __REACTOS__
*(PVOID*)lpInterface = NULL;
#else
*(DWORD*)lpInterface = 0;
#endif
#ifdef __REACTOS__
if (!IsEqualGUID(&clsid, &CLSID_QueryAssociations) &&
!IsEqualGUID(&clsid, &IID_IQueryAssociations))
{
if (GetProcessOsVersion() < _WIN32_WINNT_VISTA)
return AssocCreateElement(&clsid, refiid, lpInterface);
return CLASS_E_CLASSNOTAVAILABLE;
}
#else
if (!IsEqualGUID(&clsid, &CLSID_QueryAssociations))
return CLASS_E_CLASSNOTAVAILABLE;
#endif
return SHCoCreateInstance( NULL, &clsid, NULL, refiid, lpInterface );
}
+3
View File
@@ -35,6 +35,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -35,6 +35,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -35,6 +35,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -35,6 +35,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -35,6 +35,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -35,6 +35,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s Eo"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -37,6 +37,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -35,6 +35,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -35,6 +35,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -35,6 +35,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "このコンピューターの制限により、この操作は取り消されました。システム管理者にお問い合わせください。"
IDS_RESTRICTIONS "システムの制限"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -35,6 +35,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -35,6 +35,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -35,6 +35,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -35,6 +35,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -36,6 +36,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "Operacja została anulowana ze względu na ograniczenia nałożone na ten komputer. Skontaktuj się z administratorem systemu."
IDS_RESTRICTIONS "Ograniczenia"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -38,6 +38,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -38,6 +38,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EO"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -35,6 +35,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s ЭБ"
IDS_RESTRICTED "Операция отменена из-за ограничений, действующих на этом компьютере. Обратитесь к системному администратору."
IDS_RESTRICTIONS "Ограничения"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -36,6 +36,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -35,6 +35,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -35,6 +35,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -35,6 +35,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -35,6 +35,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -35,6 +35,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -35,6 +35,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+3
View File
@@ -38,6 +38,9 @@ STRINGTABLE
IDS_EB_FORMAT "%s EB"
IDS_RESTRICTED "This operation has been cancelled due to restrictions on this computer. Please contact your system administrator."
IDS_RESTRICTIONS "Restrictions"
IDS_ANY_FILE "%s File"
IDS_FILE "File"
IDS_FOLDER "Folder"
#endif
}
+4
View File
@@ -36,6 +36,10 @@
#define IDS_EB_FORMAT 73
#define IDS_RESTRICTED 283
#define IDS_RESTRICTIONS 284
/* The following three values must match dll/win32/shell32/evalcmd/resource.h's ones */
#define IDS_ANY_FILE 4864
#define IDS_FILE 4865
#define IDS_FOLDER 4866
#endif
/* These numbers match native IDs and shouldn't be arbitrarily changed */
@@ -0,0 +1,582 @@
/*
* PROJECT: ReactOS API tests
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: Tests for AssocCreateElement
* COPYRIGHT: Copyright 2026 Katayama Hirofumi MZ <[email protected]>
*/
#include <apitest.h>
#define WIN32_NO_STATUS
#include <windef.h>
#include <winbase.h>
#include <objbase.h>
#include <shlwapi.h>
#include <shlobj.h>
#include <undocshell.h>
#include <shlobj_undoc.h>
#include <shlguid_undoc.h>
#include <shlwapi_undoc.h>
#include <shellutils.h>
#include <versionhelpers.h>
#define ASSOCQUERY_DE (ASSOCQUERY_DIRECT | ASSOCQUERY_EXISTS)
#define ASSOCQUERY_SDE (ASSOCQUERY_STRING | ASSOCQUERY_DE)
#define ASSOCQUERY_SDED (ASSOCQUERY_SDE | ASSOCQUERY_DWORD)
#define ASSOCQUERY_SDEI (ASSOCQUERY_SDE | ASSOCQUERY_INDIRECT)
#define ASSOCQUERY_SDEEV (ASSOCQUERY_SDE | ASSOCQUERY_EXTRA_VERB)
typedef HRESULT (WINAPI *FN_AssocCreateElement)(REFCLSID, REFIID, PVOID*);
static FN_AssocCreateElement g_fnAssocCreateElement = NULL;
static BOOL g_bVistaPlus = FALSE;
static HRESULT MyAssocCreateElement(REFCLSID rclsid, REFIID riid, PVOID* ppvObj)
{
if (g_fnAssocCreateElement)
return g_fnAssocCreateElement(rclsid, riid, ppvObj);
return AssocCreate(rclsid, riid, ppvObj);
}
struct CLASS_ENTRY
{
const CLSID *pclsid;
PCWSTR pszName;
};
static const CLASS_ENTRY g_Classes[] =
{
{ &CLSID_AssocShellElement, L"AssocShellElement" },
{ &CLSID_AssocApplicationElement, L"AssocApplicationElement" },
{ &CLSID_AssocProgidElement, L"AssocProgidElement" },
{ &CLSID_AssocClsidElement, L"AssocClsidElement" },
{ &CLSID_AssocSystemElement, L"AssocSystemElement" },
{ &CLSID_AssocFolderElement, L"AssocFolderElement" },
{ &CLSID_AssocStarElement, L"AssocStarElement" },
{ &CLSID_AssocPerceivedElement, L"AssocPerceivedElement" },
{ &CLSID_AssocClientElement, L"AssocClientElement" },
};
// Verify that CLASS_E_CLASSNOTAVAILABLE is returned when an unknown CLSID is passed
static void Test_InvalidClsid(void)
{
IUnknown *pUnk = (IUnknown *)(LONG_PTR)0xdeadbeef;
HRESULT hr = MyAssocCreateElement(CLSID_NULL, IID_PPV_ARG(IUnknown, &pUnk));
ok_hex(hr, CLASS_E_CLASSNOTAVAILABLE);
ok(pUnk == NULL, "pUnk should be NULL, got %p\n", pUnk);
}
// For all public CLSIDs, verify that:
// - instantiation succeeds;
// - IPersist / IPersistString2 / IObjectWithQuerySourceOld can be obtained; and
// - GetClassID returns the CLSID passed during instantiation.
static void Test_QueryInterfaceAndClassID(void)
{
HRESULT hr;
for (size_t i = 0; i < _countof(g_Classes); ++i)
{
const CLASS_ENTRY& entry = g_Classes[i];
if (g_bVistaPlus)
{
IAssociationElement *pElement = NULL;
hr = MyAssocCreateElement(*entry.pclsid,
IID_PPV_ARG(IAssociationElement, &pElement));
ok(hr == S_OK, "[%s] AssocCreateElement failed: 0x%08lX\n",
wine_dbgstr_w(entry.pszName), hr);
if (!pElement)
continue;
IPersist *pPersist = NULL;
hr = pElement->QueryInterface(IID_PPV_ARG(IPersist, &pPersist));
ok(hr == S_OK, "[%s] QI(IPersist) failed: 0x%08lX\n",
wine_dbgstr_w(entry.pszName), hr);
if (pPersist)
{
CLSID clsid;
hr = pPersist->GetClassID(&clsid);
ok(hr == S_OK, "[%s] GetClassID failed: 0x%08lX\n",
wine_dbgstr_w(entry.pszName), hr);
ok(IsEqualCLSID(clsid, *entry.pclsid),
"[%s] GetClassID returned an unexpected CLSID\n", wine_dbgstr_w(entry.pszName));
pPersist->Release();
}
IPersistString2 *pPS2 = NULL;
hr = pElement->QueryInterface(IID_PPV_ARG(IPersistString2, &pPS2));
ok(hr == S_OK, "[%s] QI(IPersistString2) failed: 0x%08lX\n",
wine_dbgstr_w(entry.pszName), hr);
if (pPS2)
pPS2->Release();
IObjectWithQuerySourceOld *pOWQS = NULL;
hr = pElement->QueryInterface(IID_PPV_ARG(IObjectWithQuerySourceOld, &pOWQS));
ok(hr == S_OK, "[%s] QI(IObjectWithQuerySourceOld) failed: 0x%08lX\n",
wine_dbgstr_w(entry.pszName), hr);
if (pOWQS)
pOWQS->Release();
pElement->Release();
}
else
{
IAssociationElementOld *pElement = NULL;
hr = MyAssocCreateElement(*entry.pclsid,
IID_PPV_ARG(IAssociationElementOld, &pElement));
ok(hr == S_OK, "[%s] AssocCreateElement failed: 0x%08lX\n",
wine_dbgstr_w(entry.pszName), hr);
if (!pElement)
continue;
IPersist *pPersist = NULL;
hr = pElement->QueryInterface(IID_PPV_ARG(IPersist, &pPersist));
ok(hr == S_OK, "[%s] QI(IPersist) failed: 0x%08lX\n",
wine_dbgstr_w(entry.pszName), hr);
if (pPersist)
{
CLSID clsid;
hr = pPersist->GetClassID(&clsid);
ok(hr == S_OK, "[%s] GetClassID failed: 0x%08lX\n",
wine_dbgstr_w(entry.pszName), hr);
ok(IsEqualCLSID(clsid, *entry.pclsid),
"[%s] GetClassID returned an unexpected CLSID\n", wine_dbgstr_w(entry.pszName));
pPersist->Release();
}
IPersistString2 *pPS2 = NULL;
hr = pElement->QueryInterface(IID_PPV_ARG(IPersistString2, &pPS2));
ok(hr == S_OK, "[%s] QI(IPersistString2) failed: 0x%08lX\n",
wine_dbgstr_w(entry.pszName), hr);
if (pPS2)
pPS2->Release();
IObjectWithQuerySourceOld *pOWQS = NULL;
hr = pElement->QueryInterface(IID_PPV_ARG(IObjectWithQuerySourceOld, &pOWQS));
ok(hr == S_OK, "[%s] QI(IObjectWithQuerySourceOld) failed: 0x%08lX\n",
wine_dbgstr_w(entry.pszName), hr);
if (pOWQS)
pOWQS->Release();
pElement->Release();
}
}
}
// Verify that calling QueryString before SetString results in E_INVALIDARG
static void Test_QueryBeforeInit(void)
{
if (g_bVistaPlus)
{
IAssociationElement *pElement = NULL;
HRESULT hr = MyAssocCreateElement(CLSID_AssocShellElement,
IID_PPV_ARG(IAssociationElement, &pElement));
ok(hr == S_OK, "AssocCreateElement failed: 0x%08lX\n", hr);
if (!pElement)
return;
PWSTR psz = NULL;
_SEH2_TRY
{
hr = pElement->QueryString(ASSOCQUERY_SDEI, NULL, &psz);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
hr = 0xDEAD;
}
_SEH2_END;
ok(hr == 0xDEAD, "hr was 0x%08lX\n", hr);
pElement->Release();
}
else
{
IAssociationElementOld *pElement = NULL;
HRESULT hr = MyAssocCreateElement(CLSID_AssocShellElement,
IID_PPV_ARG(IAssociationElementOld, &pElement));
ok(hr == S_OK, "AssocCreateElement failed: 0x%08lX\n", hr);
if (!pElement)
return;
PWSTR psz = NULL;
hr = pElement->QueryString(ASSOCQUERY_SDEI, NULL, &psz);
ok_hex(hr, E_INVALIDARG);
ok(psz == NULL, "psz should be NULL\n");
pElement->Release();
}
}
// Verify that calling SetString twice results in E_UNEXPECTED
static void Test_DoubleSetString(void)
{
IPersistString2 *pPS2 = NULL;
HRESULT hr = MyAssocCreateElement(CLSID_AssocShellElement,
IID_PPV_ARG(IPersistString2, &pPS2));
ok(hr == S_OK, "AssocCreateElement failed: 0x%08lX\n", hr);
if (!pPS2)
return;
hr = pPS2->SetString(L"txtfile");
ok(hr == S_OK, "First SetString failed: 0x%08lX\n", hr);
hr = pPS2->SetString(L"txtfile");
if (g_bVistaPlus)
ok_hex(hr, S_OK);
else
ok_hex(hr, E_UNEXPECTED);
pPS2->Release();
}
// Retrieve FriendlyTypeName / DefaultIcon using CLSID_AssocShellElement + SetString(L"txtfile")
static void Test_ShellElement_txtfile(void)
{
IPersistString2 *pPS2 = NULL;
HRESULT hr = MyAssocCreateElement(CLSID_AssocShellElement,
IID_PPV_ARG(IPersistString2, &pPS2));
ok(hr == S_OK, "AssocCreateElement(AssocShellElement) failed: 0x%08lX\n", hr);
if (!pPS2)
return;
hr = pPS2->SetString(L"txtfile");
if (hr != S_OK)
{
skip("\"txtfile\" ProgID was not found in HKCR, skipping\n");
pPS2->Release();
return;
}
if (g_bVistaPlus)
{
IAssociationElement *pElement = NULL;
hr = pPS2->QueryInterface(IID_PPV_ARG(IAssociationElement, &pElement));
ok(hr == S_OK, "QI(IAssociationElement) failed: 0x%08lX\n", hr);
if (pElement)
{
PWSTR psz = NULL;
hr = pElement->QueryString(ASSOCQUERY_SDEI, NULL, &psz);
ok(hr == S_OK, "QueryString(FriendlyTypeName) failed: 0x%08lX\n", hr);
ok(psz != NULL && psz[0] != UNICODE_NULL, "Friendly type name is empty\n");
if (psz)
{
trace("txtfile FriendlyTypeName: %s\n", wine_dbgstr_w(psz));
CoTaskMemFree(psz);
}
hr = pElement->QueryExists((ASSOCQUERY_SDE | 0x1), NULL);
ok(hr == S_OK, "QueryExists(DefaultIcon) failed: 0x%08lX\n", hr);
pElement->Release();
}
}
else
{
IAssociationElementOld *pElement = NULL;
hr = pPS2->QueryInterface(IID_PPV_ARG(IAssociationElementOld, &pElement));
ok(hr == S_OK, "QI(IAssociationElementOld) failed: 0x%08lX\n", hr);
if (pElement)
{
PWSTR psz = NULL;
hr = pElement->QueryString(ASSOCQUERY_SDEI, NULL, &psz);
ok(hr == S_OK, "QueryString(FriendlyTypeName) failed: 0x%08lX\n", hr);
ok(psz != NULL && psz[0] != UNICODE_NULL, "Friendly type name is empty\n");
if (psz)
{
trace("txtfile FriendlyTypeName: %s\n", wine_dbgstr_w(psz));
CoTaskMemFree(psz);
}
hr = pElement->QueryExists((ASSOCQUERY_SDE | 0x1), NULL);
ok(hr == S_OK, "QueryExists(DefaultIcon) failed: 0x%08lX\n", hr);
pElement->Release();
}
}
pPS2->Release();
}
// A pattern where you create a custom registry source using QuerySourceCreateFromKey
// instead of SetString, and attach it directly via IObjectWithQuerySource[Old]::SetSource.
static void Test_ShellElement_ExplicitSource(void)
{
HRESULT hr;
if (g_bVistaPlus)
{
IQuerySource *pSource = NULL;
hr = QuerySourceCreateFromKey(HKEY_CLASSES_ROOT, L"txtfile", FALSE,
IID_PPV_ARG(IQuerySource, &pSource));
if (FAILED(hr))
{
skip("QuerySourceCreateFromKey(txtfile) failed: 0x%08lX\n", hr);
return;
}
IObjectWithQuerySource *pOWQS = NULL;
hr = MyAssocCreateElement(CLSID_AssocShellElement,
IID_PPV_ARG(IObjectWithQuerySource, &pOWQS));
ok(hr == S_OK, "AssocCreateElement(AssocShellElement) failed: 0x%08lX\n", hr);
if (pOWQS)
{
hr = pOWQS->SetSource(pSource);
ok(hr == S_OK, "SetSource failed: 0x%08lX\n", hr);
IAssociationElement *pElement = NULL;
hr = pOWQS->QueryInterface(IID_PPV_ARG(IAssociationElement, &pElement));
ok(hr == S_OK, "QI(IAssociationElementOld) failed: 0x%08lX\n", hr);
if (pElement)
{
PWSTR psz = NULL;
hr = pElement->QueryString(ASSOCQUERY_SDEI, NULL, &psz);
ok(hr == S_OK, "QueryString(FriendlyTypeName) failed: 0x%08lX\n", hr);
if (psz)
{
trace("txtfile (explicit source) FriendlyTypeName: %s\n",
wine_dbgstr_w(psz));
CoTaskMemFree(psz);
}
pElement->Release();
}
// The second call to SetSource should result in E_UNEXPECTED
hr = pOWQS->SetSource(pSource);
ok_hex(hr, E_UNEXPECTED);
pOWQS->Release();
}
if (pSource)
pSource->Release();
}
else
{
IQuerySourceOld *pSource = NULL;
hr = QuerySourceCreateFromKey(HKEY_CLASSES_ROOT, L"txtfile", FALSE,
IID_PPV_ARG(IQuerySourceOld, &pSource));
if (FAILED(hr))
{
skip("QuerySourceCreateFromKey(txtfile) failed: 0x%08lX\n", hr);
return;
}
IObjectWithQuerySourceOld *pOWQS = NULL;
hr = MyAssocCreateElement(CLSID_AssocShellElement,
IID_PPV_ARG(IObjectWithQuerySourceOld, &pOWQS));
ok(hr == S_OK, "AssocCreateElement(AssocShellElement) failed: 0x%08lX\n", hr);
if (pOWQS)
{
hr = pOWQS->SetSource(pSource);
ok(hr == S_OK, "SetSource failed: 0x%08lX\n", hr);
IAssociationElementOld *pElement = NULL;
hr = pOWQS->QueryInterface(IID_PPV_ARG(IAssociationElementOld, &pElement));
ok(hr == S_OK, "QI(IAssociationElementOld) failed: 0x%08lX\n", hr);
if (pElement)
{
PWSTR psz = NULL;
hr = pElement->QueryString(ASSOCQUERY_SDEI, NULL, &psz);
ok(hr == S_OK, "QueryString(FriendlyTypeName) failed: 0x%08lX\n", hr);
if (psz)
{
trace("txtfile (explicit source) FriendlyTypeName: %s\n",
wine_dbgstr_w(psz));
CoTaskMemFree(psz);
}
pElement->Release();
}
// The second call to SetSource should result in E_UNEXPECTED
hr = pOWQS->SetSource(pSource);
ok_hex(hr, E_UNEXPECTED);
pOWQS->Release();
}
if (pSource)
pSource->Release();
}
}
// Verify resolution from the file extension using CLSID_AssocProgidElement + SetString(L".txt")
static void Test_ProgidElement_DotTxt(void)
{
IPersistString2 *pPS2 = NULL;
HRESULT hr = MyAssocCreateElement(CLSID_AssocProgidElement,
IID_PPV_ARG(IPersistString2, &pPS2));
ok(hr == S_OK, "AssocCreateElement(AssocProgidElement) failed: 0x%08lX\n", hr);
if (!pPS2)
return;
hr = pPS2->SetString(L".txt");
ok(hr == S_OK || hr == S_FALSE, "SetString(.txt) failed: 0x%08lX\n", hr);
if (g_bVistaPlus)
{
IAssociationElement *pElement = NULL;
HRESULT hr2 = pPS2->QueryInterface(IID_PPV_ARG(IAssociationElement, &pElement));
ok(hr2 == S_OK, "QI(IAssociationElement) failed: 0x%08lX\n", hr2);
if (pElement)
pElement->Release();
}
else
{
IAssociationElementOld *pElement = NULL;
HRESULT hr2 = pPS2->QueryInterface(IID_PPV_ARG(IAssociationElementOld, &pElement));
ok(hr2 == S_OK, "QI(IAssociationElementOld) failed: 0x%08lX\n", hr2);
if (pElement)
{
PWSTR psz = NULL;
HRESULT hr3 = pElement->QueryString(ASSOCQUERY_SDEI, NULL, &psz);
ok(hr3 == S_OK, "QueryString(FriendlyTypeName) for .txt failed: 0x%08lX\n", hr3);
if (psz)
{
trace(".txt FriendlyTypeName: %s\n", wine_dbgstr_w(psz));
CoTaskMemFree(psz);
}
pElement->Release();
}
}
pPS2->Release();
}
// CLSID_AssocStarElement: Verify that the generic "File" name can be retrieved even for
// unknown file extensions
static void Test_StarElement_UnknownExt(void)
{
IPersistString2 *pPS2 = NULL;
HRESULT hr = MyAssocCreateElement(CLSID_AssocStarElement,
IID_PPV_ARG(IPersistString2, &pPS2));
ok(hr == S_OK, "AssocCreateElement(AssocStarElement) failed: 0x%08lX\n", hr);
if (!pPS2)
return;
hr = pPS2->SetString(L".rostestunknownext");
ok(hr == S_OK, "SetString failed: 0x%08lX\n", hr);
if (g_bVistaPlus)
{
IAssociationElement *pElement = NULL;
HRESULT hr2 = pPS2->QueryInterface(IID_PPV_ARG(IAssociationElement, &pElement));
ok(hr2 == S_OK, "QI(IAssociationElement) failed: 0x%08lX\n", hr2);
if (pElement)
{
PWSTR psz = NULL;
HRESULT hr3 = pElement->QueryString(ASSOCQUERY_SDEI, NULL, &psz);
ok(hr3 == S_OK, "QueryString for unknown extension failed: 0x%08lX\n", hr3);
ok(psz != NULL && psz[0] != UNICODE_NULL, "Generic type name is empty\n");
if (psz)
{
trace("Generic file type name: %s\n", wine_dbgstr_w(psz));
CoTaskMemFree(psz);
}
pElement->Release();
}
}
else
{
IAssociationElementOld *pElement = NULL;
HRESULT hr2 = pPS2->QueryInterface(IID_PPV_ARG(IAssociationElementOld, &pElement));
ok(hr2 == S_OK, "QI(IAssociationElementOld) failed: 0x%08lX\n", hr2);
if (pElement)
{
PWSTR psz = NULL;
HRESULT hr3 = pElement->QueryString(ASSOCQUERY_SDEI, NULL, &psz);
ok(hr3 == S_OK, "QueryString for unknown extension failed: 0x%08lX\n", hr3);
ok(psz != NULL && psz[0] != UNICODE_NULL, "Generic type name is empty\n");
if (psz)
{
trace("Generic file type name: %s\n", wine_dbgstr_w(psz));
CoTaskMemFree(psz);
}
pElement->Release();
}
}
pPS2->Release();
}
// CLSID_AssocFolderElement: Always opens HKCR\Folder
static void Test_FolderElement(void)
{
IPersistString2 *pPS2 = NULL;
HRESULT hr = MyAssocCreateElement(CLSID_AssocFolderElement,
IID_PPV_ARG(IPersistString2, &pPS2));
ok(hr == S_OK, "AssocCreateElement(AssocFolderElement) failed: 0x%08lX\n", hr);
if (!pPS2)
return;
hr = pPS2->SetString(L"");
if (g_bVistaPlus)
ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), "SetString hr: 0x%08lX\n", hr);
else
ok(hr == S_OK, "SetString failed: 0x%08lX\n", hr);
if (g_bVistaPlus)
{
IAssociationElement *pElement = NULL;
HRESULT hr2 = pPS2->QueryInterface(IID_PPV_ARG(IAssociationElement, &pElement));
ok(hr2 == S_OK, "QI(IAssociationElement) failed: 0x%08lX\n", hr2);
if (pElement)
{
PWSTR psz = NULL;
HRESULT hr3 = pElement->QueryString(ASSOCQUERY_SDEI, NULL, &psz);
ok(hr3 == S_OK, "QueryString(Folder) failed: 0x%08lX\n", hr3);
if (psz)
{
trace("Folder type name: %s\n", wine_dbgstr_w(psz));
CoTaskMemFree(psz);
}
pElement->Release();
}
}
else
{
IAssociationElementOld *pElement = NULL;
HRESULT hr2 = pPS2->QueryInterface(IID_PPV_ARG(IAssociationElementOld, &pElement));
ok(hr2 == S_OK, "QI(IAssociationElementOld) failed: 0x%08lX\n", hr2);
if (pElement)
{
PWSTR psz = NULL;
HRESULT hr3 = pElement->QueryString(ASSOCQUERY_SDEI, NULL, &psz);
ok(hr3 == S_OK, "QueryString(Folder) failed: 0x%08lX\n", hr3);
if (psz)
{
trace("Folder type name: %s\n", wine_dbgstr_w(psz));
CoTaskMemFree(psz);
}
pElement->Release();
}
}
pPS2->Release();
}
START_TEST(AssocCreateElement)
{
g_bVistaPlus = IsWindowsVistaOrGreater();
HINSTANCE hShell32 = GetModuleHandleW(L"shell32.dll");
g_fnAssocCreateElement =
(FN_AssocCreateElement)GetProcAddress(hShell32, MAKEINTRESOURCEA(764));
if (!g_fnAssocCreateElement)
trace("shell32!AssocCreateElement not found. Using shlwapi!AssocCreate instead...\n");
HRESULT hrCo = CoInitialize(NULL);
Test_InvalidClsid();
Test_QueryInterfaceAndClassID();
Test_QueryBeforeInit();
Test_DoubleSetString();
Test_ShellElement_txtfile();
Test_ShellElement_ExplicitSource();
Test_ProgidElement_DotTxt();
Test_StarElement_UnknownExt();
Test_FolderElement();
if (SUCCEEDED(hrCo))
CoUninitialize();
}
@@ -3,6 +3,7 @@ spec2def(shell32_apitest.exe shell32_apitest.spec)
list(APPEND SOURCE
AddCommas.cpp
AssocCreateElement.cpp
CFSFolder.cpp
CheckEscapes.cpp
CIDLData.cpp
@@ -3,6 +3,7 @@
#include <wine/test.h>
extern void func_AddCommas(void);
extern void func_AssocCreateElement(void);
extern void func_Control_RunDLLW(void);
extern void func_CFSFolder(void);
extern void func_CheckEscapes(void);
@@ -64,6 +65,7 @@ extern void func_StrRStr(void);
const struct test winetest_testlist[] =
{
{ "AddCommas", func_AddCommas },
{ "AssocCreateElement", func_AssocCreateElement },
{ "Control_RunDLLW", func_Control_RunDLLW },
{ "CFSFolder", func_CFSFolder },
{ "CheckEscapes", func_CheckEscapes },
+10
View File
@@ -999,12 +999,22 @@ LWSTDAPI AssocCreate(_In_ CLSID, _In_ REFIID, _Outptr_ LPVOID*);
LWSTDAPI_(BOOL) AssocIsDangerous(_In_ LPCWSTR);
#endif // _WIN32_IE_IE60SP1
typedef INT PERCEIVEDFLAG;
#define PERCEIVEDFLAG_UNDEFINED 0x0000
#define PERCEIVEDFLAG_SOFTCODED 0x0001
#define PERCEIVEDFLAG_HARDCODED 0x0002
#define PERCEIVEDFLAG_NATIVESUPPORT 0x0004
#define PERCEIVEDFLAG_GDIPLUS 0x0010
#define PERCEIVEDFLAG_WMSDK 0x0020
#define PERCEIVEDFLAG_ZIPFOLDER 0x0040
LWSTDAPI AssocQueryStringA(_In_ ASSOCF, _In_ ASSOCSTR, _In_ LPCSTR, _In_opt_ LPCSTR, _Out_writes_opt_(*pcchOut) LPSTR, _Inout_ LPDWORD pcchOut);
LWSTDAPI AssocQueryStringW(_In_ ASSOCF, _In_ ASSOCSTR, _In_ LPCWSTR, _In_opt_ LPCWSTR, _Out_writes_opt_(*pcchOut) LPWSTR, _Inout_ LPDWORD pcchOut);
LWSTDAPI AssocQueryStringByKeyA(_In_ ASSOCF, _In_ ASSOCSTR, _In_ HKEY, _In_opt_ LPCSTR, _Out_writes_opt_(*pcchOut) LPSTR, _Inout_ LPDWORD pcchOut);
LWSTDAPI AssocQueryStringByKeyW(_In_ ASSOCF, _In_ ASSOCSTR, _In_ HKEY, _In_opt_ LPCWSTR, _Out_writes_opt_(*pcchOut) LPWSTR, _Inout_ LPDWORD pcchOut);
LWSTDAPI AssocQueryKeyA(_In_ ASSOCF, _In_ ASSOCKEY, _In_ LPCSTR, _In_opt_ LPCSTR, _Out_ PHKEY);
LWSTDAPI AssocQueryKeyW(_In_ ASSOCF, _In_ ASSOCKEY, _In_ LPCWSTR, _In_opt_ LPCWSTR, _Out_ PHKEY);
LWSTDAPI AssocGetPerceivedType(LPCWSTR lpszExt, PERCEIVED *lpType, INT *lpFlag, LPWSTR *lppszType);
#ifdef UNICODE
#define AssocQueryString AssocQueryStringW
+25
View File
@@ -0,0 +1,25 @@
/*
* PROJECT: ReactOS Shell
* LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
* PURPOSE: SHEvaluateSystemCommandTemplate
* COPYRIGHT: Copyright 2026 Katayama Hirofumi MZ <[email protected]>
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
HRESULT _PathCopyExeAndTrimWhiteSpaces(PWSTR pszBuff, size_t cchBuff,
PCWSTR pszSrc, size_t cchSrc);
HRESULT _PathFindInFolder(_In_ INT csidl, _In_ PCWSTR pszSrc, _Out_ PWSTR pszPath,
_In_ UINT cchPath);
HRESULT _PathFindInSystem(_Inout_ PWSTR pszPath, _In_ UINT cchPath);
HRESULT WINAPI
AssocCreateElement(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ PVOID* ppvObj);
#ifdef __cplusplus
} // extern "C"
#endif
+12
View File
@@ -220,6 +220,16 @@ DEFINE_GUID(POLID_CompareJunctionness, 0xB3AB7D3B, 0x698F, 0x401E,
DEFINE_GUID(IID_IObjectWithRegistryKeyOld, 0x5747C63F, 0x1DE8, 0x423F, 0x98, 0x0F, 0x00, 0xCB, 0x07, 0xF4, 0xC4, 0x5B);
DEFINE_GUID(IID_IObjectWithRegistryKey, 0xD960050C, 0xF4E1, 0x4294, 0xAC, 0x4B, 0x59, 0x89, 0x13, 0x60, 0x59, 0x23);
DEFINE_GUID(CLSID_AssocApplicationElement, 0x0C2BF91B, 0x8746, 0x4FB1, 0xB4, 0xD7, 0x7C, 0x03, 0xF8, 0x90, 0xB1, 0x68);
DEFINE_GUID(CLSID_AssocClientElement, 0x3C81E7FA, 0x1F3B, 0x464A, 0xA3, 0x50, 0x11, 0x4A, 0x25, 0xBE, 0xB2, 0xA2);
DEFINE_GUID(CLSID_AssocClsidElement, 0x57AEA081, 0x5EE9, 0x4C27, 0xB2, 0x18, 0xC4, 0xB7, 0x02, 0x96, 0x4C, 0x54);
DEFINE_GUID(CLSID_AssocFolderElement, 0x7566DF7A, 0x42CC, 0x475D, 0xA0, 0x25, 0x12, 0x05, 0xDD, 0xF4, 0x91, 0x1F);
DEFINE_GUID(CLSID_AssocPerceivedElement, 0x0DC5FB21, 0xB93D, 0x4E3D, 0xBB, 0x2F, 0xCE, 0x4E, 0x36, 0xA7, 0x06, 0x01);
DEFINE_GUID(CLSID_AssocProgidElement, 0x9016D0DD, 0x7C41, 0x46CC, 0xA6, 0x64, 0xBF, 0x22, 0xF7, 0xCB, 0x18, 0x6A);
DEFINE_GUID(CLSID_AssocShellElement, 0xC461837F, 0xEA59, 0x494A, 0xB7, 0xC6, 0xCD, 0x04, 0x0E, 0x37, 0x18, 0x5E);
DEFINE_GUID(CLSID_AssocStarElement, 0x0633B720, 0x6926, 0x404C, 0xB6, 0xB3, 0x92, 0x3B, 0x1A, 0x50, 0x17, 0x43);
DEFINE_GUID(CLSID_AssocSystemElement, 0xA6C4BAAD, 0x4AF5, 0x4191, 0x86, 0x85, 0xC2, 0xC8, 0x95, 0x3A, 0x14, 0x8C);
#define CGID_IExplorerToolbar IID_IExplorerToolbar
#define SID_IExplorerToolbar IID_IExplorerToolbar
#define SID_ITargetFrame2 IID_ITargetFrame2
@@ -231,4 +241,6 @@ DEFINE_GUID(IID_IObjectWithRegistryKey, 0xD960050C, 0xF4E1, 0x4294,
#define SID_IBandSite IID_IBandSite
#define SID_IShellBrowser IID_IShellBrowser
#define IID_IObjectWithQuerySourceOld IID_IObjectWithQuerySource
#endif // __SHLGUID_UNDOC_H
+28
View File
@@ -946,9 +946,37 @@ DECLARE_INTERFACE_(IQuerySource, IUnknown) // {7BC28AC2-0D9C-4941-BB9A-72BECB184
#define IQuerySource_OpenSource(T,a,b) (T)->lpVtbl->OpenSource(T,a,b)
#endif
/*****************************************************************************
* IObjectWithQuerySourceOld interface
*
* @see IObjectWithQuerySource
* @see https://www.geoffchappell.com/studies/windows/shell/shell32/interfaces/iobjectwithquerysource.htm
*/
#define INTERFACE IObjectWithQuerySourceOld
DECLARE_INTERFACE_(IObjectWithQuerySourceOld, IUnknown) // {B3DCB623-4280-4EB1-84B3-8D07E84F299A}
{
/*** IUnknown ***/
STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
/*** IObjectWithQuerySourceOld ***/
STDMETHOD(SetSource)(THIS_ IQuerySourceOld *pSource) PURE;
STDMETHOD(GetSource)(THIS_ REFIID riid, PVOID *ppSource) PURE;
};
#undef INTERFACE
#ifdef COBJMACROS
#define IObjectWithQuerySourceOld_QueryInterface(T,a,b) (T)->lpVtbl->QueryInterface(T,a,b)
#define IObjectWithQuerySourceOld_AddRef(T) (T)->lpVtbl->AddRef(T)
#define IObjectWithQuerySourceOld_Release(T) (T)->lpVtbl->Release(T)
#define IObjectWithQuerySourceOld_SetSource(T,a) (T)->lpVtbl->SetSource(T,a)
#define IObjectWithQuerySourceOld_GetSource(T,a,b) (T)->lpVtbl->GetSource(T,a,b)
#endif
/*****************************************************************************
* IObjectWithQuerySource interface
*
* @see IObjectWithQuerySourceOld
* @see https://www.geoffchappell.com/studies/windows/shell/shell32/interfaces/iobjectwithquerysource.htm
*/
#define INTERFACE IObjectWithQuerySource
+9
View File
@@ -358,6 +358,10 @@ enum _shellkey_flags
};
HKEY WINAPI SHGetShellKey(DWORD flags, LPCWSTR sub_key, BOOL create);
HRESULT WINAPI SKGetValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value, DWORD *type,
void *data, DWORD *count);
HRESULT WINAPI SKSetValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value,
DWORD type, void *data, DWORD count);
int
WINAPIV
@@ -561,6 +565,11 @@ SHWindowsPolicyEx(_In_ REFGUID rpolid, _In_ DWORD dwDefaultValue)
return (SUCCEEDED(hr) ? dwData : dwDefaultValue);
}
#if (NTDDI_VERSION >= NTDDI_LONGHORN) || defined(_SHELL32_)
HRESULT WINAPI
AssocCreateElement(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ PVOID* ppvObj);
#endif
/*****************************************************************************
* ZoneCheck*
*/