mirror of
https://github.com/reactos/reactos.git
synced 2025-02-28 19:32:59 +00:00
[UXTHEME][UXTHEME_APITEST][SDK] GetThemeParseErrorInfo (#7662)
Implementing missing features... JIRA issue: CORE-12805 - Add dll/win32/uxtheme/errinfo.c. - Implement GetThemeParseErrorInfo function in errinfo.c. - Modify uxtheme.spec. - Add GetThemeParseErrorInfo prototype to <uxundoc.h>. - Adapt <uxundoc.h> to C++. - Add global variable gdwErrorInfoTlsIndex. - Add UXTHEME_UnInitSystem function.
This commit is contained in:
parent
0e327e9a70
commit
1b5f6c2dc0
10 changed files with 327 additions and 2 deletions
|
@ -6,6 +6,7 @@ spec2def(uxtheme.dll uxtheme.spec ADD_IMPORTLIB)
|
|||
list(APPEND SOURCE
|
||||
buffer.c
|
||||
draw.c
|
||||
errinfo.c
|
||||
main.c
|
||||
metric.c
|
||||
msstyles.c
|
||||
|
|
150
dll/win32/uxtheme/errinfo.c
Normal file
150
dll/win32/uxtheme/errinfo.c
Normal file
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* PROJECT: ReactOS uxtheme.dll
|
||||
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
|
||||
* PURPOSE: UXTHEME error reporting helpers
|
||||
* COPYRIGHT: Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||
*/
|
||||
|
||||
#include "uxthemep.h"
|
||||
#include <stdlib.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
PTMERRINFO
|
||||
UXTHEME_GetParseErrorInfo(_In_ BOOL bCreate)
|
||||
{
|
||||
PTMERRINFO pErrInfo;
|
||||
|
||||
if (gdwErrorInfoTlsIndex == TLS_OUT_OF_INDEXES)
|
||||
return NULL;
|
||||
|
||||
pErrInfo = TlsGetValue(gdwErrorInfoTlsIndex);
|
||||
if (pErrInfo)
|
||||
return pErrInfo;
|
||||
|
||||
if (bCreate)
|
||||
{
|
||||
pErrInfo = LocalAlloc(LPTR, sizeof(*pErrInfo));
|
||||
TlsSetValue(gdwErrorInfoTlsIndex, pErrInfo);
|
||||
}
|
||||
|
||||
return pErrInfo;
|
||||
}
|
||||
|
||||
VOID
|
||||
UXTHEME_DeleteParseErrorInfo(VOID)
|
||||
{
|
||||
PTMERRINFO pErrInfo = UXTHEME_GetParseErrorInfo(FALSE);
|
||||
if (!pErrInfo)
|
||||
return;
|
||||
|
||||
TlsSetValue(gdwErrorInfoTlsIndex, NULL);
|
||||
LocalFree(pErrInfo);
|
||||
}
|
||||
|
||||
static BOOL
|
||||
UXTHEME_FormatLocalMsg(
|
||||
_In_ HINSTANCE hInstance,
|
||||
_In_ UINT uID,
|
||||
_Out_ LPWSTR pszDest,
|
||||
_In_ SIZE_T cchDest,
|
||||
_In_ LPCWSTR pszDrive,
|
||||
_In_ PTMERRINFO pErrInfo)
|
||||
{
|
||||
WCHAR szFormat[MAX_PATH];
|
||||
LPCWSTR args[2] = { pErrInfo->szParam1, pErrInfo->szParam2 };
|
||||
|
||||
if (!LoadStringW(hInstance, uID, szFormat, _countof(szFormat)) || !szFormat[0])
|
||||
return FALSE;
|
||||
|
||||
return FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
||||
szFormat, 0, 0, pszDest, cchDest, (va_list *)args) != 0;
|
||||
}
|
||||
|
||||
static HRESULT
|
||||
UXTHEME_FormatParseMessage(
|
||||
_In_ PTMERRINFO pErrInfo,
|
||||
_Out_ LPWSTR pszDest,
|
||||
_In_ SIZE_T cchDest)
|
||||
{
|
||||
DWORD nID;
|
||||
HMODULE hMod, hUxTheme;
|
||||
WCHAR szFullPath[_MAX_PATH];
|
||||
WCHAR szDrive[_MAX_DRIVE + 1], szDir[_MAX_DIR], szFileName[_MAX_FNAME], szExt[_MAX_EXT];
|
||||
BOOL ret;
|
||||
HRESULT hr;
|
||||
|
||||
nID = LOWORD(pErrInfo->nID);
|
||||
if (!GetModuleFileNameW(NULL, szFullPath, _countof(szFullPath)))
|
||||
return S_OK;
|
||||
|
||||
_wsplitpath(szFullPath, szDrive, szDir, szFileName, szExt);
|
||||
if (lstrcmpiW(szFileName, L"packthem") == 0)
|
||||
{
|
||||
hMod = GetModuleHandleW(NULL);
|
||||
if (UXTHEME_FormatLocalMsg(hMod, nID, pszDest, cchDest, szDrive, pErrInfo))
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
hUxTheme = LoadLibraryW(L"uxtheme.dll");
|
||||
if (!hUxTheme)
|
||||
return E_FAIL;
|
||||
|
||||
ret = UXTHEME_FormatLocalMsg(hUxTheme, nID, pszDest, cchDest, szDrive, pErrInfo);
|
||||
hr = (ret ? S_OK : UXTHEME_MakeLastError());
|
||||
FreeLibrary(hUxTheme);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Parser should use this function on failure
|
||||
HRESULT
|
||||
UXTHEME_MakeParseError(
|
||||
_In_ UINT nID,
|
||||
_In_ LPCWSTR pszParam1,
|
||||
_In_ LPCWSTR pszParam2,
|
||||
_In_ LPCWSTR pszFile,
|
||||
_In_ LPCWSTR pszLine,
|
||||
_In_ INT nLineNo)
|
||||
{
|
||||
PTMERRINFO pErrInfo = UXTHEME_GetParseErrorInfo(TRUE);
|
||||
if (pErrInfo)
|
||||
{
|
||||
pErrInfo->nID = nID;
|
||||
pErrInfo->nLineNo = nLineNo;
|
||||
StringCchCopyW(pErrInfo->szParam1, _countof(pErrInfo->szParam1), pszParam1);
|
||||
StringCchCopyW(pErrInfo->szParam2, _countof(pErrInfo->szParam2), pszParam2);
|
||||
StringCchCopyW(pErrInfo->szFile, _countof(pErrInfo->szFile), pszFile);
|
||||
StringCchCopyW(pErrInfo->szLine, _countof(pErrInfo->szLine), pszLine);
|
||||
}
|
||||
return HRESULT_FROM_WIN32(ERROR_UNKNOWN_PROPERTY);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* GetThemeParseErrorInfo (UXTHEME.48)
|
||||
*/
|
||||
HRESULT WINAPI
|
||||
GetThemeParseErrorInfo(_Inout_ PPARSE_ERROR_INFO pInfo)
|
||||
{
|
||||
PTMERRINFO pErrInfo;
|
||||
HRESULT hr;
|
||||
|
||||
if (!pInfo)
|
||||
return E_POINTER;
|
||||
|
||||
if (pInfo->cbSize != sizeof(*pInfo))
|
||||
return E_INVALIDARG;
|
||||
|
||||
pErrInfo = UXTHEME_GetParseErrorInfo(TRUE);
|
||||
if (!pErrInfo)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
hr = UXTHEME_FormatParseMessage(pErrInfo, pInfo->szDescription, _countof(pInfo->szDescription));
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
pInfo->nID = pErrInfo->nID;
|
||||
pInfo->nLineNo = pErrInfo->nLineNo;
|
||||
StringCchCopyW(pInfo->szFile, _countof(pInfo->szFile), pErrInfo->szFile);
|
||||
StringCchCopyW(pInfo->szLine, _countof(pInfo->szLine), pErrInfo->szLine);
|
||||
return hr;
|
||||
}
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
/***********************************************************************/
|
||||
|
||||
/* For the moment, do nothing here. */
|
||||
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
|
||||
{
|
||||
TRACE("%p 0x%x %p: stub\n", hInstDLL, fdwReason, lpv);
|
||||
|
@ -32,6 +31,12 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
|
|||
UXTHEME_InitSystem(hInstDLL);
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
UXTHEME_UnInitSystem(hInstDLL);
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
break;
|
||||
case DLL_THREAD_DETACH:
|
||||
UXTHEME_DeleteParseErrorInfo();
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include <winreg.h>
|
||||
#include <uxundoc.h>
|
||||
|
||||
DWORD gdwErrorInfoTlsIndex = TLS_OUT_OF_INDEXES;
|
||||
|
||||
/***********************************************************************
|
||||
* Defines and global variables
|
||||
*/
|
||||
|
@ -588,6 +590,19 @@ void UXTHEME_InitSystem(HINSTANCE hInst)
|
|||
|
||||
RtlInitializeHandleTable(0xFFF, sizeof(UXTHEME_HANDLE), &g_UxThemeHandleTable);
|
||||
g_cHandles = 0;
|
||||
|
||||
gdwErrorInfoTlsIndex = TlsAlloc();
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* UXTHEME_UnInitSystem
|
||||
*/
|
||||
void UXTHEME_UnInitSystem(HINSTANCE hInst)
|
||||
{
|
||||
UXTHEME_DeleteParseErrorInfo();
|
||||
|
||||
TlsFree(gdwErrorInfoTlsIndex);
|
||||
gdwErrorInfoTlsIndex = TLS_OUT_OF_INDEXES;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
45 stdcall -noname ClassicSystemParametersInfoW(long long ptr long)
|
||||
46 stdcall -noname ClassicAdjustWindowRectEx(ptr long long long)
|
||||
47 stdcall DrawThemeBackgroundEx(ptr ptr long long ptr ptr)
|
||||
48 stub -noname GetThemeParseErrorInfo
|
||||
48 stdcall -noname GetThemeParseErrorInfo(ptr)
|
||||
49 stdcall GetThemeAppProperties()
|
||||
50 stdcall GetThemeBackgroundContentRect(ptr ptr long long ptr ptr)
|
||||
51 stdcall GetThemeBackgroundExtent(ptr ptr long long ptr ptr)
|
||||
|
|
|
@ -90,6 +90,16 @@ typedef struct _THEME_FILE {
|
|||
PTHEME_IMAGE images;
|
||||
} THEME_FILE, *PTHEME_FILE;
|
||||
|
||||
typedef struct tagTMERRINFO
|
||||
{
|
||||
UINT nID;
|
||||
WCHAR szParam1[MAX_PATH];
|
||||
WCHAR szParam2[MAX_PATH];
|
||||
WCHAR szFile[MAX_PATH];
|
||||
WCHAR szLine[MAX_PATH];
|
||||
INT nLineNo;
|
||||
} TMERRINFO, *PTMERRINFO;
|
||||
|
||||
typedef struct _UXINI_FILE *PUXINI_FILE;
|
||||
|
||||
typedef struct _UXTHEME_HANDLE
|
||||
|
@ -276,6 +286,7 @@ extern ATOM atWndContext;
|
|||
extern BOOL g_bThemeHooksActive;
|
||||
|
||||
void UXTHEME_InitSystem(HINSTANCE hInst);
|
||||
void UXTHEME_UnInitSystem(HINSTANCE hInst);
|
||||
void UXTHEME_LoadTheme(BOOL bLoad);
|
||||
BOOL CALLBACK UXTHEME_broadcast_theme_changed (HWND hWnd, LPARAM enable);
|
||||
|
||||
|
@ -286,4 +297,33 @@ BOOL CALLBACK UXTHEME_broadcast_theme_changed (HWND hWnd, LPARAM enable);
|
|||
/* Full alpha blending */
|
||||
#define ALPHABLEND_FULL 2
|
||||
|
||||
extern DWORD gdwErrorInfoTlsIndex;
|
||||
|
||||
VOID UXTHEME_DeleteParseErrorInfo(VOID);
|
||||
|
||||
static inline
|
||||
HRESULT
|
||||
UXTHEME_MakeError(_In_ LONG error)
|
||||
{
|
||||
if (error < 0)
|
||||
return (HRESULT)error;
|
||||
return HRESULT_FROM_WIN32(error);
|
||||
}
|
||||
|
||||
static inline
|
||||
HRESULT
|
||||
UXTHEME_MakeLastError(VOID)
|
||||
{
|
||||
return UXTHEME_MakeError(GetLastError());
|
||||
}
|
||||
|
||||
HRESULT
|
||||
UXTHEME_MakeParseError(
|
||||
_In_ UINT nID,
|
||||
_In_ LPCWSTR pszParam1,
|
||||
_In_ LPCWSTR pszParam2,
|
||||
_In_ LPCWSTR pszFile,
|
||||
_In_ LPCWSTR pszLine,
|
||||
_In_ INT nLineNo);
|
||||
|
||||
#endif /* _UXTHEME_PCH_ */
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
list(APPEND SOURCE
|
||||
CloseThemeData.c
|
||||
DrawThemeParentBackground.c
|
||||
GetThemeParseErrorInfo.c
|
||||
SetWindowTheme.c
|
||||
SetThemeAppProperties.c
|
||||
../include/msgtrace.c
|
||||
|
|
92
modules/rostests/apitests/uxtheme/GetThemeParseErrorInfo.c
Normal file
92
modules/rostests/apitests/uxtheme/GetThemeParseErrorInfo.c
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* PROJECT: ReactOS API tests
|
||||
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
|
||||
* PURPOSE: Tests for GetThemeParseErrorInfo
|
||||
* COPYRIGHT: Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||
*/
|
||||
|
||||
#include <apitest.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <uxtheme.h>
|
||||
#include <uxundoc.h>
|
||||
|
||||
typedef HRESULT (WINAPI *FN_GetThemeParseErrorInfo)(PPARSE_ERROR_INFO);
|
||||
typedef HRESULT (WINAPI *FN_ParseThemeIniFile)(LPCWSTR, LPWSTR, PARSETHEMEINIFILEPROC, LPVOID);
|
||||
|
||||
static BOOL CALLBACK
|
||||
ParseThemeIniFileProc(
|
||||
DWORD dwType,
|
||||
LPWSTR pszParam1,
|
||||
LPWSTR pszParam2,
|
||||
LPWSTR pszParam3,
|
||||
DWORD dwParam,
|
||||
LPVOID lpData)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
START_TEST(GetThemeParseErrorInfo)
|
||||
{
|
||||
HRESULT hr;
|
||||
PARSE_ERROR_INFO Info;
|
||||
WCHAR szPath[MAX_PATH];
|
||||
|
||||
FN_GetThemeParseErrorInfo GetThemeParseErrorInfo =
|
||||
(FN_GetThemeParseErrorInfo)GetProcAddress(GetModuleHandleW(L"uxtheme.dll"), MAKEINTRESOURCEA(48));
|
||||
if (!GetThemeParseErrorInfo)
|
||||
{
|
||||
skip("No GetThemeParseErrorInfo found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
hr = GetThemeParseErrorInfo(NULL);
|
||||
ok_hex(hr, E_POINTER);
|
||||
|
||||
ZeroMemory(&Info, sizeof(Info));
|
||||
hr = GetThemeParseErrorInfo(&Info);
|
||||
ok_hex(hr, E_INVALIDARG);
|
||||
|
||||
ZeroMemory(&Info, sizeof(Info));
|
||||
Info.cbSize = sizeof(Info);
|
||||
hr = GetThemeParseErrorInfo(&Info);
|
||||
ok_hex(hr, HRESULT_FROM_WIN32(ERROR_RESOURCE_NAME_NOT_FOUND));
|
||||
|
||||
FN_ParseThemeIniFile ParseThemeIniFile =
|
||||
(FN_ParseThemeIniFile)GetProcAddress(GetModuleHandleW(L"uxtheme.dll"), MAKEINTRESOURCEA(11));
|
||||
if (!ParseThemeIniFile)
|
||||
{
|
||||
skip("No ParseThemeIniFile found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *fout = _wfopen(L"invalid.ini", L"wb");
|
||||
fprintf(fout, "[InvalidKey]\n");
|
||||
fprintf(fout, "InvalidValueName=InvalidValue\n");
|
||||
fclose(fout);
|
||||
|
||||
hr = ParseThemeIniFile(L"invalid.ini", szPath, ParseThemeIniFileProc, NULL);
|
||||
ok_hex(hr, HRESULT_FROM_WIN32(ERROR_UNKNOWN_PROPERTY));
|
||||
|
||||
_wremove(L"invalid.ini");
|
||||
|
||||
ZeroMemory(&Info, sizeof(Info));
|
||||
Info.cbSize = sizeof(Info);
|
||||
Info.szDescription[0] = L'@';
|
||||
Info.szDescription[MAX_PATH] = L'@';
|
||||
Info.szFile[0] = L'@';
|
||||
Info.szLine[0] = L'@';
|
||||
hr = GetThemeParseErrorInfo(&Info);
|
||||
ok_hex(hr, S_OK);
|
||||
ok_int(Info.nID, 160);
|
||||
|
||||
ok(Info.szDescription[0] != UNICODE_NULL, "Info.szDescription was empty\n");
|
||||
ok(Info.szDescription[0] != L'@', "Info.szDescription had no change\n");
|
||||
trace("szDescription: %s\n", wine_dbgstr_w(Info.szDescription)); // "Must be Primitive, enum, or type: InvalidValueName"
|
||||
|
||||
ok_int(Info.szDescription[MAX_PATH], L'@');
|
||||
ok_wstr(Info.szFile, L"invalid.ini");
|
||||
ok_wstr(Info.szLine, L"InvalidValueName=InvalidValue");
|
||||
ok_int(Info.nLineNo, 2);
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
extern void func_CloseThemeData(void);
|
||||
extern void func_DrawThemeParentBackground(void);
|
||||
extern void func_GetThemeParseErrorInfo(void);
|
||||
extern void func_SetThemeAppProperties(void);
|
||||
extern void func_SetWindowTheme(void);
|
||||
|
||||
|
@ -12,6 +13,7 @@ const struct test winetest_testlist[] =
|
|||
{
|
||||
{ "CloseThemeData", func_CloseThemeData },
|
||||
{ "DrawThemeParentBackground", func_DrawThemeParentBackground },
|
||||
{ "GetThemeParseErrorInfo", func_GetThemeParseErrorInfo },
|
||||
{ "SetWindowTheme", func_SetWindowTheme },
|
||||
{ "SetThemeAppProperties", func_SetThemeAppProperties },
|
||||
{ 0, 0 }
|
||||
|
|
|
@ -1,7 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef HANDLE HTHEMEFILE;
|
||||
|
||||
typedef struct tagPARSE_ERROR_INFO
|
||||
{
|
||||
DWORD cbSize;
|
||||
UINT nID;
|
||||
WCHAR szDescription[2 * MAX_PATH];
|
||||
WCHAR szFile[MAX_PATH];
|
||||
WCHAR szLine[MAX_PATH];
|
||||
INT nLineNo;
|
||||
} PARSE_ERROR_INFO, *PPARSE_ERROR_INFO;
|
||||
|
||||
HRESULT WINAPI GetThemeParseErrorInfo(_Inout_ PPARSE_ERROR_INFO pInfo);
|
||||
|
||||
/**********************************************************************
|
||||
* ENUMTHEMEPROC
|
||||
*
|
||||
|
@ -118,3 +134,6 @@ BOOL WINAPI ThemeHooksInstall(VOID);
|
|||
|
||||
BOOL WINAPI ThemeHooksRemove(VOID);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue