diff --git a/dll/win32/shlwapi/CMakeLists.txt b/dll/win32/shlwapi/CMakeLists.txt index 3acd1b127a8..caed6103141 100644 --- a/dll/win32/shlwapi/CMakeLists.txt +++ b/dll/win32/shlwapi/CMakeLists.txt @@ -28,6 +28,7 @@ list(APPEND PCH_SKIP_SOURCE propbag.cpp utils.cpp wsprintf.c + zonechk.c ${CMAKE_CURRENT_BINARY_DIR}/shlwapi_stubs.c) add_library(shlwapi MODULE diff --git a/dll/win32/shlwapi/ordinal.c b/dll/win32/shlwapi/ordinal.c index e0ef146efa0..9086ec8ec23 100644 --- a/dll/win32/shlwapi/ordinal.c +++ b/dll/win32/shlwapi/ordinal.c @@ -5534,6 +5534,7 @@ INT WINAPI SHFormatDateTimeA(const FILETIME UNALIGNED *fileTime, DWORD *flags, return retval; } +#ifndef __REACTOS__ /* See zonechk.c */ /*********************************************************************** * ZoneCheckUrlExW [SHLWAPI.231] * @@ -5558,6 +5559,7 @@ INT WINAPI ZoneCheckUrlExW(LPWSTR szURL, PVOID pUnknown, DWORD dwUnknown2, return 0; } +#endif /*********************************************************************** * SHVerbExistsNA [SHLWAPI.196] diff --git a/dll/win32/shlwapi/shlwapi.spec b/dll/win32/shlwapi/shlwapi.spec index 209299fe389..544e56b7ce9 100644 --- a/dll/win32/shlwapi/shlwapi.spec +++ b/dll/win32/shlwapi/shlwapi.spec @@ -223,16 +223,16 @@ 223 stdcall -noname SHGlobalCounterGetValue(long) 224 stdcall -noname SHGlobalCounterIncrement(long) 225 stdcall -noname SHStripMneumonicW(wstr) -226 stub -noname ZoneCheckPathA -227 stub -noname ZoneCheckPathW -228 stub -noname ZoneCheckUrlA -229 stub -noname ZoneCheckUrlW -230 stub -noname ZoneCheckUrlExA -231 stdcall -noname ZoneCheckUrlExW(wstr ptr long long long long long long) -232 stub -noname ZoneCheckUrlExCacheA -233 stub -noname ZoneCheckUrlExCacheW -234 stub -noname ZoneCheckHost -235 stub -noname ZoneCheckHostEx +226 stdcall -noname ZoneCheckPathA(str long long ptr) +227 stdcall -noname ZoneCheckPathW(wstr long long ptr) +228 stdcall -noname ZoneCheckUrlA(str long long ptr) +229 stdcall -noname ZoneCheckUrlW(wstr long long ptr) +230 stdcall -noname ZoneCheckUrlExA(str ptr long ptr long long long ptr) +231 stdcall -noname ZoneCheckUrlExW(wstr ptr long ptr long long long ptr) +232 stdcall -noname ZoneCheckUrlExCacheA(str ptr long ptr long long long ptr ptr) +233 stdcall -noname ZoneCheckUrlExCacheW(wstr ptr long ptr long long long ptr ptr) +234 stdcall -noname ZoneCheckHost(ptr wstr long) +235 stdcall -noname ZoneCheckHostEx(ptr ptr long ptr long wstr long) 236 stdcall -noname SHPinDllOfCLSID(ptr) 237 stdcall -noname SHRegisterClassW(ptr) 238 stdcall -noname SHUnregisterClassesA(ptr ptr long) diff --git a/dll/win32/shlwapi/shlwapi_main.c b/dll/win32/shlwapi/shlwapi_main.c index 56f9b8c97c2..71e45a8d1f8 100644 --- a/dll/win32/shlwapi/shlwapi_main.c +++ b/dll/win32/shlwapi/shlwapi_main.c @@ -34,8 +34,10 @@ DECLSPEC_HIDDEN HINSTANCE shlwapi_hInstance = 0; DECLSPEC_HIDDEN DWORD SHLWAPI_ThreadRef_index = TLS_OUT_OF_INDEXES; #ifdef __REACTOS__ +extern CRITICAL_SECTION g_csZoneMgrLock; extern CRITICAL_SECTION g_csBagCacheLock; VOID FreeViewStatePropertyBagCache(VOID); +VOID SHLWAPI_DeleteCachedZonesManager(VOID); #endif /************************************************************************* @@ -68,6 +70,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad) shlwapi_hInstance = hinstDLL; SHLWAPI_ThreadRef_index = TlsAlloc(); #ifdef __REACTOS__ + InitializeCriticalSection(&g_csZoneMgrLock); InitializeCriticalSection(&g_csBagCacheLock); #endif break; @@ -75,7 +78,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad) if (fImpLoad) break; #ifdef __REACTOS__ FreeViewStatePropertyBagCache(); + SHLWAPI_DeleteCachedZonesManager(); DeleteCriticalSection(&g_csBagCacheLock); + DeleteCriticalSection(&g_csZoneMgrLock); #endif if (SHLWAPI_ThreadRef_index != TLS_OUT_OF_INDEXES) TlsFree(SHLWAPI_ThreadRef_index); break; diff --git a/dll/win32/shlwapi/zonechk.c b/dll/win32/shlwapi/zonechk.c new file mode 100644 index 00000000000..098e127195f --- /dev/null +++ b/dll/win32/shlwapi/zonechk.c @@ -0,0 +1,347 @@ +/* + * PROJECT: ReactOS Shell + * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later) + * PURPOSE: Implementing ZoneCheck* functions (Internet Zone Manager) + * COPYRIGHT: Copyright 2026 Katayama Hirofumi MZ + */ + +#include +#include +#include +#define NO_SHLWAPI_REG +#include +#include + +WINE_DEFAULT_DEBUG_CHANNEL(zonechk); + +static IClassFactory *g_pZoneMgrCF = NULL; /* Internet Zone Manager's Class Factory (cached) */ +CRITICAL_SECTION g_csZoneMgrLock; /* Guards g_pZoneMgrCF (ReactOS only) */ +static HINSTANCE g_hinstZoneMgr = NULL; /* The module of Zone Manager */ + +static HRESULT +SHLWAPI_GetCachedZonesManagerInner( + _In_ REFIID riid, + _Out_ PVOID *ppv) +{ + HRESULT hr; + IClassFactory *pCF; + + if (!g_pZoneMgrCF) + { + hr = CoGetClassObject(&CLSID_InternetSecurityManager, CLSCTX_INPROC_SERVER, NULL, + &IID_IClassFactory, (PVOID *)&pCF); + if (FAILED(hr)) + { + *ppv = NULL; + return hr; + } + + g_pZoneMgrCF = pCF; + g_hinstZoneMgr = SHPinDllOfCLSID(&CLSID_InternetSecurityManager); + } + + return g_pZoneMgrCF->lpVtbl->CreateInstance(g_pZoneMgrCF, NULL, riid, ppv); +} + +/************************************************************************* + * SHLWAPI_GetCachedZonesManager + * + * An internal helper that caches the InternetSecurityManager's IClassFactory and + * returns an instance of the specified interface. + */ +static HRESULT +SHLWAPI_GetCachedZonesManager( + _In_ REFIID riid, + _Out_ PVOID *ppv) +{ + HRESULT hr; + EnterCriticalSection(&g_csZoneMgrLock); + hr = SHLWAPI_GetCachedZonesManagerInner(riid, ppv); + LeaveCriticalSection(&g_csZoneMgrLock); + return hr; +} + +EXTERN_C VOID SHLWAPI_DeleteCachedZonesManager(VOID) +{ + EnterCriticalSection(&g_csZoneMgrLock); + if (g_pZoneMgrCF) + { + g_pZoneMgrCF->lpVtbl->Release(g_pZoneMgrCF); + g_pZoneMgrCF = NULL; + } + if (g_hinstZoneMgr) + { + FreeLibrary(g_hinstZoneMgr); + g_hinstZoneMgr = NULL; + } + LeaveCriticalSection(&g_csZoneMgrLock); +} + +/************************************************************************* + * SuperPrivate_ZoneCheckPath + * + * An internal helper, used in SHRegisterValidateTemplate + */ +HRESULT SuperPrivate_ZoneCheckPath(PCWSTR pszPath, DWORD dwExpectedZone) +{ + IInternetSecurityManager *pISM; + HRESULT hr = SHLWAPI_GetCachedZonesManager(&IID_IInternetSecurityManager, (PVOID *)&pISM); + if (FAILED(hr)) + return E_ACCESSDENIED; + + DWORD dwRealZone = URLZONE_UNTRUSTED; + hr = pISM->lpVtbl->MapUrlToZone(pISM, pszPath, &dwRealZone, 0); + if (SUCCEEDED(hr) && dwRealZone == dwExpectedZone) + hr = S_OK; + else + hr = E_ACCESSDENIED; + + pISM->lpVtbl->Release(pISM); + return hr; +} + +/************************************************************************* + * ZoneCheckUrlExCacheA [SHLWAPI.232] + */ +HRESULT WINAPI +ZoneCheckUrlExCacheA( + _In_ PCSTR pszUrl, + _Out_writes_bytes_opt_(cbPolicy) PBYTE pbPolicy, + _In_ DWORD cbPolicy, + _In_reads_bytes_opt_(cbContext) PBYTE pbContext, + _In_ DWORD cbContext, + _In_ DWORD dwAction, + _In_ DWORD dwFlags, + _In_opt_ IInternetSecurityMgrSite *pSecuritySite, + _In_opt_ IInternetSecurityManager *pISM) +{ + WCHAR szUrl[2048]; + if (!pszUrl) + { + ERR("pszUrl was NULL\n"); + return E_INVALIDARG; + } + SHAnsiToUnicode(pszUrl, szUrl, _countof(szUrl)); + return ZoneCheckUrlExCacheW(szUrl, pbPolicy, cbPolicy, pbContext, cbContext, + dwAction, dwFlags, pSecuritySite, pISM); +} + +/************************************************************************* + * ZoneCheckUrlExCacheW [SHLWAPI.233] + */ +HRESULT WINAPI +ZoneCheckUrlExCacheW( + _In_ PCWSTR pszUrl, + _Out_writes_bytes_opt_(cbPolicy) PBYTE pbPolicy, + _In_ DWORD cbPolicy, + _In_reads_bytes_opt_(cbContext) PBYTE pbContext, + _In_ DWORD cbContext, + _In_ DWORD dwAction, + _In_ DWORD dwFlags, + _In_opt_ IInternetSecurityMgrSite *pSecuritySite, + _In_opt_ IInternetSecurityManager *pISM) +{ + HRESULT hr; + IInternetSecurityManager *pWorkISM; + DWORD dwPolicyBuf, dwContextBuf; + + if (!pszUrl) + { + ERR("pszUrl was NULL\n"); + return E_INVALIDARG; + } + + if (pISM && pISM->lpVtbl) + hr = pISM->lpVtbl->QueryInterface(pISM, &IID_IInternetSecurityManager, (PVOID *)&pWorkISM); + else + hr = SHLWAPI_GetCachedZonesManager(&IID_IInternetSecurityManager, (PVOID *)&pWorkISM); + + if (FAILED(hr)) + { + ERR("hr: 0x%lX\n", hr); + return hr; + } + + if (pSecuritySite) + pWorkISM->lpVtbl->SetSecuritySite(pWorkISM, pSecuritySite); + + if (!pbContext) + { + dwContextBuf = 0; + pbContext = (PBYTE)&dwContextBuf; + cbContext = sizeof(dwContextBuf); + } + + if (!pbPolicy) + { + dwPolicyBuf = 0; + pbPolicy = (PBYTE)&dwPolicyBuf; + cbPolicy = sizeof(dwPolicyBuf); + } + + hr = pWorkISM->lpVtbl->ProcessUrlAction(pWorkISM, pszUrl, dwAction, pbPolicy, cbPolicy, + pbContext, cbContext, dwFlags, 0); + + if (pSecuritySite) + pWorkISM->lpVtbl->SetSecuritySite(pWorkISM, NULL); + + pWorkISM->lpVtbl->Release(pWorkISM); + return hr; +} + +/************************************************************************* + * ZoneCheckPathA [SHLWAPI.226] + */ +HRESULT WINAPI +ZoneCheckPathA( + _In_ PCSTR pszPath, + _In_ DWORD dwAction, + _In_ DWORD dwFlags, + _In_opt_ IInternetSecurityMgrSite *pSecuritySite) +{ + WCHAR szPath[2048]; + if (!pszPath) + { + ERR("pszPath was NULL\n"); + return E_INVALIDARG; + } + SHAnsiToUnicode(pszPath, szPath, _countof(szPath)); + return ZoneCheckPathW(szPath, dwAction, dwFlags, pSecuritySite); +} + +/************************************************************************* + * ZoneCheckPathW [SHLWAPI.227] + */ +HRESULT WINAPI +ZoneCheckPathW( + _In_ PCWSTR pszPath, + _In_ DWORD dwAction, + _In_ DWORD dwFlags, + _In_opt_ IInternetSecurityMgrSite *pSecuritySite) +{ + return ZoneCheckUrlW(pszPath, dwAction, dwFlags | PUAF_ISFILE, pSecuritySite); +} + +/************************************************************************* + * ZoneCheckUrlA [SHLWAPI.228] + */ +HRESULT WINAPI +ZoneCheckUrlA( + _In_ PCSTR pszUrl, + _In_ DWORD dwAction, + _In_ DWORD dwFlags, + _In_opt_ IInternetSecurityMgrSite *pSecuritySite) +{ + WCHAR szUrl[2048]; + if (!pszUrl) + { + ERR("pszUrl was NULL\n"); + return E_INVALIDARG; + } + SHAnsiToUnicode(pszUrl, szUrl, _countof(szUrl)); + return ZoneCheckUrlW(szUrl, dwAction, dwFlags, pSecuritySite); +} + +/************************************************************************* + * ZoneCheckUrlW [SHLWAPI.229] + */ +HRESULT WINAPI +ZoneCheckUrlW( + _In_ PCWSTR pszUrl, + _In_ DWORD dwAction, + _In_ DWORD dwFlags, + _In_opt_ IInternetSecurityMgrSite *pSecuritySite) +{ + return ZoneCheckUrlExW(pszUrl, NULL, 0, NULL, 0, dwAction, dwFlags, pSecuritySite); +} + +/************************************************************************* + * ZoneCheckUrlExA [SHLWAPI.230] + */ +HRESULT WINAPI +ZoneCheckUrlExA( + _In_ PCSTR pszUrl, + _Out_writes_bytes_opt_(cbPolicy) PBYTE pbPolicy, + _In_ DWORD cbPolicy, + _In_reads_bytes_opt_(cbContext) PBYTE pbContext, + _In_ DWORD cbContext, + _In_ DWORD dwAction, + _In_ DWORD dwFlags, + _In_opt_ IInternetSecurityMgrSite *pSecuritySite) +{ + WCHAR szUrl[2048]; + if (!pszUrl) + { + ERR("pszUrl was NULL\n"); + return E_INVALIDARG; + } + SHAnsiToUnicode(pszUrl, szUrl, _countof(szUrl)); + return ZoneCheckUrlExW(szUrl, pbPolicy, cbPolicy, pbContext, cbContext, + dwAction, dwFlags, pSecuritySite); +} + +/************************************************************************* + * ZoneCheckUrlExW [SHLWAPI.231] + */ +HRESULT WINAPI +ZoneCheckUrlExW( + _In_ PCWSTR pszUrl, + _Out_writes_bytes_opt_(cbPolicy) PBYTE pbPolicy, + _In_ DWORD cbPolicy, + _In_reads_bytes_opt_(cbContext) PBYTE pbContext, + _In_ DWORD cbContext, + _In_ DWORD dwAction, + _In_ DWORD dwFlags, + _In_opt_ IInternetSecurityMgrSite *pSecuritySite) +{ + return ZoneCheckUrlExCacheW(pszUrl, pbPolicy, cbPolicy, pbContext, cbContext, + dwAction, dwFlags, pSecuritySite, NULL); +} + +/************************************************************************* + * ZoneCheckHost [SHLWAPI.234] + */ +HRESULT WINAPI +ZoneCheckHost( + _In_ IInternetSecurityManager *pISM, + _In_ PCWSTR pszUrl, + _In_ DWORD dwAction) +{ + return ZoneCheckHostEx(pISM, NULL, 0, NULL, 0, pszUrl, dwAction); +} + +/************************************************************************* + * ZoneCheckHostEx [SHLWAPI.235] + */ +HRESULT WINAPI +ZoneCheckHostEx( + _In_ IInternetSecurityManager *pISM, + _Out_writes_bytes_opt_(cbPolicy) PBYTE pbPolicy, + _In_ DWORD cbPolicy, + _In_reads_bytes_opt_(cbContext) PBYTE pbContext, + _In_ DWORD cbContext, + _In_ PCWSTR pszUrl, + _In_ DWORD dwAction) +{ + DWORD dwPolicyBuf, dwContextBuf; + + if (!pISM || !pszUrl) + return E_INVALIDARG; + + if (!pbPolicy) + { + dwPolicyBuf = 0; + pbPolicy = (PBYTE)&dwPolicyBuf; + cbPolicy = sizeof(dwPolicyBuf); + } + + if (!pbContext) + { + dwContextBuf = 0; + pbContext = (PBYTE)&dwContextBuf; + cbContext = sizeof(dwContextBuf); + } + + return pISM->lpVtbl->ProcessUrlAction(pISM, pszUrl, dwAction, pbPolicy, cbPolicy, + pbContext, cbContext, 0, 0); +} diff --git a/sdk/include/reactos/shlwapi_undoc.h b/sdk/include/reactos/shlwapi_undoc.h index 89e260a0fc5..549760d3285 100644 --- a/sdk/include/reactos/shlwapi_undoc.h +++ b/sdk/include/reactos/shlwapi_undoc.h @@ -464,6 +464,112 @@ DECLARE_INTERFACE_(IAssociationElementOld, IUnknown) // {E58B1ABF-9596-4DBA-8997 #define IAssociationElementOld_QueryObject(T,a,b,c,d) (T)->lpVtbl->QueryObject(T,a,b,c,d) #endif +/***************************************************************************** + * ZoneCheck* + */ + +HRESULT WINAPI +ZoneCheckUrlExCacheA( + _In_ PCSTR pszUrl, + _Out_writes_bytes_opt_(cbPolicy) PBYTE pbPolicy, + _In_ DWORD cbPolicy, + _In_reads_bytes_opt_(cbContext) PBYTE pbContext, + _In_ DWORD cbContext, + _In_ DWORD dwAction, + _In_ DWORD dwFlags, + _In_opt_ IInternetSecurityMgrSite *pSecuritySite, + _In_opt_ IInternetSecurityManager *pISM); + +HRESULT WINAPI +ZoneCheckUrlExCacheW( + _In_ PCWSTR pszUrl, + _Out_writes_bytes_opt_(cbPolicy) PBYTE pbPolicy, + _In_ DWORD cbPolicy, + _In_reads_bytes_opt_(cbContext) PBYTE pbContext, + _In_ DWORD cbContext, + _In_ DWORD dwAction, + _In_ DWORD dwFlags, + _In_opt_ IInternetSecurityMgrSite *pSecuritySite, + _In_opt_ IInternetSecurityManager *pISM); + +HRESULT WINAPI +ZoneCheckPathA( + _In_ PCSTR pszPath, + _In_ DWORD dwAction, + _In_ DWORD dwFlags, + _In_opt_ IInternetSecurityMgrSite *pSecuritySite); + +HRESULT WINAPI +ZoneCheckPathW( + _In_ PCWSTR pszPath, + _In_ DWORD dwAction, + _In_ DWORD dwFlags, + _In_opt_ IInternetSecurityMgrSite *pSecuritySite); + +HRESULT WINAPI +ZoneCheckUrlA( + _In_ PCSTR pszUrl, + _In_ DWORD dwAction, + _In_ DWORD dwFlags, + _In_opt_ IInternetSecurityMgrSite *pSecuritySite); + +HRESULT WINAPI +ZoneCheckUrlW( + _In_ PCWSTR pszUrl, + _In_ DWORD dwAction, + _In_ DWORD dwFlags, + _In_opt_ IInternetSecurityMgrSite *pSecuritySite); + +HRESULT WINAPI +ZoneCheckUrlExA( + _In_ PCSTR pszUrl, + _Out_writes_bytes_opt_(cbPolicy) PBYTE pbPolicy, + _In_ DWORD cbPolicy, + _In_reads_bytes_opt_(cbContext) PBYTE pbContext, + _In_ DWORD cbContext, + _In_ DWORD dwAction, + _In_ DWORD dwFlags, + _In_opt_ IInternetSecurityMgrSite *pSecuritySite); + +HRESULT WINAPI +ZoneCheckUrlExW( + _In_ PCWSTR pszUrl, + _Out_writes_bytes_opt_(cbPolicy) PBYTE pbPolicy, + _In_ DWORD cbPolicy, + _In_reads_bytes_opt_(cbContext) PBYTE pbContext, + _In_ DWORD cbContext, + _In_ DWORD dwAction, + _In_ DWORD dwFlags, + _In_opt_ IInternetSecurityMgrSite *pSecuritySite); + +HRESULT WINAPI +ZoneCheckHost( + _In_ IInternetSecurityManager *pISM, + _In_ PCWSTR pszUrl, + _In_ DWORD dwAction); + +HRESULT WINAPI +ZoneCheckHostEx( + _In_ IInternetSecurityManager *pISM, + _Out_writes_bytes_opt_(cbPolicy) PBYTE pbPolicy, + _In_ DWORD cbPolicy, + _In_reads_bytes_opt_(cbContext) PBYTE pbContext, + _In_ DWORD cbContext, + _In_ PCWSTR pszUrl, + _In_ DWORD dwAction); + +#ifdef UNICODE + #define ZoneCheckUrlExCache ZoneCheckUrlExCacheW + #define ZoneCheckPath ZoneCheckPathW + #define ZoneCheckUrl ZoneCheckUrlW + #define ZoneCheckUrlEx ZoneCheckUrlExW +#else + #define ZoneCheckUrlExCache ZoneCheckUrlExCacheA + #define ZoneCheckPath ZoneCheckPathA + #define ZoneCheckUrl ZoneCheckUrlA + #define ZoneCheckUrlEx ZoneCheckUrlExA +#endif + #ifdef __cplusplus } /* extern "C" */ #endif