mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 16:32:59 +00:00
[SHLWAPI][SDK][BOOTDATA] Implement SHGetAppCompatFlags (#8137)
Compatibility is a key that the system works well. JIRA issue: CORE-19278 - Add appcompat.c. - Implement SHGetAppCompatFlags function. - Add Str_SetPtrA prototype to <commctrl.h>. - Add SHACF_... flags to <shlwapi_undoc.h>. - Add comctl32 delay import (for Str_SetPtrA). - Modify boot/bootdata/hivesft.inf for registry key HRESULTKLM\SOFTWARE\Microsoft\ Windows\CurrentVersion\ ShellCompatibility\Applications.
This commit is contained in:
parent
1a11aa059f
commit
b199e9d05f
6 changed files with 595 additions and 5 deletions
|
@ -222,6 +222,85 @@ HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies",,0x00000012
|
|||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer","NoSimpleStartMenu",0x00010003,1
|
||||
|
||||
; Application compatibility
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\coolcat.exe",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\coolcat.exe","Version",2,"4.*"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\coolcat.exe","ANSIDISPLAYNAMES",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\coreldrw.exe",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\coreldrw.exe","Version",2,"9.*"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\coreldrw.exe","OLDREGITEMGDN",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\creatr32.exe",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\creatr32.exe","Version",2,"3.*"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\creatr32.exe","MYCOMPUTERFIRST",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\creatr32.exe","WIN95DEFVIEW",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\creatr32.exe","OLDCREATEVIEWWND",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\creatr32.exe","IGNOREENUMRESET",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\creatr32.exe","RequiredFile",2,"trkwrite.dll"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\cutftp32.exe",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\cutftp32.exe","Version",2,"3.*"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\cutftp32.exe","OLDREGITEMGDN",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\diskjockey.exe",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\diskjockey.exe","Version",2,"2,*"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\diskjockey.exe","OLDREGITEMGDN",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\dlwin.exe",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\dlwin.exe\DownLoader 6.*",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\dlwin.exe\DownLoader 6.*","Version",2,"6.*"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\dlwin.exe\DownLoader 6.*","FILEOPENBOGUSCTRLID",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\dlwin.exe\DownLoader 7.01",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\dlwin.exe\DownLoader 7.01","Version",2,"7.*"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\dlwin.exe\DownLoader 7.01","FILEOPENBOGUSCTRLID",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\fusion.exe",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\fusion.exe","Version",2,"5.*"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\fusion.exe","FILEOPENNEEDSEXT",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\install.exe",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\install.exe\Starcraft 1.03",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\install.exe\Starcraft 1.03","RequiredFile",2,"help\\star.htm"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\install.exe\Starcraft 1.03","Version",2,"Version 1.03"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\install.exe\Starcraft 1.03","OLDREGITEMGDN",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\msdev.exe",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\msdev.exe","Version",2,"6.*"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\msdev.exe","FILEOPENNEEDSEXT",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\mswin.exe",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\mswin.exe\Metastock 6.*",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\mswin.exe\Metastock 6.*","Version",2,"6.*"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\mswin.exe\Metastock 6.*","FILEOPENBOGUSCTRLID",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\mswin.exe\Metastock 7.01",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\mswin.exe\Metastock 7.01","Version",2,"7.*"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\mswin.exe\Metastock 7.01","FILEOPENBOGUSCTRLID",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\photoed.exe",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\photoed.exe","Version",2,"3.*"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\photoed.exe","FILEOPENNEEDSEXT",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\pwrplay.exe",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\pwrplay.exe","Version",2,"6.*"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\pwrplay.exe","FILEOPENBOGUSCTRLID",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\qstitch.exe",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\qstitch.exe","Version",2,"1,*"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\qstitch.exe","WIN95BINDTOOBJECT",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\qstitch.exe\Version 2",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\qstitch.exe\Version 2","Version",2,"2.*"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\qstitch.exe\Version 2","WIN95BINDTOOBJECT",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\recycle.exe",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\recycle.exe","Version",2,"1,*"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\recycle.exe","FILEOPENNEEDSEXT",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\sesapp.exe",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\sesapp.exe","Version",2,"3.*"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\sesapp.exe","OLDREGITEMGDN",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\snapshot.exe",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\snapshot.exe","RequiredFile",2,"ssres.dll"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\snapshot.exe","Version",2,"1.*"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\snapshot.exe","LOADCOLUMNHANDLER",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\trace.exe",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\trace.exe","Version",2,"9.*"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\trace.exe","OLDREGITEMGDN",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\uni.exe",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\uni.exe","Version",2,"5, 5,*"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\uni.exe","ANSIDISPLAYNAMES",2,""
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\vcafe.exe",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\vcafe.exe","Version",2,"4.0"
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellCompatibility\Applications\vcafe.exe","FORCELFNIDLIST",2,""
|
||||
|
||||
; Extra Control Panel Applets
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Control Panel\Cpls",,0x00000012
|
||||
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Control Panel\Cpls","Console",0x00020000,"%SystemRoot%\system32\console.dll"
|
||||
|
|
|
@ -8,6 +8,7 @@ add_definitions(
|
|||
spec2def(shlwapi.dll shlwapi.spec ADD_IMPORTLIB)
|
||||
|
||||
list(APPEND SOURCE
|
||||
appcompat.c
|
||||
clist.c
|
||||
istream.c
|
||||
msgbox.c
|
||||
|
@ -50,7 +51,7 @@ add_dependencies(shlwapi_autocomp psdk)
|
|||
|
||||
set_module_type(shlwapi win32dll UNICODE)
|
||||
target_link_libraries(shlwapi uuid wine cpprt)
|
||||
add_delay_importlibs(shlwapi userenv oleaut32 ole32 comdlg32 mpr mlang urlmon shell32 winmm version)
|
||||
add_delay_importlibs(shlwapi userenv oleaut32 ole32 comctl32 comdlg32 mpr mlang urlmon shell32 winmm version)
|
||||
add_importlibs(shlwapi user32 gdi32 advapi32 wininet msvcrt kernel32 ntdll)
|
||||
add_pch(shlwapi precomp.h "${PCH_SKIP_SOURCE}")
|
||||
add_cd_file(TARGET shlwapi DESTINATION reactos/system32 FOR all)
|
||||
|
|
472
dll/win32/shlwapi/appcompat.c
Normal file
472
dll/win32/shlwapi/appcompat.c
Normal file
|
@ -0,0 +1,472 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Shell
|
||||
* LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
|
||||
* PURPOSE: Shell application compatibility flags
|
||||
* COPYRIGHT: Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
#include <winreg.h>
|
||||
#include <winver.h>
|
||||
#include <commctrl.h>
|
||||
#include <shlwapi_undoc.h>
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||
|
||||
// Indicates if the compatibility system has been initialized
|
||||
static BOOL g_fAppCompatInitialized = FALSE;
|
||||
|
||||
static DWORD g_dwAppCompatFlags = 0; // Cached compatibility flags
|
||||
|
||||
// SHACF flags and their corresponding names
|
||||
typedef struct tagFLAGMAP
|
||||
{
|
||||
DWORD flags;
|
||||
LPCSTR name;
|
||||
} FLAGMAP, *PFLAGMAP;
|
||||
static FLAGMAP g_appCompatFlagMaps[] =
|
||||
{
|
||||
{ SHACF_CONTEXTMENU, "CONTEXTMENU" },
|
||||
{ SHACF_CORELINTERNETENUM, "CORELINTERNETENUM" },
|
||||
{ SHACF_OLDCREATEVIEWWND, "OLDCREATEVIEWWND" },
|
||||
{ SHACF_WIN95DEFVIEW, "WIN95DEFVIEW" },
|
||||
{ SHACF_DOCOBJECT, "DOCOBJECT" },
|
||||
{ SHACF_FLUSHNOWAITALWAYS, "FLUSHNOWAITALWAYS" },
|
||||
{ SHACF_MYCOMPUTERFIRST, "MYCOMPUTERFIRST" },
|
||||
{ SHACF_OLDREGITEMGDN, "OLDREGITEMGDN" },
|
||||
{ SHACF_LOADCOLUMNHANDLER, "LOADCOLUMNHANDLER" },
|
||||
{ SHACF_ANSI, "ANSI" },
|
||||
{ SHACF_STAROFFICE5PRINTER, "STAROFFICE5PRINTER" },
|
||||
{ SHACF_NOVALIDATEFSIDS, "NOVALIDATEFSIDS" },
|
||||
{ SHACF_WIN95SHLEXEC, "WIN95SHLEXEC" },
|
||||
{ SHACF_FILEOPENNEEDSEXT, "FILEOPENNEEDSEXT" },
|
||||
{ SHACF_WIN95BINDTOOBJECT, "WIN95BINDTOOBJECT" },
|
||||
{ SHACF_IGNOREENUMRESET, "IGNOREENUMRESET" },
|
||||
{ SHACF_ANSIDISPLAYNAMES, "ANSIDISPLAYNAMES" },
|
||||
{ SHACF_FILEOPENBOGUSCTRLID, "FILEOPENBOGUSCTRLID" },
|
||||
{ SHACF_FORCELFNIDLIST, "FORCELFNIDLIST" },
|
||||
};
|
||||
|
||||
// Get compatibility flags from registry values
|
||||
static DWORD
|
||||
SHLWAPI_GetMappedFlags(_In_ HKEY hKey, _In_ const FLAGMAP *pEntries, _In_ UINT nEntries)
|
||||
{
|
||||
DWORD flags = 0;
|
||||
for (UINT iEntry = 0; iEntry < nEntries; ++iEntry)
|
||||
{
|
||||
DWORD error = SHGetValueA(hKey, NULL, pEntries[iEntry].name, NULL, NULL, NULL);
|
||||
if (error == ERROR_SUCCESS)
|
||||
flags |= pEntries[iEntry].flags;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
#define MAJOR_VER_ONLY "\x01" // A mark to indicate that only major version will be compared.
|
||||
|
||||
// App compatibility info
|
||||
// Extracted from: https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/util/getappcompatflags.htm
|
||||
typedef struct tagAPPCOMPATINFO
|
||||
{
|
||||
PCSTR pszAppName;
|
||||
PCSTR pszAppVersion;
|
||||
DWORD dwCompatFlags;
|
||||
} APPCOMPATINFO, *PAPPCOMPATINFO;
|
||||
static APPCOMPATINFO g_appCompatInfo[] =
|
||||
{
|
||||
{ "abcmm.exe", NULL, SHACF_LOADCOLUMNHANDLER },
|
||||
{ "autorun.exe", "4.00.950", SHACF_ANSI },
|
||||
{ "autorun.exe", "4.10.1998", SHACF_ANSI },
|
||||
{ "coreldrw.exe", MAJOR_VER_ONLY "7", SHACF_OLDREGITEMGDN },
|
||||
{ "dad9.exe", MAJOR_VER_ONLY "9", SHACF_CORELINTERNETENUM },
|
||||
{ "filler51.exe", NULL, SHACF_OLDREGITEMGDN },
|
||||
{ "hotdog4.exe", NULL, SHACF_DOCOBJECT },
|
||||
{ "msmoney.exe", "7.05.1107", SHACF_WIN95SHLEXEC },
|
||||
{ "pdexplo.exe", MAJOR_VER_ONLY "1", SHACF_CONTEXTMENU | SHACF_MYCOMPUTERFIRST },
|
||||
{ "pdexplo.exe", MAJOR_VER_ONLY "2", SHACF_CONTEXTMENU | SHACF_MYCOMPUTERFIRST },
|
||||
{ "pdexplo.exe", MAJOR_VER_ONLY "3", SHACF_MYCOMPUTERFIRST | SHACF_OLDREGITEMGDN },
|
||||
{ "pdxwin32.exe", NULL, SHACF_CONTEXTMENU | SHACF_CORELINTERNETENUM | SHACF_OLDREGITEMGDN },
|
||||
{ "pfim80.exe", NULL, SHACF_CONTEXTMENU | SHACF_CORELINTERNETENUM | SHACF_OLDREGITEMGDN },
|
||||
{ "powerpnt.exe", MAJOR_VER_ONLY "8", SHACF_WIN95SHLEXEC },
|
||||
{ "pp70.exe", NULL, SHACF_LOADCOLUMNHANDLER },
|
||||
{ "pp80.exe", NULL, SHACF_LOADCOLUMNHANDLER },
|
||||
{ "prwin70.exe", NULL, SHACF_CONTEXTMENU | SHACF_CORELINTERNETENUM },
|
||||
{ "prwin8.exe", NULL, SHACF_CORELINTERNETENUM | SHACF_OLDREGITEMGDN },
|
||||
{ "prwin9.exe", MAJOR_VER_ONLY "9", SHACF_CORELINTERNETENUM },
|
||||
{ "ps80.exe", NULL, SHACF_CONTEXTMENU | SHACF_CORELINTERNETENUM | SHACF_OLDREGITEMGDN },
|
||||
{ "ps80.exe", NULL, SHACF_OLDREGITEMGDN },
|
||||
{ "qfinder.exe", NULL, SHACF_CORELINTERNETENUM | SHACF_OLDREGITEMGDN },
|
||||
{ "qpw.exe", MAJOR_VER_ONLY "7", SHACF_CONTEXTMENU },
|
||||
{ "qpw.exe", MAJOR_VER_ONLY "8", SHACF_CORELINTERNETENUM | SHACF_OLDREGITEMGDN | SHACF_ANSIDISPLAYNAMES },
|
||||
{ "qpw.exe", MAJOR_VER_ONLY "9", SHACF_CORELINTERNETENUM },
|
||||
{ "rnaapp.exe", NULL, SHACF_CONTEXTMENU },
|
||||
{ "sitebuilder.exe", NULL, SHACF_CONTEXTMENU | SHACF_CORELINTERNETENUM | SHACF_OLDREGITEMGDN },
|
||||
{ "sizemgr.exe", MAJOR_VER_ONLY "3", SHACF_CORELINTERNETENUM | SHACF_OLDREGITEMGDN },
|
||||
{ "smartctr.exe", "96.0", SHACF_CONTEXTMENU },
|
||||
{ "soffice.exe", MAJOR_VER_ONLY "5", SHACF_STAROFFICE5PRINTER },
|
||||
{ "ua80.exe", NULL, SHACF_CONTEXTMENU | SHACF_CORELINTERNETENUM | SHACF_OLDREGITEMGDN },
|
||||
{ "ue32.exe", "2.00.0.0", SHACF_OLDREGITEMGDN },
|
||||
{ "wpwin7.exe", NULL, SHACF_CONTEXTMENU | SHACF_CORELINTERNETENUM },
|
||||
{ "wpwin8.exe", NULL, SHACF_CORELINTERNETENUM | SHACF_OLDREGITEMGDN },
|
||||
{ "wpwin9.exe", MAJOR_VER_ONLY "9", SHACF_CORELINTERNETENUM },
|
||||
};
|
||||
|
||||
// Window class name and compatibility flags
|
||||
typedef struct tagWNDCOMPATINFO
|
||||
{
|
||||
PCSTR pszLengthAndClassName;
|
||||
DWORD dwCompatFlags;
|
||||
} WNDCOMPATINFO, *PWNDCOMPATINFO;
|
||||
static WNDCOMPATINFO g_wndCompatInfo[] =
|
||||
{
|
||||
// The first byte indicates the string length
|
||||
{ "\x09" "bosa_sdm_", SHACF_UNKNOWN1 | SHACF_UNKNOWN2 },
|
||||
{ "\x18" "File Open Message Window", SHACF_UNKNOWN1 | SHACF_UNKNOWN2 },
|
||||
};
|
||||
|
||||
// Internal structure for SHLWAPI_WndCompatEnumProc
|
||||
typedef struct tagAPPCOMPATENUM
|
||||
{
|
||||
PWNDCOMPATINFO pItems;
|
||||
SIZE_T nItems;
|
||||
DWORD dwProcessId;
|
||||
INT iFound;
|
||||
} APPCOMPATENUM, *PAPPCOMPATENUM;
|
||||
|
||||
static BOOL CALLBACK
|
||||
SHLWAPI_WndCompatEnumProc(_In_ HWND hWnd, _In_ LPARAM lParam)
|
||||
{
|
||||
PAPPCOMPATENUM pEnum = (PAPPCOMPATENUM)lParam;
|
||||
|
||||
CHAR szClass[256];
|
||||
if (!pEnum->nItems || !GetClassNameA(hWnd, szClass, _countof(szClass)))
|
||||
return TRUE; // Ignore and continue
|
||||
|
||||
// Search for the target window in pEnum
|
||||
const INT cchClass = lstrlenA(szClass);
|
||||
for (UINT iItem = 0; iItem < pEnum->nItems; ++iItem)
|
||||
{
|
||||
PCSTR pszLengthAndClassName = pEnum->pItems[iItem].pszLengthAndClassName;
|
||||
|
||||
INT cchLength = pszLengthAndClassName[0]; // The first byte represents the length
|
||||
if (cchClass < cchLength)
|
||||
cchLength = cchClass; // Ignore trailing characters
|
||||
|
||||
// Compare the string
|
||||
if (StrCmpNA(szClass, &pszLengthAndClassName[1], cchLength) == 0) // Class name matched
|
||||
{
|
||||
// Get the process ID
|
||||
DWORD dwProcessId;
|
||||
GetWindowThreadProcessId(hWnd, &dwProcessId);
|
||||
if (dwProcessId == pEnum->dwProcessId) // Same process
|
||||
{
|
||||
pEnum->iFound = iItem; // Found
|
||||
return FALSE; // Quit enumeration
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE; // Continue enumeration
|
||||
}
|
||||
|
||||
// English (US) UTF-16
|
||||
#define PRODUCT_VER_ENGLISH_US_UTF16 "\\StringFileInfo\\040904E4\\ProductVersion"
|
||||
// German (Germany) UTF-16
|
||||
#define PRODUCT_VER_GERMAN_UTF16 "\\StringFileInfo\\040704E4\\ProductVersion"
|
||||
// English (US) Western European
|
||||
#define PRODUCT_VER_ENGLISH_US_WE "\\StringFileInfo\\040904B0\\ProductVersion"
|
||||
// English (US) Neutral
|
||||
#define PRODUCT_VER_ENGLISH_US_NEUTRAL "\\StringFileInfo\\04090000\\ProductVersion"
|
||||
// Swedish (Sweden) Western European
|
||||
#define PRODUCT_VER_SWEDISH_WE "\\StringFileInfo\\041D04B0\\ProductVersion"
|
||||
|
||||
typedef struct tagLANGANDCODEPAGE
|
||||
{
|
||||
WORD wLanguage;
|
||||
WORD wCodePage;
|
||||
} LANGANDCODEPAGE, *PLANGANDCODEPAGE;
|
||||
|
||||
static HRESULT
|
||||
SHLWAPI_GetModuleVersion(_In_ PCSTR pszFileName, _Out_ PSTR *ppszDest)
|
||||
{
|
||||
DWORD dwHandle;
|
||||
PBYTE pbData;
|
||||
PVOID pvData;
|
||||
|
||||
*ppszDest = NULL;
|
||||
|
||||
// Obtain the version info
|
||||
UINT size = GetFileVersionInfoSizeA(pszFileName, &dwHandle);
|
||||
if (!size)
|
||||
{
|
||||
TRACE("No version info\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
pbData = (PBYTE)LocalAlloc(LPTR, size);
|
||||
if (!pbData)
|
||||
{
|
||||
ERR("E_OUTOFMEMORY\n");
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
GetFileVersionInfoA(pszFileName, dwHandle, size, pbData);
|
||||
|
||||
// Getting the product version
|
||||
HRESULT hr = E_FAIL;
|
||||
if ((VerQueryValueA(pbData, PRODUCT_VER_ENGLISH_US_UTF16, &pvData, &size) ||
|
||||
VerQueryValueA(pbData, PRODUCT_VER_GERMAN_UTF16, &pvData, &size) ||
|
||||
VerQueryValueA(pbData, PRODUCT_VER_ENGLISH_US_WE, &pvData, &size) ||
|
||||
VerQueryValueA(pbData, PRODUCT_VER_ENGLISH_US_NEUTRAL, &pvData, &size) ||
|
||||
VerQueryValueA(pbData, PRODUCT_VER_SWEDISH_WE, &pvData, &size)) && size)
|
||||
{
|
||||
// NOTE: *ppszDest must be freed using LocalFree later
|
||||
*ppszDest = StrDupA((PSTR)pvData);
|
||||
hr = *ppszDest ? S_OK : E_OUTOFMEMORY;
|
||||
}
|
||||
else if (VerQueryValueA(pbData, "\\VarFileInfo\\Translation", &pvData, &size))
|
||||
{
|
||||
PVOID pDataSaved = pvData;
|
||||
PLANGANDCODEPAGE pEntry = (PLANGANDCODEPAGE)pvData;
|
||||
for (; (PBYTE)pEntry + sizeof(LANGANDCODEPAGE) <= (PBYTE)pDataSaved + size; ++pEntry)
|
||||
{
|
||||
CHAR szPath[MAX_PATH];
|
||||
wnsprintfA(szPath, _countof(szPath), "\\StringFileInfo\\%04X%04X\\ProductVersion",
|
||||
pEntry->wLanguage, pEntry->wCodePage);
|
||||
if (VerQueryValueA(pbData, szPath, &pvData, &size) && size)
|
||||
{
|
||||
// NOTE: *ppszDest must be freed using LocalFree later
|
||||
*ppszDest = StrDupA((PSTR)pvData);
|
||||
hr = *ppszDest ? S_OK : E_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
WARN("hr: 0x%lX\n", hr);
|
||||
|
||||
LocalFree(pbData);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
SHLWAPI_DoesModuleVersionMatch(_In_ PCSTR pszFileName, _In_opt_ PCSTR pszVersionPattern)
|
||||
{
|
||||
if (!pszVersionPattern)
|
||||
return TRUE;
|
||||
|
||||
PSTR pszModuleVersion = NULL;
|
||||
HRESULT hr = SHLWAPI_GetModuleVersion(pszFileName, &pszModuleVersion);
|
||||
if (FAILED(hr))
|
||||
return FALSE;
|
||||
|
||||
BOOL ret = FALSE;
|
||||
if (pszVersionPattern[0] == MAJOR_VER_ONLY[0]) // Special handling for major version only
|
||||
{
|
||||
// Truncate at comma (',') if present
|
||||
PSTR pchComma = StrChrA(pszModuleVersion, ',');
|
||||
if (pchComma)
|
||||
*pchComma = ANSI_NULL;
|
||||
|
||||
// Truncate at dot ('.') if present
|
||||
PSTR pchDot = StrChrA(pszModuleVersion, '.');
|
||||
if (pchDot)
|
||||
*pchDot = ANSI_NULL;
|
||||
|
||||
ret = (lstrcmpiA(pszModuleVersion, &pszVersionPattern[1]) == 0);
|
||||
}
|
||||
else // Otherwise, perform a normal match
|
||||
{
|
||||
PSTR pchAsterisk = StrChrA(pszVersionPattern, '*'); // Find an asterisk ('*')
|
||||
if (pchAsterisk) // Asterisk found
|
||||
{
|
||||
// Check for a match, ignoring the substring after '*'
|
||||
INT cchPrefix = (INT)(pchAsterisk - pszVersionPattern);
|
||||
if (cchPrefix > 0)
|
||||
ret = (StrCmpNIA(pszModuleVersion, pszVersionPattern, cchPrefix) == 0);
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
ret = (lstrcmpiA(pszModuleVersion, pszVersionPattern) == 0); // Full match
|
||||
}
|
||||
|
||||
LocalFree(pszModuleVersion);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DWORD
|
||||
SHLWAPI_GetRegistryCompatFlags(_In_ PCSTR pszPath)
|
||||
{
|
||||
// Build the path to the "application compatibility" registry key
|
||||
CHAR szText[MAX_PATH];
|
||||
wnsprintfA(szText, _countof(szText),
|
||||
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ShellCompatibility\\Applications\\%s",
|
||||
PathFindFileNameA(pszPath));
|
||||
|
||||
// Open the key
|
||||
HKEY hKey;
|
||||
const REGSAM samDesired = KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS;
|
||||
LSTATUS error = RegOpenKeyExA(HKEY_LOCAL_MACHINE, szText, 0, samDesired, &hKey);
|
||||
if (error != ERROR_SUCCESS)
|
||||
{
|
||||
ERR("error: %lu\n", error);
|
||||
return 0; // Failed
|
||||
}
|
||||
|
||||
// Build the base directory
|
||||
CHAR szBaseDir[MAX_PATH];
|
||||
lstrcpynA(szBaseDir, pszPath, _countof(szBaseDir));
|
||||
PathRemoveFileSpecA(szBaseDir);
|
||||
|
||||
// Search from the registry key
|
||||
DWORD dwCompatFlags = 0;
|
||||
szText[0] = ANSI_NULL; // The first attempt is for the non-subkey path
|
||||
for (DWORD dwIndex = 0; error == ERROR_SUCCESS;)
|
||||
{
|
||||
HKEY hSubKey;
|
||||
error = RegOpenKeyExA(hKey, szText, 0, KEY_QUERY_VALUE, &hSubKey);
|
||||
if (error != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
// Get the "RequiredFile" value
|
||||
CHAR szRequired[MAX_PATH];
|
||||
DWORD cbData = sizeof(szRequired);
|
||||
error = SHGetValueA(hSubKey, NULL, "RequiredFile", NULL, szRequired, &cbData);
|
||||
BOOL bValueExists = (error == ERROR_SUCCESS);
|
||||
BOOL bRequiredFileExists = FALSE;
|
||||
if (bValueExists) // Does the "RequiredFile" value exist?
|
||||
{
|
||||
// Build required file path to szText
|
||||
PathCombineA(szText, szBaseDir, szRequired);
|
||||
TRACE("RequiredFile: %s\n", wine_dbgstr_a(szRequired));
|
||||
TRACE("szText: %s\n", wine_dbgstr_a(szText));
|
||||
// Now szText is a full path
|
||||
bRequiredFileExists = (GetFileAttributesA(szText) != INVALID_FILE_ATTRIBUTES);
|
||||
}
|
||||
|
||||
// If the "RequiredFile" value doesn't exist, or the file specified by szText exists:
|
||||
if (!bValueExists || bRequiredFileExists)
|
||||
{
|
||||
// Check the "Version" value if necessary
|
||||
error = SHGetValueA(hSubKey, NULL, "Version", NULL, szText, &cbData);
|
||||
PCSTR pszVersionPattern = ((error == ERROR_SUCCESS) ? szText : NULL);
|
||||
TRACE("pszVersionPattern: %s\n", wine_dbgstr_a(pszVersionPattern));
|
||||
|
||||
// Does the pattern match?
|
||||
if (SHLWAPI_DoesModuleVersionMatch(pszPath, pszVersionPattern))
|
||||
{
|
||||
// Add additional flags from the registry key
|
||||
dwCompatFlags |= SHLWAPI_GetMappedFlags(hSubKey, g_appCompatFlagMaps,
|
||||
_countof(g_appCompatFlagMaps));
|
||||
}
|
||||
}
|
||||
|
||||
RegCloseKey(hSubKey);
|
||||
|
||||
// Go to the next sub-key
|
||||
++dwIndex;
|
||||
error = RegEnumKeyA(hKey, dwIndex, szText, _countof(szText));
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
|
||||
return dwCompatFlags;
|
||||
}
|
||||
|
||||
static DWORD
|
||||
SHLWAPI_InitAppCompat(VOID)
|
||||
{
|
||||
if (GetProcessVersion(0) >= MAKELONG(0, 5))
|
||||
return 0; // Flags are not needed
|
||||
|
||||
// Get module pathname
|
||||
CHAR szModulePathA[MAX_PATH];
|
||||
if (!GetModuleFileNameA(NULL, szModulePathA, _countof(szModulePathA)))
|
||||
return 0;
|
||||
|
||||
PCSTR pszFileName = PathFindFileNameA(szModulePathA); // Get the file title from the path
|
||||
|
||||
// Search the file title from g_appCompatInfo
|
||||
DWORD dwAppCompatFlags = 0;
|
||||
for (UINT iItem = 0; iItem < _countof(g_appCompatInfo); ++iItem)
|
||||
{
|
||||
const APPCOMPATINFO *pInfo = &g_appCompatInfo[iItem];
|
||||
if (lstrcmpiA(pInfo->pszAppName, pszFileName) == 0 &&
|
||||
SHLWAPI_DoesModuleVersionMatch(pszFileName, pInfo->pszAppVersion))
|
||||
{
|
||||
// Found, set the flags
|
||||
dwAppCompatFlags = g_appCompatInfo[iItem].dwCompatFlags;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add additional flags from the registry
|
||||
dwAppCompatFlags |= SHLWAPI_GetRegistryCompatFlags(pszFileName);
|
||||
|
||||
return dwAppCompatFlags;
|
||||
}
|
||||
|
||||
// These flags require SHLWAPI_InitAppCompat
|
||||
#define SHACF_TO_INIT ( \
|
||||
SHACF_CONTEXTMENU | \
|
||||
SHACF_DOCOBJECT | \
|
||||
SHACF_CORELINTERNETENUM | \
|
||||
SHACF_MYCOMPUTERFIRST | \
|
||||
SHACF_OLDREGITEMGDN | \
|
||||
SHACF_LOADCOLUMNHANDLER | \
|
||||
SHACF_ANSI | \
|
||||
SHACF_WIN95SHLEXEC | \
|
||||
SHACF_STAROFFICE5PRINTER | \
|
||||
SHACF_NOVALIDATEFSIDS | \
|
||||
SHACF_FILEOPENNEEDSEXT | \
|
||||
SHACF_WIN95BINDTOOBJECT | \
|
||||
SHACF_IGNOREENUMRESET | \
|
||||
SHACF_ANSIDISPLAYNAMES | \
|
||||
SHACF_FILEOPENBOGUSCTRLID | \
|
||||
SHACF_FORCELFNIDLIST \
|
||||
)
|
||||
|
||||
/*************************************************************************
|
||||
* SHGetAppCompatFlags [SHLWAPI.461]
|
||||
*
|
||||
* Thanks to Geoff Chappell.
|
||||
* @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/util/getappcompatflags.htm
|
||||
*/
|
||||
DWORD WINAPI
|
||||
SHGetAppCompatFlags(_In_ DWORD dwMask)
|
||||
{
|
||||
TRACE("(0x%lX)\n", dwMask);
|
||||
|
||||
// Initialize and retrieve flags if necessary
|
||||
if (dwMask & SHACF_TO_INIT)
|
||||
{
|
||||
if (!g_fAppCompatInitialized)
|
||||
{
|
||||
DWORD dwAppCompatFlags = SHLWAPI_InitAppCompat();
|
||||
InterlockedExchange((PLONG)&g_dwAppCompatFlags, dwAppCompatFlags);
|
||||
|
||||
g_fAppCompatInitialized = TRUE; // Mark as initialized
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve additional flags if necessary
|
||||
DWORD dwAppCompatFlags = g_dwAppCompatFlags;
|
||||
if (dwAppCompatFlags && (dwMask & (SHACF_UNKNOWN1 | SHACF_UNKNOWN2)))
|
||||
{
|
||||
// Find the target window and its flags using g_wndCompatInfo
|
||||
APPCOMPATENUM data =
|
||||
{
|
||||
g_wndCompatInfo, _countof(g_wndCompatInfo), GetCurrentProcessId(), -1
|
||||
};
|
||||
EnumWindows(SHLWAPI_WndCompatEnumProc, (LPARAM)&data);
|
||||
|
||||
// Add the target flags if a match is found
|
||||
if (data.iFound >= 0)
|
||||
dwAppCompatFlags |= g_wndCompatInfo[data.iFound].dwCompatFlags;
|
||||
|
||||
dwAppCompatFlags |= SHACF_UNKNOWN3;
|
||||
|
||||
InterlockedExchange((PLONG)&g_dwAppCompatFlags, dwAppCompatFlags);
|
||||
}
|
||||
|
||||
return dwAppCompatFlags;
|
||||
}
|
||||
|
||||
// FIXME: SHGetObjectCompatFlags
|
|
@ -4725,7 +4725,7 @@ VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef __REACTOS__ /* See appcompat.c */
|
||||
/*************************************************************************
|
||||
* @ [SHLWAPI.461]
|
||||
*/
|
||||
|
@ -4734,7 +4734,7 @@ DWORD WINAPI SHGetAppCompatFlags(DWORD dwUnknown)
|
|||
FIXME("(0x%08x) stub\n", dwUnknown);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
* @ [SHLWAPI.549]
|
||||
|
|
|
@ -4879,12 +4879,24 @@ typedef struct {
|
|||
_In_ LPARAM lParam,
|
||||
_In_ UINT options);
|
||||
|
||||
WINCOMMCTRLAPI
|
||||
BOOL
|
||||
WINAPI Str_SetPtrA(
|
||||
_Inout_ LPSTR *ppsz,
|
||||
_In_opt_ LPCSTR psz);
|
||||
|
||||
WINCOMMCTRLAPI
|
||||
BOOL
|
||||
WINAPI Str_SetPtrW(
|
||||
_Inout_ LPWSTR *ppsz,
|
||||
_In_opt_ LPCWSTR psz);
|
||||
|
||||
#ifdef UNICODE
|
||||
#define Str_SetPtr Str_SetPtrW
|
||||
#else
|
||||
#define Str_SetPtr Str_SetPtrA
|
||||
#endif
|
||||
|
||||
typedef struct _DPASTREAMINFO {
|
||||
int iPos;
|
||||
void *pvItem;
|
||||
|
|
|
@ -397,8 +397,34 @@ HRESULT WINAPI SHRunIndirectRegClientCommand(_In_ HWND hWnd, _In_ PCWSTR pszClie
|
|||
|
||||
DWORD WINAPI SHGetObjectCompatFlags(IUnknown *pUnk, const CLSID *clsid);
|
||||
|
||||
#define SHACF_WIN95SHLEXEC 0x00000200 /* Geoff Chappell */
|
||||
DWORD WINAPI SHGetAppCompatFlags(DWORD dwMask);
|
||||
/* Flags for SHGetAppCompatFlags */
|
||||
#define SHACF_CONTEXTMENU 0x00000001
|
||||
#define SHACF_FLUSHNOWAITALWAYS SHACF_CONTEXTMENU
|
||||
#define SHACF_DOCOBJECT 0x00000002
|
||||
#define SHACF_CORELINTERNETENUM 0x00000004
|
||||
#define SHACF_OLDCREATEVIEWWND SHACF_CORELINTERNETENUM
|
||||
#define SHACF_WIN95DEFVIEW SHACF_CORELINTERNETENUM
|
||||
#define SHACF_MYCOMPUTERFIRST 0x00000008
|
||||
#define SHACF_OLDREGITEMGDN 0x00000010
|
||||
// 0x00000020
|
||||
#define SHACF_LOADCOLUMNHANDLER 0x00000040
|
||||
#define SHACF_ANSI 0x00000080
|
||||
#define SHACF_UNKNOWN1 0x00000100
|
||||
#define SHACF_WIN95SHLEXEC 0x00000200
|
||||
#define SHACF_STAROFFICE5PRINTER 0x00000400
|
||||
#define SHACF_NOVALIDATEFSIDS 0x00000800
|
||||
#define SHACF_FILEOPENNEEDSEXT 0x00001000
|
||||
#define SHACF_WIN95BINDTOOBJECT 0x00002000
|
||||
#define SHACF_IGNOREENUMRESET 0x00004000
|
||||
// 0x00008000
|
||||
#define SHACF_ANSIDISPLAYNAMES 0x00010000
|
||||
#define SHACF_FILEOPENBOGUSCTRLID 0x00020000
|
||||
#define SHACF_FORCELFNIDLIST 0x00040000
|
||||
// 0x00080000
|
||||
#define SHACF_UNKNOWN2 0x01000000
|
||||
#define SHACF_UNKNOWN3 0x80000000
|
||||
|
||||
DWORD WINAPI SHGetAppCompatFlags(_In_ DWORD dwMask);
|
||||
|
||||
/*****************************************************************************
|
||||
* IAssociationElementOld interface
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue