ReactOS.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2025
March
February
January
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
May
April
March
February
January
2004
December
November
October
September
August
July
June
May
April
March
February
List overview
Download
Ros-diffs
February 2025
----- 2025 -----
March 2025
February 2025
January 2025
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
ros-diffs@reactos.org
17 participants
79 discussions
Start a n
N
ew thread
[reactos] 01/01: [POWRPROF] Sync Powrprof to WINE-10.0 - Add some functions too (#7681)
by Justin Miller
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3368adc547f4595c0b23a…
commit 3368adc547f4595c0b23a8f55077404ba5954f95 Author: Justin Miller <justin.miller(a)reactos.org> AuthorDate: Tue Feb 11 17:33:45 2025 -0800 Commit: GitHub <noreply(a)github.com> CommitDate: Tue Feb 11 17:33:45 2025 -0800 [POWRPROF] Sync Powrprof to WINE-10.0 - Add some functions too (#7681) Co-authored-by: Hermès BÉLUSCA - MAÏTO <hermes.belusca-maito(a)reactos.org> "Sync" to WINE-10.0, plus add some functions we need. Required for various apps going forward. --- dll/win32/powrprof/CMakeLists.txt | 5 + dll/win32/powrprof/powrprof.c | 111 +++++++++++++++++++ dll/win32/powrprof/powrprof.spec | 18 ++- sdk/include/psdk/powrprof.h | 223 +++++++++++++++++++++++++------------- 4 files changed, 277 insertions(+), 80 deletions(-) diff --git a/dll/win32/powrprof/CMakeLists.txt b/dll/win32/powrprof/CMakeLists.txt index cf6a2199a9b..a2b3ca0c056 100644 --- a/dll/win32/powrprof/CMakeLists.txt +++ b/dll/win32/powrprof/CMakeLists.txt @@ -6,6 +6,11 @@ add_library(powrprof MODULE powrprof.rc ${CMAKE_CURRENT_BINARY_DIR}/powrprof.def) +if(MSVC) + # Disable warning C4312: 'type cast': conversion from 'unsigned int' to 'HANDLE' of greater size + target_compile_options(powrprof PRIVATE /wd4312) +endif() + set_module_type(powrprof win32dll UNICODE) target_link_libraries(powrprof wine) add_importlibs(powrprof advapi32 user32 comctl32 msvcrt kernel32 ntdll) diff --git a/dll/win32/powrprof/powrprof.c b/dll/win32/powrprof/powrprof.c index 7172bb43646..fa19aec0868 100644 --- a/dll/win32/powrprof/powrprof.c +++ b/dll/win32/powrprof/powrprof.c @@ -510,6 +510,12 @@ PowerGetActiveScheme(HKEY UserRootPowerKey, GUID **polguid) return ERROR_CALL_NOT_IMPLEMENTED; } +DWORD WINAPI PowerSetActiveScheme(HKEY UserRootPowerKey, GUID *polguid) +{ + FIXME("(%p,%s) stub!\n", UserRootPowerKey, wine_dbgstr_guid(polguid)); + return ERROR_SUCCESS; +} + DWORD WINAPI PowerReadDCValue(HKEY RootPowerKey, const GUID *Scheme, const GUID *SubGroup, const GUID *PowerSettings, PULONG Type, PUCHAR Buffer, DWORD *BufferSize) { @@ -517,6 +523,111 @@ PowerReadDCValue(HKEY RootPowerKey, const GUID *Scheme, const GUID *SubGroup, co return ERROR_CALL_NOT_IMPLEMENTED; } +DWORD WINAPI PowerReadFriendlyName(HKEY RootPowerKey, const GUID *Scheme, + const GUID *SubGroup, const GUID *PowerSettings, UCHAR *Buffer, + DWORD *BufferSize) +{ + FIXME("(%p,%s,%s,%s,%p,%p) stub!\n", RootPowerKey, debugstr_guid(Scheme), debugstr_guid(SubGroup), debugstr_guid(PowerSettings), Buffer, BufferSize); + return ERROR_CALL_NOT_IMPLEMENTED; +} + +POWER_PLATFORM_ROLE WINAPI PowerDeterminePlatformRole(void) +{ + FIXME("stub\n"); + return PlatformRoleDesktop; +} + +POWER_PLATFORM_ROLE WINAPI PowerDeterminePlatformRoleEx(ULONG version) +{ + FIXME("%lu stub.\n", version); + return PlatformRoleDesktop; +} + +DWORD WINAPI PowerEnumerate(HKEY key, const GUID *scheme, const GUID *subgroup, POWER_DATA_ACCESSOR flags, + ULONG index, UCHAR *buffer, DWORD *buffer_size) +{ + FIXME("(%p,%s,%s,%d,%ld,%p,%p) stub!\n", key, debugstr_guid(scheme), debugstr_guid(subgroup), + flags, index, buffer, buffer_size); + return ERROR_CALL_NOT_IMPLEMENTED; +} + +DWORD WINAPI PowerRegisterSuspendResumeNotification(DWORD flags, HANDLE recipient, PHPOWERNOTIFY handle) +{ + FIXME("(0x%08lx,%p,%p) stub!\n", flags, recipient, handle); + *handle = (HPOWERNOTIFY)0xdeadbeef; + return ERROR_SUCCESS; +} + +DWORD WINAPI PowerUnregisterSuspendResumeNotification(HPOWERNOTIFY handle) +{ + FIXME("(%p) stub!\n", handle); + return ERROR_SUCCESS; +} + +DWORD WINAPI PowerSettingRegisterNotification(const GUID *setting, DWORD flags, HANDLE recipient, PHPOWERNOTIFY handle) +{ + FIXME("(%s,0x%08lx,%p,%p) stub!\n", debugstr_guid(setting), flags, recipient, handle); + *handle = (PHPOWERNOTIFY)0xdeadbeef; + return ERROR_SUCCESS; +} + +DWORD WINAPI PowerSettingUnregisterNotification(HPOWERNOTIFY handle) +{ + FIXME("(%p) stub!\n", handle); + return ERROR_SUCCESS; +} + +DWORD WINAPI PowerWriteACValueIndex(HKEY key, const GUID *scheme, const GUID *subgroup, const GUID *setting, DWORD index) +{ + FIXME("(%p,%s,%s,%s,0x%08lx) stub!\n", key, debugstr_guid(scheme), debugstr_guid(subgroup), debugstr_guid(setting), index); + return ERROR_SUCCESS; +} + +#ifdef __REACTOS__ +DWORD WINAPI PowerWriteDCValueIndex( + HKEY key, + const GUID *scheme, + const GUID *subgroup, + const GUID *setting, + DWORD index +) +{ + FIXME("(%p,%s,%s,%s,0x%08lx) stub!\n", key, debugstr_guid(scheme), debugstr_guid(subgroup), debugstr_guid(setting), index); + return ERROR_SUCCESS; +} + +DWORD WINAPI PowerReadACValueIndex( + HKEY key, + const GUID *scheme, + const GUID *subgroup, + const GUID *setting, + LPDWORD AcValueIndex +) +{ + FIXME("(%p,%s,%s,%s,0x%08lx) stub!\n", key, debugstr_guid(scheme), debugstr_guid(subgroup), debugstr_guid(setting)); + return ERROR_SUCCESS; +} + +DWORD WINAPI PowerReadDCValueIndex( + HKEY key, + const GUID *scheme, + const GUID *subgroup, + const GUID *setting, + LPDWORD DcValuetIndex +) +{ + FIXME("(%p,%s,%s,%s,0x%08lx) stub!\n", key, debugstr_guid(scheme), debugstr_guid(subgroup), debugstr_guid(setting)); + return ERROR_SUCCESS; +} + +DWORD WINAPI +PowerReadACValue(HKEY RootPowerKey, const GUID *Scheme, const GUID *SubGroup, const GUID *PowerSettings, PULONG Type, PUCHAR Buffer, DWORD *BufferSize) +{ + FIXME("(%p,%s,%s,%s,%p,%p,%p) stub!\n", RootPowerKey, debugstr_guid(Scheme), debugstr_guid(SubGroup), debugstr_guid(PowerSettings), Type, Buffer, BufferSize); + return ERROR_CALL_NOT_IMPLEMENTED; +} +#endif + BOOLEAN WINAPI ReadGlobalPwrPolicy(PGLOBAL_POWER_POLICY pGlobalPowerPolicy) { diff --git a/dll/win32/powrprof/powrprof.spec b/dll/win32/powrprof/powrprof.spec index 43a9723f793..37f2b02c84d 100644 --- a/dll/win32/powrprof/powrprof.spec +++ b/dll/win32/powrprof/powrprof.spec @@ -10,8 +10,22 @@ @ stdcall IsPwrHibernateAllowed () @ stdcall IsPwrShutdownAllowed () @ stdcall IsPwrSuspendAllowed () +@ stdcall PowerDeterminePlatformRole () +@ stdcall PowerDeterminePlatformRoleEx(long) +@ stdcall PowerEnumerate(long ptr ptr long long ptr ptr) @ stdcall PowerGetActiveScheme (ptr ptr) -@ stdcall PowerReadDCValue (ptr ptr ptr ptr ptr ptr ptr) +@ stdcall PowerSetActiveScheme (ptr ptr) +@ stdcall PowerReadACValue(ptr ptr ptr ptr ptr ptr ptr) +@ stdcall PowerReadACValueIndex(ptr ptr ptr ptr ptr) +@ stdcall PowerReadDCValue(ptr ptr ptr ptr ptr ptr ptr) +@ stdcall PowerReadDCValueIndex(ptr ptr ptr ptr ptr) +@ stdcall PowerReadFriendlyName (ptr ptr ptr ptr ptr ptr) +@ stdcall PowerRegisterSuspendResumeNotification(long ptr ptr) +@ stdcall PowerUnregisterSuspendResumeNotification(ptr) +@ stdcall PowerSettingRegisterNotification(ptr long ptr ptr) +@ stdcall PowerSettingUnregisterNotification(ptr) +@ stdcall PowerWriteACValueIndex(ptr ptr ptr ptr long) +@ stdcall PowerWriteDCValueIndex(ptr ptr ptr ptr long) @ stdcall ReadGlobalPwrPolicy (ptr) @ stdcall ReadProcessorPwrScheme (long ptr) @ stdcall ReadPwrScheme (long ptr) @@ -20,4 +34,4 @@ @ stdcall WriteGlobalPwrPolicy (ptr) @ stdcall WriteProcessorPwrScheme (long ptr) @ stdcall WritePwrScheme (ptr str str ptr) -@ stdcall ValidatePowerPolicies (ptr ptr) \ No newline at end of file +@ stdcall ValidatePowerPolicies (ptr ptr) diff --git a/sdk/include/psdk/powrprof.h b/sdk/include/psdk/powrprof.h index 50e54cd6ad9..4c5f0c69f3c 100644 --- a/sdk/include/psdk/powrprof.h +++ b/sdk/include/psdk/powrprof.h @@ -12,87 +12,147 @@ extern "C" { #endif -#define EnableMultiBatteryDisplay 2 -#define EnablePasswordLogon 4 -#define EnableSysTrayBatteryMeter 1 -#define EnableWakeOnRing 8 -#define EnableVideoDimDisplay 16 +#ifdef __REACTOS__ #define NEWSCHEME (UINT)-1 -#ifndef RC_INVOKED - -typedef struct _GLOBAL_MACHINE_POWER_POLICY{ - ULONG Revision; - SYSTEM_POWER_STATE LidOpenWakeAc; - SYSTEM_POWER_STATE LidOpenWakeDc; - ULONG BroadcastCapacityResolution; -} GLOBAL_MACHINE_POWER_POLICY, *PGLOBAL_MACHINE_POWER_POLICY; -typedef struct _GLOBAL_USER_POWER_POLICY{ - ULONG Revision; - POWER_ACTION_POLICY PowerButtonAc; - POWER_ACTION_POLICY PowerButtonDc; - POWER_ACTION_POLICY SleepButtonAc; - POWER_ACTION_POLICY SleepButtonDc; - POWER_ACTION_POLICY LidCloseAc; - POWER_ACTION_POLICY LidCloseDc; - SYSTEM_POWER_LEVEL DischargePolicy[NUM_DISCHARGE_POLICIES]; - ULONG GlobalFlags; -} GLOBAL_USER_POWER_POLICY, *PGLOBAL_USER_POWER_POLICY; -typedef struct _GLOBAL_POWER_POLICY{ - GLOBAL_USER_POWER_POLICY user; - GLOBAL_MACHINE_POWER_POLICY mach; -} GLOBAL_POWER_POLICY, *PGLOBAL_POWER_POLICY; -typedef struct _MACHINE_POWER_POLICY{ - ULONG Revision; - SYSTEM_POWER_STATE MinSleepAc; - SYSTEM_POWER_STATE MinSleepDc; - SYSTEM_POWER_STATE ReducedLatencySleepAc; - SYSTEM_POWER_STATE ReducedLatencySleepDc; - ULONG DozeTimeoutAc; - ULONG DozeTimeoutDc; - ULONG DozeS4TimeoutAc; - ULONG DozeS4TimeoutDc; - UCHAR MinThrottleAc; - UCHAR MinThrottleDc; - UCHAR pad1[2]; - POWER_ACTION_POLICY OverThrottledAc; - POWER_ACTION_POLICY OverThrottledDc; -} MACHINE_POWER_POLICY, *PMACHINE_POWER_POLICY; +typedef enum _POWER_PLATFORM_ROLE { + PlatformRoleUnspecified, + PlatformRoleDesktop, + PlatformRoleMobile, + PlatformRoleWorkstation, + PlatformRoleEnterpriseServer, + PlatformRoleSOHOServer, + PlatformRoleAppliancePC, + PlatformRolePerformanceServer, + PlatformRoleSlate, + PlatformRoleMaximum +} POWER_PLATFORM_ROLE, *PPOWER_PLATFORM_ROLE; +#endif + +#define EnableSysTrayBatteryMeter 0x01 +#define EnableMultiBatteryDisplay 0x02 +#define EnablePasswordLogon 0x04 +#define EnableWakeOnRing 0x08 +#define EnableVideoDimDisplay 0x10 + +typedef struct _GLOBAL_MACHINE_POWER_POLICY { + ULONG Revision; + SYSTEM_POWER_STATE LidOpenWakeAc; + SYSTEM_POWER_STATE LidOpenWakeDc; + ULONG BroadcastCapacityResolution; +} GLOBAL_MACHINE_POWER_POLICY, +*PGLOBAL_MACHINE_POWER_POLICY; + +typedef struct _GLOBAL_USER_POWER_POLICY { + ULONG Revision; + POWER_ACTION_POLICY PowerButtonAc; + POWER_ACTION_POLICY PowerButtonDc; + POWER_ACTION_POLICY SleepButtonAc; + POWER_ACTION_POLICY SleepButtonDc; + POWER_ACTION_POLICY LidCloseAc; + POWER_ACTION_POLICY LidCloseDc; + SYSTEM_POWER_LEVEL DischargePolicy[NUM_DISCHARGE_POLICIES]; + ULONG GlobalFlags; +} GLOBAL_USER_POWER_POLICY, +*PGLOBAL_USER_POWER_POLICY; + +typedef struct _GLOBAL_POWER_POLICY { + GLOBAL_USER_POWER_POLICY user; + GLOBAL_MACHINE_POWER_POLICY mach; +} GLOBAL_POWER_POLICY, +*PGLOBAL_POWER_POLICY; + +typedef struct _MACHINE_POWER_POLICY { + ULONG Revision; + SYSTEM_POWER_STATE MinSleepAc; + SYSTEM_POWER_STATE MinSleepDc; + SYSTEM_POWER_STATE ReducedLatencySleepAc; + SYSTEM_POWER_STATE ReducedLatencySleepDc; + ULONG DozeTimeoutAc; + ULONG DozeTimeoutDc; + ULONG DozeS4TimeoutAc; + ULONG DozeS4TimeoutDc; + UCHAR MinThrottleAc; + UCHAR MinThrottleDc; + UCHAR pad1[2]; + POWER_ACTION_POLICY OverThrottledAc; + POWER_ACTION_POLICY OverThrottledDc; +} MACHINE_POWER_POLICY, +*PMACHINE_POWER_POLICY; + typedef struct _MACHINE_PROCESSOR_POWER_POLICY { - ULONG Revision; - PROCESSOR_POWER_POLICY ProcessorPolicyAc; - PROCESSOR_POWER_POLICY ProcessorPolicyDc; -} MACHINE_PROCESSOR_POWER_POLICY, *PMACHINE_PROCESSOR_POWER_POLICY; -typedef struct _USER_POWER_POLICY{ - ULONG Revision; - POWER_ACTION_POLICY IdleAc; - POWER_ACTION_POLICY IdleDc; - ULONG IdleTimeoutAc; - ULONG IdleTimeoutDc; - UCHAR IdleSensitivityAc; - UCHAR IdleSensitivityDc; - UCHAR ThrottlePolicyAc; - UCHAR ThrottlePolicyDc; - SYSTEM_POWER_STATE MaxSleepAc; - SYSTEM_POWER_STATE MaxSleepDc; - ULONG Reserved[2]; - ULONG VideoTimeoutAc; - ULONG VideoTimeoutDc; - ULONG SpindownTimeoutAc; - ULONG SpindownTimeoutDc; - BOOLEAN OptimizeForPowerAc; - BOOLEAN OptimizeForPowerDc; - UCHAR FanThrottleToleranceAc; - UCHAR FanThrottleToleranceDc; - UCHAR ForcedThrottleAc; - UCHAR ForcedThrottleDc; -} USER_POWER_POLICY, *PUSER_POWER_POLICY; -typedef struct _POWER_POLICY{ - USER_POWER_POLICY user; - MACHINE_POWER_POLICY mach; -} POWER_POLICY, *PPOWER_POLICY; + ULONG Revision; + PROCESSOR_POWER_POLICY ProcessorPolicyAc; + PROCESSOR_POWER_POLICY ProcessorPolicyDc; +} MACHINE_PROCESSOR_POWER_POLICY, +*PMACHINE_PROCESSOR_POWER_POLICY; + +typedef struct _USER_POWER_POLICY { + ULONG Revision; + POWER_ACTION_POLICY IdleAc; + POWER_ACTION_POLICY IdleDc; + ULONG IdleTimeoutAc; + ULONG IdleTimeoutDc; + UCHAR IdleSensitivityAc; + UCHAR IdleSensitivityDc; + UCHAR ThrottlePolicyAc; + UCHAR ThrottlePolicyDc; + SYSTEM_POWER_STATE MaxSleepAc; + SYSTEM_POWER_STATE MaxSleepDc; + ULONG Reserved[2]; + ULONG VideoTimeoutAc; + ULONG VideoTimeoutDc; + ULONG SpindownTimeoutAc; + ULONG SpindownTimeoutDc; + BOOLEAN OptimizeForPowerAc; + BOOLEAN OptimizeForPowerDc; + UCHAR FanThrottleToleranceAc; + UCHAR FanThrottleToleranceDc; + UCHAR ForcedThrottleAc; + UCHAR ForcedThrottleDc; +} USER_POWER_POLICY, +*PUSER_POWER_POLICY; + +typedef struct _POWER_POLICY { + USER_POWER_POLICY user; + MACHINE_POWER_POLICY mach; +} POWER_POLICY, +*PPOWER_POLICY; + +typedef enum _POWER_DATA_ACCESSOR { + ACCESS_AC_POWER_SETTING_INDEX, + ACCESS_DC_POWER_SETTING_INDEX, + ACCESS_FRIENDLY_NAME, + ACCESS_DESCRIPTION, + ACCESS_POSSIBLE_POWER_SETTING, + ACCESS_POSSIBLE_POWER_SETTING_FRIENDLY_NAME, + ACCESS_POSSIBLE_POWER_SETTING_DESCRIPTION, + ACCESS_DEFAULT_AC_POWER_SETTING, + ACCESS_DEFAULT_DC_POWER_SETTING, + ACCESS_POSSIBLE_VALUE_MIN, + ACCESS_POSSIBLE_VALUE_MAX, + ACCESS_POSSIBLE_VALUE_INCREMENT, + ACCESS_POSSIBLE_VALUE_UNITS, + ACCESS_ICON_RESOURCE, + ACCESS_DEFAULT_SECURITY_DESCRIPTOR, + ACCESS_ATTRIBUTES, + ACCESS_SCHEME, + ACCESS_SUBGROUP, + ACCESS_INDIVIDUAL_SETTING, + ACCESS_ACTIVE_SCHEME, + ACCESS_CREATE_SCHEME, + ACCESS_AC_POWER_SETTING_MAX, + ACCESS_DC_POWER_SETTING_MAX, + ACCESS_AC_POWER_SETTING_MIN, + ACCESS_DC_POWER_SETTING_MIN, + ACCESS_PROFILE, + ACCESS_OVERLAY_SCHEME, + ACCESS_ACTIVE_OVERLAY_SCHEME, +} POWER_DATA_ACCESSOR, *PPOWER_DATA_ACCESSOR; + typedef BOOLEAN (CALLBACK* PWRSCHEMESENUMPROC)(UINT, DWORD, LPWSTR, DWORD, LPWSTR, PPOWER_POLICY, LPARAM); -typedef BOOLEAN (CALLBACK* PFNNTINITIATEPWRACTION)(POWER_ACTION, SYSTEM_POWER_STATE, ULONG, BOOLEAN); +typedef PVOID HPOWERNOTIFY, *PHPOWERNOTIFY; + NTSTATUS WINAPI CallNtPowerInformation(POWER_INFORMATION_LEVEL, PVOID, ULONG, PVOID, ULONG); BOOLEAN WINAPI CanUserWritePwrScheme(VOID); BOOLEAN WINAPI DeletePwrScheme(UINT); @@ -105,6 +165,12 @@ BOOLEAN WINAPI IsAdminOverrideActive(PADMINISTRATOR_POWER_POLICY); BOOLEAN WINAPI IsPwrHibernateAllowed(VOID); BOOLEAN WINAPI IsPwrShutdownAllowed(VOID); BOOLEAN WINAPI IsPwrSuspendAllowed(VOID); +DWORD WINAPI PowerEnumerate(HKEY, const GUID *, const GUID *, POWER_DATA_ACCESSOR, ULONG, UCHAR *, DWORD *); +DWORD WINAPI PowerRegisterSuspendResumeNotification(DWORD, HANDLE, PHPOWERNOTIFY); +DWORD WINAPI PowerUnregisterSuspendResumeNotification(HPOWERNOTIFY); +DWORD WINAPI PowerSettingRegisterNotification(const GUID *, DWORD, HANDLE, PHPOWERNOTIFY); +DWORD WINAPI PowerSettingUnregisterNotification(HPOWERNOTIFY); +DWORD WINAPI PowerWriteACValueIndex(HKEY, const GUID *, const GUID *, const GUID *, DWORD); BOOLEAN WINAPI ReadGlobalPwrPolicy(PGLOBAL_POWER_POLICY); BOOLEAN WINAPI ReadProcessorPwrScheme(UINT, PMACHINE_PROCESSOR_POWER_POLICY); BOOLEAN WINAPI ReadPwrScheme(UINT, PPOWER_POLICY); @@ -115,7 +181,8 @@ BOOLEAN WINAPI WriteProcessorPwrScheme(UINT, PMACHINE_PROCESSOR_POWER_POLICY); BOOLEAN WINAPI ValidatePowerPolicies(PGLOBAL_POWER_POLICY, PPOWER_POLICY); BOOLEAN WINAPI WritePwrScheme(PUINT, LPWSTR, LPWSTR, PPOWER_POLICY); -#endif /* RC_INVOKED */ +/* Power scheme */ +POWER_PLATFORM_ROLE WINAPI PowerDeterminePlatformRole(void); #ifdef __cplusplus }
2 weeks, 5 days
1
0
0
0
[reactos] 01/01: [COMCTL32] fix version number reading/writing image lists and counting pointers for mixing image & mask
by Denis Malikov
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=28b802b229e1515686875…
commit 28b802b229e151568687593c7eeae84085de9022 Author: Denis Malikov <filedem(a)gmail.com> AuthorDate: Fri Jun 15 22:58:48 2018 +0700 Commit: Justin Miller <justinmiller100(a)gmail.com> CommitDate: Sun Feb 9 12:15:51 2025 -0800 [COMCTL32] fix version number reading/writing image lists and counting pointers for mixing image & mask --- dll/win32/comctl32/imagelist.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/dll/win32/comctl32/imagelist.c b/dll/win32/comctl32/imagelist.c index 8d74aac6ba6..5692af16ae8 100644 --- a/dll/win32/comctl32/imagelist.c +++ b/dll/win32/comctl32/imagelist.c @@ -112,11 +112,15 @@ struct _IMAGELIST BOOL color_table_set; LONG ref; /* reference count */ +#ifdef __REACTOS__ + USHORT usVersion; /* hack for IL from stream. Keep version here */ +#endif }; #define IMAGELIST_MAGIC 0x53414D58 #ifdef __REACTOS__ #define IMAGELIST_MAGIC_DESTROYED 0x44454144 +#define IMAGELIST_VERSION 0x101 #endif /* Header used by ImageList_Read() and ImageList_Write() */ @@ -841,6 +845,9 @@ ImageList_Create (INT cx, INT cy, UINT flags, himl->clrFg = CLR_DEFAULT; himl->clrBk = CLR_NONE; himl->color_table_set = FALSE; +#ifdef __REACTOS__ + himl->usVersion = 0; +#endif /* initialize overlay mask indices */ for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++) @@ -2477,7 +2484,13 @@ HIMAGELIST WINAPI ImageList_Read(IStream *pstm) return NULL; if (ilHead.usMagic != (('L' << 8) | 'I')) return NULL; +#ifdef __REACTOS__ + if (ilHead.usVersion != IMAGELIST_VERSION && + ilHead.usVersion != 0x600 && /* XP/2003 version */ + ilHead.usVersion != 0x620) /* Vista/7 version */ +#else if (ilHead.usVersion != 0x101) /* probably version? */ +#endif return NULL; TRACE("cx %u, cy %u, flags 0x%04x, cCurImage %u, cMaxImage %u\n", @@ -2487,6 +2500,11 @@ HIMAGELIST WINAPI ImageList_Read(IStream *pstm) if (!himl) return NULL; +#ifdef __REACTOS__ + /* keep version from stream */ + himl->usVersion = ilHead.usVersion; +#endif + if (!(image_bits = read_bitmap(pstm, image_info))) { WARN("failed to read bitmap from stream\n"); @@ -2506,17 +2524,34 @@ HIMAGELIST WINAPI ImageList_Read(IStream *pstm) { DWORD *ptr = image_bits; BYTE *mask_ptr = mask_bits; +#ifdef __REACTOS__ + int stride = himl->cy * (ilHead.usVersion != IMAGELIST_VERSION ? himl->cx : image_info->bmiHeader.biWidth); + int image_step = ilHead.usVersion != IMAGELIST_VERSION ? 1 : TILE_COUNT; + int mask_step = ilHead.usVersion != IMAGELIST_VERSION ? 4 : 8; +#else int stride = himl->cy * image_info->bmiHeader.biWidth; - +#endif if (image_info->bmiHeader.biHeight > 0) /* bottom-up */ { ptr += image_info->bmiHeader.biHeight * image_info->bmiHeader.biWidth - stride; +#ifdef __REACTOS__ + mask_ptr += (image_info->bmiHeader.biHeight * image_info->bmiHeader.biWidth - stride) / mask_step; +#else mask_ptr += (image_info->bmiHeader.biHeight * image_info->bmiHeader.biWidth - stride) / 8; +#endif stride = -stride; image_info->bmiHeader.biHeight = himl->cy; } else image_info->bmiHeader.biHeight = -himl->cy; - +#ifdef __REACTOS__ + for (i = 0; i < ilHead.cCurImage; i += image_step) + { + add_dib_bits(himl, i, min(ilHead.cCurImage - i, image_step), + himl->cx, himl->cy, image_info, mask_info, ptr, mask_ptr); + ptr += stride; + mask_ptr += stride / mask_step; + } +#else for (i = 0; i < ilHead.cCurImage; i += TILE_COUNT) { add_dib_bits( himl, i, min( ilHead.cCurImage - i, TILE_COUNT ), @@ -2524,6 +2559,7 @@ HIMAGELIST WINAPI ImageList_Read(IStream *pstm) ptr += stride; mask_ptr += stride / 8; } +#endif } else {
3 weeks, 1 day
1
0
0
0
[reactos] 01/01: [SHELL32] Expand .lnk working directory string before checking if it's valid (#7710)
by Whindmar Saksit
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e4216bd015965ab45b7a4…
commit e4216bd015965ab45b7a4cb1e35a7eeb3f43c666 Author: Whindmar Saksit <whindsaks(a)proton.me> AuthorDate: Sun Feb 9 20:07:17 2025 +0100 Commit: GitHub <noreply(a)github.com> CommitDate: Sun Feb 9 20:07:17 2025 +0100 [SHELL32] Expand .lnk working directory string before checking if it's valid (#7710) Handles the case where SEE_MASK_DOENVSUBST will expand it later inside ShellExeute. CORE-19987 --- dll/win32/shell32/CShellLink.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/dll/win32/shell32/CShellLink.cpp b/dll/win32/shell32/CShellLink.cpp index 6ad2dec1e9a..b60987d40a3 100644 --- a/dll/win32/shell32/CShellLink.cpp +++ b/dll/win32/shell32/CShellLink.cpp @@ -216,6 +216,22 @@ static LPWSTR __inline strdupW(LPCWSTR src) return dest; } +static BOOL PathEnvSubstIsDirectory(LPCWSTR pszPath) +{ + // Note: Don't call SHExpandEnvironmentStringsW here, we need the required length + WCHAR szStack[MAX_PATH]; + DWORD cch = ExpandEnvironmentStringsW(pszPath, szStack, _countof(szStack)); + if (cch <= _countof(szStack)) + return cch && PathIsDirectory(szStack); + + PWSTR szHeap = (PWSTR)SHAlloc(cch); + if (!szHeap) + return FALSE; + BOOL bResult = ExpandEnvironmentStringsW(pszPath, szHeap, cch) && PathIsDirectory(szHeap); + SHFree(szHeap); + return bResult; +} + // TODO: Use it for constructor & destructor too VOID CShellLink::Reset() { @@ -2667,7 +2683,7 @@ HRESULT CShellLink::DoOpen(LPCMINVOKECOMMANDINFO lpici) sei.nShow = lpici->nShow; // Allow invoker to override .lnk show mode // Use the invoker specified working directory if the link did not specify one - if (StrIsNullOrEmpty(sei.lpDirectory) || !PathIsDirectoryW(sei.lpDirectory)) + if (StrIsNullOrEmpty(sei.lpDirectory) || !PathEnvSubstIsDirectory(sei.lpDirectory)) { LPCSTR pszDirA = lpici->lpDirectory; if (unicode && !StrIsNullOrEmpty(iciex->lpDirectoryW))
3 weeks, 1 day
1
0
0
0
[reactos] 01/01: [RICHED20_WINETEST] Sync to Wine-6.10. (#7692)
by Doug Lyons
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=364d6e0346e62d6e9ece7…
commit 364d6e0346e62d6e9ece700be1adac76be763d68 Author: Doug Lyons <douglyons(a)douglyons.com> AuthorDate: Sat Feb 8 13:04:04 2025 -0600 Commit: GitHub <noreply(a)github.com> CommitDate: Sat Feb 8 13:04:04 2025 -0600 [RICHED20_WINETEST] Sync to Wine-6.10. (#7692) ROSTESTS-398 and CORE-6727 --- modules/rostests/winetests/riched20/editor.c | 73 ++- modules/rostests/winetests/riched20/richole.c | 890 +++++++++++++++----------- modules/rostests/winetests/riched20/txtsrv.c | 285 ++++++++- sdk/include/psdk/textserv.h | 88 ++- 4 files changed, 915 insertions(+), 421 deletions(-) diff --git a/modules/rostests/winetests/riched20/editor.c b/modules/rostests/winetests/riched20/editor.c index 791f471dee2..6bac7e0a89b 100644 --- a/modules/rostests/winetests/riched20/editor.c +++ b/modules/rostests/winetests/riched20/editor.c @@ -33,6 +33,8 @@ #include <ole2.h> #include <richedit.h> #include <richole.h> +#include <imm.h> +#include <textserv.h> #include <commdlg.h> #include <time.h> #include <wine/test.h> @@ -51,12 +53,38 @@ static CHAR string1[MAX_PATH], string2[MAX_PATH], string3[MAX_PATH]; static HMODULE hmoduleRichEdit; static BOOL is_lang_japanese; +#if defined(__i386__) && !defined(__MINGW32__) && (!defined(_MSC_VER) || !defined(__clang__)) +static void disable_beep( HWND hwnd ) +{ + /* don't attempt to disable beep if we don't have thiscall compiler support */ +} +#else +#define ITextServices_OnTxPropertyBitsChange(This,a,b) (This)->lpVtbl->OnTxPropertyBitsChange(This,a,b) +static void disable_beep( HWND hwnd ) +{ + IRichEditOle *richole; + ITextServices *services; + IID *pIID_ITextServices = (IID *)GetProcAddress( hmoduleRichEdit, "IID_ITextServices" ); + + if (SendMessageW( hwnd, EM_GETOLEINTERFACE, 0, (LPARAM)&richole )) + { + if (SUCCEEDED( IRichEditOle_QueryInterface( richole, pIID_ITextServices, (void **)&services ) )) + { + ITextServices_OnTxPropertyBitsChange( services, TXTBIT_ALLOWBEEP, 0 ); + ITextServices_Release( services ); + } + IRichEditOle_Release( richole ); + } +} +#endif + static HWND new_window(LPCSTR lpClassName, DWORD dwStyle, HWND parent) { HWND hwnd; hwnd = CreateWindowA(lpClassName, NULL, dwStyle|WS_POPUP|WS_HSCROLL|WS_VSCROLL |WS_VISIBLE, 0, 0, 200, 60, parent, NULL, hmoduleRichEdit, NULL); ok(hwnd != NULL, "class: %s, error: %d\n", lpClassName, (int) GetLastError()); + disable_beep( hwnd ); return hwnd; } @@ -66,6 +94,7 @@ static HWND new_windowW(LPCWSTR lpClassName, DWORD dwStyle, HWND parent) { |WS_VISIBLE, 0, 0, 200, 60, parent, NULL, hmoduleRichEdit, NULL); ok(hwnd != NULL, "class: %s, error: %d\n", wine_dbgstr_w(lpClassName), (int) GetLastError()); + disable_beep( hwnd ); return hwnd; } @@ -615,7 +644,7 @@ static void test_EM_POSFROMCHAR(void) "gg\n" "hh\n"; - rtl = (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_FONTSIGNATURE, + rtl = (GetLocaleInfoA(LOCALE_SYSTEM_DEFAULT, LOCALE_FONTSIGNATURE, (LPSTR) &sig, sizeof(LOCALESIGNATURE)) && (sig.lsUsb[3] & 0x08000000) != 0); @@ -772,7 +801,7 @@ static void test_EM_SETCHARFORMAT(void) BOOL rtl; DWORD expect_effects; - rtl = (GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_FONTSIGNATURE, + rtl = (GetLocaleInfoA(LOCALE_SYSTEM_DEFAULT, LOCALE_FONTSIGNATURE, (LPSTR) &sig, sizeof(LOCALESIGNATURE)) && (sig.lsUsb[3] & 0x08000000) != 0); @@ -1791,8 +1820,8 @@ static void test_EM_GETTEXTRANGE(void) textRange.chrg.cpMin = 4; textRange.chrg.cpMax = 8; result = SendMessageA(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange); - todo_wine ok(result == 5, "EM_GETTEXTRANGE returned %ld\n", result); - todo_wine ok(!strcmp("ef\x8e\xf0g", buffer), "EM_GETTEXTRANGE filled %s\n", buffer); + ok(result == 5, "EM_GETTEXTRANGE returned %ld\n", result); + ok(!strcmp("ef\x8e\xf0g", buffer), "EM_GETTEXTRANGE filled %s\n", buffer); } DestroyWindow(hwndRichEdit); @@ -1829,8 +1858,8 @@ static void test_EM_GETSELTEXT(void) SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"abcdef\x8e\xf0ghijk"); SendMessageA(hwndRichEdit, EM_SETSEL, 4, 8); result = SendMessageA(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffer); - todo_wine ok(result == 5, "EM_GETSELTEXT returned %ld\n", result); - todo_wine ok(!strcmp("ef\x8e\xf0g", buffer), "EM_GETSELTEXT filled %s\n", buffer); + ok(result == 5, "EM_GETSELTEXT returned %ld\n", result); + ok(!strcmp("ef\x8e\xf0g", buffer), "EM_GETSELTEXT filled %s\n", buffer); } DestroyWindow(hwndRichEdit); @@ -1863,6 +1892,7 @@ static void test_EM_SETOPTIONS(void) hmoduleRichEdit, NULL); ok(hwndRichEdit != NULL, "class: %s, error: %d\n", RICHEDIT_CLASS20A, (int) GetLastError()); + disable_beep( hwndRichEdit ); options = SendMessageA(hwndRichEdit, EM_GETOPTIONS, 0, 0); /* WS_[VH]SCROLL cause the ECO_AUTO[VH]SCROLL options to be set */ ok(options == (ECO_AUTOVSCROLL|ECO_AUTOHSCROLL), @@ -3110,11 +3140,9 @@ static void test_scrollbar_visibility(void) GetScrollInfo(hwndRichEdit, SB_VERT, &si); ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0), "Vertical scrollbar is invisible, should be visible.\n"); - todo_wine { ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 100, "reported page/range is %d (%d..%d) expected 0 (0..100)\n", si.nPage, si.nMin, si.nMax); - } /* Ditto, see above */ SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0); @@ -3124,11 +3152,9 @@ static void test_scrollbar_visibility(void) GetScrollInfo(hwndRichEdit, SB_VERT, &si); ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0), "Vertical scrollbar is invisible, should be visible.\n"); - todo_wine { ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 100, "reported page/range is %d (%d..%d) expected 0 (0..100)\n", si.nPage, si.nMin, si.nMax); - } /* Ditto, see above */ SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"a"); @@ -3138,11 +3164,9 @@ static void test_scrollbar_visibility(void) GetScrollInfo(hwndRichEdit, SB_VERT, &si); ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0), "Vertical scrollbar is invisible, should be visible.\n"); - todo_wine { ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 100, "reported page/range is %d (%d..%d) expected 0 (0..100)\n", si.nPage, si.nMin, si.nMax); - } /* Ditto, see above */ SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)"a\na"); @@ -3152,11 +3176,9 @@ static void test_scrollbar_visibility(void) GetScrollInfo(hwndRichEdit, SB_VERT, &si); ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0), "Vertical scrollbar is invisible, should be visible.\n"); - todo_wine { ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 100, "reported page/range is %d (%d..%d) expected 0 (0..100)\n", si.nPage, si.nMin, si.nMax); - } /* Ditto, see above */ SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0); @@ -3166,11 +3188,9 @@ static void test_scrollbar_visibility(void) GetScrollInfo(hwndRichEdit, SB_VERT, &si); ok (((GetWindowLongA(hwndRichEdit, GWL_STYLE) & WS_VSCROLL) != 0), "Vertical scrollbar is invisible, should be visible.\n"); - todo_wine { ok(si.nPage == 0 && si.nMin == 0 && si.nMax == 100, "reported page/range is %d (%d..%d) expected 0 (0..100)\n", si.nPage, si.nMin, si.nMax); - } SendMessageA(hwndRichEdit, WM_SETTEXT, 0, (LPARAM)text); SendMessageA(hwndRichEdit, WM_SETTEXT, 0, 0); @@ -5610,7 +5630,7 @@ static void test_EM_FORMATRANGE(void) {"WINE\r\n\r\nwine\r\nwine", 5, 6} }; - skip_non_english = (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH); + skip_non_english = (PRIMARYLANGID(GetSystemDefaultLangID()) != LANG_ENGLISH); if (skip_non_english) skip("Skipping some tests on non-English platform\n"); @@ -6348,6 +6368,7 @@ static void test_WM_CHAR(void) hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP, 0, 0, 200, 60, 0, 0, 0, 0); ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError()); + disable_beep( hwnd ); p = char_list; while (*p != '\0') { @@ -6951,6 +6972,7 @@ static void test_undo_coalescing(void) hwnd = CreateWindowExA(0, "RichEdit20W", NULL, WS_POPUP|ES_MULTILINE, 0, 0, 200, 60, 0, 0, 0, 0); ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError()); + disable_beep( hwnd ); result = SendMessageA(hwnd, EM_CANUNDO, 0, 0); ok (result == FALSE, "Can undo after window creation.\n"); @@ -7461,12 +7483,25 @@ static void test_format_rect(void) ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc), wine_dbgstr_rect(&expected)); + /* reset back to client rect and now try adding selection bar */ + SendMessageA(hwnd, EM_SETRECT, 0, 0); + expected = clientRect; + InflateRect(&expected, -1, 0); + SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc); + ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc), + wine_dbgstr_rect(&expected)); + SendMessageA(hwnd, EM_SETOPTIONS, ECOOP_OR, ECO_SELECTIONBAR); + SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc); + ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc), + wine_dbgstr_rect(&expected)); + SendMessageA(hwnd, EM_SETOPTIONS, ECOOP_AND, ~ECO_SELECTIONBAR); + /* Set the absolute value of the formatting rectangle. */ rc = clientRect; SendMessageA(hwnd, EM_SETRECT, 0, (LPARAM)&rc); expected = clientRect; SendMessageA(hwnd, EM_GETRECT, 0, (LPARAM)&rc); - ok(EqualRect(&rc, &expected), "[n=%d] rect %s != %s\n", n, wine_dbgstr_rect(&rc), + ok(EqualRect(&rc, &expected), "rect %s != %s\n", wine_dbgstr_rect(&rc), wine_dbgstr_rect(&expected)); /* MSDN documents the EM_SETRECT message as using the rectangle provided in @@ -9026,7 +9061,7 @@ START_TEST( editor ) * RICHED20.DLL, so the linker doesn't actually link to it. */ hmoduleRichEdit = LoadLibraryA("riched20.dll"); ok(hmoduleRichEdit != NULL, "error: %d\n", (int) GetLastError()); - is_lang_japanese = (PRIMARYLANGID(GetUserDefaultLangID()) == LANG_JAPANESE); + is_lang_japanese = (PRIMARYLANGID(GetSystemDefaultLangID()) == LANG_JAPANESE); test_window_classes(); test_WM_CHAR(); diff --git a/modules/rostests/winetests/riched20/richole.c b/modules/rostests/winetests/riched20/richole.c index 492bdc3fa9a..3885eb527fc 100644 --- a/modules/rostests/winetests/riched20/richole.c +++ b/modules/rostests/winetests/riched20/richole.c @@ -149,6 +149,7 @@ static void test_Interfaces(void) LRESULT res; HWND w; ULONG refcount; + IUnknown *unk, *unk2; w = new_richedit(NULL); if (!w) { @@ -180,6 +181,14 @@ static void test_Interfaces(void) hres = ITextDocument_GetSelection(txtDoc, &txtSel); ok(hres == S_OK, "got 0x%08x\n", hres); + hres = ITextDocument_QueryInterface(txtDoc, &IID_IUnknown, (void **)&unk); + ok(hres == S_OK, "got 0x%08x\n", hres); + hres = ITextSelection_QueryInterface(txtSel, &IID_IUnknown, (void **)&unk2); + ok(hres == S_OK, "got 0x%08x\n", hres); + ok(unk != unk2, "unknowns are the same\n"); + IUnknown_Release(unk2); + IUnknown_Release(unk); + EXPECT_REF(txtDoc, 4); EXPECT_REF(txtSel, 2); @@ -3203,29 +3212,62 @@ static void fill_reobject_struct(REOBJECT *reobj, LONG cp, LPOLEOBJECT poleobj, reobj->dwUser = user; } -#define CHECK_REOBJECT_STRUCT(reobj,poleobj,pstg,polesite,user) \ - _check_reobject_struct(reobj, poleobj, pstg, polesite, user, __LINE__) -static void _check_reobject_struct(REOBJECT reobj, LPOLEOBJECT poleobj, LPSTORAGE pstg, - LPOLECLIENTSITE polesite, DWORD user, int line) +#define CHECK_REOBJECT_STRUCT(reole,index,flags,cp,poleobj,pstg,polesite,user) \ + _check_reobject_struct(reole, index, flags, cp, poleobj, pstg, polesite, user, __LINE__) +static void _check_reobject_struct(IRichEditOle *reole, LONG index, DWORD flags, LONG cp, + LPOLEOBJECT poleobj, LPSTORAGE pstg, LPOLECLIENTSITE polesite, DWORD user, int line) { + REOBJECT reobj; + HRESULT hr; + + reobj.cbStruct = sizeof(reobj); + reobj.cp = cp; + hr = IRichEditOle_GetObject(reole, index, &reobj, flags); + ok(hr == S_OK, "IRichEditOle_GetObject failed: %#x.\n", hr); ok_(__FILE__,line)(reobj.poleobj == poleobj, "got wrong object interface.\n"); ok_(__FILE__,line)(reobj.pstg == pstg, "got wrong storage interface.\n"); ok_(__FILE__,line)(reobj.polesite == polesite, "got wrong site interface.\n"); ok_(__FILE__,line)(reobj.dwUser == user, "got wrong user-defined value.\n"); } +#define INSERT_REOBJECT(reole,reobj,cp,user) \ + _insert_reobject(reole, reobj, cp, user, __LINE__) +static void _insert_reobject(IRichEditOle *reole, REOBJECT *reobj, LONG cp, DWORD user, int line) +{ + IOleClientSite *clientsite; + HRESULT hr; + hr = IRichEditOle_GetClientSite(reole, &clientsite); + ok_(__FILE__,line)(hr == S_OK, "IRichEditOle_GetClientSite got hr %#x.\n", hr); + fill_reobject_struct(reobj, cp, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, user); + hr = IRichEditOle_InsertObject(reole, reobj); + ok_(__FILE__,line)(hr == S_OK, "IRichEditOle_InsertObject got hr %#x.\n", hr); + IOleClientSite_Release(clientsite); +} + static void test_InsertObject(void) { static CHAR test_text1[] = "abcdefg"; IRichEditOle *reole = NULL; ITextDocument *doc = NULL; - IOleClientSite *clientsite; - REOBJECT reo1, reo2, reo3, received_reo1, received_reo2, received_reo3, received_reo4; + REOBJECT reo1, reo2, reo3, received_reo; HRESULT hr; HWND hwnd; - LONG count; + const WCHAR *expected_string; + const CHAR *expected_stringA; + ITextSelection *selection; + IDataObject *dataobject; + TEXTRANGEA textrange; + FORMATETC formatetc; + CHARRANGE charrange; + GETTEXTEX gettextex; + STGMEDIUM stgmedium; + WCHAR buffer[1024]; + CHAR bufferA[1024]; + LONG count, result; + ITextRange *range; + BSTR bstr; - create_interfaces(&hwnd, &reole, &doc, NULL); + create_interfaces(&hwnd, &reole, &doc, &selection); SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1); hr = IRichEditOle_InsertObject(reole, NULL); @@ -3233,161 +3275,278 @@ static void test_InsertObject(void) /* insert object1 in (0, 1)*/ SendMessageA(hwnd, EM_SETSEL, 0, 1); - hr = IRichEditOle_GetClientSite(reole, &clientsite); - ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr); - fill_reobject_struct(&reo1, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 1); - hr = IRichEditOle_InsertObject(reole, &reo1); - ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr); + INSERT_REOBJECT(reole, &reo1, REO_CP_SELECTION, 1); count = IRichEditOle_GetObjectCount(reole); ok(count == 1, "got wrong object count: %d\n", count); - IOleClientSite_Release(clientsite); /* insert object2 in (2, 3)*/ SendMessageA(hwnd, EM_SETSEL, 2, 3); - hr = IRichEditOle_GetClientSite(reole, &clientsite); - ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr); - fill_reobject_struct(&reo2, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 2); - hr = IRichEditOle_InsertObject(reole, &reo2); - ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr); + INSERT_REOBJECT(reole, &reo2, REO_CP_SELECTION, 2); count = IRichEditOle_GetObjectCount(reole); ok(count == 2, "got wrong object count: %d\n", count); - IOleClientSite_Release(clientsite); /* insert object3 in (1, 2)*/ SendMessageA(hwnd, EM_SETSEL, 1, 2); - hr = IRichEditOle_GetClientSite(reole, &clientsite); - ok(hr == S_OK, "IRichEditOle_GetClientSite failed: 0x%08x\n", hr); - fill_reobject_struct(&reo3, REO_CP_SELECTION, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 3); - hr = IRichEditOle_InsertObject(reole, &reo3); - ok(hr == S_OK, "IRichEditOle_InsertObject failed: 0x%08x\n", hr); + INSERT_REOBJECT(reole, &reo3, REO_CP_SELECTION, 3); count = IRichEditOle_GetObjectCount(reole); ok(count == 3, "got wrong object count: %d\n", count); - IOleClientSite_Release(clientsite); /* tests below show that order of rebject (from 0 to 2) is: reo1,reo3,reo2 */ - received_reo1.cbStruct = sizeof(received_reo1); - hr = IRichEditOle_GetObject(reole, 0, &received_reo1, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo1, NULL, NULL, reo1.polesite, 1); - - received_reo2.cbStruct = sizeof(received_reo2); - hr = IRichEditOle_GetObject(reole, 1, &received_reo2, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo2, NULL, NULL, reo3.polesite, 3); - - received_reo3.cbStruct = sizeof(received_reo3); - hr = IRichEditOle_GetObject(reole, 2, &received_reo3, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo3, NULL, NULL, reo2.polesite, 2); + CHECK_REOBJECT_STRUCT(reole, 0, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo1.polesite, 1); + CHECK_REOBJECT_STRUCT(reole, 1, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo3.polesite, 3); + CHECK_REOBJECT_STRUCT(reole, 2, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo2.polesite, 2); hr = IRichEditOle_GetObject(reole, 2, NULL, REO_GETOBJ_ALL_INTERFACES); ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr); - received_reo4.cbStruct = 0; - hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_ALL_INTERFACES); + received_reo.cbStruct = 0; + hr = IRichEditOle_GetObject(reole, 2, &received_reo, REO_GETOBJ_ALL_INTERFACES); ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr); - received_reo4.cbStruct = sizeof(received_reo4); - hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_PSTG); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, NULL, 2); - - hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_POLESITE); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo2.polesite, 2); + CHECK_REOBJECT_STRUCT(reole, 2, REO_GETOBJ_PSTG, 0, NULL, NULL, NULL, 2); + CHECK_REOBJECT_STRUCT(reole, 2, REO_GETOBJ_POLESITE, 0, NULL, NULL, reo2.polesite, 2); - hr = IRichEditOle_GetObject(reole, 4, &received_reo4, REO_GETOBJ_POLESITE); + hr = IRichEditOle_GetObject(reole, 3, &received_reo, REO_GETOBJ_POLESITE); ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr); - hr = IRichEditOle_GetObject(reole, 1024, &received_reo4, REO_GETOBJ_POLESITE); + hr = IRichEditOle_GetObject(reole, 4, &received_reo, REO_GETOBJ_POLESITE); ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr); - /* received_reo4 will be zeroed before be used */ - hr = IRichEditOle_GetObject(reole, 2, &received_reo4, REO_GETOBJ_NO_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, NULL, 2); + hr = IRichEditOle_GetObject(reole, 1024, &received_reo, REO_GETOBJ_POLESITE); + ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 0; - hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo4, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo1.polesite, 1); + hr = IRichEditOle_GetObject(reole, -10, &received_reo, REO_GETOBJ_POLESITE); + ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 1; - hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo4, REO_GETOBJ_ALL_INTERFACES); + /* received_reo will be zeroed before be used */ + received_reo.cbStruct = sizeof(received_reo); + received_reo.polesite = (IOleClientSite *)0xdeadbeef; + hr = IRichEditOle_GetObject(reole, 2, &received_reo, REO_GETOBJ_NO_INTERFACES); ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo3.polesite, 3); + ok(received_reo.polesite == (IOleClientSite *)NULL, "Got wrong site interface.\n"); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 2; - hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo4, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo2.polesite, 2); + CHECK_REOBJECT_STRUCT(reole, REO_IOB_USE_CP, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo1.polesite, 1); + CHECK_REOBJECT_STRUCT(reole, REO_IOB_USE_CP, REO_GETOBJ_ALL_INTERFACES, 1, NULL, NULL, reo3.polesite, 3); + CHECK_REOBJECT_STRUCT(reole, REO_IOB_USE_CP, REO_GETOBJ_ALL_INTERFACES, 2, NULL, NULL, reo2.polesite, 2); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 4; - hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo4, REO_GETOBJ_ALL_INTERFACES); + received_reo.cbStruct = sizeof(received_reo); + received_reo.polesite = (IOleClientSite *)0xdeadbeef; + received_reo.dwUser = 4; + received_reo.cp = 4; + hr = IRichEditOle_GetObject(reole, REO_IOB_USE_CP, &received_reo, REO_GETOBJ_ALL_INTERFACES); ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr); - /* received_reo4 didn't be zeroed in E_INVALIDARG case */ - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo2.polesite, 2); + ok(received_reo.polesite == (IOleClientSite *)0xdeadbeef, "Got wrong site interface.\n"); + ok(received_reo.dwUser == 4, "Got wrong user-defined value: %d.\n", received_reo.dwUser); SendMessageA(hwnd, EM_SETSEL, 0, 1); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 1; - hr = IRichEditOle_GetObject(reole, REO_IOB_SELECTION, &received_reo4, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo1.polesite, 1); + CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo1.polesite, 1); SendMessageA(hwnd, EM_SETSEL, 1, 2); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 0; - hr = IRichEditOle_GetObject(reole, REO_IOB_SELECTION, &received_reo4, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo3.polesite, 3); + CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo3.polesite, 3); SendMessageA(hwnd, EM_SETSEL, 2, 3); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 0; - hr = IRichEditOle_GetObject(reole, REO_IOB_SELECTION, &received_reo4, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo2.polesite, 2); + CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo2.polesite, 2); SendMessageA(hwnd, EM_SETSEL, 0, 2); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 0; - hr = IRichEditOle_GetObject(reole, REO_IOB_SELECTION, &received_reo4, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo1.polesite, 1); + CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo1.polesite, 1); SendMessageA(hwnd, EM_SETSEL, 1, 3); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 0; - hr = IRichEditOle_GetObject(reole, REO_IOB_SELECTION, &received_reo4, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo3.polesite, 3); + CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo3.polesite, 3); SendMessageA(hwnd, EM_SETSEL, 2, 0); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 0; - hr = IRichEditOle_GetObject(reole, REO_IOB_SELECTION, &received_reo4, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo1.polesite, 1); + CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo1.polesite, 1); SendMessageA(hwnd, EM_SETSEL, 0, 6); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 0; - hr = IRichEditOle_GetObject(reole, REO_IOB_SELECTION, &received_reo4, REO_GETOBJ_ALL_INTERFACES); - ok(hr == S_OK, "IRichEditOle_GetObject failed: 0x%08x\n", hr); - CHECK_REOBJECT_STRUCT(received_reo4, NULL, NULL, reo1.polesite, 1); + CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 0, NULL, NULL, reo1.polesite, 1); SendMessageA(hwnd, EM_SETSEL, 4, 5); - received_reo4.cbStruct = sizeof(received_reo4); - received_reo4.cp = 0; - hr = IRichEditOle_GetObject(reole, REO_IOB_SELECTION, &received_reo4, REO_GETOBJ_ALL_INTERFACES); + received_reo.cbStruct = sizeof(received_reo); + received_reo.cp = 0; + hr = IRichEditOle_GetObject(reole, REO_IOB_SELECTION, &received_reo, REO_GETOBJ_ALL_INTERFACES); ok(hr == E_INVALIDARG, "IRichEditOle_GetObject should fail: 0x%08x\n", hr); - release_interfaces(&hwnd, &reole, &doc, NULL); + SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1); + + /* "abc|d|efg" */ + INSERT_REOBJECT(reole, &reo1, 3, 1); + INSERT_REOBJECT(reole, &reo2, 5, 2); + + SendMessageW(hwnd, EM_SETSEL, 2, 3); + result = SendMessageW(hwnd, EM_SELECTIONTYPE, 0, 0); + ok(result == SEL_TEXT, "Got selection type: %x.\n", result); + + SendMessageW(hwnd, EM_SETSEL, 3, 4); + result = SendMessageW(hwnd, EM_SELECTIONTYPE, 0, 0); + todo_wine ok(result == SEL_OBJECT, "Got selection type: %x.\n", result); + todo_wine CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 1, NULL, NULL, reo1.polesite, 1); + + SendMessageW(hwnd, EM_SETSEL, 2, 4); + result = SendMessageW(hwnd, EM_SELECTIONTYPE, 0, 0); + todo_wine ok(result == (SEL_TEXT | SEL_OBJECT), "Got selection type: %x.\n", result); + + SendMessageW(hwnd, EM_SETSEL, 5, 6); + todo_wine CHECK_REOBJECT_STRUCT(reole, REO_IOB_SELECTION, REO_GETOBJ_ALL_INTERFACES, 1, NULL, NULL, reo2.polesite, 2); + +#ifdef __REACTOS__ + expected_string = L"abc\xfffc"L"d\xfffc"L"efg"; +#else + expected_string = L"abc\xfffc""d\xfffc""efg"; +#endif + + gettextex.cb = sizeof(buffer); + gettextex.flags = GT_DEFAULT; + gettextex.codepage = 1200; + gettextex.lpDefaultChar = NULL; + gettextex.lpUsedDefChar = NULL; + result = SendMessageW(hwnd, EM_GETTEXTEX, (WPARAM)&gettextex, (LPARAM)buffer); + ok(result == lstrlenW(expected_string), "Got wrong length: %d.\n", result); + todo_wine ok(!lstrcmpW(buffer, expected_string), "Got wrong content: %s.\n", debugstr_w(buffer)); + + gettextex.flags = GT_RAWTEXT; + memset(buffer, 0, sizeof(buffer)); + result = SendMessageW(hwnd, EM_GETTEXTEX, (WPARAM)&gettextex, (LPARAM)buffer); + ok(result == lstrlenW(expected_string), "Got wrong length: %d.\n", result); + todo_wine ok(!lstrcmpW(buffer, expected_string), "Got wrong content: %s.\n", debugstr_w(buffer)); + + expected_stringA = "abc d efg"; + memset(bufferA, 0, sizeof(bufferA)); + SendMessageA(hwnd, EM_SETSEL, 0, -1); + result = SendMessageA(hwnd, EM_GETSELTEXT, (WPARAM)sizeof(bufferA), (LPARAM)bufferA); + ok(result == strlen(expected_stringA), "Got wrong length: %d.\n", result); + todo_wine ok(!strcmp(bufferA, expected_stringA), "Got wrong content: %s.\n", bufferA); + + memset(bufferA, 0, sizeof(bufferA)); + textrange.lpstrText = bufferA; + textrange.chrg.cpMin = 0; + textrange.chrg.cpMax = 11; + result = SendMessageA(hwnd, EM_GETTEXTRANGE, 0, (LPARAM)&textrange); + ok(result == strlen(expected_stringA), "Got wrong length: %d.\n", result); + todo_wine ok(!strcmp(bufferA, expected_stringA), "Got wrong content: %s.\n", bufferA); + +#ifdef __REACTOS__ + expected_string = L"abc\xfffc"L"d\xfffc"L"efg\r"; +#else + expected_string = L"abc\xfffc""d\xfffc""efg\r"; +#endif + + hr = ITextDocument_Range(doc, 0, 11, &range); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = ITextRange_GetText(range, &bstr); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(lstrlenW(bstr) == lstrlenW(expected_string), "Got wrong length: %d.\n", lstrlenW(bstr)); + todo_wine ok(!lstrcmpW(bstr, expected_string), "Got text: %s.\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + hr = ITextRange_SetRange(range, 3, 4); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = ITextRange_GetChar(range, &result); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(result == 0xfffc, "Got char: %c\n", result); + ITextRange_Release(range); + + SendMessageW(hwnd, EM_SETSEL, 0, -1); + hr = ITextSelection_GetText(selection, &bstr); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(lstrlenW(bstr) == lstrlenW(expected_string), "Got wrong length: %d.\n", lstrlenW(bstr)); + todo_wine ok(!lstrcmpW(bstr, expected_string), "Got text: %s.\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + SendMessageW(hwnd, EM_SETSEL, 3, 4); + result = 0; + hr = ITextSelection_GetChar(selection, &result); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(result == 0xfffc, "Got char: %c\n", result); + + SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)""); + result = SendMessageW(hwnd, EM_SETTEXTMODE, (WPARAM)TM_PLAINTEXT, 0); + ok(!result, "Got result %x.\n", result); + /* "abc|d|efg" */ + SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1); + INSERT_REOBJECT(reole, &reo1, 3, 1); + INSERT_REOBJECT(reole, &reo2, 5, 2); + + expected_string = L"abc d efg"; + charrange.cpMin = 0; + charrange.cpMax = 11; + hr = IRichEditOle_GetClipboardData(reole, &charrange, 1, &dataobject); + ok(hr == S_OK, "Got hr %#x.\n", hr); + formatetc.cfFormat = CF_UNICODETEXT; + formatetc.dwAspect = DVASPECT_CONTENT; + formatetc.ptd = NULL; + formatetc.tymed = TYMED_HGLOBAL; + formatetc.lindex = -1; + hr = IDataObject_GetData(dataobject, &formatetc, &stgmedium); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(lstrlenW(stgmedium.hGlobal) == lstrlenW(expected_string), "Got wrong length: %d.\n", result); + todo_wine ok(!lstrcmpW(stgmedium.hGlobal, expected_string), "Got wrong content: %s.\n", debugstr_w(stgmedium.hGlobal)); + +#ifdef __REACTOS__ + expected_string = L"abc\xfffc"L"d\xfffc"L"efg"; +#else + expected_string = L"abc\xfffc""d\xfffc""efg"; +#endif + + gettextex.cb = sizeof(buffer); + gettextex.flags = GT_DEFAULT; + gettextex.codepage = 1200; + gettextex.lpDefaultChar = NULL; + gettextex.lpUsedDefChar = NULL; + result = SendMessageW(hwnd, EM_GETTEXTEX, (WPARAM)&gettextex, (LPARAM)buffer); + ok(result == lstrlenW(expected_string), "Got wrong length: %d.\n", result); + todo_wine ok(!lstrcmpW(buffer, expected_string), "Got wrong content: %s.\n", debugstr_w(buffer)); + + gettextex.flags = GT_RAWTEXT; + memset(buffer, 0, sizeof(buffer)); + result = SendMessageW(hwnd, EM_GETTEXTEX, (WPARAM)&gettextex, (LPARAM)buffer); + ok(result == lstrlenW(expected_string), "Got wrong length: %d.\n", result); + todo_wine ok(!lstrcmpW(buffer, expected_string), "Got wrong content: %s.\n", debugstr_w(buffer)); + + expected_stringA = "abc d efg"; + memset(bufferA, 0, sizeof(bufferA)); + SendMessageA(hwnd, EM_SETSEL, 0, -1); + result = SendMessageA(hwnd, EM_GETSELTEXT, (WPARAM)sizeof(bufferA), (LPARAM)bufferA); + ok(result == strlen(expected_stringA), "Got wrong length: %d.\n", result); + todo_wine ok(!strcmp(bufferA, expected_stringA), "Got wrong content: %s.\n", bufferA); + + memset(bufferA, 0, sizeof(bufferA)); + textrange.lpstrText = bufferA; + textrange.chrg.cpMin = 0; + textrange.chrg.cpMax = 11; + result = SendMessageA(hwnd, EM_GETTEXTRANGE, 0, (LPARAM)&textrange); + ok(result == strlen(expected_stringA), "Got wrong length: %d.\n", result); + todo_wine ok(!strcmp(bufferA, expected_stringA), "Got wrong content: %s.\n", bufferA); + +#ifdef __REACTOS__ + expected_string = L"abc\xfffc"L"d\xfffc"L"efg"; +#else + expected_string = L"abc\xfffc""d\xfffc""efg"; +#endif + + hr = ITextDocument_Range(doc, 0, 11, &range); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = ITextRange_GetText(range, &bstr); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(lstrlenW(bstr) == lstrlenW(expected_string), "Got wrong length: %d.\n", lstrlenW(bstr)); + todo_wine ok(!lstrcmpW(bstr, expected_string), "Got text: %s.\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + hr = ITextRange_SetRange(range, 3, 4); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = ITextRange_GetChar(range, &result); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(result == 0xfffc, "Got char: %c\n", result); + ITextRange_Release(range); + + SendMessageW(hwnd, EM_SETSEL, 0, -1); + hr = ITextSelection_GetText(selection, &bstr); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(lstrlenW(bstr) == lstrlenW(expected_string), "Got wrong length: %d.\n", lstrlenW(bstr)); + todo_wine ok(!lstrcmpW(bstr, expected_string), "Got text: %s.\n", wine_dbgstr_w(bstr)); + SysFreeString(bstr); + SendMessageW(hwnd, EM_SETSEL, 3, 4); + result = 0; + hr = ITextSelection_GetChar(selection, &result); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(result == 0xfffc, "Got char: %c\n", result); + + release_interfaces(&hwnd, &reole, &doc, &selection); } static void test_GetStoryLength(void) @@ -3694,7 +3853,7 @@ static void test_Expand(void) ITextRange_Release(range); } -static void test_MoveEnd(void) +static void test_MoveEnd_story(void) { static const char test_text1[] = "Word1 Word2"; IRichEditOle *reole = NULL; @@ -3808,272 +3967,288 @@ static void test_MoveEnd(void) ITextRange_Release(range); } -static void test_ITextRange_SetStart(void) +static void test_character_movestart(ITextRange *range, int textlen, int i, int j, LONG target) { - HWND w; - IRichEditOle *reOle = NULL; - ITextDocument *txtDoc = NULL; - ITextRange *txtRge = NULL; - HRESULT hres; - LONG first, lim, start, end; - static const CHAR test_text1[] = "TestSomeText"; - - create_interfaces(&w, &reOle, &txtDoc, NULL); - SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); - - first = 4, lim = 8; - ITextDocument_Range(txtDoc, first, lim, &txtRge); - hres = ITextRange_SetStart(txtRge, first); - ok(hres == S_FALSE, "ITextRange_SetStart\n"); - -#define TEST_TXTRGE_SETSTART(cp, expected_start, expected_end) \ - hres = ITextRange_SetStart(txtRge, cp); \ - ok(hres == S_OK, "ITextRange_SetStart\n"); \ - ITextRange_GetStart(txtRge, &start); \ - ITextRange_GetEnd(txtRge, &end); \ - ok(start == expected_start, "got wrong start value: %d\n", start); \ - ok(end == expected_end, "got wrong end value: %d\n", end); - - TEST_TXTRGE_SETSTART(2, 2, 8) - TEST_TXTRGE_SETSTART(-1, 0, 8) - TEST_TXTRGE_SETSTART(13, 12, 12) - - release_interfaces(&w, &reOle, &txtDoc, NULL); + HRESULT hr; + LONG delta = 0; + LONG expected_delta; + LONG expected_start = target; + + if (expected_start < 0) + expected_start = 0; + else if (expected_start > textlen) + expected_start = textlen; + expected_delta = expected_start - i; + hr = ITextRange_SetRange(range, i, j); + ok(SUCCEEDED(hr), "got 0x%08x\n", hr); + hr = ITextRange_MoveStart(range, tomCharacter, target - i, &delta); + if (expected_start == i) { + ok(hr == S_FALSE, "(%d,%d) move by %d got hr=0x%08x\n", i, j, target - i, hr); + ok(delta == 0, "(%d,%d) move by %d got delta %d\n", i, j, target - i, delta); + CHECK_RANGE(range, i, j); + } else { + ok(hr == S_OK, "(%d,%d) move by %d got hr=0x%08x\n", i, j, target - i, hr); + ok(delta == expected_delta, "(%d,%d) move by %d got delta %d\n", i, j, target - i, delta); + if (expected_start <= j) + CHECK_RANGE(range, expected_start, j); + else + CHECK_RANGE(range, expected_start, expected_start); + } } -static void test_ITextRange_SetEnd(void) +static void test_character_moveend(ITextRange *range, int textlen, int i, int j, LONG target) { - HWND w; - IRichEditOle *reOle = NULL; - ITextDocument *txtDoc = NULL; - ITextRange *txtRge = NULL; - HRESULT hres; - LONG first, lim, start, end; - static const CHAR test_text1[] = "TestSomeText"; - - create_interfaces(&w, &reOle, &txtDoc, NULL); - SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); - - first = 4, lim = 8; - ITextDocument_Range(txtDoc, first, lim, &txtRge); - hres = ITextRange_SetEnd(txtRge, lim); - ok(hres == S_FALSE, "ITextRange_SetEnd\n"); - -#define TEST_TXTRGE_SETEND(cp, expected_start, expected_end) \ - hres = ITextRange_SetEnd(txtRge, cp); \ - ok(hres == S_OK, "ITextRange_SetEnd\n"); \ - ITextRange_GetStart(txtRge, &start); \ - ITextRange_GetEnd(txtRge, &end); \ - ok(start == expected_start, "got wrong start value: %d\n", start); \ - ok(end == expected_end, "got wrong end value: %d\n", end); - - TEST_TXTRGE_SETEND(6, 4, 6) - TEST_TXTRGE_SETEND(14, 4, 13) - TEST_TXTRGE_SETEND(-1, 0, 0) - - ITextRange_Release(txtRge); - release_interfaces(&w, &reOle, &txtDoc, NULL); + HRESULT hr; + LONG delta; + LONG expected_delta; + LONG expected_end = target; + + if (expected_end < 0) + expected_end = 0; + else if (expected_end > textlen + 1) + expected_end = textlen + 1; + expected_delta = expected_end - j; + hr = ITextRange_SetRange(range, i, j); + ok(SUCCEEDED(hr), "got 0x%08x\n", hr); + hr = ITextRange_MoveEnd(range, tomCharacter, target - j, &delta); + if (expected_end == j) { + ok(hr == S_FALSE, "(%d,%d) move by %d got hr=0x%08x\n", i, j, target - j, hr); + ok(delta == 0, "(%d,%d) move by %d got delta %d\n", i, j, target - j, delta); + CHECK_RANGE(range, i, j); + } else { + ok(hr == S_OK, "(%d,%d) move by %d got hr=0x%08x\n", i, j, target - j, hr); + ok(delta == expected_delta, "(%d,%d) move by %d got delta %d\n", i, j, target - j, delta); + if (i <= expected_end) + CHECK_RANGE(range, i, expected_end); + else + CHECK_RANGE(range, expected_end, expected_end); + } } -static void test_ITextSelection_SetStart(void) +static void test_character_move(ITextRange *range, int textlen, int i, int j, LONG target) { - HWND w; - IRichEditOle *reOle = NULL; - ITextDocument *txtDoc = NULL; - ITextSelection *txtSel = NULL; - HRESULT hres; - LONG first, lim, start, end; - static const CHAR test_text1[] = "TestSomeText"; - - create_interfaces(&w, &reOle, &txtDoc, &txtSel); - SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); - - first = 4, lim = 8; - SendMessageA(w, EM_SETSEL, first, lim); - hres = ITextSelection_SetStart(txtSel, first); - ok(hres == S_FALSE, "ITextSelection_SetStart\n"); - -#define TEST_TXTSEL_SETSTART(cp, expected_start, expected_end) \ - hres = ITextSelection_SetStart(txtSel, cp); \ - ok(hres == S_OK, "ITextSelection_SetStart\n"); \ - SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end); \ - ok(start == expected_start, "got wrong start value: %d\n", start); \ - ok(end == expected_end, "got wrong end value: %d\n", end); - - TEST_TXTSEL_SETSTART(2, 2, 8) - TEST_TXTSEL_SETSTART(-1, 0, 8) - TEST_TXTSEL_SETSTART(13, 12, 12) + HRESULT hr; + LONG move_by; + LONG delta = 0; + LONG expected_delta; + LONG expected_location = target; + + if (expected_location < 0) + expected_location = 0; + else if (expected_location > textlen) + expected_location = textlen; + + if (target <= i) { + move_by = target - i; + expected_delta = expected_location - i; + if (i != j) { + --move_by; + --expected_delta; + } + } else if (j <= target) { + move_by = target - j; + expected_delta = expected_location - j; + if (i != j) { + ++move_by; + ++expected_delta; + } + } else { + /* There's no way to move to a point between start and end: */ + return; + } - release_interfaces(&w, &reOle, &txtDoc, &txtSel); + hr = ITextRange_SetRange(range, i, j); + ok(SUCCEEDED(hr), "got 0x%08x\n", hr); + hr = ITextRange_Move(range, tomCharacter, move_by, &delta); + if (expected_delta == 0) { + ok(hr == S_FALSE, "(%d,%d) move by %d got hr=0x%08x\n", i, j, move_by, hr); + ok(delta == 0, "(%d,%d) move by %d got delta %d\n", i, j, move_by, delta); + CHECK_RANGE(range, expected_location, expected_location); + } else { + ok(hr == S_OK, "(%d,%d) move by %d got hr=0x%08x\n", i, j, move_by, hr); + ok(delta == expected_delta, "(%d,%d) move by %d got delta %d\n", i, j, move_by, delta); + CHECK_RANGE(range, expected_location, expected_location); + } } -static void test_ITextSelection_SetEnd(void) +static void test_character_startof(ITextRange *range, int textlen, int i, int j) { - HWND w; - IRichEditOle *reOle = NULL; - ITextDocument *txtDoc = NULL; - ITextSelection *txtSel = NULL; - HRESULT hres; - LONG first, lim, start, end; - static const CHAR test_text1[] = "TestSomeText"; - - create_interfaces(&w, &reOle, &txtDoc, &txtSel); - SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); - - first = 4, lim = 8; - SendMessageA(w, EM_SETSEL, first, lim); - hres = ITextSelection_SetEnd(txtSel, lim); - ok(hres == S_FALSE, "ITextSelection_SetEnd\n"); - -#define TEST_TXTSEL_SETEND(cp, expected_start, expected_end) \ - hres = ITextSelection_SetEnd(txtSel, cp); \ - ok(hres == S_OK, "ITextSelection_SetEnd\n"); \ - SendMessageA(w, EM_GETSEL, (LPARAM)&start, (WPARAM)&end); \ - ok(start == expected_start, "got wrong start value: %d\n", start); \ - ok(end == expected_end, "got wrong end value: %d\n", end); - - TEST_TXTSEL_SETEND(6, 4, 6) - TEST_TXTSEL_SETEND(14, 4, 13) - TEST_TXTSEL_SETEND(-1, 0, 0) - - release_interfaces(&w, &reOle, &txtDoc, &txtSel); + HRESULT hr; + LONG delta; + + hr = ITextRange_SetRange(range, i, j); + ok(SUCCEEDED(hr), "got 0x%08x\n", hr); + hr = ITextRange_StartOf(range, tomCharacter, tomMove, &delta); + if (i == j) { + ok(hr == S_FALSE, "(%d,%d) tomMove got hr=0x%08x\n", i, j, hr); + ok(delta == 0, "(%d,%d) tomMove got delta %d\n", i, j, delta); + } else { + ok(hr == S_OK, "(%d,%d) tomMove got hr=0x%08x\n", i, j, hr); + ok(delta == -1, "(%d,%d) tomMove got delta %d\n", i, j, delta); + } + CHECK_RANGE(range, i, i); + + hr = ITextRange_SetRange(range, i, j); + ok(SUCCEEDED(hr), "got 0x%08x\n", hr); + hr = ITextRange_StartOf(range, tomCharacter, tomExtend, &delta); + ok(hr == S_FALSE, "(%d,%d) tomExtend got hr=0x%08x\n", i, j, hr); + ok(delta == 0, "(%d,%d) tomExtend got delta %d\n", i, j, delta); + CHECK_RANGE(range, i, j); } -static void test_ITextRange_GetFont(void) +static void test_character_endof(ITextRange *range, int textlen, int i, int j) { - HWND w; - IRichEditOle *reOle = NULL; - ITextDocument *txtDoc = NULL; - ITextRange *txtRge = NULL; - ITextFont *txtFont = NULL, *txtFont1 = NULL; - HRESULT hres; - int first, lim; - int refcount; - static const CHAR test_text1[] = "TestSomeText"; - LONG value; - - create_interfaces(&w, &reOle, &txtDoc, NULL); - SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); - - first = 4, lim = 4; - ITextDocument_Range(txtDoc, first, lim, &txtRge); - refcount = get_refcount((IUnknown *)txtRge); - ok(refcount == 1, "got wrong ref count: %d\n", refcount); - - hres = ITextRange_GetFont(txtRge, &txtFont); - ok(hres == S_OK, "ITextRange_GetFont\n"); - refcount = get_refcount((IUnknown *)txtFont); - ok(refcount == 1, "got wrong ref count: %d\n", refcount); - refcount = get_refcount((IUnknown *)txtRge); - ok(refcount == 2, "got wrong ref count: %d\n", refcount); - - hres = ITextRange_GetFont(txtRge, &txtFont1); - ok(hres == S_OK, "ITextRange_GetFont\n"); - ok(txtFont1 != txtFont, "A new pointer should be return\n"); - refcount = get_refcount((IUnknown *)txtFont1); - ok(refcount == 1, "got wrong ref count: %d\n", refcount); - ITextFont_Release(txtFont1); - refcount = get_refcount((IUnknown *)txtRge); - ok(refcount == 2, "got wrong ref count: %d\n", refcount); - - ITextRange_Release(txtRge); - release_interfaces(&w, &reOle, &txtDoc, NULL); - - hres = ITextFont_GetOutline(txtFont, &value); - ok(hres == CO_E_RELEASED, "ITextFont after ITextDocument destroyed\n"); - - ITextFont_Release(txtFont); + HRESULT hr; + LONG end; + LONG delta; + + hr = ITextRange_SetRange(range, i, j); + ok(SUCCEEDED(hr), "got 0x%08x\n", hr); + hr = ITextRange_EndOf(range, tomCharacter, tomMove, &delta); + + /* A character "end", apparently cannot be before the very first character */ + end = j; + if (j == 0) + ++end; + + if (i == end) { + ok(hr == S_FALSE, "(%d,%d) tomMove got hr=0x%08x\n", i, j, hr); + ok(delta == 0, "(%d,%d) tomMove got delta %d\n", i, j, delta); + } else { + ok(hr == S_OK, "(%d,%d) tomMove got hr=0x%08x\n", i, j, hr); + ok(delta == 1, "(%d,%d) tomMove got delta %d\n", i, j, delta); + } + CHECK_RANGE(range, end, end); + + hr = ITextRange_SetRange(range, i, j); + ok(SUCCEEDED(hr), "got 0x%08x\n", hr); + hr = ITextRange_EndOf(range, tomCharacter, tomExtend, &delta); + if (0 < j) { + ok(hr == S_FALSE, "(%d,%d) tomExtend got hr=0x%08x\n", i, j, hr); + ok(delta == 0, "(%d,%d) tomExtend got delta %d\n", i, j, delta); + } else { + ok(hr == S_OK, "(%d,%d) tomExtend got hr=0x%08x\n", i, j, hr); + ok(delta == 1, "(%d,%d) tomExtend got delta %d\n", i, j, delta); + } + CHECK_RANGE(range, i, end); } -static void test_ITextSelection_GetFont(void) +static void test_character_movement(void) { - HWND w; - IRichEditOle *reOle = NULL; - ITextDocument *txtDoc = NULL; - ITextSelection *txtSel = NULL; - ITextFont *txtFont = NULL, *txtFont1 = NULL; - HRESULT hres; - int first, lim; - int refcount; - static const CHAR test_text1[] = "TestSomeText"; - LONG value; - - create_interfaces(&w, &reOle, &txtDoc, &txtSel); - SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); - - first = 4, lim = 4; - SendMessageA(w, EM_SETSEL, first, lim); - refcount = get_refcount((IUnknown *)txtSel); - ok(refcount == 2, "got wrong ref count: %d\n", refcount); - - hres = ITextSelection_GetFont(txtSel, &txtFont); - ok(hres == S_OK, "ITextSelection_GetFont\n"); - refcount = get_refcount((IUnknown *)txtFont); - ok(refcount == 1, "got wrong ref count: %d\n", refcount); - refcount = get_refcount((IUnknown *)txtSel); - ok(refcount == 3, "got wrong ref count: %d\n", refcount); + static const char test_text1[] = "ab\n c"; + IRichEditOle *reole = NULL; + ITextDocument *doc = NULL; + ITextRange *range; + ITextSelection *selection; + HRESULT hr; + HWND hwnd; + int i, j; + const int textlen = strlen(test_text1); - hres = ITextSelection_GetFont(txtSel, &txtFont1); - ok(hres == S_OK, "ITextSelection_GetFont\n"); - ok(txtFont1 != txtFont, "A new pointer should be return\n"); - refcount = get_refcount((IUnknown *)txtFont1); - ok(refcount == 1, "got wrong ref count: %d\n", refcount); - ITextFont_Release(txtFont1); - refcount = get_refcount((IUnknown *)txtSel); - ok(refcount == 3, "got wrong ref count: %d\n", refcount); + create_interfaces(&hwnd, &reole, &doc, &selection); + SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)test_text1); - release_interfaces(&w, &reOle, &txtDoc, &txtSel); + hr = ITextDocument_Range(doc, 0, 0, &range); + ok(hr == S_OK, "got 0x%08x\n", hr); - hres = ITextFont_GetOutline(txtFont, &value); - ok(hres == CO_E_RELEASED, "ITextFont after ITextDocument destroyed\n"); + /* Exhaustive test of every possible combination of (start,end) locations, + * against every possible target location to move to. */ + for (i = 0; i <= textlen; i++) { + for (j = i; j <= textlen; j++) { + LONG target; + for (target = -2; target <= textlen + 3; target++) { + test_character_moveend(range, textlen, i, j, target); + test_character_movestart(range, textlen, i, j, target); + test_character_move(range, textlen, i, j, target); + } + test_character_startof(range, textlen, i, j); + test_character_endof(range, textlen, i, j); + } + } - ITextFont_Release(txtFont); + release_interfaces(&hwnd, &reole, &doc, NULL); + ITextSelection_Release(selection); + ITextRange_Release(range); } -static void test_ITextRange_GetPara(void) +#define CLIPBOARD_RANGE_CONTAINS(range, start, end, expected) _clipboard_range_contains(range, start, end, expected, __LINE__, 0); +#define TODO_CLIPBOARD_RANGE_CONTAINS(range, start, end, expected) _clipboard_range_contains(range, start, end, expected, __LINE__, 1); +static void _clipboard_range_contains(ITextRange *range, LONG start, LONG end, const char *expected, int line, int todo) { - HWND w; - IRichEditOle *reOle = NULL; - ITextDocument *txtDoc = NULL; - ITextRange *txtRge = NULL; - ITextPara *txtPara = NULL, *txtPara1 = NULL; - HRESULT hres; - int first, lim; - int refcount; - static const CHAR test_text1[] = "TestSomeText"; - LONG value; - - create_interfaces(&w, &reOle, &txtDoc, NULL); - SendMessageA(w, WM_SETTEXT, 0, (LPARAM)test_text1); - - first = 4, lim = 4; - ITextDocument_Range(txtDoc, first, lim, &txtRge); - refcount = get_refcount((IUnknown *)txtRge); - ok(refcount == 1, "got wrong ref count: %d\n", refcount); + HRESULT hr; + BOOL clipboard_open; + HGLOBAL global; + const char *clipboard_text; + + hr = ITextRange_SetRange(range, start, end); + ok_(__FILE__,line)(SUCCEEDED(hr), "SetRange failed: 0x%08x\n", hr); + hr = ITextRange_Copy(range, NULL); + ok_(__FILE__,line)(hr == S_OK, "Copy failed: 0x%08x\n", hr); + + clipboard_open = OpenClipboard(NULL); + ok_(__FILE__,line)(clipboard_open, "OpenClipboard failed: %d\n", GetLastError()); + global = GetClipboardData(CF_TEXT); + ok_(__FILE__,line)(global != NULL, "GetClipboardData failed: %p\n", global); + clipboard_text = GlobalLock(global); + ok_(__FILE__,line)(clipboard_text != NULL, "GlobalLock failed: %p\n", clipboard_text); +#ifdef __REACTOS__ + if (expected != NULL && clipboard_text != NULL) + todo_wine_if(todo) ok_(__FILE__,line)(!strcmp(expected, clipboard_text), "unexpected contents: %s\n", wine_dbgstr_a(clipboard_text)); + else + todo_wine_if(todo) ok_(__FILE__,line)(FALSE, "Either 'expected' or 'clipboard_text' was NULL\n"); +#else + todo_wine_if(todo) ok_(__FILE__,line)(!strcmp(expected, clipboard_text), "unexpected contents: %s\n", wine_dbgstr_a(clipboard_text)); +#endif + GlobalUnlock(global); + CloseClipboard(); +} - hres = ITextRange_GetPara(txtRge, &txtPara); - ok(hres == S_OK, "ITextRange_GetPara\n"); - refcount = get_refcount((IUnknown *)txtPara); - ok(refcount == 1, "got wrong ref count: %d\n", refcount); - refcount = get_refcount((IUnknown *)txtRge); - ok(refcount == 2, "got wrong ref count: %d\n", refcount); +static void test_clipboard(void) +{ + static const char text_in[] = "ab\n c"; + IRichEditOle *reole = NULL; + ITextDocument *doc = NULL; + ITextRange *range; + ITextSelection *selection; + HRESULT hr; + HWND hwnd; - hres = ITextRange_GetPara(txtRge, &txtPara1); - ok(hres == S_OK, "ITextRange_GetPara\n"); - ok(txtPara1 != txtPara, "A new pointer should be return\n"); - refcount = get_refcount((IUnknown *)txtPara1); - ok(refcount == 1, "got wrong ref count: %d\n", refcount); - ITextPara_Release(txtPara1); - refcount = get_refcount((IUnknown *)txtRge); - ok(refcount == 2, "got wrong ref count: %d\n", refcount); + create_interfaces(&hwnd, &reole, &doc, &selection); + SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)text_in); - ITextRange_Release(txtRge); - release_interfaces(&w, &reOle, &txtDoc, NULL); + hr = ITextDocument_Range(doc, 0, 0, &range); + ok(hr == S_OK, "got 0x%08x\n", hr); - hres = ITextPara_GetStyle(txtPara, &value); - ok(hres == CO_E_RELEASED, "ITextPara after ITextDocument destroyed\n"); + CLIPBOARD_RANGE_CONTAINS(range, 0, 5, "ab\r\n c") + CLIPBOARD_RANGE_CONTAINS(range, 0, 0, "ab\r\n c") + CLIPBOARD_RANGE_CONTAINS(range, 1, 1, "ab\r\n c") + CLIPBOARD_RANGE_CONTAINS(range, 0, 1, "a") + CLIPBOARD_RANGE_CONTAINS(range, 5, 6, "") + + /* Setting password char does not stop Copy */ + SendMessageA(hwnd, EM_SETPASSWORDCHAR, '*', 0); + CLIPBOARD_RANGE_CONTAINS(range, 0, 1, "a") + + /* Cut can be undone */ + hr = ITextRange_SetRange(range, 0, 1); + ok(SUCCEEDED(hr), "SetRange failed: 0x%08x\n", hr); + hr = ITextRange_Cut(range, NULL); + ok(hr == S_OK, "Cut failed: 0x%08x\n", hr); + CLIPBOARD_RANGE_CONTAINS(range, 0, 4, "b\r\n c"); + hr = ITextDocument_Undo(doc, 1, NULL); + todo_wine ok(hr == S_OK, "Undo failed: 0x%08x\n", hr); + TODO_CLIPBOARD_RANGE_CONTAINS(range, 0, 5, "ab\r\n c"); + + /* Cannot cut when read-only */ + SendMessageA(hwnd, EM_SETREADONLY, TRUE, 0); + hr = ITextRange_SetRange(range, 0, 1); + ok(SUCCEEDED(hr), "SetRange failed: 0x%08x\n", hr); + hr = ITextRange_Cut(range, NULL); + ok(hr == E_ACCESSDENIED, "got 0x%08x\n", hr); - ITextPara_Release(txtPara); + release_interfaces(&hwnd, &reole, &doc, NULL); + ITextSelection_Release(selection); + ITextRange_Release(range); } START_TEST(richole) @@ -4088,21 +4263,14 @@ START_TEST(richole) test_GetText(); test_ITextSelection_GetChar(); test_ITextSelection_GetStart_GetEnd(); - test_ITextSelection_SetStart(); - test_ITextSelection_SetEnd(); test_ITextSelection_Collapse(); - test_ITextSelection_GetFont(); test_ITextDocument_Range(); test_ITextRange_GetChar(); test_ITextRange_ScrollIntoView(); test_ITextRange_GetStart_GetEnd(); test_ITextRange_SetRange(); test_ITextRange_GetDuplicate(); - test_ITextRange_SetStart(); - test_ITextRange_SetEnd(); test_ITextRange_Collapse(); - test_ITextRange_GetFont(); - test_ITextRange_GetPara(); test_GetClientSite(); test_IOleWindow_GetWindow(); test_IOleInPlaceSite_GetWindow(); @@ -4121,5 +4289,7 @@ START_TEST(richole) test_GetStoryLength(); test_ITextSelection_GetDuplicate(); test_Expand(); - test_MoveEnd(); + test_MoveEnd_story(); + test_character_movement(); + test_clipboard(); } diff --git a/modules/rostests/winetests/riched20/txtsrv.c b/modules/rostests/winetests/riched20/txtsrv.c index dd290e3fb2f..1f789da8a37 100644 --- a/modules/rostests/winetests/riched20/txtsrv.c +++ b/modules/rostests/winetests/riched20/txtsrv.c @@ -48,7 +48,7 @@ static PCreateTextServices pCreateTextServices; /* Use a special table for x86 machines to convert the thiscall * calling convention. This isn't needed on other platforms. */ -#if defined(__i386__) && !defined(__MINGW32__) +#if defined(__i386__) && !defined(__MINGW32__) && (!defined(_MSC_VER) || !defined(__clang__)) static ITextServicesVtbl itextServicesStdcallVtbl; #define TXTSERV_VTABLE(This) (&itextServicesStdcallVtbl) #else /* __i386__ */ @@ -61,8 +61,8 @@ static ITextServicesVtbl itextServicesStdcallVtbl; #define ITextServices_TxGetVScroll(This,a,b,c,d,e) TXTSERV_VTABLE(This)->TxGetVScroll(This,a,b,c,d,e) #define ITextServices_OnTxSetCursor(This,a,b,c,d,e,f,g,h,i) TXTSERV_VTABLE(This)->OnTxSetCursor(This,a,b,c,d,e,f,g,h,i) #define ITextServices_TxQueryHitPoint(This,a,b,c,d,e,f,g,h,i,j) TXTSERV_VTABLE(This)->TxQueryHitPoint(This,a,b,c,d,e,f,g,h,i,j) -#define ITextServices_OnTxInplaceActivate(This,a) TXTSERV_VTABLE(This)->OnTxInplaceActivate(This,a) -#define ITextServices_OnTxInplaceDeactivate(This) TXTSERV_VTABLE(This)->OnTxInplaceDeactivate(This) +#define ITextServices_OnTxInPlaceActivate(This,a) TXTSERV_VTABLE(This)->OnTxInPlaceActivate(This,a) +#define ITextServices_OnTxInPlaceDeactivate(This) TXTSERV_VTABLE(This)->OnTxInPlaceDeactivate(This) #define ITextServices_OnTxUIActivate(This) TXTSERV_VTABLE(This)->OnTxUIActivate(This) #define ITextServices_OnTxUIDeactivate(This) TXTSERV_VTABLE(This)->OnTxUIDeactivate(This) #define ITextServices_TxGetText(This,a) TXTSERV_VTABLE(This)->TxGetText(This,a) @@ -85,7 +85,10 @@ typedef struct ITextHostTestImpl { ITextHost ITextHost_iface; LONG refCount; + HWND window; + RECT client_rect; CHARFORMAT2W char_format; + DWORD scrollbars, props; } ITextHostTestImpl; static inline ITextHostTestImpl *impl_from_ITextHost(ITextHost *iface) @@ -93,6 +96,11 @@ static inline ITextHostTestImpl *impl_from_ITextHost(ITextHost *iface) return CONTAINING_RECORD(iface, ITextHostTestImpl, ITextHost_iface); } +static const WCHAR lorem[] = L"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. " + "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. " + "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. " + "Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; + static HRESULT WINAPI ITextHostImpl_QueryInterface(ITextHost *iface, REFIID riid, LPVOID *ppvObject) @@ -133,6 +141,7 @@ static HDC __thiscall ITextHostImpl_TxGetDC(ITextHost *iface) { ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxGetDC(%p)\n", This); + if (This->window) return GetDC( This->window ); return NULL; } @@ -140,6 +149,7 @@ static INT __thiscall ITextHostImpl_TxReleaseDC(ITextHost *iface, HDC hdc) { ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxReleaseDC(%p)\n", This); + if (This->window) return ReleaseDC( This->window, hdc ); return 0; } @@ -287,7 +297,8 @@ static HRESULT __thiscall ITextHostImpl_TxGetClientRect(ITextHost *iface, LPRECT { ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxGetClientRect(%p, prc=%p)\n", This, prc); - return E_NOTIMPL; + *prc = This->client_rect; + return S_OK; } static HRESULT __thiscall ITextHostImpl_TxGetViewInset(ITextHost *iface, LPRECT prc) @@ -333,12 +344,12 @@ static HRESULT __thiscall ITextHostImpl_TxGetMaxLength(ITextHost *iface, DWORD * return E_NOTIMPL; } -static HRESULT __thiscall ITextHostImpl_TxGetScrollBars(ITextHost *iface, DWORD *pdwScrollBar) +static HRESULT __thiscall ITextHostImpl_TxGetScrollBars(ITextHost *iface, DWORD *scrollbars) { ITextHostTestImpl *This = impl_from_ITextHost(iface); - TRACECALL("Call to TxGetScrollBars(%p, pdwScrollBar=%p)\n", - This, pdwScrollBar); - return E_NOTIMPL; + TRACECALL("Call to TxGetScrollBars(%p, scrollbars=%p)\n", This, scrollbars); + *scrollbars = This->scrollbars; + return S_OK; } static HRESULT __thiscall ITextHostImpl_TxGetPasswordChar(ITextHost *iface, WCHAR *pch) @@ -383,15 +394,28 @@ static HRESULT __thiscall ITextHostImpl_TxGetPropertyBits(ITextHost *iface, DWOR ITextHostTestImpl *This = impl_from_ITextHost(iface); TRACECALL("Call to TxGetPropertyBits(%p, dwMask=0x%08x, pdwBits=%p)\n", This, dwMask, pdwBits); - *pdwBits = 0; + *pdwBits = This->props & dwMask; return S_OK; } -static HRESULT __thiscall ITextHostImpl_TxNotify(ITextHost *iface, DWORD iNotify, void *pv) +static int en_vscroll_sent; +static int en_update_sent; +static HRESULT __thiscall ITextHostImpl_TxNotify( ITextHost *iface, DWORD code, void *data ) { ITextHostTestImpl *This = impl_from_ITextHost(iface); - TRACECALL("Call to TxNotify(%p, iNotify=%d, pv=%p)\n", This, iNotify, pv); - return E_NOTIMPL; + TRACECALL( "Call to TxNotify(%p, code = %#x, data = %p)\n", This, code, data ); + switch (code) + { + case EN_VSCROLL: + en_vscroll_sent++; + ok( !data, "got %p\n", data ); + break; + case EN_UPDATE: + en_update_sent++; + ok( !data, "got %p\n", data ); + break; + } + return S_OK; } static HIMC __thiscall ITextHostImpl_TxImmGetContext(ITextHost *iface) @@ -492,7 +516,7 @@ typedef struct static void setup_thiscall_wrappers(void) { -#if defined(__i386__) && !defined(__MINGW32__) +#if defined(__i386__) && !defined(__MINGW32__) && (!defined(_MSC_VER) || !defined(__clang__)) void** pVtable; void** pVtableEnd; THISCALL_TO_STDCALL_THUNK *thunk; @@ -591,9 +615,13 @@ static BOOL init_texthost(ITextServices **txtserv, ITextHost **ret) } dummyTextHost->ITextHost_iface.lpVtbl = &itextHostVtbl; dummyTextHost->refCount = 1; + dummyTextHost->window = NULL; + SetRectEmpty( &dummyTextHost->client_rect ); memset(&dummyTextHost->char_format, 0, sizeof(dummyTextHost->char_format)); dummyTextHost->char_format.cbSize = sizeof(dummyTextHost->char_format); dummyTextHost->char_format.dwMask = CFM_ALL2; + dummyTextHost->scrollbars = 0; + dummyTextHost->props = 0; hf = GetStockObject(DEFAULT_GUI_FONT); hf_to_cf(hf, &dummyTextHost->char_format); @@ -602,6 +630,7 @@ static BOOL init_texthost(ITextServices **txtserv, ITextHost **ret) ITextServices object. */ result = pCreateTextServices(NULL, &dummyTextHost->ITextHost_iface, &init); ok(result == S_OK, "Did not return S_OK when created (result = %x)\n", result); + ok(dummyTextHost->refCount == 1, "host ref %d\n", dummyTextHost->refCount); if (result != S_OK) { CoTaskMemFree(dummyTextHost); win_skip("CreateTextServices failed.\n"); @@ -621,9 +650,30 @@ static BOOL init_texthost(ITextServices **txtserv, ITextHost **ret) return TRUE; } +static void fill_reobject_struct(REOBJECT *reobj, LONG cp, LPOLEOBJECT poleobj, + LPSTORAGE pstg, LPOLECLIENTSITE polesite, LONG sizel_cx, + LONG sizel_cy, DWORD aspect, DWORD flags, DWORD user) +{ + reobj->cbStruct = sizeof(*reobj); + reobj->clsid = CLSID_NULL; + reobj->cp = cp; + reobj->poleobj = poleobj; + reobj->pstg = pstg; + reobj->polesite = polesite; + reobj->sizel.cx = sizel_cx; + reobj->sizel.cy = sizel_cy; + reobj->dvaspect = aspect; + reobj->dwFlags = flags; + reobj->dwUser = user; +} + static void test_TxGetText(void) { + const WCHAR *expected_string; + IOleClientSite *clientsite; ITextServices *txtserv; + IRichEditOle *reole; + REOBJECT reobject; ITextHost *host; HRESULT hres; BSTR rettext; @@ -635,6 +685,24 @@ static void test_TxGetText(void) ok(hres == S_OK, "ITextServices_TxGetText failed (result = %x)\n", hres); SysFreeString(rettext); + hres = ITextServices_TxSetText(txtserv, L"abcdefg"); + ok(hres == S_OK, "Got hres: %#x.\n", hres); + hres = ITextServices_QueryInterface(txtserv, &IID_IRichEditOle, (void **)&reole); + ok(hres == S_OK, "Got hres: %#x.\n", hres); + hres = IRichEditOle_GetClientSite(reole, &clientsite); + ok(hres == S_OK, "Got hres: %#x.\n", hres); + expected_string = L"abc\xfffc""defg"; + fill_reobject_struct(&reobject, 3, NULL, NULL, clientsite, 10, 10, DVASPECT_CONTENT, 0, 1); + hres = IRichEditOle_InsertObject(reole, &reobject); + ok(hres == S_OK, "Got hres: %#x.\n", hres); + hres = ITextServices_TxGetText(txtserv, &rettext); + ok(hres == S_OK, "Got hres: %#x.\n", hres); + ok(lstrlenW(rettext) == lstrlenW(expected_string), "Got wrong length: %d.\n", lstrlenW(rettext)); + todo_wine ok(!lstrcmpW(rettext, expected_string), "Got wrong content: %s.\n", debugstr_w(rettext)); + SysFreeString(rettext); + IOleClientSite_Release(clientsite); + IRichEditOle_Release(reole); + ITextServices_Release(txtserv); ITextHost_Release(host); } @@ -689,7 +757,7 @@ static void _check_txgetnaturalsize(HRESULT res, LONG width, LONG height, HDC hd expected_width = expected_rect.right - expected_rect.left; expected_height = expected_rect.bottom - expected_rect.top; ok_(__FILE__,line)(res == S_OK, "ITextServices_TxGetNaturalSize failed: 0x%08x.\n", res); - ok_(__FILE__,line)(width >= expected_width && width <= expected_width + 1, + todo_wine ok_(__FILE__,line)(width >= expected_width && width <= expected_width + 1, "got wrong width: %d, expected: %d {+1}.\n", width, expected_width); ok_(__FILE__,line)(height == expected_height, "got wrong height: %d, expected: %d.\n", height, expected_height); @@ -701,7 +769,7 @@ static void test_TxGetNaturalSize(void) ITextHost *host; HRESULT result; SIZEL extent; - static const WCHAR test_text[] = {'T','e','s','t','S','o','m','e','T','e','x','t',0}; + static const WCHAR test_text[] = L"TestSomeText"; LONG width, height; HDC hdcDraw; HWND hwnd; @@ -736,7 +804,7 @@ static void test_TxGetNaturalSize(void) height = 0; result = ITextServices_TxGetNaturalSize(txtserv, DVASPECT_CONTENT, hdcDraw, NULL, NULL, TXTNS_FITTOCONTENT, &extent, &width, &height); - todo_wine CHECK_TXGETNATURALSIZE(result, width, height, hdcDraw, rect, test_text); + CHECK_TXGETNATURALSIZE(result, width, height, hdcDraw, rect, test_text); ReleaseDC(hwnd, hdcDraw); DestroyWindow(hwnd); @@ -748,26 +816,51 @@ static void test_TxDraw(void) { ITextServices *txtserv; ITextHost *host; - HDC tmphdc = GetDC(NULL); - DWORD dwAspect = DVASPECT_CONTENT; - HDC hicTargetDev = NULL; /* Means "default" device */ - DVTARGETDEVICE *ptd = NULL; - void *pvAspect = NULL; - HRESULT result; - RECTL client = {0,0,100,100}; - + HRESULT hr; + RECT client = {0, 0, 100, 100}; + ITextHostTestImpl *host_impl; + HDC hdc; if (!init_texthost(&txtserv, &host)) return; - todo_wine { - result = ITextServices_TxDraw(txtserv, dwAspect, 0, pvAspect, ptd, - tmphdc, hicTargetDev, &client, NULL, - NULL, NULL, 0, 0); - ok(result == S_OK, "TxDraw failed (result = %x)\n", result); - } - + host_impl = impl_from_ITextHost( host ); + host_impl->window = CreateWindowExA( 0, "static", NULL, WS_POPUP | WS_VISIBLE, + 0, 0, 400, 400, 0, 0, 0, NULL ); + host_impl->client_rect = client; + host_impl->props = TXTBIT_MULTILINE | TXTBIT_RICHTEXT | TXTBIT_WORDWRAP; + ITextServices_OnTxPropertyBitsChange( txtserv, TXTBIT_CLIENTRECTCHANGE | TXTBIT_MULTILINE | TXTBIT_RICHTEXT | TXTBIT_WORDWRAP, + host_impl->props ); + hdc = GetDC( host_impl->window ); + + hr = ITextServices_TxDraw( txtserv, DVASPECT_CONTENT, 0, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, 0, TXTVIEW_INACTIVE ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + hr = ITextServices_TxDraw( txtserv, DVASPECT_CONTENT, 0, NULL, NULL, hdc, NULL, NULL, NULL, + NULL, NULL, 0, TXTVIEW_INACTIVE ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + hr = ITextServices_TxDraw( txtserv, DVASPECT_CONTENT, 0, NULL, NULL, NULL, NULL, (RECTL *)&client, NULL, + NULL, NULL, 0, TXTVIEW_INACTIVE ); + ok( hr == E_FAIL, "got %08x\n", hr ); + hr = ITextServices_TxDraw( txtserv, DVASPECT_CONTENT, 0, NULL, NULL, hdc, NULL, (RECTL *)&client, NULL, + NULL, NULL, 0, TXTVIEW_INACTIVE ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = ITextServices_TxDraw( txtserv, DVASPECT_CONTENT, 0, NULL, NULL, hdc, NULL, (RECTL *)&client, NULL, + NULL, NULL, 0, TXTVIEW_ACTIVE ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = ITextServices_OnTxInPlaceActivate( txtserv, &client ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = ITextServices_TxDraw( txtserv, DVASPECT_CONTENT, 0, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, 0, TXTVIEW_INACTIVE ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = ITextServices_OnTxInPlaceDeactivate( txtserv ); + + ReleaseDC( host_impl->window, hdc ); ITextServices_Release(txtserv); + DestroyWindow( host_impl->window ); ITextHost_Release(host); } @@ -863,6 +956,7 @@ static void test_QueryInterface(void) IRichEditOle *reole, *txtsrv_reole; ITextDocument *txtdoc, *txtsrv_txtdoc; ITextDocument2Old *txtdoc2old, *txtsrv_txtdoc2old; + IUnknown *unk, *unk2; ULONG refcount; if(!init_texthost(&txtserv, &host)) @@ -879,6 +973,14 @@ static void test_QueryInterface(void) refcount = get_refcount((IUnknown *)txtsrv_reole); ok(refcount == 2, "got wrong ref count: %d\n", refcount); + hres = ITextServices_QueryInterface( txtserv, &IID_IUnknown, (void **)&unk ); + ok( hres == S_OK, "got 0x%08x\n", hres ); + hres = IRichEditOle_QueryInterface( txtsrv_reole, &IID_IUnknown, (void **)&unk2 ); + ok( hres == S_OK, "got 0x%08x\n", hres ); + ok( unk == unk2, "unknowns differ\n" ); + IUnknown_Release( unk2 ); + IUnknown_Release( unk ); + hres = IRichEditOle_QueryInterface(txtsrv_reole, &IID_ITextDocument, (void **)&txtdoc); ok(hres == S_OK, "IRichEditOle_QueryInterface: 0x%08x\n", hres); refcount = get_refcount((IUnknown *)txtserv); @@ -987,20 +1089,134 @@ static void test_TxGetScroll(void) ITextServices *txtserv; ITextHost *host; HRESULT ret; + LONG min_pos, max_pos, pos, page; + BOOL enabled; + ITextHostTestImpl *host_impl; + RECT client = {0, 0, 100, 100}; if (!init_texthost(&txtserv, &host)) return; + host_impl = impl_from_ITextHost( host ); + ret = ITextServices_TxGetHScroll(txtserv, NULL, NULL, NULL, NULL, NULL); - ok(ret == S_OK, "ITextSerHices_GetVScroll failed: 0x%08x.\n", ret); + ok(ret == S_OK, "ITextServices_TxGetHScroll failed: 0x%08x.\n", ret); ret = ITextServices_TxGetVScroll(txtserv, NULL, NULL, NULL, NULL, NULL); - ok(ret == S_OK, "ITextServices_GetVScroll failed: 0x%08x.\n", ret); - + ok(ret == S_OK, "ITextServices_TxGetVScroll failed: 0x%08x.\n", ret); + + ret = ITextServices_TxGetVScroll( txtserv, &min_pos, &max_pos, &pos, &page, &enabled ); + ok( ret == S_OK, "ITextServices_TxGetHScroll failed: 0x%08x.\n", ret ); + ok( min_pos == 0, "got %d\n", min_pos ); + ok( max_pos == 0, "got %d\n", max_pos ); + ok( pos == 0, "got %d\n", pos ); + ok( page == 0, "got %d\n", page ); + ok( !enabled, "got %d\n", enabled ); + + host_impl->scrollbars = WS_VSCROLL; + host_impl->props = TXTBIT_MULTILINE | TXTBIT_RICHTEXT | TXTBIT_WORDWRAP; + ITextServices_OnTxPropertyBitsChange( txtserv, TXTBIT_SCROLLBARCHANGE | TXTBIT_MULTILINE | TXTBIT_RICHTEXT | TXTBIT_WORDWRAP, host_impl->props ); + + host_impl->window = CreateWindowExA( 0, "static", NULL, WS_POPUP | WS_VISIBLE, + 0, 0, 400, 400, 0, 0, 0, NULL ); + host_impl->client_rect = client; + ret = ITextServices_OnTxInPlaceActivate( txtserv, &client ); + ok( ret == S_OK, "got 0x%08x.\n", ret ); + + ret = ITextServices_TxGetVScroll( txtserv, &min_pos, &max_pos, &pos, &page, &enabled ); + ok( ret == S_OK, "ITextServices_TxGetHScroll failed: 0x%08x.\n", ret ); + ok( min_pos == 0, "got %d\n", min_pos ); +todo_wine + ok( max_pos == 0, "got %d\n", max_pos ); + ok( pos == 0, "got %d\n", pos ); + ok( page == client.bottom, "got %d\n", page ); + ok( !enabled, "got %d\n", enabled ); + + ret = ITextServices_TxSetText( txtserv, lorem ); + ok( ret == S_OK, "got 0x%08x.\n", ret ); + + ret = ITextServices_TxGetVScroll( txtserv, &min_pos, &max_pos, &pos, &page, &enabled ); + ok( ret == S_OK, "ITextServices_TxGetHScroll failed: 0x%08x.\n", ret ); + ok( min_pos == 0, "got %d\n", min_pos ); + ok( max_pos > client.bottom, "got %d\n", max_pos ); + ok( pos == 0, "got %d\n", pos ); + ok( page == client.bottom, "got %d\n", page ); + ok( enabled, "got %d\n", enabled ); + + host_impl->scrollbars = WS_VSCROLL | ES_DISABLENOSCROLL; + ITextServices_OnTxPropertyBitsChange( txtserv, TXTBIT_SCROLLBARCHANGE, host_impl->props ); + ITextServices_TxSetText( txtserv, L"short" ); + + ret = ITextServices_TxGetVScroll( txtserv, &min_pos, &max_pos, &pos, &page, &enabled ); + ok( ret == S_OK, "ITextServices_TxGetHScroll failed: 0x%08x.\n", ret ); + ok( min_pos == 0, "got %d\n", min_pos ); +todo_wine + ok( max_pos == 0, "got %d\n", max_pos ); + ok( pos == 0, "got %d\n", pos ); + ok( page == client.bottom, "got %d\n", page ); + ok( !enabled, "got %d\n", enabled ); + + DestroyWindow( host_impl->window ); ITextServices_Release(txtserv); ITextHost_Release(host); } +static void test_notifications( void ) +{ + ITextServices *txtserv; + ITextHost *host; + LRESULT res; + HRESULT hr; + RECT client = { 0, 0, 100, 100 }; + ITextHostTestImpl *host_impl; + + init_texthost( &txtserv, &host ); + host_impl = impl_from_ITextHost( host ); + + host_impl->scrollbars = WS_VSCROLL; + host_impl->props = TXTBIT_MULTILINE | TXTBIT_RICHTEXT | TXTBIT_WORDWRAP; + ITextServices_OnTxPropertyBitsChange( txtserv, TXTBIT_SCROLLBARCHANGE | TXTBIT_MULTILINE | TXTBIT_RICHTEXT | TXTBIT_WORDWRAP, host_impl->props ); + + ITextServices_TxSetText( txtserv, lorem ); + + host_impl->window = CreateWindowExA( 0, "static", NULL, WS_POPUP | WS_VISIBLE, + 0, 0, 400, 400, 0, 0, 0, NULL ); + host_impl->client_rect = client; + hr = ITextServices_OnTxInPlaceActivate( txtserv, &client ); + ok( hr == S_OK, "got 0x%08x.\n", hr ); + + hr = ITextServices_TxSendMessage( txtserv, EM_SETEVENTMASK, 0, ENM_SCROLL, &res ); + ok( hr == S_OK, "got %08x\n", hr ); + + /* check EN_VSCROLL notification is sent */ + en_vscroll_sent = 0; + hr = ITextServices_TxSendMessage( txtserv, WM_VSCROLL, SB_LINEDOWN, 0, &res ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( en_vscroll_sent == 1, "got %d\n", en_vscroll_sent ); + + hr = ITextServices_TxSendMessage( txtserv, WM_VSCROLL, SB_BOTTOM, 0, &res ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( en_vscroll_sent == 2, "got %d\n", en_vscroll_sent ); + + /* but not when the thumb is moved */ + hr = ITextServices_TxSendMessage( txtserv, WM_VSCROLL, MAKEWPARAM( SB_THUMBTRACK, 0 ), 0, &res ); + ok( hr == S_OK, "got %08x\n", hr ); + hr = ITextServices_TxSendMessage( txtserv, WM_VSCROLL, MAKEWPARAM( SB_THUMBPOSITION, 0 ), 0, &res ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( en_vscroll_sent == 2, "got %d\n", en_vscroll_sent ); + + /* EN_UPDATE is sent by TxDraw() */ + en_update_sent = 0; + hr = ITextServices_TxDraw( txtserv, DVASPECT_CONTENT, 0, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, 0, TXTVIEW_ACTIVE ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( en_update_sent == 1, "got %d\n", en_update_sent ); + + DestroyWindow( host_impl->window ); + ITextServices_Release( txtserv ); + ITextHost_Release( host ); +} + START_TEST( txtsrv ) { ITextServices *txtserv; @@ -1033,6 +1249,7 @@ START_TEST( txtsrv ) test_QueryInterface(); test_default_format(); test_TxGetScroll(); + test_notifications(); } if (wrapperCodeMem) VirtualFree(wrapperCodeMem, 0, MEM_RELEASE); } diff --git a/sdk/include/psdk/textserv.h b/sdk/include/psdk/textserv.h index 455e88c5581..26278cc85c8 100644 --- a/sdk/include/psdk/textserv.h +++ b/sdk/include/psdk/textserv.h @@ -33,9 +33,9 @@ extern "C" { #define THISCALLMETHOD_(type,method) type (__thiscall *method) #endif -DEFINE_GUID(IID_ITextServices,0x8d33f740,0xcf58,0x11ce,0xa8,0x9d,0x00,0xaa,0x00,0x6c,0xad,0xc5); -DEFINE_GUID(IID_ITextHost, 0xc5bdd8d0,0xd26e,0x11ce,0xa8,0x9e,0x00,0xaa,0x00,0x6c,0xad,0xc5); -DEFINE_GUID(IID_ITextHost2, 0xc5bdd8d0,0xd26e,0x11ce,0xa8,0x9e,0x00,0xaa,0x00,0x6c,0xad,0xc5); +EXTERN_C const IID IID_ITextServices; +EXTERN_C const IID IID_ITextHost; +EXTERN_C const IID IID_ITextHost2; /***************************************************************************** * ITextServices interface @@ -108,10 +108,10 @@ DECLARE_INTERFACE_(ITextServices,IUnknown) INT y, DWORD* pHitResult) PURE; - THISCALLMETHOD_(HRESULT,OnTxInplaceActivate)( THIS_ + THISCALLMETHOD_(HRESULT,OnTxInPlaceActivate)( THIS_ LPCRECT prcClient) PURE; - THISCALLMETHOD_(HRESULT,OnTxInplaceDeactivate)( THIS ) PURE; + THISCALLMETHOD_(HRESULT,OnTxInPlaceDeactivate)( THIS ) PURE; THISCALLMETHOD_(HRESULT,OnTxUIActivate)( THIS ) PURE; @@ -151,6 +151,7 @@ DECLARE_INTERFACE_(ITextServices,IUnknown) DWORD* pdwHeight) PURE; }; +#undef INTERFACE #ifdef COBJMACROS /*** IUnknown methods ***/ @@ -159,8 +160,6 @@ DECLARE_INTERFACE_(ITextServices,IUnknown) #define ITextServices_Release(p) (p)->lpVtbl->Release(p) #endif -#undef INTERFACE - typedef enum _TXTBACKSTYLE { TXTBACK_TRANSPARENT = 0, TXTBACK_OPAQUE @@ -180,7 +179,7 @@ enum TXTNATURALSIZE { enum TXTVIEW { TXTVIEW_ACTIVE = 0, - TXTVIEW_INACTIVE = 1 + TXTVIEW_INACTIVE = -1 }; #define TXTBIT_RICHTEXT 0x000001 @@ -361,6 +360,7 @@ DECLARE_INTERFACE_(ITextHost,IUnknown) LONG* lSelBarWidth) PURE; }; +#undef INTERFACE #ifdef COBJMACROS /*** IUnknown methods ***/ @@ -369,8 +369,80 @@ DECLARE_INTERFACE_(ITextHost,IUnknown) #define ITextHost_Release(p) (p)->lpVtbl->Release(p) #endif +/***************************************************************************** + * ITextHost2 interface + */ +#define INTERFACE ITextHost2 +DECLARE_INTERFACE_(ITextHost2,ITextHost) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface)( THIS_ REFIID riid, void** ppvObject ) PURE; + STDMETHOD_(ULONG,AddRef)( THIS ) PURE; + STDMETHOD_(ULONG,Release)( THIS ) PURE; + /*** ITextHost methods ***/ + THISCALLMETHOD_(HDC,TxGetDC)( THIS ) PURE; + THISCALLMETHOD_(INT,TxReleaseDC)( THIS_ HDC hdc ) PURE; + THISCALLMETHOD_(BOOL,TxShowScrollBar)( THIS_ INT fnBar, BOOL fShow ) PURE; + THISCALLMETHOD_(BOOL,TxEnableScrollBar)( THIS_ INT fuSBFlags, INT fuArrowflags ) PURE; + THISCALLMETHOD_(BOOL,TxSetScrollRange)( THIS_ INT fnBar, LONG nMinPos, INT nMaxPos, BOOL fRedraw ) PURE; + THISCALLMETHOD_(BOOL,TxSetScrollPos)( THIS_ INT fnBar, INT nPos, BOOL fRedraw ) PURE; + THISCALLMETHOD_(void,TxInvalidateRect)( THIS_ LPCRECT prc, BOOL fMode ) PURE; + THISCALLMETHOD_(void,TxViewChange)( THIS_ BOOL fUpdate ) PURE; + THISCALLMETHOD_(BOOL,TxCreateCaret)( THIS_ HBITMAP hbmp, INT xWidth, INT yHeight ) PURE; + THISCALLMETHOD_(BOOL,TxShowCaret)( THIS_ BOOL fShow ) PURE; + THISCALLMETHOD_(BOOL,TxSetCaretPos)( THIS_ INT x, INT y ) PURE; + THISCALLMETHOD_(BOOL,TxSetTimer)( THIS_ UINT idTimer, UINT uTimeout ) PURE; + THISCALLMETHOD_(void,TxKillTimer)( THIS_ UINT idTimer ) PURE; + THISCALLMETHOD_(void,TxScrollWindowEx)( THIS_ INT dx, INT dy, LPCRECT lprcScroll, LPCRECT lprcClip, + HRGN hRgnUpdate, LPRECT lprcUpdate, UINT fuScroll ) PURE; + THISCALLMETHOD_(void,TxSetCapture)( THIS_ BOOL fCapture ) PURE; + THISCALLMETHOD_(void,TxSetFocus)( THIS ) PURE; + THISCALLMETHOD_(void,TxSetCursor)( THIS_ HCURSOR hcur, BOOL fText ) PURE; + THISCALLMETHOD_(BOOL,TxScreenToClient)( THIS_ LPPOINT lppt ) PURE; + THISCALLMETHOD_(BOOL,TxClientToScreen)( THIS_ LPPOINT lppt ) PURE; + THISCALLMETHOD_(HRESULT,TxActivate)( THIS_ LONG* plOldState ) PURE; + THISCALLMETHOD_(HRESULT,TxDeactivate)( THIS_ LONG lNewState ) PURE; + THISCALLMETHOD_(HRESULT,TxGetClientRect)( THIS_ LPRECT prc ) PURE; + THISCALLMETHOD_(HRESULT,TxGetViewInset)( THIS_ LPRECT prc ) PURE; + THISCALLMETHOD_(HRESULT,TxGetCharFormat)( THIS_ const CHARFORMATW** ppCF ) PURE; + THISCALLMETHOD_(HRESULT,TxGetParaFormat)( THIS_ const PARAFORMAT** ppPF ) PURE; + THISCALLMETHOD_(COLORREF,TxGetSysColor)( THIS_ int nIndex ) PURE; + THISCALLMETHOD_(HRESULT,TxGetBackStyle)( THIS_ TXTBACKSTYLE* pStyle ) PURE; + THISCALLMETHOD_(HRESULT,TxGetMaxLength)( THIS_ DWORD* plength ) PURE; + THISCALLMETHOD_(HRESULT,TxGetScrollBars)( THIS_ DWORD* pdwScrollBar ) PURE; + THISCALLMETHOD_(HRESULT,TxGetPasswordChar)( THIS_ WCHAR* pch ) PURE; + THISCALLMETHOD_(HRESULT,TxGetAcceleratorPos)( THIS_ LONG* pch ) PURE; + THISCALLMETHOD_(HRESULT,TxGetExtent)( THIS_ LPSIZEL lpExtent ) PURE; + THISCALLMETHOD_(HRESULT,OnTxCharFormatChange)( THIS_ const CHARFORMATW* pcf ) PURE; + THISCALLMETHOD_(HRESULT,OnTxParaFormatChange)( THIS_ const PARAFORMAT* ppf ) PURE; + THISCALLMETHOD_(HRESULT,TxGetPropertyBits)( THIS_ DWORD dwMask, DWORD* pdwBits ) PURE; + THISCALLMETHOD_(HRESULT,TxNotify)( THIS_ DWORD iNotify, void* pv ) PURE; + THISCALLMETHOD_(HIMC,TxImmGetContext)( THIS ) PURE; + THISCALLMETHOD_(void,TxImmReleaseContext)( THIS_ HIMC himc ) PURE; + THISCALLMETHOD_(HRESULT,TxGetSelectionBarWidth)( THIS_ LONG* lSelBarWidth ) PURE; + /* ITextHost2 methods */ + THISCALLMETHOD_(BOOL,TxIsDoubleClickPending)( THIS ) PURE; + THISCALLMETHOD_(HRESULT,TxGetWindow)( THIS_ HWND *hwnd ) PURE; + THISCALLMETHOD_(HRESULT,TxSetForegroundWindow)( THIS ) PURE; + THISCALLMETHOD_(HPALETTE,TxGetPalette)( THIS ) PURE; + THISCALLMETHOD_(HRESULT,TxGetEastAsianFlags)( THIS_ LONG *flags ) PURE; + THISCALLMETHOD_(HCURSOR,TxSetCursor2)( THIS_ HCURSOR cursor, BOOL text ) PURE; + THISCALLMETHOD_(void,TxFreeTextServicesNotification)( THIS ) PURE; + THISCALLMETHOD_(HRESULT,TxGetEditStyle)( THIS_ DWORD item, DWORD *data ) PURE; + THISCALLMETHOD_(HRESULT,TxGetWindowStyles)( THIS_ DWORD *style, DWORD *ex_style ) PURE; + THISCALLMETHOD_(HRESULT,TxShowDropCaret)( THIS_ BOOL show, HDC hdc, const RECT *rect ) PURE; + THISCALLMETHOD_(HRESULT,TxDestroyCaret)( THIS ) PURE; + THISCALLMETHOD_(HRESULT,TxGetHorzExtent)( THIS_ LONG *horz_extent ) PURE; +}; #undef INTERFACE +#ifdef COBJMACROS +/*** IUnknown methods ***/ +#define ITextHost2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define ITextHost2_AddRef(p) (p)->lpVtbl->AddRef(p) +#define ITextHost2_Release(p) (p)->lpVtbl->Release(p) +#endif + HRESULT WINAPI CreateTextServices(IUnknown*,ITextHost*,IUnknown**); typedef HRESULT (WINAPI *PCreateTextServices)(IUnknown*,ITextHost*,IUnknown**);
3 weeks, 2 days
1
0
0
0
[reactos] 01/01: [SHIMGVW] Fixes and enhancements (#7705)
by Whindmar Saksit
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=dd34ad7037edbc90117db…
commit dd34ad7037edbc90117dbf24dcdca6135ac9c1b6 Author: Whindmar Saksit <whindsaks(a)proton.me> AuthorDate: Sat Feb 8 16:22:20 2025 +0100 Commit: GitHub <noreply(a)github.com> CommitDate: Sat Feb 8 16:22:20 2025 +0100 [SHIMGVW] Fixes and enhancements (#7705) Fixes: - Reduce flicker when resizing main window - Fixed slideshow starting with 1x1 pixel image zoom - Don't reset zoom levels > 100% when resizing main window - Always retain an active window on toggle slideshow (show/hide actions order) - Enable/disable real-size button as required - Correctly handle accelerators in main window after slideshow has been closed - Use same zoom shortcuts as NT6 New features (unique to ROS): - Fullscreen mode (slideshow mode but without timer) - Alt+Enter or double-click to toggle fullscreen mode - Shift +/- to change fullscreen slideshow next picture timer CORE-19358 --- dll/win32/shimgvw/resource.h | 5 ++ dll/win32/shimgvw/shimgvw.c | 132 +++++++++++++++++++++++++++++++++++++------ dll/win32/shimgvw/shimgvw.rc | 11 +++- 3 files changed, 131 insertions(+), 17 deletions(-) diff --git a/dll/win32/shimgvw/resource.h b/dll/win32/shimgvw/resource.h index ec2fbf116bd..17fce85b7fc 100644 --- a/dll/win32/shimgvw/resource.h +++ b/dll/win32/shimgvw/resource.h @@ -30,6 +30,11 @@ /* ToolBar buttons */ #define IDC_TOOL_BASE 500 +#define IDC_ACCEL_BASE (IDC_TOOL_BASE + 100) /* Accelerator commands not on the toolbar */ + +#define IDC_TOGGLEFULLSCREEN (IDC_ACCEL_BASE + 0) +#define IDC_INCTIMER (IDC_ACCEL_BASE + 1) +#define IDC_DECTIMER (IDC_ACCEL_BASE + 2) #define IDC_PREV_PIC (IDC_TOOL_BASE + 0) #define IDC_NEXT_PIC (IDC_TOOL_BASE + 1) diff --git a/dll/win32/shimgvw/shimgvw.c b/dll/win32/shimgvw/shimgvw.c index 693b499761f..c0ce4de2d39 100644 --- a/dll/win32/shimgvw/shimgvw.c +++ b/dll/win32/shimgvw/shimgvw.c @@ -20,6 +20,8 @@ /* Slide show timer */ #define SLIDESHOW_TIMER_ID 0xFACE #define SLIDESHOW_TIMER_INTERVAL 5000 /* 5 seconds */ +#define HIDECURSOR_TIMER_ID 0xBABE +#define HIDECURSOR_TIMER_TIMEOUT 3000 HINSTANCE g_hInstance = NULL; HWND g_hMainWnd = NULL; @@ -109,11 +111,15 @@ typedef struct tagPREVIEW_DATA INT m_xScrollOffset; INT m_yScrollOffset; UINT m_nMouseDownMsg; + UINT m_nTimerInterval; + BOOL m_bHideCursor; POINT m_ptOrigin; IStream *m_pMemStream; WCHAR m_szFile[MAX_PATH]; } PREVIEW_DATA, *PPREVIEW_DATA; +static VOID Preview_ToggleSlideShowEx(PPREVIEW_DATA pData, BOOL StartTimer); + static inline PPREVIEW_DATA Preview_GetData(HWND hwnd) { @@ -131,14 +137,34 @@ Preview_RestartTimer(HWND hwnd) { if (!Preview_IsMainWnd(hwnd)) { + PPREVIEW_DATA pData = Preview_GetData(hwnd); KillTimer(hwnd, SLIDESHOW_TIMER_ID); - SetTimer(hwnd, SLIDESHOW_TIMER_ID, SLIDESHOW_TIMER_INTERVAL, NULL); + if (pData->m_nTimerInterval) + SetTimer(hwnd, SLIDESHOW_TIMER_ID, pData->m_nTimerInterval, NULL); } } static VOID -ZoomWnd_UpdateScroll(PPREVIEW_DATA pData, HWND hwnd, BOOL bResetPos) +Preview_ChangeSlideShowTimer(PPREVIEW_DATA pData, BOOL bSlower) { + BOOL IsFullscreen = !Preview_IsMainWnd(pData->m_hwnd); + enum { mintime = 1000, maxtime = SLIDESHOW_TIMER_INTERVAL * 3, step = 1000 }; + UINT interval = pData->m_nTimerInterval ? pData->m_nTimerInterval : SLIDESHOW_TIMER_INTERVAL; + if (IsFullscreen) + { + interval = bSlower ? min(interval + step, maxtime) : max(interval - step, mintime); + if (pData->m_nTimerInterval != interval) + { + pData->m_nTimerInterval = interval; + Preview_RestartTimer(pData->m_hwnd); + } + } +} + +static VOID +ZoomWnd_UpdateScroll(PPREVIEW_DATA pData, BOOL bResetPos) +{ + HWND hwnd = pData->m_hwndZoom; RECT rcClient; UINT ImageWidth, ImageHeight, ZoomedWidth, ZoomedHeight; SCROLLINFO si; @@ -221,10 +247,10 @@ Preview_UpdateZoom(PPREVIEW_DATA pData, UINT NewZoom, BOOL bEnableBestFit, BOOL bEnableZoomOut = (NewZoom > MIN_ZOOM); /* Update toolbar buttons */ - PostMessageW(hToolBar, TB_ENABLEBUTTON, IDC_ZOOM_OUT, bEnableZoomOut); - PostMessageW(hToolBar, TB_ENABLEBUTTON, IDC_ZOOM_IN, bEnableZoomIn); - PostMessageW(hToolBar, TB_ENABLEBUTTON, IDC_BEST_FIT, bEnableBestFit); - PostMessageW(hToolBar, TB_ENABLEBUTTON, IDC_REAL_SIZE, bEnableRealSize); + SendMessageW(hToolBar, TB_ENABLEBUTTON, IDC_BEST_FIT, bEnableBestFit); + SendMessageW(hToolBar, TB_ENABLEBUTTON, IDC_REAL_SIZE, NewZoom != 100); + SendMessageW(hToolBar, TB_ENABLEBUTTON, IDC_ZOOM_IN, bEnableZoomIn); + SendMessageW(hToolBar, TB_ENABLEBUTTON, IDC_ZOOM_OUT, bEnableZoomOut); /* Redraw the display window */ InvalidateRect(pData->m_hwndZoom, NULL, TRUE); @@ -233,7 +259,7 @@ Preview_UpdateZoom(PPREVIEW_DATA pData, UINT NewZoom, BOOL bEnableBestFit, BOOL Preview_RestartTimer(pData->m_hwnd); /* Update scroll info */ - ZoomWnd_UpdateScroll(pData, pData->m_hwndZoom, FALSE); + ZoomWnd_UpdateScroll(pData, FALSE); } static VOID @@ -592,7 +618,7 @@ Preview_UpdateImage(PPREVIEW_DATA pData) if (!Preview_IsMainWnd(pData->m_hwnd)) Preview_ResetZoom(pData); - ZoomWnd_UpdateScroll(pData, pData->m_hwndZoom, TRUE); + ZoomWnd_UpdateScroll(pData, TRUE); } static SHIMGVW_FILENODE* @@ -985,11 +1011,24 @@ Preview_EndSlideShow(HWND hwnd) return; KillTimer(hwnd, SLIDESHOW_TIMER_ID); + ShowWindow(g_hMainWnd, SW_SHOW); ShowWindow(hwnd, SW_HIDE); - ShowWindow(g_hMainWnd, SW_SHOWNORMAL); Preview_ResetZoom(Preview_GetData(g_hMainWnd)); } +static VOID +GenerateSetCursor(HWND hwnd, UINT uMsg) +{ + SendMessage(hwnd, WM_SETCURSOR, (WPARAM)hwnd, MAKELONG(HTCLIENT, uMsg)); +} + +static VOID +ZoomWnd_StopHideCursor(PPREVIEW_DATA pData) +{ + pData->m_bHideCursor = FALSE; + KillTimer(pData->m_hwndZoom, HIDECURSOR_TIMER_ID); +} + static VOID ZoomWnd_OnButtonDown(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { @@ -1002,6 +1041,7 @@ ZoomWnd_OnButtonDown(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) return; } + ZoomWnd_StopHideCursor(pData); pData->m_nMouseDownMsg = uMsg; pData->m_ptOrigin.x = GET_X_LPARAM(lParam); pData->m_ptOrigin.y = GET_Y_LPARAM(lParam); @@ -1015,6 +1055,13 @@ ZoomWnd_OnMouseMove(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) PPREVIEW_DATA pData = Preview_GetData(hwnd); POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; + if (!Preview_IsMainWnd(pData->m_hwnd)) + { + ZoomWnd_StopHideCursor(pData); + if (!pData->m_nMouseDownMsg) + SetTimer(hwnd, HIDECURSOR_TIMER_ID, HIDECURSOR_TIMER_TIMEOUT, NULL); + } + if (pData->m_nMouseDownMsg == WM_MBUTTONDOWN) { INT x = GetScrollPos(hwnd, SB_HORZ) - (pt.x - pData->m_ptOrigin.x); @@ -1034,6 +1081,12 @@ ZoomWnd_OnSetCursor(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) SetCursor(LoadCursorW(g_hInstance, MAKEINTRESOURCEW(IDC_HANDDRAG))); return TRUE; } + + if (pData->m_bHideCursor) + { + SetCursor(NULL); /* Hide cursor in fullscreen */ + return TRUE; + } return FALSE; } @@ -1041,8 +1094,15 @@ static VOID ZoomWnd_OnButtonUp(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { PPREVIEW_DATA pData = Preview_GetData(hwnd); + BOOL wasdrag = pData->m_nMouseDownMsg == WM_MBUTTONDOWN; + pData->m_nMouseDownMsg = 0; + if (wasdrag) + GenerateSetCursor(hwnd, uMsg); /* Reset to default cursor */ ReleaseCapture(); + + if (!Preview_IsMainWnd(pData->m_hwnd)) + SetTimer(hwnd, HIDECURSOR_TIMER_ID, HIDECURSOR_TIMER_TIMEOUT, NULL); } static VOID @@ -1167,6 +1227,12 @@ ZoomWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) ZoomWnd_OnButtonUp(hwnd, uMsg, wParam, lParam); break; } + case WM_LBUTTONDBLCLK: + { + if (Preview_IsMainWnd(pData->m_hwnd)) + Preview_ToggleSlideShowEx(pData, FALSE); + break; + } case WM_PAINT: { ZoomWnd_OnPaint(pData, hwnd); @@ -1184,8 +1250,19 @@ ZoomWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) break; case WM_TIMER: { + if (wParam == HIDECURSOR_TIMER_ID) + { + ZoomWnd_StopHideCursor(pData); + if (IsWindowVisible(hwnd)) + { + pData->m_bHideCursor = TRUE; + GenerateSetCursor(hwnd, uMsg); + } + } if (Anime_OnTimer(&pData->m_Anime, wParam)) + { InvalidateRect(hwnd, NULL, FALSE); + } break; } default: @@ -1298,7 +1375,9 @@ Preview_OnSize(HWND hwnd) MoveWindow(pData->m_hwndZoom, 0, 0, cx, cy - (rc.bottom - rc.top), TRUE); - if (!IsIconic(hwnd)) /* Is it not minimized? */ + if (pData->m_nZoomPercents > 100) + ZoomWnd_UpdateScroll(pData, FALSE); + else if (!IsIconic(hwnd)) /* Is it not minimized? */ Preview_ResetZoom(pData); Preview_OnMoveSize(hwnd); @@ -1372,7 +1451,7 @@ Preview_Edit(HWND hwnd) } static VOID -Preview_ToggleSlideShow(PPREVIEW_DATA pData) +Preview_ToggleSlideShowEx(PPREVIEW_DATA pData, BOOL StartTimer) { if (!IsWindow(g_hwndFullscreen)) { @@ -1385,18 +1464,28 @@ Preview_ToggleSlideShow(PPREVIEW_DATA pData) if (IsWindowVisible(g_hwndFullscreen)) { - ShowWindow(g_hwndFullscreen, SW_HIDE); - ShowWindow(g_hMainWnd, SW_SHOWNORMAL); KillTimer(g_hwndFullscreen, SLIDESHOW_TIMER_ID); + ShowWindow(g_hMainWnd, SW_SHOW); + ShowWindow(g_hwndFullscreen, SW_HIDE); } else { - ShowWindow(g_hMainWnd, SW_HIDE); + PPREVIEW_DATA pSlideData = Preview_GetData(g_hwndFullscreen); + pSlideData->m_nTimerInterval = StartTimer ? SLIDESHOW_TIMER_INTERVAL : 0; ShowWindow(g_hwndFullscreen, SW_SHOWMAXIMIZED); + ShowWindow(g_hMainWnd, SW_HIDE); + Preview_ResetZoom(pSlideData); Preview_RestartTimer(g_hwndFullscreen); + PostMessage(pSlideData->m_hwndZoom, WM_MOUSEMOVE, 0, 0); /* Start hide cursor */ } } +static inline VOID +Preview_ToggleSlideShow(PPREVIEW_DATA pData) +{ + Preview_ToggleSlideShowEx(pData, TRUE); +} + static VOID Preview_GoNextPic(PPREVIEW_DATA pData, BOOL bNext) { @@ -1452,6 +1541,15 @@ Preview_OnCommand(HWND hwnd, UINT nCommandID) Preview_EndSlideShow(hwnd); break; + case IDC_TOGGLEFULLSCREEN: + Preview_ToggleSlideShowEx(pData, FALSE); + break; + + case IDC_INCTIMER: + case IDC_DECTIMER: + Preview_ChangeSlideShowTimer(pData, nCommandID == IDC_INCTIMER); + break; + default: break; } @@ -1541,6 +1639,7 @@ Preview_OnDestroy(HWND hwnd) PPREVIEW_DATA pData = Preview_GetData(hwnd); KillTimer(hwnd, SLIDESHOW_TIMER_ID); + KillTimer(hwnd, HIDECURSOR_TIMER_ID); pFreeFileList(g_pCurrentFile); g_pCurrentFile = NULL; @@ -1683,7 +1782,7 @@ ImageView_Main(HWND hwnd, LPCWSTR szFileName) WndClass.style = CS_HREDRAW | CS_VREDRAW; WndClass.hIcon = LoadIconW(g_hInstance, MAKEINTRESOURCEW(IDI_APP_ICON)); WndClass.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); - WndClass.hbrBackground = (HBRUSH)UlongToHandle(COLOR_3DFACE + 1); + WndClass.hbrBackground = GetStockBrush(NULL_BRUSH); /* less flicker */ if (!RegisterClassW(&WndClass)) return -1; WndClass.lpszClassName = WC_ZOOM; @@ -1714,7 +1813,8 @@ ImageView_Main(HWND hwnd, LPCWSTR szFileName) /* Message Loop */ while (GetMessageW(&msg, NULL, 0, 0) > 0) { - if (g_hwndFullscreen && TranslateAcceleratorW(g_hwndFullscreen, hAccel, &msg)) + const HWND hwndFull = g_hwndFullscreen; + if (IsWindowVisible(hwndFull) && TranslateAcceleratorW(hwndFull, hAccel, &msg)) continue; if (TranslateAcceleratorW(hMainWnd, hAccel, &msg)) continue; diff --git a/dll/win32/shimgvw/shimgvw.rc b/dll/win32/shimgvw/shimgvw.rc index bb46198ded1..bec550cb4c3 100644 --- a/dll/win32/shimgvw/shimgvw.rc +++ b/dll/win32/shimgvw/shimgvw.rc @@ -43,10 +43,19 @@ BEGIN "B", IDC_BEST_FIT, VIRTKEY, CONTROL "A", IDC_REAL_SIZE, VIRTKEY, CONTROL VK_F11, IDC_SLIDE_SHOW, VIRTKEY + VK_RETURN, IDC_TOGGLEFULLSCREEN, VIRTKEY, ALT + VK_ADD, IDC_INCTIMER, VIRTKEY, SHIFT + VK_OEM_PLUS, IDC_INCTIMER, VIRTKEY, SHIFT + VK_OEM_MINUS,IDC_DECTIMER, VIRTKEY, SHIFT + VK_SUBTRACT, IDC_DECTIMER, VIRTKEY, SHIFT VK_ADD, IDC_ZOOM_IN, VIRTKEY + VK_ADD, IDC_ZOOM_IN, VIRTKEY, CONTROL + VK_OEM_PLUS, IDC_ZOOM_IN, VIRTKEY + VK_OEM_PLUS, IDC_ZOOM_IN, VIRTKEY, CONTROL VK_SUBTRACT, IDC_ZOOM_OUT, VIRTKEY - VK_OEM_PLUS, IDC_ZOOM_IN, VIRTKEY, SHIFT + VK_SUBTRACT, IDC_ZOOM_OUT, VIRTKEY, CONTROL VK_OEM_MINUS,IDC_ZOOM_OUT, VIRTKEY + VK_OEM_MINUS,IDC_ZOOM_OUT, VIRTKEY, CONTROL "K", IDC_ROT_CLOCKW, VIRTKEY, CONTROL "L", IDC_ROT_COUNCW, VIRTKEY, CONTROL VK_DELETE, IDC_DELETE, VIRTKEY
3 weeks, 2 days
1
0
0
0
[reactos] 01/01: [PROPSYS] Sync to wine-10.0 (#7677)
by Mikhail Tyukin
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2d1144a5cd63ae1c4a0d2…
commit 2d1144a5cd63ae1c4a0d2c5b52f85a3e38115637 Author: Mikhail Tyukin <mishakeys20(a)gmail.com> AuthorDate: Fri Feb 7 16:00:48 2025 -0500 Commit: GitHub <noreply(a)github.com> CommitDate: Fri Feb 7 22:00:48 2025 +0100 [PROPSYS] Sync to wine-10.0 (#7677) [WINESYNC] propsys/tests: Merge test files. wine commit id d189b55d2ffb038474cb6656dc8743eb34c35a3d by Nikolay Sivov <nsivov(a)codeweavers.com> [WINESYNC] propsys: Add a semi-stub for PSCreatePropertyStoreFromObject(). Wine-Bug:
https://bugs.winehq.org/show_bug.cgi?id=47958
wine commit id acb2e4fc7a4242c74ac91657edb97bf1e402656a by Nikolay Sivov <nsivov(a)codeweavers.com> [WINESYNC] propsys: Allow only ASCII digits in PSPropertyKeyFromString. wine commit id 6e8c2d836e637e1fbd83c231cfd846ecb9333964 by Jacek Caban <jacek(a)codeweavers.com> [WINESYNC] propsys/tests: Get rid of strcmp_wa(). wine commit id 2340212ee9c48c731c85bbad8c81ed833458bf15 by Michael Stefaniuc <mstefani(a)winehq.org> [WINESYNC] propsys: Use wide-char string literals. wine commit id b72440fa2e1016681cbfcebcdc4792b6ced3eb53 by Michael Stefaniuc <mstefani(a)winehq.org> reduce wine diff and add stuff from previous commit [WINESYNC] propsys: Use --prefer_native instead of DLL_WINE_PREATTACH. wine commit id f99113192ffac37506a905827415d3d21d0ebbf8 by Alexandre Julliard <julliard(a)winehq.org> [WINESYNC] propsys: Use nameless unions. wine commit id 1d8e5079f0e53a767a783e5107f57f04c1897951 by Jacek Caban <jacek(a)codeweavers.com> [WINESYNC] propsys/tests: Use nameless unions. wine commit id 497de3cc19f971808ca4105f52038e61dc818db1 by Jacek Caban <jacek(a)codeweavers.com> [WINESYNC] winecrt0: Add a default implementation for DllCanUnloadNow(). wine commit id bd6b53740c28c6974300e15f965c12feb0252085 by Alexandre Julliard <julliard(a)winehq.org> [WINESYNC] winecrt0: Add a default implementation DllRegisterServer()/DllUnregisterServer(). wine commit id 5d82baf9747b7b133cad3be77c0cc9e24cc09582 by Alexandre Julliard <julliard(a)winehq.org> [WINESYNC] propsys: Add support for VT_VECTOR|VT_UI1 type in PropVariantCompareEx(). wine commit id e91b05bb5be6fd70a767bea9991e818a49cc5547 by Nikolay Sivov <nsivov(a)codeweavers.com> [WINESYNC] propsys: Fix VT_UI4 comparison, use ulVal instead of uiVal. wine commit id 58eeb1a86433db1104d3a9ccf9ad7435ec81443a by Rémi Bernon <rbernon(a)codeweavers.com> [WINESYNC] propsys/tests: Add a VT_UI4 test for PropVariantCompareEx(). A test for 58eeb1a86433db1104d3a9ccf9ad7435ec81443a. wine commit id 10359e17ce64f39461a7b7b54f73857e6458d1fb by Nikolay Sivov <nsivov(a)codeweavers.com> [WINESYNC] propsys/tests: Avoid "misleading indentation" warnings. wine commit id 7cd6681b3be35cf6c02f056cb5131c90c0674c16 by Fabian Maurer <dark.shadow4(a)web.de> [WINESYNC] propsys: Enable compilation with long types. wine commit id a9c797e4538a37716e62bb81c3fed3de39561b41 by Eric Pouech <eric.pouech(a)gmail.com> [WINESYNC] propsys/tests: Enable compilation with long types. wine commit id c1c393595d43bd95390d3ddf86dcbc46bc4f52ba by Eric Pouech <eric.pouech(a)gmail.com> [WINESYNC] propsys: Implement InitVariantFromFileTime. wine commit id f2b8ccb7b0b22b7b5d661d908f8f8ee02f22647d by Daniel Lehman <dlehman(a)esri.com> [WINESYNC] propsys/tests: Add some InitVariantFromFileTime tests. wine commit id 083dea7fce4372840ac18176496a7d05dadd5ad8 by Daniel Lehman <dlehman(a)esri.com> [WINESYNC] propsys: Implement VariantToStringWithDefault. wine commit id bf0f1fdcf80657a42116b79a0953181191cf9221 by Mohamad Al-Jaf <mohamadaljaf(a)gmail.com> [WINESYNC] propsys/tests: Add VariantToStringWithDefault tests. wine commit id 89aba13dc381dbbda62d1019e1af2af5a589b0cf by Mohamad Al-Jaf <mohamadaljaf(a)gmail.com> [WINESYNC] include: Add Stg functions declaration in propvarutil.h. wine commit id 0d294ad26544913414277daa164004d731ae6e33 by Biswapriyo Nath <nathbappai(a)gmail.com> [WINESYNC] propsys: Add InitPropVariantFromStringVector(). wine commit id 3a1146d8e63d7ceff38441fee08f7f7080527020 by Nikolay Sivov <nsivov(a)codeweavers.com> [WINESYNC] Remove unused NONAMELESS defines. wine commit id 20afe438320f77d103a96d1d8cd562d0899ebac7 by Alexandre Julliard <julliard(a)winehq.org> [WINESYNC] propsys: Partially implement VariantToString(). Wine-Bug:
https://bugs.winehq.org/show_bug.cgi?id=55708
wine commit id f7ef02bd8f74ea052d61e48cd84b226d8a5867a8 by Nikolay Sivov <nsivov(a)codeweavers.com> [WINESYNC] propsys: Handle VT_I4 type in VariantToString(). Wine-Bug:
https://bugs.winehq.org/show_bug.cgi?id=55708
wine commit id 001e0543bfd5aea060053af0c76233bb90fbb43b by Nikolay Sivov <nsivov(a)codeweavers.com> [WINESYNC] propsys: Implement PropVariantToUInt32WithDefault. Wine-Bug:
https://bugs.winehq.org/show_bug.cgi?id=55713
wine commit id d177709b10ce07ddd234b0e8e00764ae4b1d8488 by Fabian Maurer <dark.shadow4(a)web.de> [WINESYNC] include: Use proper dllimports for propsys functions. wine commit id f0b2e0d00c86fb04d47467f39e49c587250ffec5 by Alexandre Julliard <julliard(a)winehq.org> [WINESYNC] propsys: Remove DECLSPEC_HIDDEN usage. wine commit id e9ff53e098ef3871d692c7b907151cfbb2f0673f by Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com> Update propsys_private.h [WINESYNC] propsys: Force debug info in critical sections. wine commit id 67bea281cc851eda6a08430c70f6c9e848d3fbe1 by Paul Gofman <pgofman(a)codeweavers.com> [WINESYNC] include: Fix typos in IID_IPropertyEnumType2 and CLSID_PropertySystem. wine commit id 66e6b61705a66459ed3a9e0cf9457d8b180e4564 by Alfred Agrell <floating(a)muncher.se> [WINESYNC] propsys: Add stubs for variant conversion functions. wine commit id c21f04f7adaa4a8d0ca2d2659bf9a6facdc168c3 by Ziqing Hui <zhui(a)codeweavers.com> [WINESYNC] propsys/tests: Add tests for VariantToPropVariant. wine commit id 8877889f2a8e36d22dcad061e6da84476efb3750 by Ziqing Hui <zhui(a)codeweavers.com> [WINESYNC] propsys: Initially implement VariantToPropVariant. wine commit id 6985637ed59e81e7d1716095a343cc5681082306 by Ziqing Hui <zhui(a)codeweavers.com> [WINESYNC] propsys/tests: Add tests for PropVariantToVariant. wine commit id 3277de5572b7f6c41ebeeb89f781e378a6a2c2d3 by Ziqing Hui <zhui(a)codeweavers.com> [WINESYNC] propsys/tests: Test converting clsid to string. wine commit id 7a4f9f83c51883f41ae1363e27700452472ec18f by Ziqing Hui <zhui(a)codeweavers.com> [WINESYNC] propsys: Support converting clsid to string for PropVariant. wine commit id 67b097ff46c65d525de6a7f560f019de6828320c by Ziqing Hui <zhui(a)codeweavers.com> [WINESYNC] propsys: Initially implement PropVariantToVariant. wine commit id 808b398549350fffc9fc023d637ef8de9e4bba37 by Ziqing Hui <zhui(a)codeweavers.com> [WINESYNC] propsys: Add PropVariantToBSTR stub. wine commit id 86558a4b83ebf9a0c6e76888a3d0f3fe3e36bf57 by Ziqing Hui <zhui(a)codeweavers.com> [WINESYNC] propsys/tests: Test PropVariantToBSTR. wine commit id b4ac03f1f622120906a8b6e691caa05f6539c2dd by Ziqing Hui <zhui(a)codeweavers.com> [WINESYNC] propsys/tests: Test truncating for PropVariantToString. wine commit id df16802582a56f8076ebbcf9cb6178f65bb8b9b6 by Ziqing Hui <zhui(a)codeweavers.com> [WINESYNC] propsys: Implement PropVariantToBSTR. wine commit id 66220be403ce5c3634c13da3546f0c19f04059cc by Ziqing Hui <zhui(a)codeweavers.com> [WINESYNC] propsys: Use debugstr_variant for the trace in VariantToPropVariant. wine commit id 3517aded4090229dbb11e413bde8349d1eca0be3 by Ziqing Hui <zhui(a)codeweavers.com> [WINESYNC] propsys: Support converting to BSTR for PropVariantToVariant. wine commit id c33fdc27650045a754a05a8f25e250e6e72c8072 by Ziqing Hui <zhui(a)codeweavers.com> [WINESYNC] propsys/tests: Fix a test that fails on some Windows versions. wine commit id c09f828f43101cf2dfe11d7e13f1fc6ef4b19853 by Alexandre Julliard <julliard(a)winehq.org> [WINESYNC]: propsys is now in sync with wine-staging wine-10.0 Co-authored-by: winesync <ros-dev(a)reactos.org> [PROPSYS] Remove duplicate uuid [PROPSYS] Fix headers/idl file --- dll/win32/propsys/CMakeLists.txt | 5 +- dll/win32/propsys/precomp.h | 3 +- dll/win32/propsys/propstore.c | 26 +- dll/win32/propsys/propsys.spec | 18 +- dll/win32/propsys/propsys_main.c | 60 +- dll/win32/propsys/propsys_private.h | 2 +- dll/win32/propsys/propvar.c | 502 +++++-- media/doc/WINESYNC.txt | 2 +- modules/rostests/winetests/propsys/CMakeLists.txt | 3 +- modules/rostests/winetests/propsys/propstore.c | 374 ----- modules/rostests/winetests/propsys/propsys.c | 1594 +++++++++++++++++---- modules/rostests/winetests/propsys/testlist.c | 2 - sdk/include/psdk/oaidl.idl | 11 + sdk/include/psdk/propsys.idl | 29 +- sdk/include/psdk/propvarutil.h | 144 +- sdk/tools/winesync/propsys.cfg | 9 + 16 files changed, 1939 insertions(+), 845 deletions(-) diff --git a/dll/win32/propsys/CMakeLists.txt b/dll/win32/propsys/CMakeLists.txt index 8d788ae20d4..41412950df7 100644 --- a/dll/win32/propsys/CMakeLists.txt +++ b/dll/win32/propsys/CMakeLists.txt @@ -1,6 +1,7 @@ include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine) -add_definitions(-D__WINESRC__) +remove_definitions(-D_CRT_NON_CONFORMING_SWPRINTFS -D__ROS_LONG64__) +add_definitions(-D__WINESRC__ -D_PROPSYS_) spec2def(propsys.dll propsys.spec ADD_IMPORTLIB) list(APPEND SOURCE @@ -16,7 +17,7 @@ add_library(propsys MODULE ${CMAKE_CURRENT_BINARY_DIR}/propsys.def) set_module_type(propsys win32dll) -target_link_libraries(propsys uuid wine) +target_link_libraries(propsys uuid wine wine_dll_register) add_importlibs(propsys ole32 oleaut32 msvcrt kernel32 ntdll) add_pch(propsys precomp.h SOURCE) add_cd_file(TARGET propsys DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/propsys/precomp.h b/dll/win32/propsys/precomp.h index 1f432757e3a..a233f258ae0 100644 --- a/dll/win32/propsys/precomp.h +++ b/dll/win32/propsys/precomp.h @@ -9,13 +9,14 @@ #define COM_NO_WINDOWS_H #define COBJMACROS -#define NONAMELESSUNION #include <windef.h> #include <winbase.h> #include <winnls.h> #include <objbase.h> #include <propsys.h> +#include <oleauto.h> +#include <oaidl.h> #include <wine/debug.h> diff --git a/dll/win32/propsys/propstore.c b/dll/win32/propsys/propstore.c index 6212f293123..adef3b38916 100644 --- a/dll/win32/propsys/propstore.c +++ b/dll/win32/propsys/propstore.c @@ -92,7 +92,7 @@ static ULONG WINAPI PropertyStore_AddRef(IPropertyStoreCache *iface) PropertyStore *This = impl_from_IPropertyStoreCache(iface); ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); return ref; } @@ -113,7 +113,7 @@ static ULONG WINAPI PropertyStore_Release(IPropertyStoreCache *iface) PropertyStore *This = impl_from_IPropertyStoreCache(iface); ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); if (ref == 0) { @@ -159,7 +159,7 @@ static HRESULT WINAPI PropertyStore_GetAt(IPropertyStoreCache *iface, propstore_value *value; HRESULT hr; - TRACE("%p,%d,%p\n", iface, iProp, pkey); + TRACE("%p,%ld,%p\n", iface, iProp, pkey); if (!pkey) return E_POINTER; @@ -464,7 +464,11 @@ HRESULT PropertyStore_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv This->IPropertyStoreCache_iface.lpVtbl = &PropertyStore_Vtbl; This->ref = 1; +#ifdef __REACTOS__ InitializeCriticalSection(&This->lock); +#else + InitializeCriticalSectionEx(&This->lock, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO); +#endif This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PropertyStore.lock"); list_init(&This->formats); @@ -473,3 +477,19 @@ HRESULT PropertyStore_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv return ret; } + +HRESULT WINAPI PSCreatePropertyStoreFromObject(IUnknown *obj, DWORD access, REFIID riid, void **ret) +{ + HRESULT hr; + + TRACE("(%p, %ld, %s, %p)\n", obj, access, debugstr_guid(riid), ret); + + if (!obj || !ret) + return E_POINTER; + + if (IsEqualIID(riid, &IID_IPropertyStore) && SUCCEEDED(hr = IUnknown_QueryInterface(obj, riid, ret))) + return hr; + + FIXME("Unimplemented for %s.\n", debugstr_guid(riid)); + return E_NOTIMPL; +} diff --git a/dll/win32/propsys/propsys.spec b/dll/win32/propsys/propsys.spec index 19e16aedc1e..5771848917b 100644 --- a/dll/win32/propsys/propsys.spec +++ b/dll/win32/propsys/propsys.spec @@ -42,7 +42,7 @@ @ stub InitPropVariantFromResource @ stub InitPropVariantFromStrRet @ stub InitPropVariantFromStringAsVector -@ stub InitPropVariantFromStringVector +@ stdcall InitPropVariantFromStringVector(ptr long ptr) @ stub InitPropVariantFromUInt16Vector @ stub InitPropVariantFromUInt32Vector @ stub InitPropVariantFromUInt64Vector @@ -50,7 +50,7 @@ @ stub InitVariantFromBooleanArray @ stdcall InitVariantFromBuffer(ptr long ptr) @ stub InitVariantFromDoubleArray -@ stub InitVariantFromFileTime +@ stdcall InitVariantFromFileTime(ptr ptr) @ stub InitVariantFromFileTimeArray @ stdcall InitVariantFromGUIDAsString(ptr ptr) @ stub InitVariantFromInt16Array @@ -69,7 +69,7 @@ @ stdcall PSCreateMemoryPropertyStore(ptr ptr) @ stub PSCreateMultiplexPropertyStore @ stub PSCreatePropertyChangeArray -@ stub PSCreatePropertyStoreFromObject +@ stdcall PSCreatePropertyStoreFromObject(ptr long ptr ptr) @ stub PSCreatePropertyStoreFromPropertySetStorage @ stub PSCreateSimplePropertyChange @ stub PSEnumeratePropertyDescriptions @@ -107,7 +107,7 @@ @ stub PropVariantGetUInt16Elem @ stub PropVariantGetUInt32Elem @ stub PropVariantGetUInt64Elem -@ stub PropVariantToBSTR +@ stdcall PropVariantToBSTR(ptr ptr) @ stdcall PropVariantToBoolean(ptr ptr) @ stub PropVariantToBooleanVector @ stub PropVariantToBooleanVectorAlloc @@ -146,12 +146,12 @@ @ stdcall PropVariantToUInt32(ptr ptr) @ stub PropVariantToUInt32Vector @ stub PropVariantToUInt32VectorAlloc -@ stub PropVariantToUInt32WithDefault +@ stdcall PropVariantToUInt32WithDefault(ptr long) @ stdcall PropVariantToUInt64(ptr ptr) @ stub PropVariantToUInt64Vector @ stub PropVariantToUInt64VectorAlloc @ stub PropVariantToUInt64WithDefault -@ stub PropVariantToVariant +@ stdcall PropVariantToVariant(ptr ptr) @ stub StgDeserializePropVariant @ stub StgSerializePropVariant @ stub VariantCompare @@ -189,13 +189,13 @@ @ stub VariantToInt64Array @ stub VariantToInt64ArrayAlloc @ stub VariantToInt64WithDefault -@ stub VariantToPropVariant +@ stdcall VariantToPropVariant(ptr ptr) @ stub VariantToStrRet -@ stub VariantToString +@ stdcall VariantToString(ptr ptr long) @ stub VariantToStringAlloc @ stub VariantToStringArray @ stub VariantToStringArrayAlloc -@ stub VariantToStringWithDefault +@ stdcall VariantToStringWithDefault(ptr wstr) @ stub VariantToUInt16 @ stub VariantToUInt16Array @ stub VariantToUInt16ArrayAlloc diff --git a/dll/win32/propsys/propsys_main.c b/dll/win32/propsys/propsys_main.c index 6f7dc8a397c..5557131ed4b 100644 --- a/dll/win32/propsys/propsys_main.c +++ b/dll/win32/propsys/propsys_main.c @@ -22,9 +22,6 @@ #define COBJMACROS #include <stdarg.h> -#ifdef __REACTOS__ -#include <wchar.h> -#endif #include "windef.h" #include "winbase.h" @@ -37,35 +34,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(propsys); -static HINSTANCE propsys_hInstance; - -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved); - - switch (fdwReason) - { - case DLL_WINE_PREATTACH: - return FALSE; /* prefer native version */ - case DLL_PROCESS_ATTACH: - propsys_hInstance = hinstDLL; - DisableThreadLibraryCalls(hinstDLL); - break; - } - - return TRUE; -} - -HRESULT WINAPI DllRegisterServer(void) -{ - return __wine_register_resources( propsys_hInstance ); -} - -HRESULT WINAPI DllUnregisterServer(void) -{ - return __wine_unregister_resources( propsys_hInstance ); -} - static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv) { *ppv = NULL; @@ -135,11 +103,6 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) return CLASS_E_CLASSNOTAVAILABLE; } -HRESULT WINAPI DllCanUnloadNow(void) -{ - return S_FALSE; -} - static HRESULT WINAPI propsys_QueryInterface(IPropertySystem *iface, REFIID riid, void **obj) { *obj = NULL; @@ -194,7 +157,7 @@ static HRESULT WINAPI propsys_FormatForDisplay(IPropertySystem *iface, REFPROPERTYKEY key, REFPROPVARIANT propvar, PROPDESC_FORMAT_FLAGS flags, LPWSTR dest, DWORD destlen) { - FIXME("%p %p %x %p %d: stub\n", key, propvar, flags, dest, destlen); + FIXME("%p %p %x %p %ld: stub\n", key, propvar, flags, dest, destlen); return E_NOTIMPL; } @@ -283,12 +246,6 @@ HRESULT WINAPI PSRefreshPropertySchema(void) HRESULT WINAPI PSStringFromPropertyKey(REFPROPERTYKEY pkey, LPWSTR psz, UINT cch) { - static const WCHAR guid_fmtW[] = {'{','%','0','8','X','-','%','0','4','X','-', - '%','0','4','X','-','%','0','2','X','%','0','2','X','-', - '%','0','2','X','%','0','2','X','%','0','2','X', - '%','0','2','X','%','0','2','X','%','0','2','X','}',0}; - static const WCHAR pid_fmtW[] = {'%','u',0}; - WCHAR pidW[PKEY_PIDSTR_MAX + 1]; LPWSTR p = psz; int len; @@ -308,8 +265,8 @@ HRESULT WINAPI PSStringFromPropertyKey(REFPROPERTYKEY pkey, LPWSTR psz, UINT cch return E_NOT_SUFFICIENT_BUFFER; } - swprintf(psz, guid_fmtW, pkey->fmtid.Data1, pkey->fmtid.Data2, - pkey->fmtid.Data3, pkey->fmtid.Data4[0], pkey->fmtid.Data4[1], + swprintf(psz, cch, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", pkey->fmtid.Data1, + pkey->fmtid.Data2, pkey->fmtid.Data3, pkey->fmtid.Data4[0], pkey->fmtid.Data4[1], pkey->fmtid.Data4[2], pkey->fmtid.Data4[3], pkey->fmtid.Data4[4], pkey->fmtid.Data4[5], pkey->fmtid.Data4[6], pkey->fmtid.Data4[7]); @@ -318,7 +275,7 @@ HRESULT WINAPI PSStringFromPropertyKey(REFPROPERTYKEY pkey, LPWSTR psz, UINT cch *p++ = ' '; cch -= GUIDSTRING_MAX - 1 + 1; - len = swprintf(pidW, pid_fmtW, pkey->pid); + len = swprintf(pidW, ARRAY_SIZE(pidW), L"%u", pkey->pid); if (cch >= len + 1) { @@ -498,7 +455,7 @@ HRESULT WINAPI PSPropertyKeyFromString(LPCWSTR pszString, PROPERTYKEY *pkey) } /* Overflow is not checked. */ - while (iswdigit(*pszString)) + while ('0' <= *pszString && *pszString <= '9') { pkey->pid *= 10; pkey->pid += (*pszString - '0'); @@ -517,3 +474,10 @@ HRESULT WINAPI PSCreateMemoryPropertyStore(REFIID riid, void **ppv) return PropertyStore_CreateInstance(NULL, riid, ppv); } + +#ifdef __REACTOS__ +HRESULT WINAPI DllCanUnloadNow(void) +{ + return S_FALSE; +} +#endif diff --git a/dll/win32/propsys/propsys_private.h b/dll/win32/propsys/propsys_private.h index d43de7534d2..a91b5c5c289 100644 --- a/dll/win32/propsys/propsys_private.h +++ b/dll/win32/propsys/propsys_private.h @@ -20,4 +20,4 @@ #pragma once -HRESULT PropertyStore_CreateInstance(IUnknown *outer, REFIID riid, void **ppv) DECLSPEC_HIDDEN; +HRESULT PropertyStore_CreateInstance(IUnknown *outer, REFIID riid, void **ppv); diff --git a/dll/win32/propsys/propvar.c b/dll/win32/propsys/propvar.c index f03dc148435..e1375134f11 100644 --- a/dll/win32/propsys/propvar.c +++ b/dll/win32/propsys/propvar.c @@ -23,8 +23,6 @@ #include <stdio.h> #include <stdlib.h> -#define NONAMELESSUNION - #include "windef.h" #include "winbase.h" #include "winerror.h" @@ -33,11 +31,31 @@ #include "shlobj.h" #include "propvarutil.h" #include "strsafe.h" - #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(propsys); +#define GUID_STR_LEN 38 +static HRESULT VARIANT_ValidateType(VARTYPE vt) +{ + VARTYPE vtExtra = vt & (VT_VECTOR | VT_ARRAY | VT_BYREF | VT_RESERVED); + + vt &= VT_TYPEMASK; + + if (!(vtExtra & (VT_VECTOR | VT_RESERVED))) + { + if (vt < VT_VOID || vt == VT_RECORD || vt == VT_CLSID) + { + if ((vtExtra & (VT_BYREF | VT_ARRAY)) && vt <= VT_NULL) + return DISP_E_BADVARTYPE; + if (vt != (VARTYPE)15) + return S_OK; + } + } + + return DISP_E_BADVARTYPE; +} + static HRESULT PROPVAR_ConvertFILETIME(const FILETIME *ft, PROPVARIANT *ppropvarDest, VARTYPE vt) { SYSTEMTIME time; @@ -47,11 +65,11 @@ static HRESULT PROPVAR_ConvertFILETIME(const FILETIME *ft, PROPVARIANT *ppropvar switch (vt) { case VT_LPSTR: - ppropvarDest->u.pszVal = HeapAlloc(GetProcessHeap(), 0, 64); - if (!ppropvarDest->u.pszVal) + ppropvarDest->pszVal = HeapAlloc(GetProcessHeap(), 0, 64); + if (!ppropvarDest->pszVal) return E_OUTOFMEMORY; - sprintf( ppropvarDest->u.pszVal, "%04d/%02d/%02d:%02d:%02d:%02d.%03d", + sprintf( ppropvarDest->pszVal, "%04d/%02d/%02d:%02d:%02d:%02d.%03d", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds ); @@ -74,35 +92,35 @@ static HRESULT PROPVAR_ConvertNumber(REFPROPVARIANT pv, int dest_bits, { case VT_I1: src_signed = TRUE; - *res = pv->u.cVal; + *res = pv->cVal; break; case VT_UI1: src_signed = FALSE; - *res = pv->u.bVal; + *res = pv->bVal; break; case VT_I2: src_signed = TRUE; - *res = pv->u.iVal; + *res = pv->iVal; break; case VT_UI2: src_signed = FALSE; - *res = pv->u.uiVal; + *res = pv->uiVal; break; case VT_I4: src_signed = TRUE; - *res = pv->u.lVal; + *res = pv->lVal; break; case VT_UI4: src_signed = FALSE; - *res = pv->u.ulVal; + *res = pv->ulVal; break; case VT_I8: src_signed = TRUE; - *res = pv->u.hVal.QuadPart; + *res = pv->hVal.QuadPart; break; case VT_UI8: src_signed = FALSE; - *res = pv->u.uhVal.QuadPart; + *res = pv->uhVal.QuadPart; break; case VT_EMPTY: src_signed = FALSE; @@ -111,8 +129,12 @@ static HRESULT PROPVAR_ConvertNumber(REFPROPVARIANT pv, int dest_bits, case VT_LPSTR: { char *end; - *res = _strtoi64(pv->u.pszVal, &end, 0); - if (pv->u.pszVal == end) +#ifdef __REACTOS__ + *res = _strtoi64(pv->pszVal, &end, 0); +#else + *res = strtoll(pv->pszVal, &end, 0); +#endif + if (pv->pszVal == end) return DISP_E_TYPEMISMATCH; src_signed = *res < 0; break; @@ -121,8 +143,8 @@ static HRESULT PROPVAR_ConvertNumber(REFPROPVARIANT pv, int dest_bits, case VT_BSTR: { WCHAR *end; - *res = wcstol(pv->u.pwszVal, &end, 0); - if (pv->u.pwszVal == end) + *res = wcstol(pv->pwszVal, &end, 0); + if (pv->pwszVal == end) return DISP_E_TYPEMISMATCH; src_signed = *res < 0; break; @@ -130,7 +152,7 @@ static HRESULT PROPVAR_ConvertNumber(REFPROPVARIANT pv, int dest_bits, case VT_R8: { src_signed = TRUE; - *res = pv->u.dblVal; + *res = pv->dblVal; break; } default: @@ -231,6 +253,20 @@ HRESULT WINAPI PropVariantToUInt32(REFPROPVARIANT propvarIn, ULONG *ret) return hr; } +ULONG WINAPI PropVariantToUInt32WithDefault(REFPROPVARIANT propvarIn, ULONG ulDefault) +{ + LONGLONG res; + HRESULT hr; + + TRACE("%p,%lu\n", propvarIn, ulDefault); + + hr = PROPVAR_ConvertNumber(propvarIn, 32, FALSE, &res); + if (SUCCEEDED(hr)) + return (ULONG)res; + + return ulDefault; +} + HRESULT WINAPI PropVariantToUInt64(REFPROPVARIANT propvarIn, ULONGLONG *ret) { LONGLONG res; @@ -245,10 +281,6 @@ HRESULT WINAPI PropVariantToUInt64(REFPROPVARIANT propvarIn, ULONGLONG *ret) HRESULT WINAPI PropVariantToBoolean(REFPROPVARIANT propvarIn, BOOL *ret) { - static const WCHAR trueW[] = {'t','r','u','e',0}; - static const WCHAR falseW[] = {'f','a','l','s','e',0}; - static const WCHAR true2W[] = {'#','T','R','U','E','#',0}; - static const WCHAR false2W[] = {'#','F','A','L','S','E','#',0}; LONGLONG res; HRESULT hr; @@ -259,21 +291,21 @@ HRESULT WINAPI PropVariantToBoolean(REFPROPVARIANT propvarIn, BOOL *ret) switch (propvarIn->vt) { case VT_BOOL: - *ret = propvarIn->u.boolVal == VARIANT_TRUE; + *ret = propvarIn->boolVal == VARIANT_TRUE; return S_OK; case VT_LPWSTR: case VT_BSTR: - if (!propvarIn->u.pwszVal) + if (!propvarIn->pwszVal) return DISP_E_TYPEMISMATCH; - if (!lstrcmpiW(propvarIn->u.pwszVal, trueW) || !lstrcmpW(propvarIn->u.pwszVal, true2W)) + if (!lstrcmpiW(propvarIn->pwszVal, L"true") || !lstrcmpW(propvarIn->pwszVal, L"#TRUE#")) { *ret = TRUE; return S_OK; } - if (!lstrcmpiW(propvarIn->u.pwszVal, falseW) || !lstrcmpW(propvarIn->u.pwszVal, false2W)) + if (!lstrcmpiW(propvarIn->pwszVal, L"false") || !lstrcmpW(propvarIn->pwszVal, L"#FALSE#")) { *ret = FALSE; return S_OK; @@ -281,16 +313,16 @@ HRESULT WINAPI PropVariantToBoolean(REFPROPVARIANT propvarIn, BOOL *ret) break; case VT_LPSTR: - if (!propvarIn->u.pszVal) + if (!propvarIn->pszVal) return DISP_E_TYPEMISMATCH; - if (!lstrcmpiA(propvarIn->u.pszVal, "true") || !lstrcmpA(propvarIn->u.pszVal, "#TRUE#")) + if (!lstrcmpiA(propvarIn->pszVal, "true") || !lstrcmpA(propvarIn->pszVal, "#TRUE#")) { *ret = TRUE; return S_OK; } - if (!lstrcmpiA(propvarIn->u.pszVal, "false") || !lstrcmpA(propvarIn->u.pszVal, "#FALSE#")) + if (!lstrcmpiA(propvarIn->pszVal, "false") || !lstrcmpA(propvarIn->pszVal, "#FALSE#")) { *ret = FALSE; return S_OK; @@ -303,6 +335,26 @@ HRESULT WINAPI PropVariantToBoolean(REFPROPVARIANT propvarIn, BOOL *ret) return hr; } +HRESULT WINAPI PropVariantToBSTR(REFPROPVARIANT propvar, BSTR *bstr) +{ + WCHAR *str; + HRESULT hr; + + TRACE("propvar %p, propvar->vt %#x, bstr %p.\n", + propvar, propvar ? propvar->vt : 0, bstr); + + if (FAILED(hr = PropVariantToStringAlloc(propvar, &str))) + return hr; + + *bstr = SysAllocString(str); + CoTaskMemFree(str); + + if (!*bstr) + return E_OUTOFMEMORY; + + return S_OK; +} + HRESULT WINAPI PropVariantToBuffer(REFPROPVARIANT propvarIn, void *ret, UINT cb) { HRESULT hr = S_OK; @@ -312,9 +364,9 @@ HRESULT WINAPI PropVariantToBuffer(REFPROPVARIANT propvarIn, void *ret, UINT cb) switch(propvarIn->vt) { case VT_VECTOR|VT_UI1: - if(cb > propvarIn->u.caub.cElems) + if(cb > propvarIn->caub.cElems) return E_FAIL; - memcpy(ret, propvarIn->u.caub.pElems, cb); + memcpy(ret, propvarIn->caub.pElems, cb); break; case VT_ARRAY|VT_UI1: FIXME("Unsupported type: VT_ARRAY|VT_UI1\n"); @@ -328,7 +380,6 @@ HRESULT WINAPI PropVariantToBuffer(REFPROPVARIANT propvarIn, void *ret, UINT cb) return hr; } - HRESULT WINAPI PropVariantToString(REFPROPVARIANT propvarIn, PWSTR ret, UINT cch) { HRESULT hr; @@ -369,27 +420,36 @@ HRESULT WINAPI PropVariantToStringAlloc(REFPROPVARIANT propvarIn, WCHAR **ret) break; case VT_LPSTR: - if(propvarIn->u.pszVal) + if(propvarIn->pszVal) { DWORD len; - len = MultiByteToWideChar(CP_ACP, 0, propvarIn->u.pszVal, -1, NULL, 0); + len = MultiByteToWideChar(CP_ACP, 0, propvarIn->pszVal, -1, NULL, 0); res = CoTaskMemAlloc(len*sizeof(WCHAR)); if(!res) return E_OUTOFMEMORY; - MultiByteToWideChar(CP_ACP, 0, propvarIn->u.pszVal, -1, res, len); + MultiByteToWideChar(CP_ACP, 0, propvarIn->pszVal, -1, res, len); } break; case VT_LPWSTR: case VT_BSTR: - if (propvarIn->u.pwszVal) + if (propvarIn->pwszVal) { - DWORD size = (lstrlenW(propvarIn->u.pwszVal) + 1) * sizeof(WCHAR); + DWORD size = (lstrlenW(propvarIn->pwszVal) + 1) * sizeof(WCHAR); res = CoTaskMemAlloc(size); if(!res) return E_OUTOFMEMORY; - memcpy(res, propvarIn->u.pwszVal, size); + memcpy(res, propvarIn->pwszVal, size); + } + break; + + case VT_CLSID: + if (propvarIn->puuid) + { + if (!(res = CoTaskMemAlloc((GUID_STR_LEN + 1) * sizeof(WCHAR)))) + return E_OUTOFMEMORY; + StringFromGUID2(propvarIn->puuid, res, GUID_STR_LEN + 1); } break; @@ -406,21 +466,70 @@ HRESULT WINAPI PropVariantToStringAlloc(REFPROPVARIANT propvarIn, WCHAR **ret) PCWSTR WINAPI PropVariantToStringWithDefault(REFPROPVARIANT propvarIn, LPCWSTR pszDefault) { - static const WCHAR str_empty[] = {0}; if (propvarIn->vt == VT_BSTR) { - if (propvarIn->u.bstrVal == NULL) - return str_empty; + if (propvarIn->bstrVal == NULL) + return L""; - return propvarIn->u.bstrVal; + return propvarIn->bstrVal; } - if (propvarIn->vt == VT_LPWSTR && propvarIn->u.pwszVal != NULL) - return propvarIn->u.pwszVal; + if (propvarIn->vt == VT_LPWSTR && propvarIn->pwszVal != NULL) + return propvarIn->pwszVal; return pszDefault; } +/****************************************************************** + * VariantToStringWithDefault (PROPSYS.@) + */ +PCWSTR WINAPI VariantToStringWithDefault(const VARIANT *pvar, const WCHAR *default_value) +{ + TRACE("%s, %s.\n", debugstr_variant(pvar), debugstr_w(default_value)); + + if (V_VT(pvar) == (VT_BYREF | VT_VARIANT)) pvar = V_VARIANTREF(pvar); + if (V_VT(pvar) == (VT_BYREF | VT_BSTR) || V_VT(pvar) == VT_BSTR) + { + BSTR ret = V_ISBYREF(pvar) ? *V_BSTRREF(pvar) : V_BSTR(pvar); + return ret ? ret : L""; + } + + return default_value; +} + +/****************************************************************** + * VariantToString (PROPSYS.@) + */ +HRESULT WINAPI VariantToString(REFVARIANT var, PWSTR ret, UINT cch) +{ + WCHAR buffer[64], *str = buffer; + + TRACE("%p, %p, %u.\n", var, ret, cch); + + *ret = 0; + + if (!cch) + return E_INVALIDARG; + + switch (V_VT(var)) + { + case VT_BSTR: + str = V_BSTR(var); + break; + case VT_I4: + swprintf(buffer, ARRAY_SIZE(buffer), L"%d", V_I4(var)); + break; + default: + FIXME("Unsupported type %d.\n", V_VT(var)); + return E_NOTIMPL; + } + + if (wcslen(str) > cch - 1) + return STRSAFE_E_INSUFFICIENT_BUFFER; + wcscpy(ret, str); + + return S_OK; +} /****************************************************************** * PropVariantChangeType (PROPSYS.@) @@ -437,7 +546,7 @@ HRESULT WINAPI PropVariantChangeType(PROPVARIANT *ppropvarDest, REFPROPVARIANT p return PropVariantCopy(ppropvarDest, propvarSrc); if (propvarSrc->vt == VT_FILETIME) - return PROPVAR_ConvertFILETIME(&propvarSrc->u.filetime, ppropvarDest, vt); + return PROPVAR_ConvertFILETIME(&propvarSrc->filetime, ppropvarDest, vt); switch (vt) { @@ -449,7 +558,7 @@ HRESULT WINAPI PropVariantChangeType(PROPVARIANT *ppropvarDest, REFPROPVARIANT p if (SUCCEEDED(hr)) { ppropvarDest->vt = VT_I1; - ppropvarDest->u.cVal = (char)res; + ppropvarDest->cVal = (char)res; } return hr; } @@ -462,7 +571,7 @@ HRESULT WINAPI PropVariantChangeType(PROPVARIANT *ppropvarDest, REFPROPVARIANT p if (SUCCEEDED(hr)) { ppropvarDest->vt = VT_UI1; - ppropvarDest->u.bVal = (UCHAR)res; + ppropvarDest->bVal = (UCHAR)res; } return hr; } @@ -474,7 +583,7 @@ HRESULT WINAPI PropVariantChangeType(PROPVARIANT *ppropvarDest, REFPROPVARIANT p if (SUCCEEDED(hr)) { ppropvarDest->vt = VT_I2; - ppropvarDest->u.iVal = res; + ppropvarDest->iVal = res; } return hr; } @@ -485,7 +594,7 @@ HRESULT WINAPI PropVariantChangeType(PROPVARIANT *ppropvarDest, REFPROPVARIANT p if (SUCCEEDED(hr)) { ppropvarDest->vt = VT_UI2; - ppropvarDest->u.uiVal = res; + ppropvarDest->uiVal = res; } return hr; } @@ -496,7 +605,7 @@ HRESULT WINAPI PropVariantChangeType(PROPVARIANT *ppropvarDest, REFPROPVARIANT p if (SUCCEEDED(hr)) { ppropvarDest->vt = VT_I4; - ppropvarDest->u.lVal = res; + ppropvarDest->lVal = res; } return hr; } @@ -507,7 +616,7 @@ HRESULT WINAPI PropVariantChangeType(PROPVARIANT *ppropvarDest, REFPROPVARIANT p if (SUCCEEDED(hr)) { ppropvarDest->vt = VT_UI4; - ppropvarDest->u.ulVal = res; + ppropvarDest->ulVal = res; } return hr; } @@ -518,7 +627,7 @@ HRESULT WINAPI PropVariantChangeType(PROPVARIANT *ppropvarDest, REFPROPVARIANT p if (SUCCEEDED(hr)) { ppropvarDest->vt = VT_I8; - ppropvarDest->u.hVal.QuadPart = res; + ppropvarDest->hVal.QuadPart = res; } return hr; } @@ -529,7 +638,7 @@ HRESULT WINAPI PropVariantChangeType(PROPVARIANT *ppropvarDest, REFPROPVARIANT p if (SUCCEEDED(hr)) { ppropvarDest->vt = VT_UI8; - ppropvarDest->u.uhVal.QuadPart = res; + ppropvarDest->uhVal.QuadPart = res; } return hr; } @@ -542,7 +651,7 @@ HRESULT WINAPI PropVariantChangeType(PROPVARIANT *ppropvarDest, REFPROPVARIANT p if (SUCCEEDED(hr)) { ppropvarDest->vt = VT_LPWSTR; - ppropvarDest->u.pwszVal = res; + ppropvarDest->pwszVal = res; } return hr; } @@ -562,7 +671,7 @@ HRESULT WINAPI PropVariantChangeType(PROPVARIANT *ppropvarDest, REFPROPVARIANT p { WideCharToMultiByte(CP_ACP, 0, resW, -1, res, len, NULL, NULL); ppropvarDest->vt = VT_LPSTR; - ppropvarDest->u.pszVal = res; + ppropvarDest->pszVal = res; } else hr = E_OUTOFMEMORY; @@ -577,18 +686,6 @@ HRESULT WINAPI PropVariantChangeType(PROPVARIANT *ppropvarDest, REFPROPVARIANT p return E_FAIL; } } - -static void PROPVAR_GUIDToWSTR(REFGUID guid, WCHAR *str) -{ - static const WCHAR format[] = {'{','%','0','8','X','-','%','0','4','X','-','%','0','4','X', - '-','%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X', - '%','0','2','X','%','0','2','X','%','0','2','X','}',0}; - - swprintf(str, format, guid->Data1, guid->Data2, guid->Data3, - guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], - guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]); -} - HRESULT WINAPI InitPropVariantFromGUIDAsString(REFGUID guid, PROPVARIANT *ppropvar) { TRACE("(%p %p)\n", guid, ppropvar); @@ -597,11 +694,11 @@ HRESULT WINAPI InitPropVariantFromGUIDAsString(REFGUID guid, PROPVARIANT *ppropv return E_FAIL; ppropvar->vt = VT_LPWSTR; - ppropvar->u.pwszVal = CoTaskMemAlloc(39*sizeof(WCHAR)); - if(!ppropvar->u.pwszVal) + ppropvar->pwszVal = CoTaskMemAlloc((GUID_STR_LEN + 1) * sizeof(WCHAR)); + if(!ppropvar->pwszVal) return E_OUTOFMEMORY; - PROPVAR_GUIDToWSTR(guid, ppropvar->u.pwszVal); + StringFromGUID2(guid, ppropvar->pwszVal, GUID_STR_LEN + 1); return S_OK; } @@ -615,11 +712,11 @@ HRESULT WINAPI InitVariantFromGUIDAsString(REFGUID guid, VARIANT *pvar) } V_VT(pvar) = VT_BSTR; - V_BSTR(pvar) = SysAllocStringLen(NULL, 38); + V_BSTR(pvar) = SysAllocStringLen(NULL, GUID_STR_LEN); if(!V_BSTR(pvar)) return E_OUTOFMEMORY; - PROPVAR_GUIDToWSTR(guid, V_BSTR(pvar)); + StringFromGUID2(guid, V_BSTR(pvar), GUID_STR_LEN + 1); return S_OK; } @@ -627,13 +724,13 @@ HRESULT WINAPI InitPropVariantFromBuffer(const VOID *pv, UINT cb, PROPVARIANT *p { TRACE("(%p %u %p)\n", pv, cb, ppropvar); - ppropvar->u.caub.pElems = CoTaskMemAlloc(cb); - if(!ppropvar->u.caub.pElems) + ppropvar->caub.pElems = CoTaskMemAlloc(cb); + if(!ppropvar->caub.pElems) return E_OUTOFMEMORY; ppropvar->vt = VT_VECTOR|VT_UI1; - ppropvar->u.caub.cElems = cb; - memcpy(ppropvar->u.caub.pElems, pv, cb); + ppropvar->caub.cElems = cb; + memcpy(ppropvar->caub.pElems, pv, cb); return S_OK; } @@ -641,12 +738,44 @@ HRESULT WINAPI InitPropVariantFromCLSID(REFCLSID clsid, PROPVARIANT *ppropvar) { TRACE("(%s %p)\n", debugstr_guid(clsid), ppropvar); - ppropvar->u.puuid = CoTaskMemAlloc(sizeof(*ppropvar->u.puuid)); - if(!ppropvar->u.puuid) + ppropvar->puuid = CoTaskMemAlloc(sizeof(*ppropvar->puuid)); + if(!ppropvar->puuid) return E_OUTOFMEMORY; ppropvar->vt = VT_CLSID; - memcpy(ppropvar->u.puuid, clsid, sizeof(*ppropvar->u.puuid)); + memcpy(ppropvar->puuid, clsid, sizeof(*ppropvar->puuid)); + return S_OK; +} + +HRESULT WINAPI InitPropVariantFromStringVector(PCWSTR *strs, ULONG count, PROPVARIANT *ppropvar) +{ + unsigned int i; + + TRACE("(%p %lu %p)\n", strs, count, ppropvar); + + ppropvar->calpwstr.pElems = CoTaskMemAlloc(count * sizeof(*ppropvar->calpwstr.pElems)); + if(!ppropvar->calpwstr.pElems) + return E_OUTOFMEMORY; + + ppropvar->vt = VT_LPWSTR | VT_VECTOR; + ppropvar->calpwstr.cElems = 0; + if (count) + memset(ppropvar->calpwstr.pElems, 0, count * sizeof(*ppropvar->calpwstr.pElems)); + + for (i = 0; i < count; ++i) + { + if (strs[i]) + { + if (!(ppropvar->calpwstr.pElems[i] = CoTaskMemAlloc((wcslen(strs[i]) + 1)*sizeof(**strs)))) + { + PropVariantClear(ppropvar); + return E_OUTOFMEMORY; + } + } + wcscpy(ppropvar->calpwstr.pElems[i], strs[i]); + ppropvar->calpwstr.cElems++; + } + return S_OK; } @@ -681,6 +810,21 @@ HRESULT WINAPI InitVariantFromBuffer(const VOID *pv, UINT cb, VARIANT *pvar) return S_OK; } +HRESULT WINAPI InitVariantFromFileTime(const FILETIME *ft, VARIANT *var) +{ + SYSTEMTIME st; + + TRACE("%p, %p\n", ft, var); + + VariantInit(var); + if (!FileTimeToSystemTime(ft, &st)) + return E_INVALIDARG; + if (!SystemTimeToVariantTime(&st, &V_DATE(var))) + return E_INVALIDARG; + V_VT(var) = VT_DATE; + return S_OK; +} + static inline DWORD PROPVAR_HexToNum(const WCHAR *hex) { DWORD ret; @@ -759,11 +903,11 @@ HRESULT WINAPI PropVariantToGUID(const PROPVARIANT *ppropvar, GUID *guid) switch(ppropvar->vt) { case VT_BSTR: - return PROPVAR_WCHARToGUID(ppropvar->u.bstrVal, SysStringLen(ppropvar->u.bstrVal), guid); + return PROPVAR_WCHARToGUID(ppropvar->bstrVal, SysStringLen(ppropvar->bstrVal), guid); case VT_LPWSTR: - return PROPVAR_WCHARToGUID(ppropvar->u.pwszVal, lstrlenW(ppropvar->u.pwszVal), guid); + return PROPVAR_WCHARToGUID(ppropvar->pwszVal, lstrlenW(ppropvar->pwszVal), guid); case VT_CLSID: - memcpy(guid, ppropvar->u.puuid, sizeof(*ppropvar->u.puuid)); + memcpy(guid, ppropvar->puuid, sizeof(*ppropvar->puuid)); return S_OK; default: @@ -797,17 +941,20 @@ static BOOL isemptyornull(const PROPVARIANT *propvar) if ((propvar->vt & VT_ARRAY) == VT_ARRAY) { int i; - for (i=0; i<propvar->u.parray->cDims; i++) + for (i=0; i<propvar->parray->cDims; i++) { - if (propvar->u.parray->rgsabound[i].cElements != 0) + if (propvar->parray->rgsabound[i].cElements != 0) break; } - return i == propvar->u.parray->cDims; + return i == propvar->parray->cDims; } if (propvar->vt == VT_CLSID) - return !propvar->u.puuid; + return !propvar->puuid; + + if (propvar->vt & VT_VECTOR) + return !propvar->caub.cElems; - /* FIXME: vectors, byrefs, errors? */ + /* FIXME: byrefs, errors? */ return FALSE; } @@ -816,6 +963,7 @@ INT WINAPI PropVariantCompareEx(REFPROPVARIANT propvar1, REFPROPVARIANT propvar2 { const PROPVARIANT *propvar2_converted; PROPVARIANT propvar2_static; + unsigned int count; HRESULT hr; INT res=-1; @@ -844,9 +992,9 @@ INT WINAPI PropVariantCompareEx(REFPROPVARIANT propvar1, REFPROPVARIANT propvar2 propvar2_converted = propvar2; #define CMP_NUM_VALUE(var) do { \ - if (propvar1->u.var > propvar2_converted->u.var) \ + if (propvar1->var > propvar2_converted->var) \ res = 1; \ - else if (propvar1->u.var < propvar2_converted->u.var) \ + else if (propvar1->var < propvar2_converted->var) \ res = -1; \ else \ res = 0; \ @@ -870,7 +1018,7 @@ INT WINAPI PropVariantCompareEx(REFPROPVARIANT propvar1, REFPROPVARIANT propvar2 CMP_NUM_VALUE(lVal); break; case VT_UI4: - CMP_NUM_VALUE(uiVal); + CMP_NUM_VALUE(ulVal); break; case VT_I8: CMP_NUM_VALUE(hVal.QuadPart); @@ -888,20 +1036,27 @@ INT WINAPI PropVariantCompareEx(REFPROPVARIANT propvar1, REFPROPVARIANT propvar2 case VT_LPWSTR: /* FIXME: Use other string flags. */ if (flags & (PVCF_USESTRCMPI | PVCF_USESTRCMPIC)) - res = lstrcmpiW(propvar1->u.bstrVal, propvar2_converted->u.bstrVal); + res = lstrcmpiW(propvar1->bstrVal, propvar2_converted->bstrVal); else - res = lstrcmpW(propvar1->u.bstrVal, propvar2_converted->u.bstrVal); + res = lstrcmpW(propvar1->bstrVal, propvar2_converted->bstrVal); break; case VT_LPSTR: /* FIXME: Use other string flags. */ if (flags & (PVCF_USESTRCMPI | PVCF_USESTRCMPIC)) - res = lstrcmpiA(propvar1->u.pszVal, propvar2_converted->u.pszVal); + res = lstrcmpiA(propvar1->pszVal, propvar2_converted->pszVal); else - res = lstrcmpA(propvar1->u.pszVal, propvar2_converted->u.pszVal); + res = lstrcmpA(propvar1->pszVal, propvar2_converted->pszVal); break; case VT_CLSID: - res = memcmp(propvar1->u.puuid, propvar2->u.puuid, sizeof(*propvar1->u.puuid)); + res = memcmp(propvar1->puuid, propvar2->puuid, sizeof(*propvar1->puuid)); + if (res) res = res > 0 ? 1 : -1; + break; + case VT_VECTOR | VT_UI1: + count = min(propvar1->caub.cElems, propvar2->caub.cElems); + res = count ? memcmp(propvar1->caub.pElems, propvar2->caub.pElems, sizeof(*propvar1->caub.pElems) * count) : 0; if (res) res = res > 0 ? 1 : -1; + if (!res && propvar1->caub.cElems != propvar2->caub.cElems) + res = propvar1->caub.cElems > propvar2->caub.cElems ? 1 : -1; break; default: FIXME("vartype %#x not handled\n", propvar1->vt); @@ -914,3 +1069,158 @@ INT WINAPI PropVariantCompareEx(REFPROPVARIANT propvar1, REFPROPVARIANT propvar2 return res; } + +HRESULT WINAPI PropVariantToVariant(const PROPVARIANT *propvar, VARIANT *var) +{ + HRESULT hr = S_OK; + + TRACE("propvar %p, var %p, propvar->vt %#x.\n", propvar, var, propvar ? propvar->vt : 0); + + if (!var || !propvar) + return E_INVALIDARG; + + VariantInit(var); +#ifdef __REACTOS__ + V_VT(var) = propvar->vt; +#else + var->vt = propvar->vt; +#endif + + switch (propvar->vt) + { + case VT_EMPTY: + case VT_NULL: + break; + case VT_I1: + V_I1(var) = propvar->cVal; + break; + case VT_I2: + V_I2(var) = propvar->iVal; + break; + case VT_I4: + V_I4(var) = propvar->lVal; + break; + case VT_I8: + V_I8(var) = propvar->hVal.QuadPart; + break; + case VT_UI1: + V_UI1(var) = propvar->bVal; + break; + case VT_UI2: + V_UI2(var) = propvar->uiVal; + break; + case VT_UI4: + V_UI4(var) = propvar->ulVal; + break; + case VT_UI8: + V_UI8(var) = propvar->uhVal.QuadPart; + break; + case VT_BOOL: + V_BOOL(var) = propvar->boolVal; + break; + case VT_R4: + V_R4(var) = propvar->fltVal; + break; + case VT_R8: + V_R8(var) = propvar->dblVal; + break; + case VT_LPSTR: + case VT_LPWSTR: + case VT_BSTR: + case VT_CLSID: +#ifdef __REACTOS__ + V_VT(var) = VT_BSTR; +#else + var->vt = VT_BSTR; +#endif + hr = PropVariantToBSTR(propvar, &V_BSTR(var)); + break; + default: + FIXME("Unsupported type %d.\n", propvar->vt); + return E_INVALIDARG; + } + + return hr; +} + +HRESULT WINAPI VariantToPropVariant(const VARIANT *var, PROPVARIANT *propvar) +{ + HRESULT hr; + + TRACE("var %p, propvar %p.\n", debugstr_variant(var), propvar); + + if (!var || !propvar) + return E_INVALIDARG; + +#ifdef __REACTOS__ + if (FAILED(hr = VARIANT_ValidateType(V_VT(var)))) +#else + if (FAILED(hr = VARIANT_ValidateType(var->vt))) +#endif + return hr; + + PropVariantInit(propvar); + + +#ifdef __REACTOS__ + propvar->vt = V_VT(var); +#else + propvar->vt = var->vt; +#endif + +#ifdef __REACTOS__ + switch (V_VT(var)) +#else + switch (var->vt) +#endif + { + case VT_EMPTY: + case VT_NULL: + break; + case VT_I1: + propvar->cVal = V_I1(var); + break; + case VT_I2: + propvar->iVal = V_I2(var); + break; + case VT_I4: + propvar->lVal = V_I4(var); + break; + case VT_I8: + propvar->hVal.QuadPart = V_I8(var); + break; + case VT_UI1: + propvar->bVal = V_UI1(var); + break; + case VT_UI2: + propvar->uiVal = V_UI2(var); + break; + case VT_UI4: + propvar->ulVal = V_UI4(var); + break; + case VT_UI8: + propvar->uhVal.QuadPart = V_UI8(var); + break; + case VT_BOOL: + propvar->boolVal = V_BOOL(var); + break; + case VT_R4: + propvar->fltVal = V_R4(var); + break; + case VT_R8: + propvar->dblVal = V_R8(var); + break; + case VT_BSTR: + propvar->bstrVal = SysAllocString(V_BSTR(var)); + break; + default: +#ifdef __REACTOS__ + FIXME("Unsupported type %d.\n", V_VT(var)); +#else + FIXME("Unsupported type %d.\n", var->vt); +#endif + return E_INVALIDARG; + } + + return S_OK; +} diff --git a/media/doc/WINESYNC.txt b/media/doc/WINESYNC.txt index 203f7ae3333..2b000140713 100644 --- a/media/doc/WINESYNC.txt +++ b/media/doc/WINESYNC.txt @@ -160,7 +160,7 @@ dll/win32/pdh # Synced to WineStaging-4.18 dll/win32/pidgen # Synced to WineStaging-4.18 dll/win32/powrprof # Forked at Wine-1.0rc5 dll/win32/printui # Synced to WineStaging-4.18 -dll/win32/propsys # Synced to WineStaging-4.18 +dll/win32/propsys # Synced to Wine-10.0 dll/win32/pstorec # Synced to WineStaging-3.3 dll/win32/qmgr # Synced to WineStaging-4.18 dll/win32/qmgrprxy # Synced to WineStaging-2.9 diff --git a/modules/rostests/winetests/propsys/CMakeLists.txt b/modules/rostests/winetests/propsys/CMakeLists.txt index ac14259b769..a38b9654b9d 100644 --- a/modules/rostests/winetests/propsys/CMakeLists.txt +++ b/modules/rostests/winetests/propsys/CMakeLists.txt @@ -1,6 +1,7 @@ add_definitions(-DUSE_WINE_TODOS -DWINETEST_USE_DBGSTR_LONGLONG) -add_executable(propsys_winetest propstore.c propsys.c testlist.c) +remove_definitions(-D__ROS_LONG64__) +add_executable(propsys_winetest propsys.c testlist.c) set_module_type(propsys_winetest win32cui) add_importlibs(propsys_winetest propsys ole32 oleaut32 msvcrt kernel32) diff --git a/modules/rostests/winetests/propsys/propstore.c b/modules/rostests/winetests/propsys/propstore.c deleted file mode 100644 index 5aeb562cf27..00000000000 --- a/modules/rostests/winetests/propsys/propstore.c +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Unit tests for IPropertyStore and related interfaces - * - * Copyright 2012 Vincent Povirk - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#define COBJMACROS - -#include <stdarg.h> -#include <stdio.h> - -#define NONAMELESSUNION - -#include "windef.h" -#include "winbase.h" -#include "objbase.h" -#include "propsys.h" -#include "wine/test.h" - -#include "initguid.h" - -DEFINE_GUID(PKEY_WineTest, 0x7b317433, 0xdfa3, 0x4c44, 0xad, 0x3e, 0x2f, 0x80, 0x4b, 0x90, 0xdb, 0xf4); -DEFINE_GUID(DUMMY_GUID1, 0x12345678, 0x1234,0x1234, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19); - -#define EXPECT_REF(obj,ref) _expect_ref((IUnknown *)obj, ref, __LINE__) -static void _expect_ref(IUnknown *obj, ULONG ref, int line) -{ - ULONG rc; - IUnknown_AddRef(obj); - rc = IUnknown_Release(obj); - ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc); -} - -static void test_inmemorystore(void) -{ - IPropertyStoreCache *propcache; - HRESULT hr; - PROPERTYKEY pkey; - PROPVARIANT propvar; - DWORD count; - PSC_STATE state; - - hr = CoCreateInstance(&CLSID_InMemoryPropertyStore, NULL, CLSCTX_INPROC_SERVER, - &IID_IPropertyStoreCache, (void**)&propcache); - ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr); - - if (FAILED(hr)) - { - skip("CLSID_InMemoryPropertyStore not supported\n"); - return; - } - - hr = IPropertyStoreCache_GetCount(propcache, NULL); - ok(hr == E_POINTER, "GetCount failed, hr=%x\n", hr); - - hr = IPropertyStoreCache_GetCount(propcache, &count); - ok(hr == S_OK, "GetCount failed, hr=%x\n", hr); - ok(count == 0, "GetCount returned %i, expected 0\n", count); - - hr = IPropertyStoreCache_Commit(propcache); - ok(hr == S_OK, "Commit failed, hr=%x\n", hr); - - hr = IPropertyStoreCache_Commit(propcache); - ok(hr == S_OK, "Commit failed, hr=%x\n", hr); - - hr = IPropertyStoreCache_GetAt(propcache, 0, &pkey); - ok(hr == E_INVALIDARG, "GetAt failed, hr=%x\n", hr); - - pkey.fmtid = PKEY_WineTest; - pkey.pid = 4; - - memset(&propvar, 0, sizeof(propvar)); - propvar.vt = VT_I4; - propvar.u.lVal = 12345; - - if (0) - { - /* Crashes on Windows 7 */ - hr = IPropertyStoreCache_SetValue(propcache, NULL, &propvar); - ok(hr == E_POINTER, "SetValue failed, hr=%x\n", hr); - - hr = IPropertyStoreCache_SetValue(propcache, &pkey, NULL); - ok(hr == E_POINTER, "SetValue failed, hr=%x\n", hr); - } - - hr = IPropertyStoreCache_SetValue(propcache, &pkey, &propvar); - ok(hr == S_OK, "SetValue failed, hr=%x\n", hr); - - hr = IPropertyStoreCache_GetCount(propcache, &count); - ok(hr == S_OK, "GetCount failed, hr=%x\n", hr); - ok(count == 1, "GetCount returned %i, expected 0\n", count); - - memset(&pkey, 0, sizeof(pkey)); - - hr = IPropertyStoreCache_GetAt(propcache, 0, &pkey); - ok(hr == S_OK, "GetAt failed, hr=%x\n", hr); - ok(IsEqualGUID(&pkey.fmtid, &PKEY_WineTest), "got wrong pkey\n"); - ok(pkey.pid == 4, "got pid of %i, expected 4\n", pkey.pid); - - pkey.fmtid = PKEY_WineTest; - pkey.pid = 4; - - memset(&propvar, 0, sizeof(propvar)); - - if (0) - { - /* Crashes on Windows 7 */ - hr = IPropertyStoreCache_GetValue(propcache, NULL, &propvar); - ok(hr == E_POINTER, "GetValue failed, hr=%x\n", hr); - } - - hr = IPropertyStoreCache_GetValue(propcache, &pkey, NULL); - ok(hr == E_POINTER, "GetValue failed, hr=%x\n", hr); - - hr = IPropertyStoreCache_GetValue(propcache, &pkey, &propvar); - ok(hr == S_OK, "GetValue failed, hr=%x\n", hr); - ok(propvar.vt == VT_I4, "expected VT_I4, got %d\n", propvar.vt); - ok(propvar.u.lVal == 12345, "expected 12345, got %d\n", propvar.u.lVal); - - pkey.fmtid = PKEY_WineTest; - pkey.pid = 10; - - /* Get information for field that isn't set yet */ - propvar.vt = VT_I2; - hr = IPropertyStoreCache_GetValue(propcache, &pkey, &propvar); - ok(hr == S_OK, "GetValue failed, hr=%x\n", hr); - ok(propvar.vt == VT_EMPTY, "expected VT_EMPTY, got %d\n", propvar.vt); - - state = 0xdeadbeef; - hr = IPropertyStoreCache_GetState(propcache, &pkey, &state); - ok(hr == TYPE_E_ELEMENTNOTFOUND, "GetState failed, hr=%x\n", hr); - ok(state == PSC_NORMAL, "expected PSC_NORMAL, got %d\n", state); - - propvar.vt = VT_I2; - state = 0xdeadbeef; - hr = IPropertyStoreCache_GetValueAndState(propcache, &pkey, &propvar, &state); - ok(hr == TYPE_E_ELEMENTNOTFOUND, "GetValueAndState failed, hr=%x\n", hr); - ok(propvar.vt == VT_EMPTY, "expected VT_EMPTY, got %d\n", propvar.vt); - ok(state == PSC_NORMAL, "expected PSC_NORMAL, got %d\n", state); - - /* Set state on an unset field */ - hr = IPropertyStoreCache_SetState(propcache, &pkey, PSC_NORMAL); - ok(hr == TYPE_E_ELEMENTNOTFOUND, "SetState failed, hr=%x\n", hr); - - /* Manipulate state on already set field */ - pkey.fmtid = PKEY_WineTest; - pkey.pid = 4; - - state = 0xdeadbeef; - hr = IPropertyStoreCache_GetState(propcache, &pkey, &state); - ok(hr == S_OK, "GetState failed, hr=%x\n", hr); - ok(state == PSC_NORMAL, "expected PSC_NORMAL, got %d\n", state); - - hr = IPropertyStoreCache_SetState(propcache, &pkey, 10); - ok(hr == S_OK, "SetState failed, hr=%x\n", hr); - - state = 0xdeadbeef; - hr = IPropertyStoreCache_GetState(propcache, &pkey, &state); - ok(hr == S_OK, "GetState failed, hr=%x\n", hr); - ok(state == 10, "expected 10, got %d\n", state); - - propvar.vt = VT_I4; - propvar.u.lVal = 12346; - hr = IPropertyStoreCache_SetValueAndState(propcache, &pkey, &propvar, 5); - ok(hr == S_OK, "SetValueAndState failed, hr=%x\n", hr); - - memset(&propvar, 0, sizeof(propvar)); - state = 0xdeadbeef; - hr = IPropertyStoreCache_GetValueAndState(propcache, &pkey, &propvar, &state); - ok(hr == S_OK, "GetValueAndState failed, hr=%x\n", hr); - ok(propvar.vt == VT_I4, "expected VT_I4, got %d\n", propvar.vt); - ok(propvar.u.lVal == 12346, "expected 12346, got %d\n", propvar.vt); - ok(state == 5, "expected 5, got %d\n", state); - - /* Set new field with state */ - pkey.fmtid = PKEY_WineTest; - pkey.pid = 8; - - propvar.vt = VT_I4; - propvar.u.lVal = 12347; - hr = IPropertyStoreCache_SetValueAndState(propcache, &pkey, &propvar, PSC_DIRTY); - ok(hr == S_OK, "SetValueAndState failed, hr=%x\n", hr); - - memset(&propvar, 0, sizeof(propvar)); - state = 0xdeadbeef; - hr = IPropertyStoreCache_GetValueAndState(propcache, &pkey, &propvar, &state); - ok(hr == S_OK, "GetValueAndState failed, hr=%x\n", hr); - ok(propvar.vt == VT_I4, "expected VT_I4, got %d\n", propvar.vt); - ok(propvar.u.lVal == 12347, "expected 12347, got %d\n", propvar.vt); - ok(state == PSC_DIRTY, "expected PSC_DIRTY, got %d\n", state); - - IPropertyStoreCache_Release(propcache); -} - -static void test_persistserialized(void) -{ - IPropertyStore *propstore; - IPersistSerializedPropStorage *serialized; - HRESULT hr; - SERIALIZEDPROPSTORAGE *result; - DWORD result_size; - - hr = CoCreateInstance(&CLSID_InMemoryPropertyStore, NULL, CLSCTX_INPROC_SERVER, - &IID_IPropertyStore, (void**)&propstore); - ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr); - - hr = IPropertyStore_QueryInterface(propstore, &IID_IPersistSerializedPropStorage, - (void**)&serialized); - todo_wine ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr); - - if (FAILED(hr)) - { - IPropertyStore_Release(propstore); - skip("IPersistSerializedPropStorage not supported\n"); - return; - } - - hr = IPersistSerializedPropStorage_GetPropertyStorage(serialized, NULL, &result_size); - ok(hr == E_POINTER, "GetPropertyStorage failed, hr=%x\n", hr); - - hr = IPersistSerializedPropStorage_GetPropertyStorage(serialized, &result, NULL); - ok(hr == E_POINTER, "GetPropertyStorage failed, hr=%x\n", hr); - - hr = IPersistSerializedPropStorage_GetPropertyStorage(serialized, &result, &result_size); - ok(hr == S_OK, "GetPropertyStorage failed, hr=%x\n", hr); - - if (SUCCEEDED(hr)) - { - ok(result_size == 0, "expected 0 bytes, got %i\n", result_size); - - CoTaskMemFree(result); - } - - hr = IPersistSerializedPropStorage_SetPropertyStorage(serialized, NULL, 4); - ok(hr == E_POINTER, "SetPropertyStorage failed, hr=%x\n", hr); - - hr = IPersistSerializedPropStorage_SetPropertyStorage(serialized, NULL, 0); - ok(hr == S_OK, "SetPropertyStorage failed, hr=%x\n", hr); - - hr = IPropertyStore_GetCount(propstore, &result_size); - ok(hr == S_OK, "GetCount failed, hr=%x\n", hr); - ok(result_size == 0, "expecting 0, got %d\n", result_size); - - IPropertyStore_Release(propstore); - IPersistSerializedPropStorage_Release(serialized); -} - -static void test_PSCreateMemoryPropertyStore(void) -{ - IPropertyStore *propstore, *propstore1; - IPersistSerializedPropStorage *serialized; - IPropertyStoreCache *propstorecache; - HRESULT hr; - - /* PSCreateMemoryPropertyStore(&IID_IPropertyStore, NULL); crashes */ - - hr = PSCreateMemoryPropertyStore(&IID_IPropertyStore, (void **)&propstore); - ok(hr == S_OK, "PSCreateMemoryPropertyStore failed: 0x%08x.\n", hr); - ok(propstore != NULL, "got %p.\n", propstore); - EXPECT_REF(propstore, 1); - - hr = PSCreateMemoryPropertyStore(&IID_IPersistSerializedPropStorage, (void **)&serialized); - todo_wine ok(hr == S_OK, "PSCreateMemoryPropertyStore failed: 0x%08x.\n", hr); - todo_wine ok(serialized != NULL, "got %p.\n", serialized); - EXPECT_REF(propstore, 1); - if(serialized) - { - EXPECT_REF(serialized, 1); - IPersistSerializedPropStorage_Release(serialized); - } - - hr = PSCreateMemoryPropertyStore(&IID_IPropertyStoreCache, (void **)&propstorecache); - ok(hr == S_OK, "PSCreateMemoryPropertyStore failed: 0x%08x.\n", hr); - ok(propstorecache != NULL, "got %p.\n", propstore); - ok(propstorecache != (IPropertyStoreCache *)propstore, "pointer are equal: %p, %p.\n", propstorecache, propstore); - EXPECT_REF(propstore, 1); - EXPECT_REF(propstorecache, 1); - - hr = PSCreateMemoryPropertyStore(&IID_IPropertyStore, (void **)&propstore1); - ok(hr == S_OK, "PSCreateMemoryPropertyStore failed: 0x%08x.\n", hr); - ok(propstore1 != NULL, "got %p.\n", propstore); - ok(propstore1 != propstore, "pointer are equal: %p, %p.\n", propstore1, propstore); - EXPECT_REF(propstore, 1); - EXPECT_REF(propstore1, 1); - EXPECT_REF(propstorecache, 1); - - IPropertyStore_Release(propstore1); - IPropertyStore_Release(propstore); - IPropertyStoreCache_Release(propstorecache); -} - -static void test_propertystore(void) -{ - IPropertyStore *propstore; - HRESULT hr; - PROPVARIANT propvar, ret_propvar; - PROPERTYKEY propkey; - DWORD count = 0; - - hr = PSCreateMemoryPropertyStore(&IID_IPropertyStore, (void **)&propstore); - ok(hr == S_OK, "PSCreateMemoryPropertyStore failed: 0x%08x.\n", hr); - ok(propstore != NULL, "got %p.\n", propstore); - - hr = IPropertyStore_GetCount(propstore, &count); - ok(hr == S_OK, "IPropertyStore_GetCount failed: 0x%08x.\n", hr); - ok(!count, "got wrong property count: %d, expected 0.\n", count); - - PropVariantInit(&propvar); - propvar.vt = VT_I4; - U(propvar).lVal = 123; - propkey.fmtid = DUMMY_GUID1; - propkey.pid = PID_FIRST_USABLE; - hr = IPropertyStore_SetValue(propstore, &propkey, &propvar); - ok(hr == S_OK, "IPropertyStore_SetValue failed: 0x%08x.\n", hr); - hr = IPropertyStore_Commit(propstore); - ok(hr == S_OK, "IPropertyStore_Commit failed: 0x%08x.\n", hr); - hr = IPropertyStore_GetCount(propstore, &count); - ok(hr == S_OK, "IPropertyStore_GetCount failed: 0x%08x.\n", hr); - ok(count == 1, "got wrong property count: %d, expected 1.\n", count); - PropVariantInit(&ret_propvar); - ret_propvar.vt = VT_I4; - hr = IPropertyStore_GetValue(propstore, &propkey, &ret_propvar); - ok(hr == S_OK, "IPropertyStore_GetValue failed: 0x%08x.\n", hr); - ok(ret_propvar.vt == VT_I4, "got wrong property type: %x.\n", ret_propvar.vt); - ok(U(ret_propvar).lVal == 123, "got wrong value: %d, expected 123.\n", U(ret_propvar).lVal); - PropVariantClear(&propvar); - PropVariantClear(&ret_propvar); - - PropVariantInit(&propvar); - propkey.fmtid = DUMMY_GUID1; - propkey.pid = PID_FIRST_USABLE; - hr = IPropertyStore_SetValue(propstore, &propkey, &propvar); - ok(hr == S_OK, "IPropertyStore_SetValue failed: 0x%08x.\n", hr); - hr = IPropertyStore_Commit(propstore); - ok(hr == S_OK, "IPropertyStore_Commit failed: 0x%08x.\n", hr); - hr = IPropertyStore_GetCount(propstore, &count); - ok(hr == S_OK, "IPropertyStore_GetCount failed: 0x%08x.\n", hr); - ok(count == 1, "got wrong property count: %d, expected 1.\n", count); - PropVariantInit(&ret_propvar); - hr = IPropertyStore_GetValue(propstore, &propkey, &ret_propvar); - ok(hr == S_OK, "IPropertyStore_GetValue failed: 0x%08x.\n", hr); - ok(ret_propvar.vt == VT_EMPTY, "got wrong property type: %x.\n", ret_propvar.vt); - ok(!U(ret_propvar).lVal, "got wrong value: %d, expected 0.\n", U(ret_propvar).lVal); - PropVariantClear(&propvar); - PropVariantClear(&ret_propvar); - - IPropertyStore_Release(propstore); -} - -START_TEST(propstore) -{ - CoInitialize(NULL); - - test_inmemorystore(); - test_persistserialized(); - test_PSCreateMemoryPropertyStore(); - test_propertystore(); - - CoUninitialize(); -} diff --git a/modules/rostests/winetests/propsys/propsys.c b/modules/rostests/winetests/propsys/propsys.c index 77ffe05f6d9..d63b9ddd3b2 100644 --- a/modules/rostests/winetests/propsys/propsys.c +++ b/modules/rostests/winetests/propsys/propsys.c @@ -3,6 +3,7 @@ * * Copyright 2006 Paul Vriens * Copyright 2010 Andrew Nguyen + * Copyright 2012 Vincent Povirk * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,12 +25,10 @@ #include <stdarg.h> #include <stdio.h> -#define NONAMELESSUNION - #include "windef.h" #include "winbase.h" -#include "objbase.h" #include "initguid.h" +#include "objbase.h" #include "propsys.h" #include "propvarutil.h" #include "strsafe.h" @@ -38,18 +37,23 @@ DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); DEFINE_GUID(dummy_guid, 0xdeadbeef, 0xdead, 0xbeef, 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe); DEFINE_GUID(expect_guid, 0x12345678, 0x1234, 0x1234, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12); +DEFINE_GUID(PKEY_WineTest, 0x7b317433, 0xdfa3, 0x4c44, 0xad, 0x3e, 0x2f, 0x80, 0x4b, 0x90, 0xdb, 0xf4); +DEFINE_GUID(DUMMY_GUID1, 0x12345678, 0x1234,0x1234, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19); #define GUID_MEMBERS(g) {(g).Data1, (g).Data2, (g).Data3, {(g).Data4[0], (g).Data4[1], (g).Data4[2], (g).Data4[3], (g).Data4[4], (g).Data4[5], (g).Data4[6], (g).Data4[7]}} static const char topic[] = "wine topic"; static const WCHAR topicW[] = {'w','i','n','e',' ','t','o','p','i','c',0}; static const WCHAR emptyW[] = {0}; +static const WCHAR dummy_guid_str[] = L"{DEADBEEF-DEAD-BEEF-DEAD-BEEFCAFEBABE}"; -static int strcmp_wa(LPCWSTR strw, const char *stra) +#define EXPECT_REF(obj,ref) _expect_ref((IUnknown *)obj, ref, __LINE__) +static void _expect_ref(IUnknown *obj, ULONG ref, int line) { - CHAR buf[512]; - WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL); - return lstrcmpA(stra, buf); + ULONG rc; + IUnknown_AddRef(obj); + rc = IUnknown_Release(obj); + ok_(__FILE__,line)(rc == ref, "expected refcount %ld, got %ld\n", ref, rc); } static void test_PSStringFromPropertyKey(void) @@ -144,7 +148,7 @@ static void test_PSStringFromPropertyKey(void) testcases[i].cch); ok(ret == testcases[i].hr_expect || broken(testcases[i].hr_broken && ret == testcases[i].hr2), /* Vista/Win2k8 */ - "[%d] Expected PSStringFromPropertyKey to return 0x%08x, got 0x%08x\n", + "[%d] Expected PSStringFromPropertyKey to return 0x%08lx, got 0x%08lx\n", i, testcases[i].hr_expect, ret); if (testcases[i].psz) @@ -334,6 +338,9 @@ static void test_PSPropertyKeyFromString(void) static const WCHAR fmtid_normalpidW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-', '1','2','3','4','-','1','2','3','4','-', '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','1','3','5','7','9',0}; + static const WCHAR fmtid_udigitW[] = {'{','1','2','3','4','5','6','7','8','-','1','2','3','4','-', + '1','2','3','4','-','1','2','3','4','-', + '1','2','3','4','5','6','7','8','9','0','1','2','}',' ','1','2','3',0x661,'5','7','9',0}; PROPERTYKEY out_init = {GUID_MEMBERS(dummy_guid), 0xdeadbeef}; PROPERTYKEY out; HRESULT ret; @@ -410,6 +417,7 @@ static void test_PSPropertyKeyFromString(void) {fmtid_commanegspcpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 0U}}, {fmtid_negcommapidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 0}}, {fmtid_normalpidW, &out, S_OK, {GUID_MEMBERS(expect_guid), 13579}}, + {fmtid_udigitW, &out, S_OK, {GUID_MEMBERS(expect_guid), 123}}, }; int i; @@ -421,7 +429,7 @@ static void test_PSPropertyKeyFromString(void) ret = PSPropertyKeyFromString(testcases[i].pwzString, testcases[i].pkey); ok(ret == testcases[i].hr_expect, - "[%d] Expected PSPropertyKeyFromString to return 0x%08x, got 0x%08x\n", + "[%d] Expected PSPropertyKeyFromString to return 0x%08lx, got 0x%08lx\n", i, testcases[i].hr_expect, ret); if (testcases[i].pkey) @@ -430,7 +438,7 @@ static void test_PSPropertyKeyFromString(void) "[%d] Expected GUID %s, got %s\n", i, wine_dbgstr_guid(&testcases[i].pkey_expect.fmtid), wine_dbgstr_guid(&testcases[i].pkey->fmtid)); ok(testcases[i].pkey->pid == testcases[i].pkey_expect.pid, - "[%d] Expected property ID %u, got %u\n", + "[%d] Expected property ID %lu, got %lu\n", i, testcases[i].pkey_expect.pid, testcases[i].pkey->pid); } } @@ -443,13 +451,13 @@ static void test_PSRefreshPropertySchema(void) ret = PSRefreshPropertySchema(); todo_wine ok(ret == CO_E_NOTINITIALIZED, - "Expected PSRefreshPropertySchema to return CO_E_NOTINITIALIZED, got 0x%08x\n", ret); + "Expected PSRefreshPropertySchema to return CO_E_NOTINITIALIZED, got 0x%08lx\n", ret); CoInitialize(NULL); ret = PSRefreshPropertySchema(); ok(ret == S_OK, - "Expected PSRefreshPropertySchema to return S_OK, got 0x%08x\n", ret); + "Expected PSRefreshPropertySchema to return S_OK, got 0x%08lx\n", ret); CoUninitialize(); } @@ -463,14 +471,14 @@ static void test_InitPropVariantFromGUIDAsString(void) const struct { REFGUID guid; - const char *str; + const WCHAR *str; } testcases[] = { - {&IID_NULL, "{00000000-0000-0000-0000-000000000000}" }, - {&dummy_guid, "{DEADBEEF-DEAD-BEEF-DEAD-BEEFCAFEBABE}" }, + {&IID_NULL, L"{00000000-0000-0000-0000-000000000000}" }, + {&dummy_guid, dummy_guid_str }, }; hres = InitPropVariantFromGUIDAsString(NULL, &propvar); - ok(hres == E_FAIL, "InitPropVariantFromGUIDAsString returned %x\n", hres); + ok(hres == E_FAIL, "InitPropVariantFromGUIDAsString returned %lx\n", hres); if(0) { /* Returns strange data on Win7, crashes on older systems */ @@ -484,19 +492,19 @@ static void test_InitPropVariantFromGUIDAsString(void) for(i=0; i < ARRAY_SIZE(testcases); i++) { memset(&propvar, 0, sizeof(PROPVARIANT)); hres = InitPropVariantFromGUIDAsString(testcases[i].guid, &propvar); - ok(hres == S_OK, "%d) InitPropVariantFromGUIDAsString returned %x\n", i, hres); + ok(hres == S_OK, "%d) InitPropVariantFromGUIDAsString returned %lx\n", i, hres); ok(propvar.vt == VT_LPWSTR, "%d) propvar.vt = %d\n", i, propvar.vt); - ok(!strcmp_wa(propvar.u.pwszVal, testcases[i].str), "%d) propvar.u.pwszVal = %s\n", - i, wine_dbgstr_w(propvar.u.pwszVal)); - CoTaskMemFree(propvar.u.pwszVal); + ok(!lstrcmpW(propvar.pwszVal, testcases[i].str), "%d) propvar.pwszVal = %s\n", + i, wine_dbgstr_w(propvar.pwszVal)); + CoTaskMemFree(propvar.pwszVal); memset(&var, 0, sizeof(VARIANT)); hres = InitVariantFromGUIDAsString(testcases[i].guid, &var); - ok(hres == S_OK, "%d) InitVariantFromGUIDAsString returned %x\n", i, hres); + ok(hres == S_OK, "%d) InitVariantFromGUIDAsString returned %lx\n", i, hres); ok(V_VT(&var) == VT_BSTR, "%d) V_VT(&var) = %d\n", i, V_VT(&var)); ok(SysStringLen(V_BSTR(&var)) == 38, "SysStringLen returned %d\n", SysStringLen(V_BSTR(&var))); - ok(!strcmp_wa(V_BSTR(&var), testcases[i].str), "%d) V_BSTR(&var) = %s\n", + ok(!lstrcmpW(V_BSTR(&var), testcases[i].str), "%d) V_BSTR(&var) = %s\n", i, wine_dbgstr_w(V_BSTR(&var))); VariantClear(&var); } @@ -512,47 +520,47 @@ static void test_InitPropVariantFromBuffer(void) LONG size; hres = InitPropVariantFromBuffer(NULL, 0, &propvar); - ok(hres == S_OK, "InitPropVariantFromBuffer returned %x\n", hres); + ok(hres == S_OK, "InitPropVariantFromBuffer returned %lx\n", hres); ok(propvar.vt == (VT_VECTOR|VT_UI1), "propvar.vt = %d\n", propvar.vt); - ok(propvar.u.caub.cElems == 0, "cElems = %d\n", propvar.u.caub.cElems == 0); + ok(propvar.caub.cElems == 0, "cElems = %d\n", propvar.caub.cElems == 0); PropVariantClear(&propvar); hres = InitPropVariantFromBuffer(data_in, 4, &propvar); - ok(hres == S_OK, "InitPropVariantFromBuffer returned %x\n", hres); + ok(hres == S_OK, "InitPropVariantFromBuffer returned %lx\n", hres); ok(propvar.vt == (VT_VECTOR|VT_UI1), "propvar.vt = %d\n", propvar.vt); - ok(propvar.u.caub.cElems == 4, "cElems = %d\n", propvar.u.caub.cElems == 0); - ok(!memcmp(propvar.u.caub.pElems, data_in, 4), "Data inside array is incorrect\n"); + ok(propvar.caub.cElems == 4, "cElems = %d\n", propvar.caub.cElems == 0); + ok(!memcmp(propvar.caub.pElems, data_in, 4), "Data inside array is incorrect\n"); PropVariantClear(&propvar); hres = InitVariantFromBuffer(NULL, 0, &var); - ok(hres == S_OK, "InitVariantFromBuffer returned %x\n", hres); + ok(hres == S_OK, "InitVariantFromBuffer returned %lx\n", hres); ok(V_VT(&var) == (VT_ARRAY|VT_UI1), "V_VT(&var) = %d\n", V_VT(&var)); size = SafeArrayGetDim(V_ARRAY(&var)); - ok(size == 1, "SafeArrayGetDim returned %d\n", size); + ok(size == 1, "SafeArrayGetDim returned %ld\n", size); hres = SafeArrayGetLBound(V_ARRAY(&var), 1, &size); - ok(hres == S_OK, "SafeArrayGetLBound returned %x\n", hres); - ok(size == 0, "LBound = %d\n", size); + ok(hres == S_OK, "SafeArrayGetLBound returned %lx\n", hres); + ok(size == 0, "LBound = %ld\n", size); hres = SafeArrayGetUBound(V_ARRAY(&var), 1, &size); - ok(hres == S_OK, "SafeArrayGetUBound returned %x\n", hres); - ok(size == -1, "UBound = %d\n", size); + ok(hres == S_OK, "SafeArrayGetUBound returned %lx\n", hres); + ok(size == -1, "UBound = %ld\n", size); VariantClear(&var); hres = InitVariantFromBuffer(data_in, 4, &var); - ok(hres == S_OK, "InitVariantFromBuffer returned %x\n", hres); + ok(hres == S_OK, "InitVariantFromBuffer returned %lx\n", hres); ok(V_VT(&var) == (VT_ARRAY|VT_UI1), "V_VT(&var) = %d\n", V_VT(&var)); size = SafeArrayGetDim(V_ARRAY(&var)); - ok(size == 1, "SafeArrayGetDim returned %d\n", size); + ok(size == 1, "SafeArrayGetDim returned %ld\n", size); hres = SafeArrayGetLBound(V_ARRAY(&var), 1, &size); - ok(hres == S_OK, "SafeArrayGetLBound returned %x\n", hres); - ok(size == 0, "LBound = %d\n", size); + ok(hres == S_OK, "SafeArrayGetLBound returned %lx\n", hres); + ok(size == 0, "LBound = %ld\n", size); hres = SafeArrayGetUBound(V_ARRAY(&var), 1, &size); - ok(hres == S_OK, "SafeArrayGetUBound returned %x\n", hres); - ok(size == 3, "UBound = %d\n", size); + ok(hres == S_OK, "SafeArrayGetUBound returned %lx\n", hres); + ok(size == 3, "UBound = %ld\n", size); hres = SafeArrayAccessData(V_ARRAY(&var), &data_out); - ok(hres == S_OK, "SafeArrayAccessData failed %x\n", hres); + ok(hres == S_OK, "SafeArrayAccessData failed %lx\n", hres); ok(!memcmp(data_in, data_out, 4), "Data inside safe array is incorrect\n"); hres = SafeArrayUnaccessData(V_ARRAY(&var)); - ok(hres == S_OK, "SafeArrayUnaccessData failed %x\n", hres); + ok(hres == S_OK, "SafeArrayUnaccessData failed %lx\n", hres); VariantClear(&var); } @@ -564,67 +572,67 @@ static void test_PropVariantToGUID(void) HRESULT hres; hres = InitPropVariantFromGUIDAsString(&IID_NULL, &propvar); - ok(hres == S_OK, "InitPropVariantFromGUIDAsString failed %x\n", hres); + ok(hres == S_OK, "InitPropVariantFromGUIDAsString failed %lx\n", hres); hres = PropVariantToGUID(&propvar, &guid); - ok(hres == S_OK, "PropVariantToGUID failed %x\n", hres); + ok(hres == S_OK, "PropVariantToGUID failed %lx\n", hres); ok(IsEqualGUID(&IID_NULL, &guid), "incorrect GUID created: %s\n", wine_dbgstr_guid(&guid)); PropVariantClear(&propvar); hres = InitPropVariantFromGUIDAsString(&dummy_guid, &propvar); - ok(hres == S_OK, "InitPropVariantFromGUIDAsString failed %x\n", hres); + ok(hres == S_OK, "InitPropVariantFromGUIDAsString failed %lx\n", hres); hres = PropVariantToGUID(&propvar, &guid); - ok(hres == S_OK, "PropVariantToGUID failed %x\n", hres); + ok(hres == S_OK, "PropVariantToGUID failed %lx\n", hres); ok(IsEqualGUID(&dummy_guid, &guid), "incorrect GUID created: %s\n", wine_dbgstr_guid(&guid)); ok(propvar.vt == VT_LPWSTR, "incorrect PROPVARIANT type: %d\n", propvar.vt); - propvar.u.pwszVal[1] = 'd'; - propvar.u.pwszVal[2] = 'E'; - propvar.u.pwszVal[3] = 'a'; + propvar.pwszVal[1] = 'd'; + propvar.pwszVal[2] = 'E'; + propvar.pwszVal[3] = 'a'; hres = PropVariantToGUID(&propvar, &guid); - ok(hres == S_OK, "PropVariantToGUID failed %x\n", hres); + ok(hres == S_OK, "PropVariantToGUID failed %lx\n", hres); ok(IsEqualGUID(&dummy_guid, &guid), "incorrect GUID created: %s\n", wine_dbgstr_guid(&guid)); - propvar.u.pwszVal[1] = 'z'; + propvar.pwszVal[1] = 'z'; hres = PropVariantToGUID(&propvar, &guid); - ok(hres == E_INVALIDARG, "PropVariantToGUID returned %x\n", hres); + ok(hres == E_INVALIDARG, "PropVariantToGUID returned %lx\n", hres); PropVariantClear(&propvar); hres = InitVariantFromGUIDAsString(&IID_NULL, &var); - ok(hres == S_OK, "InitVariantFromGUIDAsString failed %x\n", hres); + ok(hres == S_OK, "InitVariantFromGUIDAsString failed %lx\n", hres); hres = VariantToGUID(&var, &guid); - ok(hres == S_OK, "VariantToGUID failed %x\n", hres); + ok(hres == S_OK, "VariantToGUID failed %lx\n", hres); ok(IsEqualGUID(&IID_NULL, &guid), "incorrect GUID created: %s\n", wine_dbgstr_guid(&guid)); VariantClear(&var); hres = InitVariantFromGUIDAsString(&dummy_guid, &var); - ok(hres == S_OK, "InitVariantFromGUIDAsString failed %x\n", hres); + ok(hres == S_OK, "InitVariantFromGUIDAsString failed %lx\n", hres); hres = VariantToGUID(&var, &guid); - ok(hres == S_OK, "VariantToGUID failed %x\n", hres); + ok(hres == S_OK, "VariantToGUID failed %lx\n", hres); ok(IsEqualGUID(&dummy_guid, &guid), "incorrect GUID created: %s\n", wine_dbgstr_guid(&guid)); ok(V_VT(&var) == VT_BSTR, "incorrect VARIANT type: %d\n", V_VT(&var)); V_BSTR(&var)[1] = 'z'; hres = VariantToGUID(&var, &guid); - ok(hres == E_FAIL, "VariantToGUID returned %x\n", hres); + ok(hres == E_FAIL, "VariantToGUID returned %lx\n", hres); V_BSTR(&var)[1] = 'd'; propvar.vt = V_VT(&var); - propvar.u.bstrVal = V_BSTR(&var); + propvar.bstrVal = V_BSTR(&var); V_VT(&var) = VT_EMPTY; hres = PropVariantToGUID(&propvar, &guid); - ok(hres == S_OK, "PropVariantToGUID failed %x\n", hres); + ok(hres == S_OK, "PropVariantToGUID failed %lx\n", hres); ok(IsEqualGUID(&dummy_guid, &guid), "incorrect GUID created: %s\n", wine_dbgstr_guid(&guid)); PropVariantClear(&propvar); memset(&guid, 0, sizeof(guid)); InitPropVariantFromCLSID(&dummy_guid, &propvar); hres = PropVariantToGUID(&propvar, &guid); - ok(hres == S_OK, "PropVariantToGUID failed %x\n", hres); + ok(hres == S_OK, "PropVariantToGUID failed %lx\n", hres); ok(IsEqualGUID(&dummy_guid, &guid), "incorrect GUID created: %s\n", wine_dbgstr_guid(&guid)); PropVariantClear(&propvar); } @@ -637,35 +645,46 @@ static void test_PropVariantToStringAlloc(void) prop.vt = VT_NULL; hres = PropVariantToStringAlloc(&prop, &str); - ok(hres == S_OK, "returned %x\n", hres); + ok(hres == S_OK, "returned %lx\n", hres); ok(!lstrcmpW(str, emptyW), "got %s\n", wine_dbgstr_w(str)); CoTaskMemFree(str); prop.vt = VT_LPSTR; - prop.u.pszVal = CoTaskMemAlloc(strlen(topic)+1); - strcpy(prop.u.pszVal, topic); + prop.pszVal = CoTaskMemAlloc(strlen(topic)+1); + strcpy(prop.pszVal, topic); hres = PropVariantToStringAlloc(&prop, &str); - ok(hres == S_OK, "returned %x\n", hres); + ok(hres == S_OK, "returned %lx\n", hres); ok(!lstrcmpW(str, topicW), "got %s\n", wine_dbgstr_w(str)); CoTaskMemFree(str); PropVariantClear(&prop); prop.vt = VT_EMPTY; hres = PropVariantToStringAlloc(&prop, &str); - ok(hres == S_OK, "returned %x\n", hres); + ok(hres == S_OK, "returned %lx\n", hres); ok(!lstrcmpW(str, emptyW), "got %s\n", wine_dbgstr_w(str)); CoTaskMemFree(str); + + prop.vt = VT_CLSID; + prop.puuid = (CLSID *)&dummy_guid; + hres = PropVariantToStringAlloc(&prop, &str); + ok(hres == S_OK, "PropVariantToStringAlloc returned %#lx.\n", hres); + ok(!wcscmp(str, dummy_guid_str), "Unexpected str %s.\n", debugstr_w(str)); + CoTaskMemFree(str); } -static void test_PropVariantCompare(void) +static void test_PropVariantCompareEx(void) { PROPVARIANT empty, null, emptyarray, i2_0, i2_2, i4_large, i4_largeneg, i4_2, str_2, str_02, str_b; PROPVARIANT clsid_null, clsid, clsid2, r4_0, r4_2, r8_0, r8_2; + PROPVARIANT ui4, ui4_large; + PROPVARIANT var1, var2; INT res; static const WCHAR str_2W[] = {'2', 0}; static const WCHAR str_02W[] = {'0', '2', 0}; static const WCHAR str_bW[] = {'b', 0}; SAFEARRAY emptysafearray; + unsigned char bytevector1[] = {1,2,3}; + unsigned char bytevector2[] = {4,5,6}; PropVariantInit(&empty); PropVariantInit(&null); @@ -681,7 +700,7 @@ static void test_PropVariantCompare(void) empty.vt = VT_EMPTY; null.vt = VT_NULL; emptyarray.vt = VT_ARRAY | VT_I4; - emptyarray.u.parray = &emptysafearray; + emptyarray.parray = &emptysafearray; emptysafearray.cDims = 1; emptysafearray.fFeatures = FADF_FIXEDSIZE; emptysafearray.cbElements = 4; @@ -690,35 +709,39 @@ static void test_PropVariantCompare(void) emptysafearray.rgsabound[0].cElements = 0; emptysafearray.rgsabound[0].lLbound = 0; i2_0.vt = VT_I2; - i2_0.u.iVal = 0; + i2_0.iVal = 0; i2_2.vt = VT_I2; - i2_2.u.iVal = 2; + i2_2.iVal = 2; i4_large.vt = VT_I4; - i4_large.u.lVal = 65536; + i4_large.lVal = 65536; i4_largeneg.vt = VT_I4; - i4_largeneg.u.lVal = -65536; + i4_largeneg.lVal = -65536; i4_2.vt = VT_I4; - i4_2.u.lVal = 2; + i4_2.lVal = 2; + ui4.vt = VT_UI4; + ui4.ulVal = 2; + ui4_large.vt = VT_UI4; + ui4_large.ulVal = 65536; str_2.vt = VT_BSTR; - str_2.u.bstrVal = SysAllocString(str_2W); + str_2.bstrVal = SysAllocString(str_2W); str_02.vt = VT_BSTR; - str_02.u.bstrVal = SysAllocString(str_02W); + str_02.bstrVal = SysAllocString(str_02W); str_b.vt = VT_BSTR; - str_b.u.bstrVal = SysAllocString(str_bW); + str_b.bstrVal = SysAllocString(str_bW); clsid_null.vt = VT_CLSID; - clsid_null.u.puuid = NULL; + clsid_null.puuid = NULL; clsid.vt = VT_CLSID; - clsid.u.puuid = (GUID *)&dummy_guid; + clsid.puuid = (GUID *)&dummy_guid; clsid2.vt = VT_CLSID; - clsid2.u.puuid = (GUID *)&GUID_NULL; + clsid2.puuid = (GUID *)&GUID_NULL; r4_0.vt = VT_R4; - r4_0.u.fltVal = 0.0f; + r4_0.fltVal = 0.0f; r4_2.vt = VT_R4; - r4_2.u.fltVal = 2.0f; + r4_2.fltVal = 2.0f; r8_0.vt = VT_R8; - r8_0.u.dblVal = 0.0; + r8_0.dblVal = 0.0; r8_2.vt = VT_R8; - r8_2.u.dblVal = 2.0; + r8_2.dblVal = 2.0; res = PropVariantCompareEx(&empty, &empty, 0, 0); ok(res == 0, "res=%i\n", res); @@ -747,6 +770,12 @@ static void test_PropVariantCompare(void) res = PropVariantCompareEx(&i2_0, &i2_2, 0, 0); ok(res == -1, "res=%i\n", res); + res = PropVariantCompareEx(&ui4, &ui4_large, 0, 0); + ok(res == -1, "res=%i\n", res); + + res = PropVariantCompareEx(&ui4_large, &ui4, 0, 0); + ok(res == 1, "res=%i\n", res); + /* Always return -1 if second value cannot be converted to first type */ res = PropVariantCompareEx(&i2_0, &i4_large, 0, 0); ok(res == -1, "res=%i\n", res); @@ -817,7 +846,7 @@ static void test_PropVariantCompare(void) /* VT_R4/VT_R8 */ res = PropVariantCompareEx(&r4_0, &r8_0, 0, 0); -todo_wine + todo_wine ok(res == 0, "res=%i\n", res); res = PropVariantCompareEx(&r4_0, &r4_0, 0, 0); @@ -838,9 +867,77 @@ todo_wine res = PropVariantCompareEx(&r8_2, &r8_0, 0, 0); ok(res == 1, "res=%i\n", res); - SysFreeString(str_2.u.bstrVal); - SysFreeString(str_02.u.bstrVal); - SysFreeString(str_b.u.bstrVal); + /* VT_VECTOR | VT_UI1 */ + var1.vt = VT_VECTOR | VT_UI1; + var1.caub.cElems = 1; + var1.caub.pElems = bytevector1; + var2.vt = VT_VECTOR | VT_UI1; + var2.caub.cElems = 1; + var2.caub.pElems = bytevector2; + + res = PropVariantCompareEx(&var1, &var2, 0, 0); + ok(res == -1, "res=%i\n", res); + + res = PropVariantCompareEx(&var2, &var1, 0, 0); + ok(res == 1, "res=%i\n", res); + + /* Vector length mismatch */ + var1.caub.cElems = 2; + res = PropVariantCompareEx(&var1, &var2, 0, 0); + ok(res == -1, "res=%i\n", res); + + res = PropVariantCompareEx(&var2, &var1, 0, 0); + ok(res == 1, "res=%i\n", res); + + var1.caub.pElems = bytevector2; + var2.caub.pElems = bytevector1; + res = PropVariantCompareEx(&var1, &var2, 0, 0); + ok(res == 1, "res=%i\n", res); + + var1.caub.pElems = bytevector1; + var2.caub.pElems = bytevector2; + + var1.caub.cElems = 1; + var2.caub.cElems = 2; + res = PropVariantCompareEx(&var1, &var2, 0, 0); + ok(res == -1, "res=%i\n", res); + + res = PropVariantCompareEx(&var2, &var1, 0, 0); + ok(res == 1, "res=%i\n", res); + + /* Length mismatch over same data */ + var1.caub.pElems = bytevector1; + var2.caub.pElems = bytevector1; + + res = PropVariantCompareEx(&var1, &var2, 0, 0); + ok(res == -1, "res=%i\n", res); + + res = PropVariantCompareEx(&var2, &var1, 0, 0); + ok(res == 1, "res=%i\n", res); + + var1.caub.cElems = 1; + var2.caub.cElems = 1; + res = PropVariantCompareEx(&var1, &var2, 0, 0); + ok(res == 0, "res=%i\n", res); + + var1.caub.cElems = 0; + res = PropVariantCompareEx(&var1, &var2, 0, PVCF_TREATEMPTYASGREATERTHAN); + ok(res == 1, "res=%i\n", res); + res = PropVariantCompareEx(&var2, &var1, 0, PVCF_TREATEMPTYASGREATERTHAN); + ok(res == -1, "res=%i\n", res); + + res = PropVariantCompareEx(&var1, &var2, 0, 0); + ok(res == -1, "res=%i\n", res); + res = PropVariantCompareEx(&var2, &var1, 0, 0); + ok(res == 1, "res=%i\n", res); + + var2.caub.cElems = 0; + res = PropVariantCompareEx(&var1, &var2, 0, 0); + ok(res == 0, "res=%i\n", res); + + SysFreeString(str_2.bstrVal); + SysFreeString(str_02.bstrVal); + SysFreeString(str_b.bstrVal); } static void test_intconversions(void) @@ -862,104 +959,113 @@ static void test_intconversions(void) PropVariantClear(&propvar); propvar.vt = VT_I8; - propvar.u.hVal.QuadPart = (ULONGLONG)1 << 63; + propvar.hVal.QuadPart = (ULONGLONG)1 << 63; hr = PropVariantToInt64(&propvar, &llval); - ok(hr == S_OK, "hr=%x\n", hr); + ok(hr == S_OK, "hr=%lx\n", hr); ok(llval == (ULONGLONG)1 << 63, "got wrong value %s\n", wine_dbgstr_longlong(llval)); hr = PropVariantToUInt64(&propvar, &ullval); - ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr); + ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%lx\n", hr); hr = PropVariantToInt32(&propvar, &lval); - ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr); + ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%lx\n", hr); hr = PropVariantToUInt32(&propvar, &ulval); - ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr); + ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%lx\n", hr); + + ulval = PropVariantToUInt32WithDefault(&propvar, 77); + ok(ulval == 77, "ulval=%lu\n", ulval); hr = PropVariantToInt16(&propvar, &sval); - ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr); + ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%lx\n", hr); hr = PropVariantToUInt16(&propvar, &usval); - ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr); + ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%lx\n", hr); propvar.vt = VT_UI8; - propvar.u.uhVal.QuadPart = 5; + propvar.uhVal.QuadPart = 5; hr = PropVariantToInt64(&propvar, &llval); - ok(hr == S_OK, "hr=%x\n", hr); + ok(hr == S_OK, "hr=%lx\n", hr); ok(llval == 5, "got wrong value %s\n", wine_dbgstr_longlong(llval)); hr = PropVariantToUInt64(&propvar, &ullval); - ok(hr == S_OK, "hr=%x\n", hr); + ok(hr == S_OK, "hr=%lx\n", hr); ok(ullval == 5, "got wrong value %s\n", wine_dbgstr_longlong(ullval)); hr = PropVariantToInt32(&propvar, &lval); - ok(hr == S_OK, "hr=%x\n", hr); - ok(lval == 5, "got wrong value %d\n", lval); + ok(hr == S_OK, "hr=%lx\n", hr); + ok(lval == 5, "got wrong value %ld\n", lval); hr = PropVariantToUInt32(&propvar, &ulval); - ok(hr == S_OK, "hr=%x\n", hr); - ok(ulval == 5, "got wrong value %d\n", ulval); + ok(hr == S_OK, "hr=%lx\n", hr); + ok(ulval == 5, "got wrong value %ld\n", ulval); + + ulval = PropVariantToUInt32WithDefault(&propvar, 77); + ok(ulval == 5, "got wrong value %lu\n", ulval); hr = PropVariantToInt16(&propvar, &sval); - ok(hr == S_OK, "hr=%x\n", hr); + ok(hr == S_OK, "hr=%lx\n", hr); ok(sval == 5, "got wrong value %d\n", sval); hr = PropVariantToUInt16(&propvar, &usval); - ok(hr == S_OK, "hr=%x\n", hr); + ok(hr == S_OK, "hr=%lx\n", hr); ok(usval == 5, "got wrong value %d\n", usval); propvar.vt = VT_I8; - propvar.u.hVal.QuadPart = -5; + propvar.hVal.QuadPart = -5; hr = PropVariantToInt64(&propvar, &llval); - ok(hr == S_OK, "hr=%x\n", hr); + ok(hr == S_OK, "hr=%lx\n", hr); ok(llval == -5, "got wrong value %s\n", wine_dbgstr_longlong(llval)); hr = PropVariantToUInt64(&propvar, &ullval); - ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr); + ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%lx\n", hr); hr = PropVariantToInt32(&propvar, &lval); - ok(hr == S_OK, "hr=%x\n", hr); - ok(lval == -5, "got wrong value %d\n", lval); + ok(hr == S_OK, "hr=%lx\n", hr); + ok(lval == -5, "got wrong value %ld\n", lval); hr = PropVariantToUInt32(&propvar, &ulval); - ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr); + ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%lx\n", hr); + + ulval = PropVariantToUInt32WithDefault(&propvar, 77); + ok(ulval == 77, "ulval=%lu\n", ulval); hr = PropVariantToInt16(&propvar, &sval); - ok(hr == S_OK, "hr=%x\n", hr); + ok(hr == S_OK, "hr=%lx\n", hr); ok(sval == -5, "got wrong value %d\n", sval); hr = PropVariantToUInt16(&propvar, &usval); - ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%x\n", hr); + ok(hr == HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW), "hr=%lx\n", hr); propvar.vt = VT_UI4; - propvar.u.ulVal = 6; + propvar.ulVal = 6; hr = PropVariantToInt64(&propvar, &llval); - ok(hr == S_OK, "hr=%x\n", hr); + ok(hr == S_OK, "hr=%lx\n", hr); ok(llval == 6, "got wrong value %s\n", wine_dbgstr_longlong(llval)); propvar.vt = VT_I4; - propvar.u.lVal = -6; + propvar.lVal = -6; hr = PropVariantToInt64(&propvar, &llval); - ok(hr == S_OK, "hr=%x\n", hr); + ok(hr == S_OK, "hr=%lx\n", hr); ok(llval == -6, "got wrong value %s\n", wine_dbgstr_longlong(llval)); propvar.vt = VT_UI2; - propvar.u.uiVal = 7; + propvar.uiVal = 7; hr = PropVariantToInt64(&propvar, &llval); - ok(hr == S_OK, "hr=%x\n", hr); + ok(hr == S_OK, "hr=%lx\n", hr); ok(llval == 7, "got wrong value %s\n", wine_dbgstr_longlong(llval)); propvar.vt = VT_I2; - propvar.u.iVal = -7; + propvar.iVal = -7; hr = PropVariantToInt64(&propvar, &llval); - ok(hr == S_OK, "hr=%x\n", hr); + ok(hr == S_OK, "hr=%lx\n", hr); ok(llval == -7, "got wrong value %s\n", wine_dbgstr_longlong(llval)); } @@ -982,195 +1088,195 @@ static void test_PropVariantToBoolean(void) /* VT_BOOL */ propvar.vt = VT_BOOL; - propvar.u.boolVal = VARIANT_FALSE; + propvar.boolVal = VARIANT_FALSE; val = TRUE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == FALSE, "Unexpected value %d\n", val); propvar.vt = VT_BOOL; - propvar.u.boolVal = 1; + propvar.boolVal = 1; val = TRUE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == FALSE, "Unexpected value %d\n", val); propvar.vt = VT_BOOL; - propvar.u.boolVal = VARIANT_TRUE; + propvar.boolVal = VARIANT_TRUE; val = FALSE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == TRUE, "Unexpected value %d\n", val); /* VT_EMPTY */ propvar.vt = VT_EMPTY; - propvar.u.boolVal = VARIANT_TRUE; + propvar.boolVal = VARIANT_TRUE; val = TRUE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == FALSE, "Unexpected value %d\n", val); /* test integer conversion */ propvar.vt = VT_I4; - propvar.u.lVal = 0; + propvar.lVal = 0; val = TRUE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == FALSE, "Unexpected value %d\n", val); propvar.vt = VT_I4; - propvar.u.lVal = 1; + propvar.lVal = 1; val = FALSE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == TRUE, "Unexpected value %d\n", val); propvar.vt = VT_I4; - propvar.u.lVal = 67; + propvar.lVal = 67; val = FALSE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == TRUE, "Unexpected value %d\n", val); propvar.vt = VT_I4; - propvar.u.lVal = -67; + propvar.lVal = -67; val = FALSE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == TRUE, "Unexpected value %d\n", val); /* test string conversion */ propvar.vt = VT_LPWSTR; - propvar.u.pwszVal = str_0; + propvar.pwszVal = str_0; val = TRUE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == FALSE, "Unexpected value %d\n", val); propvar.vt = VT_LPWSTR; - propvar.u.pwszVal = str_1; + propvar.pwszVal = str_1; val = FALSE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == TRUE, "Unexpected value %d\n", val); propvar.vt = VT_LPWSTR; - propvar.u.pwszVal = str_7; + propvar.pwszVal = str_7; val = FALSE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == TRUE, "Unexpected value %d\n", val); propvar.vt = VT_LPWSTR; - propvar.u.pwszVal = str_n7; + propvar.pwszVal = str_n7; val = FALSE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == TRUE, "Unexpected value %d\n", val); propvar.vt = VT_LPWSTR; - propvar.u.pwszVal = str_true; + propvar.pwszVal = str_true; val = FALSE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == TRUE, "Unexpected value %d\n", val); propvar.vt = VT_LPWSTR; - propvar.u.pwszVal = str_true_case; + propvar.pwszVal = str_true_case; val = FALSE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == TRUE, "Unexpected value %d\n", val); propvar.vt = VT_LPWSTR; - propvar.u.pwszVal = str_true2; + propvar.pwszVal = str_true2; val = FALSE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == TRUE, "Unexpected value %d\n", val); propvar.vt = VT_LPWSTR; - propvar.u.pwszVal = str_false; + propvar.pwszVal = str_false; val = TRUE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == FALSE, "Unexpected value %d\n", val); propvar.vt = VT_LPWSTR; - propvar.u.pwszVal = str_false2; + propvar.pwszVal = str_false2; val = TRUE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == FALSE, "Unexpected value %d\n", val); propvar.vt = VT_LPWSTR; - propvar.u.pwszVal = str_true_space; + propvar.pwszVal = str_true_space; val = TRUE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == DISP_E_TYPEMISMATCH, "Unexpected hr %#x.\n", hr); + ok(hr == DISP_E_TYPEMISMATCH, "Unexpected hr %#lx.\n", hr); ok(val == FALSE, "Unexpected value %d\n", val); propvar.vt = VT_LPWSTR; - propvar.u.pwszVal = str_yes; + propvar.pwszVal = str_yes; val = TRUE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == DISP_E_TYPEMISMATCH, "Unexpected hr %#x.\n", hr); + ok(hr == DISP_E_TYPEMISMATCH, "Unexpected hr %#lx.\n", hr); ok(val == FALSE, "Unexpected value %d\n", val); propvar.vt = VT_LPWSTR; - propvar.u.pwszVal = NULL; + propvar.pwszVal = NULL; val = TRUE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == DISP_E_TYPEMISMATCH, "Unexpected hr %#x.\n", hr); + ok(hr == DISP_E_TYPEMISMATCH, "Unexpected hr %#lx.\n", hr); ok(val == FALSE, "Unexpected value %d\n", val); /* VT_LPSTR */ propvar.vt = VT_LPSTR; - propvar.u.pszVal = (char *)"#TruE#"; + propvar.pszVal = (char *)"#TruE#"; val = TRUE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == DISP_E_TYPEMISMATCH, "Unexpected hr %#x.\n", hr); + ok(hr == DISP_E_TYPEMISMATCH, "Unexpected hr %#lx.\n", hr); ok(val == FALSE, "Unexpected value %d\n", val); propvar.vt = VT_LPSTR; - propvar.u.pszVal = (char *)"#TRUE#"; + propvar.pszVal = (char *)"#TRUE#"; val = FALSE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == TRUE, "Unexpected value %d\n", val); propvar.vt = VT_LPSTR; - propvar.u.pszVal = (char *)"tRUe"; + propvar.pszVal = (char *)"tRUe"; val = FALSE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == TRUE, "Unexpected value %d\n", val); propvar.vt = VT_LPSTR; - propvar.u.pszVal = (char *)"#FALSE#"; + propvar.pszVal = (char *)"#FALSE#"; val = TRUE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == FALSE, "Unexpected value %d\n", val); propvar.vt = VT_LPSTR; - propvar.u.pszVal = (char *)"fALSe"; + propvar.pszVal = (char *)"fALSe"; val = TRUE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == FALSE, "Unexpected value %d\n", val); propvar.vt = VT_LPSTR; - propvar.u.pszVal = (char *)"1"; + propvar.pszVal = (char *)"1"; val = FALSE; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == TRUE, "Unexpected value %d\n", val); propvar.vt = VT_LPSTR; - propvar.u.pszVal = (char *)"-1"; + propvar.pszVal = (char *)"-1"; hr = PropVariantToBoolean(&propvar, &val); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(val == TRUE, "Unexpected value %d\n", val); } @@ -1195,83 +1301,88 @@ static void test_PropVariantToStringWithDefault(void) ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result)); propvar.vt = VT_BOOL; - propvar.u.boolVal = VARIANT_TRUE; + propvar.boolVal = VARIANT_TRUE; result = PropVariantToStringWithDefault(&propvar, default_value); ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result)); propvar.vt = VT_I4; - propvar.u.lVal = 15; + propvar.lVal = 15; result = PropVariantToStringWithDefault(&propvar, default_value); ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result)); + propvar.vt = VT_CLSID; + propvar.puuid = (CLSID *)&dummy_guid; + result = PropVariantToStringWithDefault(&propvar, default_value); + ok(result == default_value, "Unexpected value %s.\n", debugstr_w(result)); + /* VT_LPWSTR */ propvar.vt = VT_LPWSTR; - propvar.u.pwszVal = NULL; + propvar.pwszVal = NULL; result = PropVariantToStringWithDefault(&propvar, default_value); ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result)); propvar.vt = VT_LPWSTR; - propvar.u.pwszVal = wstr_empty; + propvar.pwszVal = wstr_empty; result = PropVariantToStringWithDefault(&propvar, default_value); ok(result == wstr_empty, "Unexpected value %s\n", wine_dbgstr_w(result)); propvar.vt = VT_LPWSTR; - propvar.u.pwszVal = wstr_space; + propvar.pwszVal = wstr_space; result = PropVariantToStringWithDefault(&propvar, default_value); ok(result == wstr_space, "Unexpected value %s\n", wine_dbgstr_w(result)); propvar.vt = VT_LPWSTR; - propvar.u.pwszVal = wstr_test2; + propvar.pwszVal = wstr_test2; result = PropVariantToStringWithDefault(&propvar, default_value); ok(result == wstr_test2, "Unexpected value %s\n", wine_dbgstr_w(result)); /* VT_LPSTR */ propvar.vt = VT_LPSTR; - propvar.u.pszVal = NULL; + propvar.pszVal = NULL; result = PropVariantToStringWithDefault(&propvar, default_value); ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result)); propvar.vt = VT_LPSTR; - propvar.u.pszVal = str_empty; + propvar.pszVal = str_empty; result = PropVariantToStringWithDefault(&propvar, default_value); ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result)); propvar.vt = VT_LPSTR; - propvar.u.pszVal = str_space; + propvar.pszVal = str_space; result = PropVariantToStringWithDefault(&propvar, default_value); ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result)); propvar.vt = VT_LPSTR; - propvar.u.pszVal = str_test2; + propvar.pszVal = str_test2; result = PropVariantToStringWithDefault(&propvar, default_value); ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result)); /* VT_BSTR */ propvar.vt = VT_BSTR; - propvar.u.bstrVal = NULL; + propvar.bstrVal = NULL; result = PropVariantToStringWithDefault(&propvar, default_value); ok(!lstrcmpW(result, wstr_empty), "Unexpected value %s\n", wine_dbgstr_w(result)); propvar.vt = VT_BSTR; - propvar.u.bstrVal = SysAllocString(wstr_empty); + propvar.bstrVal = SysAllocString(wstr_empty); result = PropVariantToStringWithDefault(&propvar, default_value); ok(!lstrcmpW(result, wstr_empty), "Unexpected value %s\n", wine_dbgstr_w(result)); - SysFreeString(propvar.u.bstrVal); + SysFreeString(propvar.bstrVal); propvar.vt = VT_BSTR; - propvar.u.bstrVal = SysAllocString(wstr_space); + propvar.bstrVal = SysAllocString(wstr_space); result = PropVariantToStringWithDefault(&propvar, default_value); ok(!lstrcmpW(result, wstr_space), "Unexpected value %s\n", wine_dbgstr_w(result)); - SysFreeString(propvar.u.bstrVal); + SysFreeString(propvar.bstrVal); propvar.vt = VT_BSTR; - propvar.u.bstrVal = SysAllocString(wstr_test2); + propvar.bstrVal = SysAllocString(wstr_test2); result = PropVariantToStringWithDefault(&propvar, default_value); ok(!lstrcmpW(result, wstr_test2), "Unexpected value %s\n", wine_dbgstr_w(result)); - SysFreeString(propvar.u.bstrVal); + SysFreeString(propvar.bstrVal); } static void test_PropVariantChangeType_LPWSTR(void) @@ -1283,29 +1394,29 @@ static void test_PropVariantChangeType_LPWSTR(void) src.vt = VT_NULL; hr = PropVariantChangeType(&dest, &src, 0, VT_LPWSTR); - ok(hr == S_OK, "hr=%x\n", hr); + ok(hr == S_OK, "hr=%lx\n", hr); ok(dest.vt == VT_LPWSTR, "got %d\n", dest.vt); - ok(!lstrcmpW(dest.u.pwszVal, emptyW), "got %s\n", wine_dbgstr_w(dest.u.pwszVal)); + ok(!lstrcmpW(dest.pwszVal, emptyW), "got %s\n", wine_dbgstr_w(dest.pwszVal)); PropVariantClear(&dest); PropVariantClear(&src); src.vt = VT_LPSTR; - src.u.pszVal = CoTaskMemAlloc(strlen(topic)+1); - strcpy(src.u.pszVal, topic); + src.pszVal = CoTaskMemAlloc(strlen(topic)+1); + strcpy(src.pszVal, topic); hr = PropVariantChangeType(&dest, &src, 0, VT_LPWSTR); - ok(hr == S_OK, "hr=%x\n", hr); + ok(hr == S_OK, "hr=%lx\n", hr); ok(dest.vt == VT_LPWSTR, "got %d\n", dest.vt); - ok(!lstrcmpW(dest.u.pwszVal, topicW), "got %s\n", wine_dbgstr_w(dest.u.pwszVal)); + ok(!lstrcmpW(dest.pwszVal, topicW), "got %s\n", wine_dbgstr_w(dest.pwszVal)); PropVariantClear(&dest); PropVariantClear(&src); src.vt = VT_LPWSTR; - src.u.pwszVal = CoTaskMemAlloc( (lstrlenW(topicW)+1) * sizeof(WCHAR)); - lstrcpyW(src.u.pwszVal, topicW); + src.pwszVal = CoTaskMemAlloc( (lstrlenW(topicW)+1) * sizeof(WCHAR)); + lstrcpyW(src.pwszVal, topicW); hr = PropVariantChangeType(&dest, &src, 0, VT_LPWSTR); - ok(hr == S_OK, "hr=%x\n", hr); + ok(hr == S_OK, "hr=%lx\n", hr); ok(dest.vt == VT_LPWSTR, "got %d\n", dest.vt); - ok(!lstrcmpW(dest.u.pwszVal, topicW), "got %s\n", wine_dbgstr_w(dest.u.pwszVal)); + ok(!lstrcmpW(dest.pwszVal, topicW), "got %s\n", wine_dbgstr_w(dest.pwszVal)); PropVariantClear(&dest); PropVariantClear(&src); } @@ -1318,13 +1429,42 @@ static void test_InitPropVariantFromCLSID(void) memset(&propvar, 0, sizeof(propvar)); propvar.vt = VT_I4; - propvar.u.lVal = 15; + propvar.lVal = 15; memset(&clsid, 0xcc, sizeof(clsid)); hr = InitPropVariantFromCLSID(&clsid, &propvar); - ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(propvar.vt == VT_CLSID, "Unexpected type %d.\n", propvar.vt); - ok(IsEqualGUID(propvar.u.puuid, &clsid), "Unexpected puuid value.\n"); + ok(IsEqualGUID(propvar.puuid, &clsid), "Unexpected puuid value.\n"); + PropVariantClear(&propvar); +} + +static void test_InitPropVariantFromStringVector(void) +{ + static const WCHAR *strs[2] = { L"abc", L"def" }; + PROPVARIANT propvar; + HRESULT hr; + + memset(&propvar, 0, sizeof(propvar)); + propvar.vt = VT_I4; + propvar.lVal = 15; + + hr = InitPropVariantFromStringVector(NULL, 0, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(propvar.vt == (VT_LPWSTR|VT_VECTOR), "Unexpected type %#x.\n", propvar.vt); + ok(!propvar.calpwstr.cElems, "Unexpected number of elements.\n"); + ok(!!propvar.calpwstr.pElems, "Unexpected vector pointer.\n"); + PropVariantClear(&propvar); + + hr = InitPropVariantFromStringVector(strs, 2, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(propvar.vt == (VT_LPWSTR|VT_VECTOR), "Unexpected type %#x.\n", propvar.vt); + ok(propvar.calpwstr.cElems == 2, "Unexpected number of elements.\n"); + ok(!!propvar.calpwstr.pElems, "Unexpected vector pointer.\n"); + ok(propvar.calpwstr.pElems[0] != strs[0], "Unexpected string pointer.\n"); + ok(!wcscmp(propvar.calpwstr.pElems[0], strs[0]), "Unexpected string %s.\n", debugstr_w(propvar.calpwstr.pElems[0])); + ok(propvar.calpwstr.pElems[1] != strs[1], "Unexpected string pointer.\n"); + ok(!wcscmp(propvar.calpwstr.pElems[1], strs[1]), "Unexpected string %s.\n", debugstr_w(propvar.calpwstr.pElems[1])); PropVariantClear(&propvar); } @@ -1336,141 +1476,262 @@ static void test_PropVariantToDouble(void) PropVariantInit(&propvar); propvar.vt = VT_R8; - propvar.u.dblVal = 15.0; + propvar.dblVal = 15.0; hr = PropVariantToDouble(&propvar, &value); - ok(hr == S_OK, "PropVariantToDouble failed: 0x%08x.\n", hr); + ok(hr == S_OK, "PropVariantToDouble failed: 0x%08lx.\n", hr); ok(value == 15.0, "Unexpected value: %f.\n", value); PropVariantClear(&propvar); propvar.vt = VT_I4; - propvar.u.lVal = 123; + propvar.lVal = 123; hr = PropVariantToDouble(&propvar, &value); - ok(hr == S_OK, "PropVariantToDouble failed: 0x%08x.\n", hr); + ok(hr == S_OK, "PropVariantToDouble failed: 0x%08lx.\n", hr); ok(value == 123.0, "Unexpected value: %f.\n", value); PropVariantClear(&propvar); propvar.vt = VT_I4; - propvar.u.lVal = -256; + propvar.lVal = -256; hr = PropVariantToDouble(&propvar, &value); - ok(hr == S_OK, "PropVariantToDouble failed: 0x%08x.\n", hr); + ok(hr == S_OK, "PropVariantToDouble failed: 0x%08lx.\n", hr); ok(value == -256, "Unexpected value: %f\n", value); PropVariantClear(&propvar); propvar.vt = VT_I8; - propvar.u.lVal = 65536; + propvar.lVal = 65536; hr = PropVariantToDouble(&propvar, &value); - ok(hr == S_OK, "PropVariantToDouble failed: 0x%08x.\n", hr); + ok(hr == S_OK, "PropVariantToDouble failed: 0x%08lx.\n", hr); ok(value == 65536.0, "Unexpected value: %f.\n", value); PropVariantClear(&propvar); propvar.vt = VT_I8; - propvar.u.lVal = -321; + propvar.lVal = -321; hr = PropVariantToDouble(&propvar, &value); - ok(hr == S_OK, "PropVariantToDouble failed: 0x%08x.\n", hr); + ok(hr == S_OK, "PropVariantToDouble failed: 0x%08lx.\n", hr); ok(value == 4294966975.0, "Unexpected value: %f.\n", value); PropVariantClear(&propvar); propvar.vt = VT_UI4; - propvar.u.ulVal = 6; + propvar.ulVal = 6; hr = PropVariantToDouble(&propvar, &value); - ok(hr == S_OK, "PropVariantToDouble failed: 0x%08x.\n", hr); + ok(hr == S_OK, "PropVariantToDouble failed: 0x%08lx.\n", hr); ok(value == 6.0, "Unexpected value: %f.\n", value); PropVariantClear(&propvar); propvar.vt = VT_UI8; - propvar.u.uhVal.QuadPart = 8; + propvar.uhVal.QuadPart = 8; hr = PropVariantToDouble(&propvar, &value); - ok(hr == S_OK, "PropVariantToDouble failed: 0x%08x.\n", hr); + ok(hr == S_OK, "PropVariantToDouble failed: 0x%08lx.\n", hr); ok(value == 8.0, "Unexpected value: %f.\n", value); } static void test_PropVariantToString(void) { - PROPVARIANT propvar; + static WCHAR stringW[] = L"Wine"; static CHAR string[] = "Wine"; - static WCHAR stringW[] = {'W','i','n','e',0}; WCHAR bufferW[256] = {0}; + PROPVARIANT propvar; HRESULT hr; PropVariantInit(&propvar); propvar.vt = VT_EMPTY; - U(propvar).pwszVal = stringW; + propvar.pwszVal = stringW; bufferW[0] = 65; hr = PropVariantToString(&propvar, bufferW, 0); - ok(hr == E_INVALIDARG, "PropVariantToString should fail: 0x%08x.\n", hr); + ok(hr == E_INVALIDARG, "PropVariantToString should fail: 0x%08lx.\n", hr); ok(!bufferW[0], "got wrong string: \"%s\".\n", wine_dbgstr_w(bufferW)); memset(bufferW, 0, sizeof(bufferW)); PropVariantClear(&propvar); PropVariantInit(&propvar); propvar.vt = VT_EMPTY; - U(propvar).pwszVal = stringW; + propvar.pwszVal = stringW; bufferW[0] = 65; hr = PropVariantToString(&propvar, bufferW, ARRAY_SIZE(bufferW)); - ok(hr == S_OK, "PropVariantToString failed: 0x%08x.\n", hr); + ok(hr == S_OK, "PropVariantToString failed: 0x%08lx.\n", hr); ok(!bufferW[0], "got wrong string: \"%s\".\n", wine_dbgstr_w(bufferW)); memset(bufferW, 0, sizeof(bufferW)); PropVariantClear(&propvar); PropVariantInit(&propvar); propvar.vt = VT_NULL; - U(propvar).pwszVal = stringW; + propvar.pwszVal = stringW; bufferW[0] = 65; hr = PropVariantToString(&propvar, bufferW, ARRAY_SIZE(bufferW)); - ok(hr == S_OK, "PropVariantToString failed: 0x%08x.\n", hr); + ok(hr == S_OK, "PropVariantToString failed: 0x%08lx.\n", hr); ok(!bufferW[0], "got wrong string: \"%s\".\n", wine_dbgstr_w(bufferW)); memset(bufferW, 0, sizeof(bufferW)); PropVariantClear(&propvar); PropVariantInit(&propvar); propvar.vt = VT_I4; - U(propvar).lVal = 22; + propvar.lVal = 22; hr = PropVariantToString(&propvar, bufferW, ARRAY_SIZE(bufferW)); - todo_wine ok(hr == S_OK, "PropVariantToString failed: 0x%08x.\n", hr); - todo_wine ok(!strcmp_wa(bufferW, "22"), "got wrong string: \"%s\".\n", wine_dbgstr_w(bufferW)); + todo_wine ok(hr == S_OK, "PropVariantToString failed: 0x%08lx.\n", hr); + todo_wine ok(!lstrcmpW(bufferW, L"22"), "got wrong string: \"%s\".\n", wine_dbgstr_w(bufferW)); memset(bufferW, 0, sizeof(bufferW)); PropVariantClear(&propvar); PropVariantInit(&propvar); propvar.vt = VT_LPWSTR; - U(propvar).pwszVal = stringW; + propvar.pwszVal = stringW; hr = PropVariantToString(&propvar, bufferW, ARRAY_SIZE(bufferW)); - ok(hr == S_OK, "PropVariantToString failed: 0x%08x.\n", hr); + ok(hr == S_OK, "PropVariantToString failed: 0x%08lx.\n", hr); ok(!lstrcmpW(bufferW, stringW), "got wrong string: \"%s\".\n", wine_dbgstr_w(bufferW)); memset(bufferW, 0, sizeof(bufferW)); PropVariantInit(&propvar); propvar.vt = VT_LPSTR; - U(propvar).pszVal = string; + propvar.pszVal = string; hr = PropVariantToString(&propvar, bufferW, ARRAY_SIZE(bufferW)); - ok(hr == S_OK, "PropVariantToString failed: 0x%08x.\n", hr); + ok(hr == S_OK, "PropVariantToString failed: 0x%08lx.\n", hr); ok(!lstrcmpW(bufferW, stringW), "got wrong string: \"%s\".\n", wine_dbgstr_w(bufferW)); memset(bufferW, 0, sizeof(bufferW)); + /* Result string will be truncated if output buffer is too small. */ + PropVariantInit(&propvar); + propvar.vt = VT_UI4; + propvar.lVal = 123456; + hr = PropVariantToString(&propvar, bufferW, 4); + todo_wine + ok(hr == STRSAFE_E_INSUFFICIENT_BUFFER, "PropVariantToString returned: %#lx.\n", hr); + todo_wine + ok(!wcscmp(bufferW, L"123"), "Unexpected string %s.\n", debugstr_w(bufferW)); + memset(bufferW, 0, sizeof(bufferW)); + PropVariantInit(&propvar); propvar.vt = VT_LPWSTR; - U(propvar).pwszVal = stringW; + propvar.pwszVal = stringW; hr = PropVariantToString(&propvar, bufferW, 4); - ok(hr == STRSAFE_E_INSUFFICIENT_BUFFER, "PropVariantToString returned: 0x%08x.\n", hr); - ok(!memcmp(bufferW, stringW, 4), "got wrong string.\n"); + ok(hr == STRSAFE_E_INSUFFICIENT_BUFFER, "PropVariantToString returned: 0x%08lx.\n", hr); + ok(!wcscmp(bufferW, L"Win"), "Unexpected string %s.\n", debugstr_w(bufferW)); memset(bufferW, 0, sizeof(bufferW)); PropVariantInit(&propvar); propvar.vt = VT_LPSTR; - U(propvar).pszVal = string; + propvar.pszVal = string; hr = PropVariantToString(&propvar, bufferW, 4); - ok(hr == STRSAFE_E_INSUFFICIENT_BUFFER, "PropVariantToString returned: 0x%08x.\n", hr); - ok(!memcmp(bufferW, stringW, 4), "got wrong string.\n"); + ok(hr == STRSAFE_E_INSUFFICIENT_BUFFER, "PropVariantToString returned: 0x%08lx.\n", hr); + ok(!wcscmp(bufferW, L"Win"), "Unexpected string %s.\n", debugstr_w(bufferW)); memset(bufferW, 0, sizeof(bufferW)); PropVariantInit(&propvar); propvar.vt = VT_BSTR; - propvar.u.bstrVal = SysAllocString(stringW); + propvar.bstrVal = SysAllocString(stringW); hr = PropVariantToString(&propvar, bufferW, ARRAY_SIZE(bufferW)); - ok(hr == S_OK, "PropVariantToString failed: 0x%08x.\n", hr); + ok(hr == S_OK, "PropVariantToString failed: 0x%08lx.\n", hr); ok(!lstrcmpW(bufferW, stringW), "got wrong string: \"%s\".\n", wine_dbgstr_w(bufferW)); memset(bufferW, 0, sizeof(bufferW)); - SysFreeString(propvar.u.bstrVal); + SysFreeString(propvar.bstrVal); + + PropVariantInit(&propvar); + propvar.vt = VT_CLSID; + propvar.puuid = (CLSID *)&dummy_guid; + hr = PropVariantToString(&propvar, bufferW, ARRAY_SIZE(bufferW)); + ok(hr == S_OK, "PropVariantToString returned %#lx.\n", hr); + ok(!wcscmp(bufferW, dummy_guid_str), "Unexpected string %s.\n", debugstr_w(bufferW)); + memset(bufferW, 0, sizeof(bufferW)); +} + +#define check_PropVariantToBSTR(type, member, value, expect_str) \ +do \ +{ \ + PROPVARIANT check_propvar_ = {.vt = (type), .member = (value)}; \ + HRESULT check_hr_; \ + BSTR check_bstr_; \ + \ + check_hr_ = PropVariantToBSTR(&check_propvar_, &check_bstr_); \ + ok_(__FILE__, __LINE__)(check_hr_ == S_OK, \ + "PropVariantToBSTR returned %#lx.\n", check_hr_); \ + \ + if (check_hr_ == S_OK) \ + { \ + ok_(__FILE__, __LINE__)(!wcscmp(check_bstr_, (expect_str)), \ + "Unexpected bstr %s.\n", debugstr_w(check_bstr_)); \ + SysFreeString(check_bstr_); \ + } \ +} while (0) + +static void test_PropVariantToBSTR(void) +{ + unsigned char test_bytes[] = {1, 20, 30, 4}; + WCHAR test_bstr[] = {'a', 0, 'b', 0, 'c'}; + PROPVARIANT propvar; + UINT length; + HRESULT hr; + BSTR bstr; + + if (0) /* Crashes. */ + { + hr = PropVariantToBSTR(&propvar, NULL); + hr = PropVariantToBSTR(NULL, &bstr); + } + + todo_wine + { + check_PropVariantToBSTR(VT_I1, cVal, -123, L"-123"); + check_PropVariantToBSTR(VT_I2, iVal, -456, L"-456"); + check_PropVariantToBSTR(VT_I4, lVal, -789, L"-789"); + check_PropVariantToBSTR(VT_I8, hVal.QuadPart, -101112, L"-101112"); + check_PropVariantToBSTR(VT_UI1, bVal, 0xcd, L"205"); + check_PropVariantToBSTR(VT_UI2, uiVal, 0xdead, L"57005"); + check_PropVariantToBSTR(VT_UI4, ulVal, 0xdeadbeef, L"3735928559"); + check_PropVariantToBSTR(VT_UI8, uhVal.QuadPart, 0xdeadbeefdeadbeef, L"16045690984833335023"); + check_PropVariantToBSTR(VT_BOOL, boolVal, TRUE, L"1"); + check_PropVariantToBSTR(VT_R4, fltVal, 0.125f, L"0.125"); + check_PropVariantToBSTR(VT_R8, dblVal, 0.456, L"0.456"); + } + check_PropVariantToBSTR(VT_CLSID, puuid, (CLSID *)&dummy_guid, dummy_guid_str); + check_PropVariantToBSTR(VT_LPSTR, pszVal, (char *)topic, topicW); + check_PropVariantToBSTR(VT_LPWSTR, pwszVal, (WCHAR *)topicW, topicW); + + PropVariantInit(&propvar); + propvar.vt = VT_FILETIME; + propvar.filetime.dwLowDateTime = 0xdead; + propvar.filetime.dwHighDateTime = 0xbeef; + hr = PropVariantToBSTR(&propvar, &bstr); + todo_wine + ok(hr == S_OK, "PropVariantToBSTR returned %#lx.\n", hr); + if (hr == S_OK) + { + ok(!wcscmp(bstr, L"1601/08/31:23:29:30.651"), "Unexpected bstr %s.\n", debugstr_w(bstr)); + SysFreeString(bstr); + } + + PropVariantInit(&propvar); + propvar.vt = VT_DATE; + propvar.date = 123.123f; + hr = PropVariantToBSTR(&propvar, &bstr); + todo_wine + ok(hr == S_OK, "PropVariantToBSTR returned %#lx.\n", hr); + if (hr == S_OK) + { + ok(!wcscmp(bstr, L"1900/05/02:02:57:07.000"), "Unexpected bstr %s.\n", debugstr_w(bstr)); + SysFreeString(bstr); + } + + PropVariantInit(&propvar); + propvar.vt = VT_VECTOR | VT_I1; + propvar.caub.cElems = ARRAY_SIZE(test_bytes); + propvar.caub.pElems = test_bytes; + hr = PropVariantToBSTR(&propvar, &bstr); + todo_wine + ok(hr == S_OK, "PropVariantToBSTR returned %#lx.\n", hr); + if (hr == S_OK) + { + ok(!wcscmp(bstr, L"1; 20; 30; 4"), "Unexpected bstr %s.\n", debugstr_w(bstr)); + SysFreeString(bstr); + } + + PropVariantInit(&propvar); + propvar.vt = VT_BSTR; + propvar.bstrVal = SysAllocStringLen(test_bstr, ARRAY_SIZE(test_bstr)); + hr = PropVariantToBSTR(&propvar, &bstr); + ok(hr == S_OK, "PropVariantToBSTR returned %#lx.\n", hr); + length = SysStringLen(bstr); + ok(length == wcslen(test_bstr), "Unexpected length %u.\n", length); + ok(!wcscmp(bstr, test_bstr), "Unexpected bstr %s.", debugstr_wn(bstr, ARRAY_SIZE(test_bstr))); + SysFreeString(bstr); + PropVariantClear(&propvar); } static void test_PropVariantToBuffer(void) @@ -1482,35 +1743,35 @@ static void test_PropVariantToBuffer(void) SAFEARRAY *sa; SAFEARRAYBOUND sabound; void *pdata; - UINT8 buffer[256]; + UINT8 buffer[256] = {0}; hr = InitPropVariantFromBuffer(data, 10, &propvar); - ok(hr == S_OK, "InitPropVariantFromBuffer failed 0x%08x.\n", hr); + ok(hr == S_OK, "InitPropVariantFromBuffer failed 0x%08lx.\n", hr); hr = PropVariantToBuffer(&propvar, NULL, 0); /* crash when cb isn't zero */ - ok(hr == S_OK, "PropVariantToBuffer failed: 0x%08x.\n", hr); + ok(hr == S_OK, "PropVariantToBuffer failed: 0x%08lx.\n", hr); PropVariantClear(&propvar); hr = InitPropVariantFromBuffer(data, 10, &propvar); - ok(hr == S_OK, "InitPropVariantFromBuffer failed 0x%08x.\n", hr); + ok(hr == S_OK, "InitPropVariantFromBuffer failed 0x%08lx.\n", hr); hr = PropVariantToBuffer(&propvar, buffer, 10); - ok(hr == S_OK, "PropVariantToBuffer failed: 0x%08x.\n", hr); + ok(hr == S_OK, "PropVariantToBuffer failed: 0x%08lx.\n", hr); ok(!memcmp(buffer, data, 10) && !buffer[10], "got wrong buffer.\n"); memset(buffer, 0, sizeof(buffer)); PropVariantClear(&propvar); hr = InitPropVariantFromBuffer(data, 10, &propvar); - ok(hr == S_OK, "InitPropVariantFromBuffer failed 0x%08x.\n", hr); + ok(hr == S_OK, "InitPropVariantFromBuffer failed 0x%08lx.\n", hr); buffer[0] = 99; hr = PropVariantToBuffer(&propvar, buffer, 11); - ok(hr == E_FAIL, "PropVariantToBuffer returned: 0x%08x.\n", hr); + ok(hr == E_FAIL, "PropVariantToBuffer returned: 0x%08lx.\n", hr); ok(buffer[0] == 99, "got wrong buffer.\n"); memset(buffer, 0, sizeof(buffer)); PropVariantClear(&propvar); hr = InitPropVariantFromBuffer(data, 10, &propvar); - ok(hr == S_OK, "InitPropVariantFromBuffer failed 0x%08x.\n", hr); + ok(hr == S_OK, "InitPropVariantFromBuffer failed 0x%08lx.\n", hr); hr = PropVariantToBuffer(&propvar, buffer, 9); - ok(hr == S_OK, "PropVariantToBuffer failed: 0x%08x.\n", hr); + ok(hr == S_OK, "PropVariantToBuffer failed: 0x%08lx.\n", hr); ok(!memcmp(buffer, data, 9) && !buffer[9], "got wrong buffer.\n"); memset(buffer, 0, sizeof(buffer)); PropVariantClear(&propvar); @@ -1523,14 +1784,14 @@ static void test_PropVariantToBuffer(void) sa = SafeArrayCreate(VT_UI1, 1, &sabound); ok(sa != NULL, "SafeArrayCreate failed.\n"); hr = SafeArrayAccessData(sa, &pdata); - ok(hr == S_OK, "SafeArrayAccessData failed: 0x%08x.\n", hr); + ok(hr == S_OK, "SafeArrayAccessData failed: 0x%08lx.\n", hr); memcpy(pdata, data, sizeof(data)); hr = SafeArrayUnaccessData(sa); - ok(hr == S_OK, "SafeArrayUnaccessData failed: 0x%08x.\n", hr); - U(propvar).parray = sa; + ok(hr == S_OK, "SafeArrayUnaccessData failed: 0x%08lx.\n", hr); + propvar.parray = sa; buffer[0] = 99; hr = PropVariantToBuffer(&propvar, buffer, 11); - todo_wine ok(hr == E_FAIL, "PropVariantToBuffer returned: 0x%08x.\n", hr); + todo_wine ok(hr == E_FAIL, "PropVariantToBuffer returned: 0x%08lx.\n", hr); ok(buffer[0] == 99, "got wrong buffer.\n"); memset(buffer, 0, sizeof(buffer)); PropVariantClear(&propvar); @@ -1543,24 +1804,24 @@ static void test_PropVariantToBuffer(void) sa = SafeArrayCreate(VT_UI1, 1, &sabound); ok(sa != NULL, "SafeArrayCreate failed.\n"); hr = SafeArrayAccessData(sa, &pdata); - ok(hr == S_OK, "SafeArrayAccessData failed: 0x%08x.\n", hr); + ok(hr == S_OK, "SafeArrayAccessData failed: 0x%08lx.\n", hr); memcpy(pdata, data, sizeof(data)); hr = SafeArrayUnaccessData(sa); - ok(hr == S_OK, "SafeArrayUnaccessData failed: 0x%08x.\n", hr); - U(propvar).parray = sa; + ok(hr == S_OK, "SafeArrayUnaccessData failed: 0x%08lx.\n", hr); + propvar.parray = sa; hr = PropVariantToBuffer(&propvar, buffer, sizeof(data)); - todo_wine ok(hr == S_OK, "PropVariantToBuffer failed: 0x%08x.\n", hr); + todo_wine ok(hr == S_OK, "PropVariantToBuffer failed: 0x%08lx.\n", hr); todo_wine ok(!memcmp(buffer, data, 10) && !buffer[10], "got wrong buffer.\n"); memset(buffer, 0, sizeof(buffer)); PropVariantClear(&propvar); PropVariantInit(&propvar); propvar.vt = VT_VECTOR|VT_I1; - U(propvar).caub.pElems = CoTaskMemAlloc(sizeof(data_int8)); - U(propvar).caub.cElems = sizeof(data_int8); - memcpy(U(propvar).caub.pElems, data_int8, sizeof(data_int8)); + propvar.caub.pElems = CoTaskMemAlloc(sizeof(data_int8)); + propvar.caub.cElems = sizeof(data_int8); + memcpy(propvar.caub.pElems, data_int8, sizeof(data_int8)); hr = PropVariantToBuffer(&propvar, buffer, sizeof(data_int8)); - ok(hr == E_INVALIDARG, "PropVariantToBuffer failed: 0x%08x.\n", hr); + ok(hr == E_INVALIDARG, "PropVariantToBuffer failed: 0x%08lx.\n", hr); PropVariantClear(&propvar); PropVariantInit(&propvar); @@ -1571,32 +1832,829 @@ static void test_PropVariantToBuffer(void) sa = SafeArrayCreate(VT_I1, 1, &sabound); ok(sa != NULL, "SafeArrayCreate failed.\n"); hr = SafeArrayAccessData(sa, &pdata); - ok(hr == S_OK, "SafeArrayAccessData failed: 0x%08x.\n", hr); + ok(hr == S_OK, "SafeArrayAccessData failed: 0x%08lx.\n", hr); memcpy(pdata, data_int8, sizeof(data_int8)); hr = SafeArrayUnaccessData(sa); - ok(hr == S_OK, "SafeArrayUnaccessData failed: 0x%08x.\n", hr); - U(propvar).parray = sa; + ok(hr == S_OK, "SafeArrayUnaccessData failed: 0x%08lx.\n", hr); + propvar.parray = sa; hr = PropVariantToBuffer(&propvar, buffer, sizeof(data_int8)); - ok(hr == E_INVALIDARG, "PropVariantToBuffer failed: 0x%08x.\n", hr); + ok(hr == E_INVALIDARG, "PropVariantToBuffer failed: 0x%08lx.\n", hr); + PropVariantClear(&propvar); +} + +static void test_inmemorystore(void) +{ + IPropertyStoreCache *propcache; + HRESULT hr; + PROPERTYKEY pkey; + PROPVARIANT propvar; + DWORD count; + PSC_STATE state; + + CoInitialize(NULL); + + hr = CoCreateInstance(&CLSID_InMemoryPropertyStore, NULL, CLSCTX_INPROC_SERVER, + &IID_IPropertyStoreCache, (void**)&propcache); + ok(hr == S_OK, "CoCreateInstance failed, hr=%lx\n", hr); + + if (FAILED(hr)) + { + win_skip("CLSID_InMemoryPropertyStore not supported\n"); + CoUninitialize(); + return; + } + + hr = IPropertyStoreCache_GetCount(propcache, NULL); + ok(hr == E_POINTER, "GetCount failed, hr=%lx\n", hr); + + hr = IPropertyStoreCache_GetCount(propcache, &count); + ok(hr == S_OK, "GetCount failed, hr=%lx\n", hr); + ok(count == 0, "GetCount returned %li, expected 0\n", count); + + hr = IPropertyStoreCache_Commit(propcache); + ok(hr == S_OK, "Commit failed, hr=%lx\n", hr); + + hr = IPropertyStoreCache_Commit(propcache); + ok(hr == S_OK, "Commit failed, hr=%lx\n", hr); + + hr = IPropertyStoreCache_GetAt(propcache, 0, &pkey); + ok(hr == E_INVALIDARG, "GetAt failed, hr=%lx\n", hr); + + pkey.fmtid = PKEY_WineTest; + pkey.pid = 4; + + memset(&propvar, 0, sizeof(propvar)); + propvar.vt = VT_I4; + propvar.lVal = 12345; + + if (0) + { + /* Crashes on Windows 7 */ + hr = IPropertyStoreCache_SetValue(propcache, NULL, &propvar); + ok(hr == E_POINTER, "SetValue failed, hr=%lx\n", hr); + + hr = IPropertyStoreCache_SetValue(propcache, &pkey, NULL); + ok(hr == E_POINTER, "SetValue failed, hr=%lx\n", hr); + } + + hr = IPropertyStoreCache_SetValue(propcache, &pkey, &propvar); + ok(hr == S_OK, "SetValue failed, hr=%lx\n", hr); + + hr = IPropertyStoreCache_GetCount(propcache, &count); + ok(hr == S_OK, "GetCount failed, hr=%lx\n", hr); + ok(count == 1, "GetCount returned %li, expected 0\n", count); + + memset(&pkey, 0, sizeof(pkey)); + + hr = IPropertyStoreCache_GetAt(propcache, 0, &pkey); + ok(hr == S_OK, "GetAt failed, hr=%lx\n", hr); + ok(IsEqualGUID(&pkey.fmtid, &PKEY_WineTest), "got wrong pkey\n"); + ok(pkey.pid == 4, "got pid of %li, expected 4\n", pkey.pid); + + pkey.fmtid = PKEY_WineTest; + pkey.pid = 4; + + memset(&propvar, 0, sizeof(propvar)); + + if (0) + { + /* Crashes on Windows 7 */ + hr = IPropertyStoreCache_GetValue(propcache, NULL, &propvar); + ok(hr == E_POINTER, "GetValue failed, hr=%lx\n", hr); + } + + hr = IPropertyStoreCache_GetValue(propcache, &pkey, NULL); + ok(hr == E_POINTER, "GetValue failed, hr=%lx\n", hr); + + hr = IPropertyStoreCache_GetValue(propcache, &pkey, &propvar); + ok(hr == S_OK, "GetValue failed, hr=%lx\n", hr); + ok(propvar.vt == VT_I4, "expected VT_I4, got %d\n", propvar.vt); + ok(propvar.lVal == 12345, "expected 12345, got %ld\n", propvar.lVal); + + pkey.fmtid = PKEY_WineTest; + pkey.pid = 10; + + /* Get information for field that isn't set yet */ + propvar.vt = VT_I2; + hr = IPropertyStoreCache_GetValue(propcache, &pkey, &propvar); + ok(hr == S_OK, "GetValue failed, hr=%lx\n", hr); + ok(propvar.vt == VT_EMPTY, "expected VT_EMPTY, got %d\n", propvar.vt); + + state = 0xdeadbeef; + hr = IPropertyStoreCache_GetState(propcache, &pkey, &state); + ok(hr == TYPE_E_ELEMENTNOTFOUND, "GetState failed, hr=%lx\n", hr); + ok(state == PSC_NORMAL, "expected PSC_NORMAL, got %d\n", state); + + propvar.vt = VT_I2; + state = 0xdeadbeef; + hr = IPropertyStoreCache_GetValueAndState(propcache, &pkey, &propvar, &state); + ok(hr == TYPE_E_ELEMENTNOTFOUND, "GetValueAndState failed, hr=%lx\n", hr); + ok(propvar.vt == VT_EMPTY, "expected VT_EMPTY, got %d\n", propvar.vt); + ok(state == PSC_NORMAL, "expected PSC_NORMAL, got %d\n", state); + + /* Set state on an unset field */ + hr = IPropertyStoreCache_SetState(propcache, &pkey, PSC_NORMAL); + ok(hr == TYPE_E_ELEMENTNOTFOUND, "SetState failed, hr=%lx\n", hr); + + /* Manipulate state on already set field */ + pkey.fmtid = PKEY_WineTest; + pkey.pid = 4; + + state = 0xdeadbeef; + hr = IPropertyStoreCache_GetState(propcache, &pkey, &state); + ok(hr == S_OK, "GetState failed, hr=%lx\n", hr); + ok(state == PSC_NORMAL, "expected PSC_NORMAL, got %d\n", state); + + hr = IPropertyStoreCache_SetState(propcache, &pkey, 10); + ok(hr == S_OK, "SetState failed, hr=%lx\n", hr); + + state = 0xdeadbeef; + hr = IPropertyStoreCache_GetState(propcache, &pkey, &state); + ok(hr == S_OK, "GetState failed, hr=%lx\n", hr); + ok(state == 10, "expected 10, got %d\n", state); + + propvar.vt = VT_I4; + propvar.lVal = 12346; + hr = IPropertyStoreCache_SetValueAndState(propcache, &pkey, &propvar, 5); + ok(hr == S_OK, "SetValueAndState failed, hr=%lx\n", hr); + + memset(&propvar, 0, sizeof(propvar)); + state = 0xdeadbeef; + hr = IPropertyStoreCache_GetValueAndState(propcache, &pkey, &propvar, &state); + ok(hr == S_OK, "GetValueAndState failed, hr=%lx\n", hr); + ok(propvar.vt == VT_I4, "expected VT_I4, got %d\n", propvar.vt); + ok(propvar.lVal == 12346, "expected 12346, got %d\n", propvar.vt); + ok(state == 5, "expected 5, got %d\n", state); + + /* Set new field with state */ + pkey.fmtid = PKEY_WineTest; + pkey.pid = 8; + + propvar.vt = VT_I4; + propvar.lVal = 12347; + hr = IPropertyStoreCache_SetValueAndState(propcache, &pkey, &propvar, PSC_DIRTY); + ok(hr == S_OK, "SetValueAndState failed, hr=%lx\n", hr); + + memset(&propvar, 0, sizeof(propvar)); + state = 0xdeadbeef; + hr = IPropertyStoreCache_GetValueAndState(propcache, &pkey, &propvar, &state); + ok(hr == S_OK, "GetValueAndState failed, hr=%lx\n", hr); + ok(propvar.vt == VT_I4, "expected VT_I4, got %d\n", propvar.vt); + ok(propvar.lVal == 12347, "expected 12347, got %d\n", propvar.vt); + ok(state == PSC_DIRTY, "expected PSC_DIRTY, got %d\n", state); + + IPropertyStoreCache_Release(propcache); + + CoUninitialize(); +} + +static void test_persistserialized(void) +{ + IPropertyStore *propstore; + IPersistSerializedPropStorage *serialized; + HRESULT hr; + SERIALIZEDPROPSTORAGE *result; + DWORD result_size; + + CoInitialize(NULL); + + hr = CoCreateInstance(&CLSID_InMemoryPropertyStore, NULL, CLSCTX_INPROC_SERVER, + &IID_IPropertyStore, (void**)&propstore); + ok(hr == S_OK, "CoCreateInstance failed, hr=%lx\n", hr); + + hr = IPropertyStore_QueryInterface(propstore, &IID_IPersistSerializedPropStorage, + (void**)&serialized); + todo_wine ok(hr == S_OK, "QueryInterface failed, hr=%lx\n", hr); + + if (FAILED(hr)) + { + IPropertyStore_Release(propstore); + skip("IPersistSerializedPropStorage not supported\n"); + CoUninitialize(); + return; + } + + hr = IPersistSerializedPropStorage_GetPropertyStorage(serialized, NULL, &result_size); + ok(hr == E_POINTER, "GetPropertyStorage failed, hr=%lx\n", hr); + + hr = IPersistSerializedPropStorage_GetPropertyStorage(serialized, &result, NULL); + ok(hr == E_POINTER, "GetPropertyStorage failed, hr=%lx\n", hr); + + hr = IPersistSerializedPropStorage_GetPropertyStorage(serialized, &result, &result_size); + ok(hr == S_OK, "GetPropertyStorage failed, hr=%lx\n", hr); + + if (SUCCEEDED(hr)) + { + ok(result_size == 0, "expected 0 bytes, got %li\n", result_size); + + CoTaskMemFree(result); + } + + hr = IPersistSerializedPropStorage_SetPropertyStorage(serialized, NULL, 4); + ok(hr == E_POINTER, "SetPropertyStorage failed, hr=%lx\n", hr); + + hr = IPersistSerializedPropStorage_SetPropertyStorage(serialized, NULL, 0); + ok(hr == S_OK, "SetPropertyStorage failed, hr=%lx\n", hr); + + hr = IPropertyStore_GetCount(propstore, &result_size); + ok(hr == S_OK, "GetCount failed, hr=%lx\n", hr); + ok(result_size == 0, "expecting 0, got %ld\n", result_size); + + IPropertyStore_Release(propstore); + IPersistSerializedPropStorage_Release(serialized); + + CoUninitialize(); +} + +static void test_PSCreateMemoryPropertyStore(void) +{ + IPropertyStore *propstore, *propstore1; + IPersistSerializedPropStorage *serialized; + IPropertyStoreCache *propstorecache; + HRESULT hr; + + /* PSCreateMemoryPropertyStore(&IID_IPropertyStore, NULL); crashes */ + + hr = PSCreateMemoryPropertyStore(&IID_IPropertyStore, (void **)&propstore); + ok(hr == S_OK, "PSCreateMemoryPropertyStore failed: 0x%08lx.\n", hr); + ok(propstore != NULL, "got %p.\n", propstore); + EXPECT_REF(propstore, 1); + + hr = PSCreateMemoryPropertyStore(&IID_IPersistSerializedPropStorage, (void **)&serialized); + todo_wine ok(hr == S_OK, "PSCreateMemoryPropertyStore failed: 0x%08lx.\n", hr); + todo_wine ok(serialized != NULL, "got %p.\n", serialized); + EXPECT_REF(propstore, 1); + if(serialized) + { + EXPECT_REF(serialized, 1); + IPersistSerializedPropStorage_Release(serialized); + } + + hr = PSCreateMemoryPropertyStore(&IID_IPropertyStoreCache, (void **)&propstorecache); + ok(hr == S_OK, "PSCreateMemoryPropertyStore failed: 0x%08lx.\n", hr); + ok(propstorecache != NULL, "got %p.\n", propstore); + ok(propstorecache != (IPropertyStoreCache *)propstore, "pointer are equal: %p, %p.\n", propstorecache, propstore); + EXPECT_REF(propstore, 1); + EXPECT_REF(propstorecache, 1); + + hr = PSCreateMemoryPropertyStore(&IID_IPropertyStore, (void **)&propstore1); + ok(hr == S_OK, "PSCreateMemoryPropertyStore failed: 0x%08lx.\n", hr); + ok(propstore1 != NULL, "got %p.\n", propstore); + ok(propstore1 != propstore, "pointer are equal: %p, %p.\n", propstore1, propstore); + EXPECT_REF(propstore, 1); + EXPECT_REF(propstore1, 1); + EXPECT_REF(propstorecache, 1); + + IPropertyStore_Release(propstore1); + IPropertyStore_Release(propstore); + IPropertyStoreCache_Release(propstorecache); +} + +static void test_propertystore(void) +{ + IPropertyStore *propstore; + HRESULT hr; + PROPVARIANT propvar, ret_propvar; + PROPERTYKEY propkey; + DWORD count = 0; + + hr = PSCreateMemoryPropertyStore(&IID_IPropertyStore, (void **)&propstore); + ok(hr == S_OK, "PSCreateMemoryPropertyStore failed: 0x%08lx.\n", hr); + ok(propstore != NULL, "got %p.\n", propstore); + + hr = IPropertyStore_GetCount(propstore, &count); + ok(hr == S_OK, "IPropertyStore_GetCount failed: 0x%08lx.\n", hr); + ok(!count, "got wrong property count: %ld, expected 0.\n", count); + + PropVariantInit(&propvar); + propvar.vt = VT_I4; + propvar.lVal = 123; + propkey.fmtid = DUMMY_GUID1; + propkey.pid = PID_FIRST_USABLE; + hr = IPropertyStore_SetValue(propstore, &propkey, &propvar); + ok(hr == S_OK, "IPropertyStore_SetValue failed: 0x%08lx.\n", hr); + hr = IPropertyStore_Commit(propstore); + ok(hr == S_OK, "IPropertyStore_Commit failed: 0x%08lx.\n", hr); + hr = IPropertyStore_GetCount(propstore, &count); + ok(hr == S_OK, "IPropertyStore_GetCount failed: 0x%08lx.\n", hr); + ok(count == 1, "got wrong property count: %ld, expected 1.\n", count); + PropVariantInit(&ret_propvar); + ret_propvar.vt = VT_I4; + hr = IPropertyStore_GetValue(propstore, &propkey, &ret_propvar); + ok(hr == S_OK, "IPropertyStore_GetValue failed: 0x%08lx.\n", hr); + ok(ret_propvar.vt == VT_I4, "got wrong property type: %x.\n", ret_propvar.vt); + ok(ret_propvar.lVal == 123, "got wrong value: %ld, expected 123.\n", ret_propvar.lVal); + PropVariantClear(&propvar); + PropVariantClear(&ret_propvar); + + PropVariantInit(&propvar); + propkey.fmtid = DUMMY_GUID1; + propkey.pid = PID_FIRST_USABLE; + hr = IPropertyStore_SetValue(propstore, &propkey, &propvar); + ok(hr == S_OK, "IPropertyStore_SetValue failed: 0x%08lx.\n", hr); + hr = IPropertyStore_Commit(propstore); + ok(hr == S_OK, "IPropertyStore_Commit failed: 0x%08lx.\n", hr); + hr = IPropertyStore_GetCount(propstore, &count); + ok(hr == S_OK, "IPropertyStore_GetCount failed: 0x%08lx.\n", hr); + ok(count == 1, "got wrong property count: %ld, expected 1.\n", count); + PropVariantInit(&ret_propvar); + hr = IPropertyStore_GetValue(propstore, &propkey, &ret_propvar); + ok(hr == S_OK, "IPropertyStore_GetValue failed: 0x%08lx.\n", hr); + ok(ret_propvar.vt == VT_EMPTY, "got wrong property type: %x.\n", ret_propvar.vt); + ok(!ret_propvar.lVal, "got wrong value: %ld, expected 0.\n", ret_propvar.lVal); PropVariantClear(&propvar); + PropVariantClear(&ret_propvar); + + IPropertyStore_Release(propstore); +} + +static void test_PSCreatePropertyStoreFromObject(void) +{ + IPropertyStore *propstore; + IUnknown *unk; + HRESULT hr; + + hr = PSCreateMemoryPropertyStore(&IID_IPropertyStore, (void **)&propstore); + ok(hr == S_OK, "Failed to create property store, hr %#lx.\n", hr); + + hr = PSCreatePropertyStoreFromObject(NULL, STGM_READWRITE, &IID_IUnknown, (void **)&unk); + ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); + + hr = PSCreatePropertyStoreFromObject((IUnknown *)propstore, STGM_READWRITE, &IID_IUnknown, NULL); + ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); + + hr = PSCreatePropertyStoreFromObject((IUnknown *)propstore, STGM_READWRITE, &IID_IUnknown, (void **)&unk); + todo_wine + ok(hr == S_OK, "Failed to create wrapper, hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + { + ok(unk != (IUnknown *)propstore, "Unexpected object returned.\n"); + IUnknown_Release(unk); + } + + hr = PSCreatePropertyStoreFromObject((IUnknown *)propstore, STGM_READWRITE, &IID_IPropertyStore, (void **)&unk); + ok(hr == S_OK, "Failed to create wrapper, hr %#lx.\n", hr); + ok(unk == (IUnknown *)propstore, "Unexpected object returned.\n"); + IUnknown_Release(unk); + + IPropertyStore_Release(propstore); +} + +static void test_InitVariantFromFileTime(void) +{ + FILETIME ft = {0}; + SYSTEMTIME st; + VARIANT var; + HRESULT hr; + double d; + + VariantInit(&var); + if (0) /* crash on Windows */ + { + InitVariantFromFileTime(&ft, NULL); + InitVariantFromFileTime(NULL, &var); + } + + ft.dwHighDateTime = -1; + ft.dwLowDateTime = -1; + V_VT(&var) = 0xdead; + V_DATE(&var) = 42.0; + hr = InitVariantFromFileTime(&ft, &var); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(V_VT(&var) == VT_EMPTY, "Unexpected VT %d\n", V_VT(&var)); + ok(V_DATE(&var) == 0.0, "got wrong value: %f, expected 0.0\n", V_DATE(&var)); + + GetSystemTimeAsFileTime(&ft); + hr = InitVariantFromFileTime(&ft, &var); + ok(V_VT(&var) == VT_DATE, "Unexpected VT %d\n", V_VT(&var)); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + FileTimeToSystemTime(&ft, &st); + SystemTimeToVariantTime(&st, &d); + ok(V_DATE(&var) == d, "got wrong value: %f, expected %f\n", V_DATE(&var), d); +} + +static void test_VariantToStringWithDefault(void) +{ + static WCHAR default_value[] = L"test"; + VARIANT var, var2; + PCWSTR result; + BSTR b; + + V_VT(&var) = VT_EMPTY; + result = VariantToStringWithDefault(&var, NULL); + ok(result == NULL, "Unexpected value %s\n", wine_dbgstr_w(result)); + result = VariantToStringWithDefault(&var, default_value); + ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result)); + + V_VT(&var) = VT_NULL; + result = VariantToStringWithDefault(&var, NULL); + ok(result == NULL, "Unexpected value %s\n", wine_dbgstr_w(result)); + result = VariantToStringWithDefault(&var, default_value); + ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result)); + + V_VT(&var) = VT_BOOL; + result = VariantToStringWithDefault(&var, NULL); + ok(result == NULL, "Unexpected value %s\n", wine_dbgstr_w(result)); + V_BOOL(&var) = VARIANT_TRUE; + result = VariantToStringWithDefault(&var, default_value); + ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result)); + + V_VT(&var) = VT_CY; + V_CY(&var).int64 = 100000; + result = VariantToStringWithDefault(&var, NULL); + ok(result == NULL, "Unexpected value %s\n", wine_dbgstr_w(result)); + result = VariantToStringWithDefault(&var, default_value); + ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result)); + + V_VT(&var) = VT_DATE; + V_DATE(&var) = 42.0; + result = VariantToStringWithDefault(&var, NULL); + ok(result == NULL, "Unexpected value %s\n", wine_dbgstr_w(result)); + result = VariantToStringWithDefault(&var, default_value); + ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result)); + + V_VT(&var) = VT_ERROR; + V_ERROR(&var) = DISP_E_PARAMNOTFOUND; + result = VariantToStringWithDefault(&var, NULL); + ok(result == NULL, "Unexpected value %s\n", wine_dbgstr_w(result)); + result = VariantToStringWithDefault(&var, default_value); + ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result)); + + V_VT(&var) = VT_I4; + V_I4(&var) = 15; + result = VariantToStringWithDefault(&var, NULL); + ok(result == NULL, "Unexpected value %s\n", wine_dbgstr_w(result)); + result = VariantToStringWithDefault(&var, default_value); + ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result)); + + V_VT(&var) = VT_I1; + V_I1(&var) = 1; + result = VariantToStringWithDefault(&var, NULL); + ok(result == NULL, "Unexpected value %s\n", wine_dbgstr_w(result)); + result = VariantToStringWithDefault(&var, default_value); + ok(result == default_value, "Unexpected value %s\n", wine_dbgstr_w(result)); + + /* V_BSTR */ + + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = NULL; + result = VariantToStringWithDefault(&var, default_value); + ok(result[0] == '\0', "Unexpected value %s\n", wine_dbgstr_w(result)); + + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = SysAllocString(L""); + result = VariantToStringWithDefault(&var, default_value); + ok(result == V_BSTR(&var), "Unexpected value %s\n", wine_dbgstr_w(result)); + VariantClear(&var); + + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = SysAllocString(L" "); + result = VariantToStringWithDefault(&var, default_value); + ok(result == V_BSTR(&var), "Unexpected value %s\n", wine_dbgstr_w(result)); + VariantClear(&var); + + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = SysAllocString(L"test1"); + result = VariantToStringWithDefault(&var, default_value); + ok(result == V_BSTR(&var), "Unexpected value %s\n", wine_dbgstr_w(result)); + VariantClear(&var); + + /* V_BSTRREF */ + + V_VT(&var) = VT_BYREF | VT_BSTR; + b = NULL; + V_BSTRREF(&var) = &b; + result = VariantToStringWithDefault(&var, default_value); + ok(result[0] == '\0', "Unexpected value %s\n", wine_dbgstr_w(result)); + + V_VT(&var) = VT_BYREF | VT_BSTR; + b = SysAllocString(L""); + V_BSTRREF(&var) = &b; + result = VariantToStringWithDefault(&var, default_value); + ok(result == b, "Unexpected value %s\n", wine_dbgstr_w(result)); + SysFreeString(b); + + V_VT(&var) = VT_BYREF | VT_BSTR; + b = SysAllocString(L" "); + V_BSTRREF(&var) = &b; + result = VariantToStringWithDefault(&var, default_value); + ok(result == b, "Unexpected value %s\n", wine_dbgstr_w(result)); + SysFreeString(b); + + V_VT(&var) = VT_BYREF | VT_BSTR; + b = SysAllocString(L"test1"); + V_BSTRREF(&var) = &b; + result = VariantToStringWithDefault(&var, default_value); + ok(result == b, "Unexpected value %s\n", wine_dbgstr_w(result)); + SysFreeString(b); + + /* Nested V_BSTR */ + + V_VT(&var) = VT_BYREF | VT_VARIANT; + V_VT(&var2) = VT_BSTR; + V_BSTR(&var2) = NULL; + V_VARIANTREF(&var) = &var2; + result = VariantToStringWithDefault(&var, default_value); + ok(result[0] == '\0', "Unexpected value %s\n", wine_dbgstr_w(result)); + + V_VT(&var) = VT_BYREF | VT_VARIANT; + V_VT(&var2) = VT_BSTR; + V_BSTR(&var2) = SysAllocString(L""); + V_VARIANTREF(&var) = &var2; + result = VariantToStringWithDefault(&var, default_value); + ok(result == V_BSTR(&var2), "Unexpected value %s\n", wine_dbgstr_w(result)); + VariantClear(&var2); + + V_VT(&var) = VT_BYREF | VT_VARIANT; + V_VT(&var2) = VT_BSTR; + V_BSTR(&var2) = SysAllocString(L" "); + V_VARIANTREF(&var) = &var2; + result = VariantToStringWithDefault(&var, default_value); + ok(result == V_BSTR(&var2), "Unexpected value %s\n", wine_dbgstr_w(result)); + VariantClear(&var2); + + V_VT(&var) = VT_BYREF | VT_VARIANT; + V_VT(&var2) = VT_BSTR; + V_BSTR(&var2) = SysAllocString(L"test1"); + V_VARIANTREF(&var) = &var2; + result = VariantToStringWithDefault(&var, default_value); + ok(result == V_BSTR(&var2), "Unexpected value %s\n", wine_dbgstr_w(result)); + VariantClear(&var2); + + /* Nested V_BSTRREF */ + + V_VT(&var) = VT_BYREF | VT_VARIANT; + V_VT(&var2) = VT_BYREF | VT_BSTR; + b = NULL; + V_BSTRREF(&var2) = &b; + V_VARIANTREF(&var) = &var2; + result = VariantToStringWithDefault(&var, default_value); + ok(result[0] == '\0', "Unexpected value %s\n", wine_dbgstr_w(result)); + + V_VT(&var) = VT_BYREF | VT_VARIANT; + V_VT(&var2) = VT_BYREF | VT_BSTR; + b = SysAllocString(L""); + V_BSTRREF(&var2) = &b; + V_VARIANTREF(&var) = &var2; + result = VariantToStringWithDefault(&var, default_value); + ok(result == b, "Unexpected value %s\n", wine_dbgstr_w(result)); + SysFreeString(b); + + V_VT(&var) = VT_BYREF | VT_VARIANT; + V_VT(&var2) = VT_BYREF | VT_BSTR; + b = SysAllocString(L" "); + V_BSTRREF(&var2) = &b; + V_VARIANTREF(&var) = &var2; + result = VariantToStringWithDefault(&var, default_value); + ok(result == b, "Unexpected value %s\n", wine_dbgstr_w(result)); + SysFreeString(b); + + V_VT(&var) = VT_BYREF | VT_VARIANT; + V_VT(&var2) = VT_BYREF | VT_BSTR; + b = SysAllocString(L"test1"); + V_BSTRREF(&var2) = &b; + V_VARIANTREF(&var) = &var2; + result = VariantToStringWithDefault(&var, default_value); + ok(result == b, "Unexpected value %s\n", wine_dbgstr_w(result)); + SysFreeString(b); +} + +static void test_VariantToString(void) +{ + HRESULT hr; + VARIANT v; + WCHAR buff[64]; + + buff[0] = 1; + V_VT(&v) = VT_EMPTY; + hr = VariantToString(&v, buff, 64); + todo_wine + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!buff[0], "Unexpected buffer.\n"); + + buff[0] = 0; + V_VT(&v) = VT_I4; + V_I4(&v) = 567; + hr = VariantToString(&v, buff, 64); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!wcscmp(buff, L"567"), "Unexpected buffer %s.\n", wine_dbgstr_w(buff)); + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = SysAllocString(L"test1"); + + buff[0] = 1; + hr = VariantToString(&v, buff, 0); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(!buff[0], "Unexpected buffer.\n"); + + hr = VariantToString(&v, buff, 5); + ok(hr == STRSAFE_E_INSUFFICIENT_BUFFER, "Unexpected hr %#lx.\n", hr); + hr = VariantToString(&v, buff, 6); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!wcscmp(buff, L"test1"), "Unexpected string.\n"); + VariantClear(&v); +} + +#define check_VariantToPropVariant(var, propvar, type, member, value, format) do \ +{ \ + V_VT(&(var)) = VT_##type; \ + V_##type(&(var)) = (value); \ + hr = VariantToPropVariant(&(var), &(propvar)); \ + ok_(__FILE__, __LINE__)(hr == S_OK, "VariantToPropVariant returned %#lx.\n", hr); \ + ok_(__FILE__, __LINE__)((propvar).vt == VT_##type, "Unexpected propvar.vt %d.\n", (propvar).vt); \ + ok_(__FILE__, __LINE__)((propvar).member == (value), \ + "Unexpected propvar."#member" "format".\n", (propvar).member); \ +} while (0) + +#define check_PropVariantToVariant(propvar, var, type, member, value, format) do \ +{ \ + (propvar).vt = VT_##type; \ + (propvar).member = (value); \ + hr = PropVariantToVariant(&(propvar), &(var)); \ + ok_(__FILE__, __LINE__)(hr == S_OK, "PropVariantToVariant returned %#lx.\n", hr); \ + ok_(__FILE__, __LINE__)(V_VT(&(var)) == VT_##type, "Unexpected vt %d.\n", V_VT(&(var))); \ + ok_(__FILE__, __LINE__)(V_##type(&(var)) == (value), \ + "Unexpected V_"#type"(&var) "format".\n", (propvar).member); \ +} while (0) + +static void test_VariantToPropVariant(void) +{ + PROPVARIANT propvar; + VARIANT var; + HRESULT hr; + + VariantInit(&var); + PropVariantInit(&propvar); + + hr = VariantToPropVariant(NULL, &propvar); + ok(hr == E_INVALIDARG, "VariantToPropVariant returned %#lx.\n", hr); + hr = VariantToPropVariant(&var, NULL); + ok(hr == E_INVALIDARG, "VariantToPropVariant returned %#lx.\n", hr); + + V_VT(&var) = 0xdead; + hr = VariantToPropVariant(&var, &propvar); + ok(hr == DISP_E_BADVARTYPE, "VariantToPropVariant returned %#lx.\n", hr); + V_VT(&var) = VT_ILLEGAL; + hr = VariantToPropVariant(&var, &propvar); + todo_wine + ok(hr == TYPE_E_TYPEMISMATCH, "VariantToPropVariant returned %#lx.\n", hr); + V_VT(&var) = VT_CLSID; + hr = VariantToPropVariant(&var, &propvar); + todo_wine + ok(hr == DISP_E_BADVARTYPE, "VariantToPropVariant returned %#lx.\n", hr); + + V_VT(&var) = VT_EMPTY; + hr = VariantToPropVariant(&var, &propvar); + ok(hr == S_OK, "VariantToPropVariant returned %#lx.\n", hr); + ok(propvar.vt == VT_EMPTY, "Unexpected propvar.vt %d.\n", propvar.vt); + + V_VT(&var) = VT_NULL; + hr = VariantToPropVariant(&var, &propvar); + ok(hr == S_OK, "VariantToPropVariant returned %#lx.\n", hr); + ok(propvar.vt == VT_NULL, "Unexpected propvar.vt %d.\n", propvar.vt); + + check_VariantToPropVariant(var, propvar, I1, cVal, -123, "%c"); + check_VariantToPropVariant(var, propvar, I2, iVal, -456, "%d"); + check_VariantToPropVariant(var, propvar, I4, lVal, -789, "%ld"); + check_VariantToPropVariant(var, propvar, I8, hVal.QuadPart, -101112, "%I64d"); + + check_VariantToPropVariant(var, propvar, UI1, bVal, 0xcd, "%#x"); + check_VariantToPropVariant(var, propvar, UI2, uiVal, 0xdead, "%#x"); + check_VariantToPropVariant(var, propvar, UI4, ulVal, 0xdeadbeef, "%#lx"); + check_VariantToPropVariant(var, propvar, UI8, uhVal.QuadPart, 0xdeadbeefdeadbeef, "%I64x"); + + check_VariantToPropVariant(var, propvar, BOOL, boolVal, TRUE, "%d"); + + check_VariantToPropVariant(var, propvar, R4, fltVal, 0.123f, "%f"); + check_VariantToPropVariant(var, propvar, R8, dblVal, 0.456f, "%f"); + + V_VT(&var) = VT_BSTR; + V_BSTR(&var) = SysAllocString(L"test"); + hr = VariantToPropVariant(&var, &propvar); + ok(hr == S_OK, "VariantToPropVariant returned %#lx.\n", hr); + ok(propvar.vt == VT_BSTR, "Unexpected propvar.vt %d.\n", propvar.vt); + ok(propvar.bstrVal != V_BSTR(&var), "Got same string pointer.\n"); + ok(!wcscmp(propvar.bstrVal, V_BSTR(&var)), "Unexpected propvar.bstrVal %s.\n", debugstr_w(propvar.bstrVal)); + + PropVariantClear(&propvar); + VariantClear(&var); +} + +static void test_PropVariantToVariant(void) +{ + PROPVARIANT propvar; + VARIANT var; + HRESULT hr; + + VariantInit(&var); + PropVariantInit(&propvar); + + hr = PropVariantToVariant(NULL, &var); + ok(hr == E_INVALIDARG, "PropVariantToVariant returned %#lx.\n", hr); + hr = PropVariantToVariant(&propvar, NULL); + ok(hr == E_INVALIDARG, "PropVariantToVariant returned %#lx.\n", hr); + + propvar.vt = 0xdead; + hr = PropVariantToVariant(&propvar, &var); + todo_wine + ok(hr == E_OUTOFMEMORY, "PropVariantToVariant returned %#lx.\n", hr); + propvar.vt = VT_ILLEGAL; + hr = PropVariantToVariant(&propvar, &var); + todo_wine + ok(hr == E_OUTOFMEMORY, "PropVariantToVariant returned %#lx.\n", hr); + + propvar.vt = VT_EMPTY; + hr = PropVariantToVariant(&propvar, &var); + ok(hr == S_OK, "PropVariantToVariant returned %#lx.\n", hr); + ok(V_VT(&var) == VT_EMPTY, "Unexpected V_VT(&var) %d.\n", V_VT(&var)); + + propvar.vt = VT_NULL; + hr = PropVariantToVariant(&propvar, &var); + ok(hr == S_OK, "PropVariantToVariant returned %#lx.\n", hr); + ok(V_VT(&var) == VT_NULL, "Unexpected V_VT(&var) %d.\n", V_VT(&var)); + + check_PropVariantToVariant(propvar, var, I1, cVal, 'X', "%c"); + check_PropVariantToVariant(propvar, var, I2, iVal, -456, "%d"); + check_PropVariantToVariant(propvar, var, I4, lVal, -789, "%ld"); + check_PropVariantToVariant(propvar, var, I8, hVal.QuadPart, -101112, "%I64d"); + + check_PropVariantToVariant(propvar, var, UI1, bVal, 0xcd, "%#x"); + check_PropVariantToVariant(propvar, var, UI2, uiVal, 0xdead, "%#x"); + check_PropVariantToVariant(propvar, var, UI4, ulVal, 0xdeadbeef, "%#lx"); + check_PropVariantToVariant(propvar, var, UI8, uhVal.QuadPart, 0xdeadbeefdeadbeef, "%I64x"); + + check_PropVariantToVariant(propvar, var, BOOL, boolVal, TRUE, "%d"); + + check_PropVariantToVariant(propvar, var, R4, fltVal, 0.123f, "%f"); + check_PropVariantToVariant(propvar, var, R8, dblVal, 0.456f, "%f"); + + propvar.vt = VT_BSTR; + propvar.bstrVal = SysAllocString(L"test"); + hr = PropVariantToVariant(&propvar, &var); + ok(hr == S_OK, "PropVariantToVariant returned %#lx.\n", hr); + ok(V_VT(&var) == VT_BSTR, "Unexpected V_VT(&var) %d.\n", V_VT(&var)); + ok(V_BSTR(&var) != propvar.bstrVal, "Got same string pointer.\n"); + ok(!wcscmp(V_BSTR(&var), propvar.bstrVal), "Unexpected V_BSTR(&var) %s.\n", debugstr_w(V_BSTR(&var))); + PropVariantClear(&propvar); + VariantClear(&var); + + propvar.vt = VT_CLSID; + propvar.puuid = (GUID *)&dummy_guid; + hr = PropVariantToVariant(&propvar, &var); + todo_wine + ok(hr == 39, "PropVariantToVariant returned %#lx.\n", hr); + ok(V_VT(&var) == VT_BSTR, "Unexpected V_VT(&var) %d.\n", V_VT(&var)); + ok(!wcscmp(V_BSTR(&var), dummy_guid_str), "Unexpected V_BSTR(&var) %s.\n", debugstr_w(V_BSTR(&var))); + VariantClear(&var); + + propvar.vt = VT_LPSTR; + propvar.pszVal = (char *)topic; + hr = PropVariantToVariant(&propvar, &var); + ok(hr == S_OK, "PropVariantToVariant returned %#lx.\n", hr); + ok(V_VT(&var) == VT_BSTR, "Unexpected V_VT(&var) %d.\n", V_VT(&var)); + ok(!wcscmp(V_BSTR(&var), topicW), "Unexpected V_BSTR(&var) %s.\n", debugstr_w(V_BSTR(&var))); + VariantClear(&var); + + propvar.vt = VT_LPWSTR; + propvar.pwszVal = (WCHAR *)topicW; + hr = PropVariantToVariant(&propvar, &var); + ok(hr == S_OK, "PropVariantToVariant returned %#lx.\n", hr); + ok(V_VT(&var) == VT_BSTR, "Unexpected V_VT(&var) %d.\n", V_VT(&var)); + ok(V_BSTR(&var) != topicW, "Got same string pointer.\n"); + ok(!wcscmp(V_BSTR(&var), topicW), "Unexpected V_BSTR(&var) %s.\n", debugstr_w(V_BSTR(&var))); + VariantClear(&var); } START_TEST(propsys) { + test_InitPropVariantFromGUIDAsString(); + test_InitPropVariantFromBuffer(); + test_InitPropVariantFromCLSID(); + test_InitPropVariantFromStringVector(); + test_InitVariantFromFileTime(); + test_PSStringFromPropertyKey(); test_PSPropertyKeyFromString(); test_PSRefreshPropertySchema(); - test_InitPropVariantFromGUIDAsString(); - test_InitPropVariantFromBuffer(); test_PropVariantToGUID(); test_PropVariantToStringAlloc(); - test_PropVariantCompare(); + test_PropVariantCompareEx(); test_intconversions(); test_PropVariantChangeType_LPWSTR(); test_PropVariantToBoolean(); test_PropVariantToStringWithDefault(); - test_InitPropVariantFromCLSID(); test_PropVariantToDouble(); test_PropVariantToString(); + test_PropVariantToBSTR(); test_PropVariantToBuffer(); + test_inmemorystore(); + test_persistserialized(); + test_PSCreateMemoryPropertyStore(); + test_propertystore(); + test_PSCreatePropertyStoreFromObject(); + test_VariantToStringWithDefault(); + test_VariantToString(); + test_VariantToPropVariant(); + test_PropVariantToVariant(); } diff --git a/modules/rostests/winetests/propsys/testlist.c b/modules/rostests/winetests/propsys/testlist.c index 3773d6ad652..364dec7c1a9 100644 --- a/modules/rostests/winetests/propsys/testlist.c +++ b/modules/rostests/winetests/propsys/testlist.c @@ -3,12 +3,10 @@ #define STANDALONE #include <wine/test.h> -extern void func_propstore(void); extern void func_propsys(void); const struct test winetest_testlist[] = { - { "propstore", func_propstore }, { "propsys", func_propsys }, { 0, 0 } }; diff --git a/sdk/include/psdk/oaidl.idl b/sdk/include/psdk/oaidl.idl index 0dc4c057460..27e27a92125 100644 --- a/sdk/include/psdk/oaidl.idl +++ b/sdk/include/psdk/oaidl.idl @@ -230,6 +230,17 @@ typedef VARIANT *LPVARIANT; typedef VARIANT VARIANTARG; typedef VARIANTARG *LPVARIANTARG; +cpp_quote("#ifdef MIDL_PASS") +typedef const VARIANT *REFVARIANT; +cpp_quote("#elif !defined(_REFVARIANT_DEFINED)") +cpp_quote("#define _REFVARIANT_DEFINED") +cpp_quote("#ifdef __cplusplus") +cpp_quote("#define REFVARIANT const VARIANT &") +cpp_quote("#else") +cpp_quote("#define REFVARIANT const VARIANT *__MIDL_CONST") +cpp_quote("#endif") +cpp_quote("#endif") + struct _wireBRECORD { ULONG fFlags; ULONG clSize; diff --git a/sdk/include/psdk/propsys.idl b/sdk/include/psdk/propsys.idl index bdd67fa6a59..240bbfd86ca 100644 --- a/sdk/include/psdk/propsys.idl +++ b/sdk/include/psdk/propsys.idl @@ -27,7 +27,13 @@ import "shtypes.idl"; import "structuredquerycondition.idl"; cpp_quote("#ifndef PSSTDAPI") -cpp_quote("#define PSSTDAPI EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE") +cpp_quote("#ifdef _PROPSYS_") +cpp_quote("#define PSSTDAPI STDAPI") +cpp_quote("#define PSSTDAPI_(type) STDAPI_(type)") +cpp_quote("#else") +cpp_quote("#define PSSTDAPI EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE") +cpp_quote("#define PSSTDAPI_(type) EXTERN_C DECLSPEC_IMPORT type STDAPICALLTYPE") +cpp_quote("#endif") cpp_quote("#endif") cpp_quote("#if 0") @@ -272,7 +278,7 @@ interface IPropertyEnumType : IUnknown } [ - uuid(9b6e051c-5ddd-4321-9070-fe2acb55e974), + uuid(9b6e051c-5ddd-4321-9070-fe2acb55e794), object, pointer_default(unique) ] @@ -799,14 +805,15 @@ cpp_quote("#define PKEY_PIDSTR_MAX 10") cpp_quote("#define GUIDSTRING_MAX 39") cpp_quote("#define PKEYSTR_MAX (GUIDSTRING_MAX + 1 + PKEY_PIDSTR_MAX)") -cpp_quote("HRESULT WINAPI PSCreateMemoryPropertyStore(REFIID,void **);") -cpp_quote("HRESULT WINAPI PSStringFromPropertyKey(REFPROPERTYKEY,LPWSTR,UINT);") -cpp_quote("HRESULT WINAPI PSPropertyKeyFromString(LPCWSTR,PROPERTYKEY*);") -cpp_quote("HRESULT WINAPI PSGetPropertyDescription(REFPROPERTYKEY,REFIID,void **);") -cpp_quote("HRESULT WINAPI PSGetPropertyDescriptionListFromString(LPCWSTR,REFIID,void **);") -cpp_quote("HRESULT WINAPI PSRefreshPropertySchema(void);") -cpp_quote("HRESULT WINAPI PSRegisterPropertySchema(LPCWSTR);") -cpp_quote("HRESULT WINAPI PSUnregisterPropertySchema(LPCWSTR);") +cpp_quote("PSSTDAPI PSCreateMemoryPropertyStore(REFIID,void **);") +cpp_quote("PSSTDAPI PSCreatePropertyStoreFromObject(IUnknown*,DWORD,REFIID,void **);") +cpp_quote("PSSTDAPI PSStringFromPropertyKey(REFPROPERTYKEY,LPWSTR,UINT);") +cpp_quote("PSSTDAPI PSPropertyKeyFromString(LPCWSTR,PROPERTYKEY*);") +cpp_quote("PSSTDAPI PSGetPropertyDescription(REFPROPERTYKEY,REFIID,void **);") +cpp_quote("PSSTDAPI PSGetPropertyDescriptionListFromString(LPCWSTR,REFIID,void **);") +cpp_quote("PSSTDAPI PSRefreshPropertySchema(void);") +cpp_quote("PSSTDAPI PSRegisterPropertySchema(LPCWSTR);") +cpp_quote("PSSTDAPI PSUnregisterPropertySchema(LPCWSTR);") /* TODO: Add remainder of the C api here */ @@ -821,7 +828,7 @@ library PropSysObjects { interface IPropertyStore; } - [uuid(b8967f86-58ae-4f96-9fb2-5d7904798f4b)] coclass PropertySystem + [uuid(b8967f85-58ae-4f46-9fb2-5d7904798f4b)] coclass PropertySystem { interface IPropertySystem; } diff --git a/sdk/include/psdk/propvarutil.h b/sdk/include/psdk/propvarutil.h index e0a21faf8c7..9f689033548 100644 --- a/sdk/include/psdk/propvarutil.h +++ b/sdk/include/psdk/propvarutil.h @@ -22,6 +22,16 @@ #include <shtypes.h> #include <shlwapi.h> +#ifndef PSSTDAPI +#ifdef _PROPSYS_ +#define PSSTDAPI STDAPI +#define PSSTDAPI_(type) STDAPI_(type) +#else +#define PSSTDAPI DECLSPEC_IMPORT STDAPI +#define PSSTDAPI_(type) DECLSPEC_IMPORT STDAPI_(type) +#endif +#endif + #ifdef __cplusplus extern "C" { #endif @@ -63,37 +73,56 @@ enum tagPROPVAR_COMPARE_FLAGS typedef int PROPVAR_COMPARE_FLAGS; -HRESULT WINAPI PropVariantChangeType(PROPVARIANT *ppropvarDest, REFPROPVARIANT propvarSrc, +PSSTDAPI PropVariantChangeType(PROPVARIANT *ppropvarDest, REFPROPVARIANT propvarSrc, PROPVAR_CHANGE_FLAGS flags, VARTYPE vt); -HRESULT WINAPI InitPropVariantFromGUIDAsString(REFGUID guid, PROPVARIANT *ppropvar); -HRESULT WINAPI InitVariantFromGUIDAsString(REFGUID guid, VARIANT *pvar); -HRESULT WINAPI InitPropVariantFromBuffer(const VOID *pv, UINT cb, PROPVARIANT *ppropvar); -HRESULT WINAPI InitPropVariantFromCLSID(REFCLSID clsid, PROPVARIANT *ppropvar); -HRESULT WINAPI InitVariantFromBuffer(const VOID *pv, UINT cb, VARIANT *pvar); -HRESULT WINAPI PropVariantToGUID(const PROPVARIANT *ppropvar, GUID *guid); -HRESULT WINAPI VariantToGUID(const VARIANT *pvar, GUID *guid); -INT WINAPI PropVariantCompareEx(REFPROPVARIANT propvar1, REFPROPVARIANT propvar2, +PSSTDAPI InitPropVariantFromGUIDAsString(REFGUID guid, PROPVARIANT *ppropvar); +PSSTDAPI InitVariantFromFileTime(const FILETIME *ft, VARIANT *var); +PSSTDAPI InitVariantFromGUIDAsString(REFGUID guid, VARIANT *pvar); +PSSTDAPI InitPropVariantFromBuffer(const VOID *pv, UINT cb, PROPVARIANT *ppropvar); +PSSTDAPI InitPropVariantFromCLSID(REFCLSID clsid, PROPVARIANT *ppropvar); +PSSTDAPI InitVariantFromBuffer(const VOID *pv, UINT cb, VARIANT *pvar); +PSSTDAPI PropVariantToGUID(const PROPVARIANT *ppropvar, GUID *guid); +PSSTDAPI VariantToGUID(const VARIANT *pvar, GUID *guid); +PSSTDAPI_(INT) PropVariantCompareEx(REFPROPVARIANT propvar1, REFPROPVARIANT propvar2, PROPVAR_COMPARE_UNIT uint, PROPVAR_COMPARE_FLAGS flags); - -HRESULT WINAPI PropVariantToDouble(REFPROPVARIANT propvarIn, double *ret); -HRESULT WINAPI PropVariantToInt16(REFPROPVARIANT propvarIn, SHORT *ret); -HRESULT WINAPI PropVariantToInt32(REFPROPVARIANT propvarIn, LONG *ret); -HRESULT WINAPI PropVariantToInt64(REFPROPVARIANT propvarIn, LONGLONG *ret); -HRESULT WINAPI PropVariantToUInt16(REFPROPVARIANT propvarIn, USHORT *ret); -HRESULT WINAPI PropVariantToUInt32(REFPROPVARIANT propvarIn, ULONG *ret); -HRESULT WINAPI PropVariantToUInt64(REFPROPVARIANT propvarIn, ULONGLONG *ret); -HRESULT WINAPI PropVariantToBoolean(REFPROPVARIANT propvarIn, BOOL *ret); -HRESULT WINAPI PropVariantToBuffer(REFPROPVARIANT propvarIn, void *ret, UINT cb); -HRESULT WINAPI PropVariantToString(REFPROPVARIANT propvarIn, PWSTR ret, UINT cch); -PCWSTR WINAPI PropVariantToStringWithDefault(REFPROPVARIANT propvarIn, LPCWSTR pszDefault); - -HRESULT WINAPI PropVariantToStringAlloc(REFPROPVARIANT propvarIn, WCHAR **ret); +PSSTDAPI InitPropVariantFromFileTime(const FILETIME *pftIn, PROPVARIANT *ppropvar); +PSSTDAPI InitPropVariantFromStringVector(PCWSTR *strs, ULONG count, PROPVARIANT *ppropvar); + +PSSTDAPI PropVariantToDouble(REFPROPVARIANT propvarIn, double *ret); +PSSTDAPI PropVariantToInt16(REFPROPVARIANT propvarIn, SHORT *ret); +PSSTDAPI PropVariantToInt32(REFPROPVARIANT propvarIn, LONG *ret); +PSSTDAPI PropVariantToInt64(REFPROPVARIANT propvarIn, LONGLONG *ret); +PSSTDAPI PropVariantToUInt16(REFPROPVARIANT propvarIn, USHORT *ret); +PSSTDAPI PropVariantToUInt32(REFPROPVARIANT propvarIn, ULONG *ret); +PSSTDAPI_(ULONG) PropVariantToUInt32WithDefault(REFPROPVARIANT propvarIn, ULONG uLDefault); +PSSTDAPI PropVariantToUInt64(REFPROPVARIANT propvarIn, ULONGLONG *ret); +PSSTDAPI PropVariantToBoolean(REFPROPVARIANT propvarIn, BOOL *ret); +PSSTDAPI PropVariantToBSTR(REFPROPVARIANT propvar, BSTR *bstr); +PSSTDAPI PropVariantToBuffer(REFPROPVARIANT propvarIn, void *ret, UINT cb); +PSSTDAPI PropVariantToString(REFPROPVARIANT propvarIn, PWSTR ret, UINT cch); +PSSTDAPI_(PCWSTR) PropVariantToStringWithDefault(REFPROPVARIANT propvarIn, LPCWSTR pszDefault); +PSSTDAPI_(PCWSTR) VariantToStringWithDefault(const VARIANT *pvar, LPCWSTR pszDefault); +PSSTDAPI VariantToString(REFVARIANT var, PWSTR ret, UINT cch); + +PSSTDAPI PropVariantToStringAlloc(REFPROPVARIANT propvarIn, WCHAR **ret); + +PSSTDAPI PropVariantToVariant(const PROPVARIANT *propvar, VARIANT *var); +PSSTDAPI VariantToPropVariant(const VARIANT* var, PROPVARIANT* propvar); #ifdef __cplusplus HRESULT InitPropVariantFromBoolean(BOOL fVal, PROPVARIANT *ppropvar); -HRESULT InitPropVariantFromString(PCWSTR psz, PROPVARIANT *ppropvar); +HRESULT InitPropVariantFromInt16(SHORT nVal, PROPVARIANT *ppropvar); +HRESULT InitPropVariantFromUInt16(USHORT uiVal, PROPVARIANT *ppropvar); +HRESULT InitPropVariantFromInt32(LONG lVal, PROPVARIANT *ppropvar); +HRESULT InitPropVariantFromUInt32(ULONG ulVal, PROPVARIANT *ppropvar); HRESULT InitPropVariantFromInt64(LONGLONG llVal, PROPVARIANT *ppropvar); +HRESULT InitPropVariantFromUInt64(ULONGLONG ullVal, PROPVARIANT *ppropvar); +HRESULT InitPropVariantFromDouble(DOUBLE dblVal, PROPVARIANT *ppropvar); +HRESULT InitPropVariantFromString(PCWSTR psz, PROPVARIANT *ppropvar); +HRESULT InitPropVariantFromGUIDAsBuffer(REFGUID guid, PROPVARIANT *ppropvar); +BOOL IsPropVariantVector(REFPROPVARIANT propvar); +BOOL IsPropVariantString(REFPROPVARIANT propvar); #ifndef NO_PROPVAR_INLINES @@ -104,6 +133,55 @@ inline HRESULT InitPropVariantFromBoolean(BOOL fVal, PROPVARIANT *ppropvar) return S_OK; } +inline HRESULT InitPropVariantFromInt16(SHORT nVal, PROPVARIANT *ppropvar) +{ + ppropvar->vt = VT_I2; + ppropvar->iVal = nVal; + return S_OK; +} + +inline HRESULT InitPropVariantFromUInt16(USHORT uiVal, PROPVARIANT *ppropvar) +{ + ppropvar->vt = VT_UI2; + ppropvar->uiVal = uiVal; + return S_OK; +} + +inline HRESULT InitPropVariantFromInt32(LONG lVal, PROPVARIANT *ppropvar) +{ + ppropvar->vt = VT_I4; + ppropvar->lVal = lVal; + return S_OK; +} + +inline HRESULT InitPropVariantFromUInt32(ULONG ulVal, PROPVARIANT *ppropvar) +{ + ppropvar->vt = VT_UI4; + ppropvar->ulVal = ulVal; + return S_OK; +} + +inline HRESULT InitPropVariantFromInt64(LONGLONG llVal, PROPVARIANT *ppropvar) +{ + ppropvar->vt = VT_I8; + ppropvar->hVal.QuadPart = llVal; + return S_OK; +} + +inline HRESULT InitPropVariantFromUInt64(ULONGLONG ullVal, PROPVARIANT *ppropvar) +{ + ppropvar->vt = VT_UI8; + ppropvar->uhVal.QuadPart = ullVal; + return S_OK; +} + +inline HRESULT InitPropVariantFromDouble(DOUBLE dblVal, PROPVARIANT *ppropvar) +{ + ppropvar->vt = VT_R8; + ppropvar->dblVal = dblVal; + return S_OK; +} + inline HRESULT InitPropVariantFromString(PCWSTR psz, PROPVARIANT *ppropvar) { HRESULT hres; @@ -117,16 +195,26 @@ inline HRESULT InitPropVariantFromString(PCWSTR psz, PROPVARIANT *ppropvar) return hres; } -inline HRESULT InitPropVariantFromInt64(LONGLONG llVal, PROPVARIANT *ppropvar) +inline HRESULT InitPropVariantFromGUIDAsBuffer(REFGUID guid, PROPVARIANT *ppropvar) { - ppropvar->vt = VT_I8; - ppropvar->hVal.QuadPart = llVal; - return S_OK; + return InitPropVariantFromBuffer(&guid, sizeof(GUID), ppropvar); +} + +inline BOOL IsPropVariantVector(REFPROPVARIANT propvar) +{ + return (propvar.vt & (VT_ARRAY | VT_VECTOR)); +} + +inline BOOL IsPropVariantString(REFPROPVARIANT propvar) +{ + return (PropVariantToStringWithDefault(propvar, NULL) != NULL); } #endif /* NO_PROPVAR_INLINES */ #endif /* __cplusplus */ +PSSTDAPI StgSerializePropVariant(const PROPVARIANT *ppropvar, SERIALIZEDPROPERTYVALUE **ppprop, ULONG *pcb); +PSSTDAPI StgDeserializePropVariant(const SERIALIZEDPROPERTYVALUE *pprop, ULONG cbmax, PROPVARIANT *ppropvar); #ifdef __cplusplus } diff --git a/sdk/tools/winesync/propsys.cfg b/sdk/tools/winesync/propsys.cfg new file mode 100644 index 00000000000..1c8b99a3dfc --- /dev/null +++ b/sdk/tools/winesync/propsys.cfg @@ -0,0 +1,9 @@ +directories: + dlls/propsys: dll/win32/propsys + dlls/propsys/tests: modules/rostests/winetests/propsys +files: + include/oaidl.idl: sdk/include/psdk/oaidl.idl + include/propsys.idl: sdk/include/psdk/propsys.idl + include/propvarutil.h: sdk/include/psdk/propvarutil.h +tags: + wine: wine-10.0
3 weeks, 3 days
1
0
0
0
[reactos] 01/01: [RAPPS] Refresh item info after installer completes (#7697)
by Whindmar Saksit
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5bc6d5914288283606c33…
commit 5bc6d5914288283606c339534c65ceb81af663e5 Author: Whindmar Saksit <whindsaks(a)proton.me> AuthorDate: Fri Feb 7 21:33:19 2025 +0100 Commit: GitHub <noreply(a)github.com> CommitDate: Fri Feb 7 21:33:19 2025 +0100 [RAPPS] Refresh item info after installer completes (#7697) - Refresh the details view of the item that was just installed. - Hint update of uninstallers list is needed. - Restore focus correctly after installer process finishes. CORE-17677 --- base/applications/rapps/appinfo.cpp | 12 +++++++-- base/applications/rapps/appview.cpp | 45 ++++++++++++++++++++++++------- base/applications/rapps/gui.cpp | 41 +++++++++++++++++++++------- base/applications/rapps/include/appinfo.h | 9 +++++++ base/applications/rapps/include/appview.h | 7 ++++- base/applications/rapps/include/gui.h | 3 +++ base/applications/rapps/include/rapps.h | 2 ++ base/applications/rapps/loaddlg.cpp | 13 ++++++--- base/applications/rapps/misc.cpp | 2 ++ base/applications/rapps/unattended.cpp | 4 +-- 10 files changed, 109 insertions(+), 29 deletions(-) diff --git a/base/applications/rapps/appinfo.cpp b/base/applications/rapps/appinfo.cpp index 1970b9459d9..5442380fbad 100644 --- a/base/applications/rapps/appinfo.cpp +++ b/base/applications/rapps/appinfo.cpp @@ -10,6 +10,14 @@ #include "rapps.h" #include "appview.h" +static inline AppsCategories +ClampAvailableCategory(AppsCategories Category) +{ + if (Category <= ENUM_LASTCATEGORY) + return Category; + return ENUM_CAT_OTHER; // Treat future categories we don't know as Other +} + CAppInfo::CAppInfo(const CStringW &Identifier, AppsCategories Category) : szIdentifier(Identifier), iCategory(Category) { @@ -24,7 +32,7 @@ CAvailableApplicationInfo::CAvailableApplicationInfo( const CStringW &PkgName, AppsCategories Category, const CPathW &BasePath) - : CAppInfo(PkgName, Category), m_Parser(Parser), m_ScrnshotRetrieved(false), m_LanguagesLoaded(false) + : CAppInfo(PkgName, ClampAvailableCategory(Category)), m_Parser(Parser), m_ScrnshotRetrieved(false), m_LanguagesLoaded(false) { m_Parser->GetString(L"Name", szDisplayName); m_Parser->GetString(L"Version", szDisplayVersion); @@ -588,7 +596,7 @@ CInstalledApplicationInfo::GetInstallerType() const BOOL CInstalledApplicationInfo::UninstallApplication(UninstallCommandFlags Flags) { - if (GetInstallerType() == INSTALLER_GENERATE) + if (GetInstallerType() == INSTALLER_GENERATE && (Flags & UCF_SAMEPROCESS)) { return UninstallGenerated(*this, Flags); } diff --git a/base/applications/rapps/appview.cpp b/base/applications/rapps/appview.cpp index c0f18107c1e..248050ebb92 100644 --- a/base/applications/rapps/appview.cpp +++ b/base/applications/rapps/appview.cpp @@ -955,19 +955,22 @@ CAppInfoDisplay::Create(HWND hwndParent) } VOID -CAppInfoDisplay::ShowAppInfo(CAppInfo *Info) +CAppInfoDisplay::ShowAppInfo(CAppInfo &Info, bool OnlyUpdateText) { - CStringW ScrnshotLocation; - if (Info->RetrieveScreenshot(ScrnshotLocation)) + if (!OnlyUpdateText) { - ScrnshotPrev->DisplayImage(ScrnshotLocation); - } - else - { - ScrnshotPrev->DisplayEmpty(); + CStringW ScrnshotLocation; + if (Info.RetrieveScreenshot(ScrnshotLocation)) + { + ScrnshotPrev->DisplayImage(ScrnshotLocation); + } + else + { + ScrnshotPrev->DisplayEmpty(); + } } ResizeChildren(); - Info->ShowAppInfo(RichEdit); + Info.ShowAppInfo(RichEdit); } void @@ -1805,6 +1808,22 @@ CApplicationView::SetRedraw(BOOL bRedraw) m_ListView->SetRedraw(bRedraw); } +void +CApplicationView::RefreshAvailableItem(PCWSTR PackageName) +{ + if (ApplicationViewType != AppViewTypeAvailableApps || !PackageName) + return; + CAppInfo *pApp; + for (UINT i = 0; (pApp = (CAppInfo*)m_ListView->GetItemData(i)) != NULL; ++i) + { + if (pApp->szIdentifier.CompareNoCase(PackageName) == 0) + { + RefreshDetailsPane(*pApp, true); + break; + } + } +} + void CApplicationView::SetFocusOnSearchBar() { @@ -2134,6 +2153,12 @@ CApplicationView::RestoreListSelection(const RESTORELISTSELECTION &Restore) } } +VOID +CApplicationView::RefreshDetailsPane(CAppInfo &Info, bool OnlyUpdateText) +{ + m_AppsInfo->ShowAppInfo(Info, OnlyUpdateText); +} + // this function is called when a item of listview get focus. // CallbackParam is the param passed to listview when adding the item (the one getting focus now). VOID @@ -2142,7 +2167,7 @@ CApplicationView::ItemGetFocus(LPVOID CallbackParam) if (CallbackParam) { CAppInfo *Info = static_cast<CAppInfo *>(CallbackParam); - m_AppsInfo->ShowAppInfo(Info); + RefreshDetailsPane(*Info); if (ApplicationViewType == AppViewTypeInstalledApps) { diff --git a/base/applications/rapps/gui.cpp b/base/applications/rapps/gui.cpp index 6f2e1a1d3d8..8470ba092d1 100644 --- a/base/applications/rapps/gui.cpp +++ b/base/applications/rapps/gui.cpp @@ -81,6 +81,8 @@ CSideTreeView::~CSideTreeView() // **** CSideTreeView **** // **** CMainWindow **** +HWND CMainWindow::m_hLastFocus = NULL; +bool CMainWindow::m_PendingInstalledViewRefresh = false; CMainWindow::CMainWindow(CAppDB *db, BOOL bAppwiz) : m_ClientPanel(NULL), m_Db(db), m_bAppwizMode(bAppwiz), SelectedEnumType(ENUM_ALL_INSTALLED) { @@ -343,10 +345,32 @@ CMainWindow::ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lPa SendMessage(WM_CLOSE, 0, 0); break; + case WM_NOTIFY_INSTALLERFINISHED: + m_PendingInstalledViewRefresh = true; // Something just installed, our uninstall list is probably outdated + m_ApplicationView->RefreshAvailableItem((PCWSTR)lParam); + break; + case DM_REPOSITION: EmulateDialogReposition(hwnd); // We are not a real dialog, we need help from a real one break; + case WM_ACTIVATE: + if (LOWORD(wParam) == WA_INACTIVE) + m_hLastFocus = ::GetFocus(); + break; + + case WM_SETFOCUS: + if (m_hLastFocus) + ::SetFocus(m_hLastFocus); + break; + + case WM_NEXTDLGCTL: + if (!LOWORD(lParam)) + HandleTabOrder(wParam ? -1 : 1); + else if (wParam) + ::SetFocus((HWND)wParam); + break; + case WM_COMMAND: OnCommand(wParam, lParam); break; @@ -678,6 +702,12 @@ CMainWindow::UpdateApplicationsList(AppsCategories EnumType, BOOL bReload, BOOL if (bCheckAvailable) CheckAvailable(); + if (m_PendingInstalledViewRefresh && IsInstalledEnum(EnumType) && !IsInstalledEnum(SelectedEnumType)) + { + m_PendingInstalledViewRefresh = FALSE; + bReload = TRUE; // Reload because we are switching from Available to Installed after something installed + } + BOOL TryRestoreSelection = SelectedEnumType == EnumType; if (SelectedEnumType != EnumType) SelectedEnumType = EnumType; @@ -812,16 +842,7 @@ CMainWindow::ItemCheckStateChanged(BOOL bChecked, LPVOID CallbackParam) BOOL CMainWindow::InstallApplication(CAppInfo *Info) { - if (Info) - { - if (DownloadApplication(Info)) - { - //FIXME: Delay UpdateApplicationsList(SelectedEnumType); until install completes - return TRUE; - } - } - - return FALSE; + return Info && DownloadApplication(Info); } BOOL diff --git a/base/applications/rapps/include/appinfo.h b/base/applications/rapps/include/appinfo.h index 32cfc20b3dd..961ad0711bd 100644 --- a/base/applications/rapps/include/appinfo.h +++ b/base/applications/rapps/include/appinfo.h @@ -41,6 +41,7 @@ enum AppsCategories ENUM_CAT_THEMES, ENUM_CAT_OTHER, ENUM_CAT_SELECTED, + ENUM_LASTCATEGORY = ENUM_CAT_SELECTED - 1, ENUM_ALL_INSTALLED = 30, ENUM_INSTALLED_APPLICATIONS, ENUM_UPDATES, @@ -54,6 +55,12 @@ enum AppsCategories inline BOOL IsAvailableEnum(INT x) { + C_ASSERT(ENUM_CAT_AUDIO == 1 && ENUM_CAT_THEMES == 15 && ENUM_CAT_OTHER == 16); + C_ASSERT(ENUM_LASTCATEGORY >= ENUM_CAT_OTHER); + C_ASSERT(ENUM_LASTCATEGORY < ENUM_CAT_SELECTED); + C_ASSERT(ENUM_LASTCATEGORY < ENUM_INSTALLED_MIN); + C_ASSERT(ENUM_CAT_SELECTED < ENUM_INSTALLED_MIN); + return (x >= ENUM_AVAILABLE_MIN && x <= ENUM_AVAILABLE_MAX); } @@ -68,7 +75,9 @@ enum UninstallCommandFlags UCF_NONE = 0x00, UCF_MODIFY = 0x01, UCF_SILENT = 0x02, + UCF_SAMEPROCESS = 0x04, }; +DEFINE_ENUM_FLAG_OPERATORS(UninstallCommandFlags); enum InstallerType { diff --git a/base/applications/rapps/include/appview.h b/base/applications/rapps/include/appview.h index d457d45c799..169d0b23151 100644 --- a/base/applications/rapps/include/appview.h +++ b/base/applications/rapps/include/appview.h @@ -175,7 +175,7 @@ class CAppInfoDisplay : public CUiWindow<CWindowImpl<CAppInfoDisplay>> Create(HWND hwndParent); VOID - ShowAppInfo(CAppInfo *Info); + ShowAppInfo(CAppInfo &Info, bool OnlyUpdateText = false); void SetWelcomeText(bool bAppwiz); VOID @@ -388,6 +388,8 @@ class CApplicationView : public CUiWindow<CWindowImpl<CApplicationView>> void SetRedraw(BOOL bRedraw); void + RefreshAvailableItem(PCWSTR PackageName); + void SetFocusOnSearchBar(); BOOL SetDisplayAppType(APPLICATION_VIEW_TYPE AppType); @@ -415,6 +417,9 @@ class CApplicationView : public CUiWindow<CWindowImpl<CApplicationView>> VOID RestoreListSelection(const RESTORELISTSELECTION &Restore); + VOID + RefreshDetailsPane(CAppInfo &Info, bool OnlyUpdateText = false); + // this function is called when a item of listview get focus. // CallbackParam is the param passed to listview when adding the item (the one getting focus now). VOID diff --git a/base/applications/rapps/include/gui.h b/base/applications/rapps/include/gui.h index 36ff852dde3..fbe36a7fea1 100644 --- a/base/applications/rapps/include/gui.h +++ b/base/applications/rapps/include/gui.h @@ -65,6 +65,9 @@ class CMainWindow : public CWindowImpl<CMainWindow, CWindow, CFrameWinTraits> AppsCategories SelectedEnumType; public: + static HWND m_hLastFocus; + static bool m_PendingInstalledViewRefresh; + explicit CMainWindow(CAppDB *db, BOOL bAppwiz = FALSE); ~CMainWindow(); diff --git a/base/applications/rapps/include/rapps.h b/base/applications/rapps/include/rapps.h index c03a06d092d..f42c5919c2e 100644 --- a/base/applications/rapps/include/rapps.h +++ b/base/applications/rapps/include/rapps.h @@ -14,8 +14,10 @@ #include "configparser.h" extern LONG g_Busy; +extern bool g_PendingInstalledViewRefresh; #define WM_NOTIFY_OPERATIONCOMPLETED (WM_APP + 0) +#define WM_NOTIFY_INSTALLERFINISHED (WM_APP + 1) #define MAINWINDOWCLASSNAME L"ROSAPPMGR2" #define MAINWINDOWMUTEX szWindowClass diff --git a/base/applications/rapps/loaddlg.cpp b/base/applications/rapps/loaddlg.cpp index c863a5e2165..21b7b88d1fc 100644 --- a/base/applications/rapps/loaddlg.cpp +++ b/base/applications/rapps/loaddlg.cpp @@ -142,8 +142,7 @@ struct DownloadInfo AppInfo.GetDownloadInfo(szUrl, szSHA1, SizeInBytes); szName = AppInfo.szDisplayName; IType = AppInfo.GetInstallerType(); - if (IType == INSTALLER_GENERATE) - szPackageName = AppInfo.szIdentifier; + szPackageName = AppInfo.szIdentifier; CConfigParser *cfg = static_cast<const CAvailableApplicationInfo&>(AppInfo).GetConfigParser(); if (cfg) @@ -452,6 +451,8 @@ ShowLastError(HWND hWndOwner, BOOL bInetError, DWORD dwLastError) return FALSE; } + if (hWndOwner && !IsWindowVisible(hWndOwner)) + hWndOwner = NULL; MessageBoxW(hWndOwner, lpMsg, NULL, MB_OK | MB_ICONERROR); return TRUE; } @@ -1090,8 +1091,12 @@ run: SendMessageW(hDlg, WM_SETSTATUS, DLSTATUS_INSTALLING, 0); // TODO: issue an install operation separately so that the apps could be downloaded in the background - WaitForSingleObject(shExInfo.hProcess, INFINITE); - CloseHandle(shExInfo.hProcess); + if (shExInfo.hProcess) + { + WaitForSingleObject(shExInfo.hProcess, INFINITE); + CloseHandle(shExInfo.hProcess); + SendMessageW(hMainWnd, WM_NOTIFY_INSTALLERFINISHED, 0, (LPARAM)(PCWSTR)Info.szPackageName); + } } else { diff --git a/base/applications/rapps/misc.cpp b/base/applications/rapps/misc.cpp index c5fe6f0c4bc..baafe5309fd 100644 --- a/base/applications/rapps/misc.cpp +++ b/base/applications/rapps/misc.cpp @@ -160,6 +160,8 @@ StartProcess(const CStringW &Path, BOOL Wait) { EnableWindow(hMainWnd, TRUE); SetForegroundWindow(hMainWnd); + // We got the real activation message during MsgWaitForMultipleObjects while + // we were disabled, we need to set the focus again now. SetFocus(hMainWnd); } diff --git a/base/applications/rapps/unattended.cpp b/base/applications/rapps/unattended.cpp index 4967f259de3..06db5f0aba6 100644 --- a/base/applications/rapps/unattended.cpp +++ b/base/applications/rapps/unattended.cpp @@ -191,7 +191,7 @@ HandleUninstallCommand(CAppDB &db, UINT argcLeft, LPWSTR *argvLeft) if (pInfo) { - retval = pInfo->UninstallApplication(silent ? UCF_SILENT : UCF_NONE); + retval = pInfo->UninstallApplication((silent ? UCF_SILENT : UCF_NONE) | UCF_SAMEPROCESS); } delete pDelete; return retval; @@ -368,7 +368,7 @@ ParseCmdAndExecute(LPWSTR lpCmdLine, BOOL bIsFirstLaunch, int nCmdShow) if (hWindow) { /* Activate the window in the other instance */ - ShowWindow(hWindow, SW_SHOW); + ShowWindow(hWindow, SW_SHOWNA); SwitchToThisWindow(hWindow, TRUE); if (bAppwizMode) PostMessage(hWindow, WM_COMMAND, ID_ACTIVATE_APPWIZ, 0);
3 weeks, 3 days
1
0
0
0
[reactos] 01/01: [WINVER] Display compatibility information (#7661)
by Thamatip Chitpong
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a610016952841038e0c29…
commit a610016952841038e0c294ad4383a1a33ca6588b Author: Thamatip Chitpong <thamatip.chitpong(a)reactos.org> AuthorDate: Sat Feb 8 00:05:03 2025 +0700 Commit: GitHub <noreply(a)github.com> CommitDate: Sat Feb 8 00:05:03 2025 +0700 [WINVER] Display compatibility information (#7661) Also don't hardcode the OS name. This make it compatible with Windows. --- base/applications/winver/CMakeLists.txt | 10 ++- base/applications/winver/lang/en-US.rc | 14 ++++ base/applications/winver/osinfo.c | 126 ++++++++++++++++++++++++++++++++ base/applications/winver/resource.h | 11 +++ base/applications/winver/winver.c | 24 +++--- base/applications/winver/winver.rc | 9 +++ base/applications/winver/winver_p.h | 34 +++++++++ 7 files changed, 217 insertions(+), 11 deletions(-) diff --git a/base/applications/winver/CMakeLists.txt b/base/applications/winver/CMakeLists.txt index ac5b762b83d..9837665d4e5 100644 --- a/base/applications/winver/CMakeLists.txt +++ b/base/applications/winver/CMakeLists.txt @@ -1,5 +1,11 @@ -add_executable(winver winver.c winver.rc) +list(APPEND SOURCE + osinfo.c + winver.c + winver_p.h) + +add_executable(winver ${SOURCE} winver.rc) +add_pch(winver winver_p.h SOURCE) set_module_type(winver win32gui UNICODE) -add_importlibs(winver shell32 comctl32 msvcrt kernel32) +add_importlibs(winver advapi32 user32 shell32 comctl32 msvcrt kernel32) add_cd_file(TARGET winver DESTINATION reactos/system32 FOR all) diff --git a/base/applications/winver/lang/en-US.rc b/base/applications/winver/lang/en-US.rc new file mode 100644 index 00000000000..d4ec8dd84d9 --- /dev/null +++ b/base/applications/winver/lang/en-US.rc @@ -0,0 +1,14 @@ +/* + * PROJECT: ReactOS Version Program + * LICENSE: MIT (
https://spdx.org/licenses/MIT
) + * PURPOSE: English (United States) resource file + * TRANSLATOR: Copyright 2025 Thamatip Chitpong <thamatip.chitpong(a)reactos.org> + */ + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +STRINGTABLE +BEGIN + IDS_OSINFO_COMPAT_FORMAT "Reporting NT %s (Build %s%s)" + IDS_OSINFO_SPK_FORMAT ": %s" +END diff --git a/base/applications/winver/osinfo.c b/base/applications/winver/osinfo.c new file mode 100644 index 00000000000..ff79baa3aab --- /dev/null +++ b/base/applications/winver/osinfo.c @@ -0,0 +1,126 @@ +/* + * PROJECT: ReactOS Version Program + * LICENSE: MIT (
https://spdx.org/licenses/MIT
) + * PURPOSE: Retrieve OS name and simple compatibility information + * COPYRIGHT: Copyright 2025 Thamatip Chitpong <thamatip.chitpong(a)reactos.org> + */ + +#include "winver_p.h" + +#define OSINFO_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion" + +static +VOID +Winver_GetRegValueString( + _In_ HKEY hKey, + _In_ LPCWSTR pValue, + _Out_ LPWSTR pBuffer, + _In_ DWORD cchSize) +{ + DWORD dwType, dwSize; + LSTATUS lError; + + /* NOTE: Reserved space for a NULL terminator */ + dwSize = (cchSize - 1) * sizeof(WCHAR); + lError = RegQueryValueExW(hKey, pValue, NULL, &dwType, (LPBYTE)pBuffer, &dwSize); + if (lError != ERROR_SUCCESS || dwType != REG_SZ) + { + /* Return empty string on failure */ + pBuffer[0] = UNICODE_NULL; + return; + } + + /* Ensure the returned string is NULL terminated */ + pBuffer[cchSize - 1] = UNICODE_NULL; +} + +static +VOID +Winver_GetFormattedSpkInfo( + _In_ HKEY hKey, + _Out_ LPWSTR pBuffer, + _In_ DWORD cchSize) +{ + WCHAR szRegValue[48]; + WCHAR szFormat[16] = L""; + + Winver_GetRegValueString(hKey, L"CSDVersion", szRegValue, _countof(szRegValue)); + if (!szRegValue[0]) + { + /* Return empty string on failure */ + pBuffer[0] = UNICODE_NULL; + return; + } + + LoadStringW(Winver_hInstance, + IDS_OSINFO_SPK_FORMAT, + szFormat, + _countof(szFormat)); + + StringCchPrintfW(pBuffer, cchSize, szFormat, szRegValue); +} + +static +VOID +Winver_FormatCompatInfo( + _In_ HKEY hKey, + _Out_ LPWSTR pBuffer, + _In_ DWORD cchSize) +{ + WCHAR szNtVersion[16]; + WCHAR szNtBuild[16]; + WCHAR szNtSpk[64]; + WCHAR szFormat[64] = L""; + + /* NOTE: Required info must be valid */ + Winver_GetRegValueString(hKey, L"CurrentVersion", szNtVersion, _countof(szNtVersion)); + Winver_GetRegValueString(hKey, L"CurrentBuildNumber", szNtBuild, _countof(szNtBuild)); + if (!szNtVersion[0] || !szNtBuild[0]) + { + /* Return empty string on failure */ + pBuffer[0] = UNICODE_NULL; + return; + } + + /* NOTE: Service pack info is optional */ + Winver_GetFormattedSpkInfo(hKey, szNtSpk, _countof(szNtSpk)); + + LoadStringW(Winver_hInstance, + IDS_OSINFO_COMPAT_FORMAT, + szFormat, + _countof(szFormat)); + + StringCchPrintfW(pBuffer, cchSize, szFormat, szNtVersion, szNtBuild, szNtSpk); +} + +BOOL +Winver_GetOSInfo( + _Out_ PWINVER_OS_INFO OSInfo) +{ + HKEY hKey; + LSTATUS lError; + + lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + OSINFO_KEY, + 0, + KEY_QUERY_VALUE, + &hKey); + if (lError != ERROR_SUCCESS) + return FALSE; + + /* OS name */ + Winver_GetRegValueString(hKey, L"ProductName", OSInfo->szName, _countof(OSInfo->szName)); + if (!OSInfo->szName[0]) + { + /* This info must be valid */ + RegCloseKey(hKey); + return FALSE; + } + + /* Compatibility information */ + Winver_FormatCompatInfo(hKey, OSInfo->szCompatInfo, _countof(OSInfo->szCompatInfo)); + + RegCloseKey(hKey); + + return TRUE; +} diff --git a/base/applications/winver/resource.h b/base/applications/winver/resource.h new file mode 100644 index 00000000000..ca00ee82314 --- /dev/null +++ b/base/applications/winver/resource.h @@ -0,0 +1,11 @@ +/* + * PROJECT: ReactOS Version Program + * LICENSE: MIT (
https://spdx.org/licenses/MIT
) + * PURPOSE: Resource header file + * COPYRIGHT: Copyright 2025 Thamatip Chitpong <thamatip.chitpong(a)reactos.org> + */ + +#pragma once + +#define IDS_OSINFO_COMPAT_FORMAT 1 +#define IDS_OSINFO_SPK_FORMAT 2 diff --git a/base/applications/winver/winver.c b/base/applications/winver/winver.c index 1e22096c4ee..3eb2a9e3adf 100644 --- a/base/applications/winver/winver.c +++ b/base/applications/winver/winver.c @@ -4,26 +4,32 @@ * FILE: base/applications/winver/winver.c */ -#include <stdarg.h> -#include <windef.h> -#include <winbase.h> -#include <winuser.h> -#include <commctrl.h> -#include <shellapi.h> +#include "winver_p.h" + +HINSTANCE Winver_hInstance; int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) { INITCOMMONCONTROLSEX iccx; + WINVER_OS_INFO OSInfo; - UNREFERENCED_PARAMETER(hInstance); UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); UNREFERENCED_PARAMETER(nCmdShow); + Winver_hInstance = hInstance; + /* Initialize common controls */ - iccx.dwSize = sizeof(INITCOMMONCONTROLSEX); + iccx.dwSize = sizeof(iccx); iccx.dwICC = ICC_STANDARD_CLASSES | ICC_WIN95_CLASSES; InitCommonControlsEx(&iccx); - return ShellAboutW(NULL, L"ReactOS", NULL, NULL); + if (!Winver_GetOSInfo(&OSInfo)) + { + /* OS info is not available, display the default contents */ + StringCchCopyW(OSInfo.szName, _countof(OSInfo.szName), L"ReactOS"); + OSInfo.szCompatInfo[0] = UNICODE_NULL; + } + + return ShellAboutW(NULL, OSInfo.szName, OSInfo.szCompatInfo, NULL); } diff --git a/base/applications/winver/winver.rc b/base/applications/winver/winver.rc index 050ae694370..1d9dec6f9d9 100644 --- a/base/applications/winver/winver.rc +++ b/base/applications/winver/winver.rc @@ -2,9 +2,18 @@ #include <windef.h> #include <winuser.h> +#include "resource.h" + #define REACTOS_STR_FILE_DESCRIPTION "ReactOS Version Program" #define REACTOS_STR_INTERNAL_NAME "winver" #define REACTOS_STR_ORIGINAL_FILENAME "winver.exe" #include <reactos/version.rc> #include <reactos/manifest_exe.rc> + +/* UTF-8 */ +#pragma code_page(65001) + +#ifdef LANGUAGE_EN_US + #include "lang/en-US.rc" +#endif diff --git a/base/applications/winver/winver_p.h b/base/applications/winver/winver_p.h new file mode 100644 index 00000000000..b7b76ed5db9 --- /dev/null +++ b/base/applications/winver/winver_p.h @@ -0,0 +1,34 @@ +/* + * PROJECT: ReactOS Version Program + * LICENSE: MIT (
https://spdx.org/licenses/MIT
) + * PURPOSE: Main header file + * COPYRIGHT: Copyright 2025 Thamatip Chitpong <thamatip.chitpong(a)reactos.org> + */ + +#pragma once + +#include <stdarg.h> +#include <stdlib.h> + +#include <windef.h> +#include <winbase.h> +#include <winreg.h> +#include <winuser.h> +#include <commctrl.h> +#include <shellapi.h> + +#include <strsafe.h> + +#include "resource.h" + +typedef struct _WINVER_OS_INFO +{ + WCHAR szName[64]; + WCHAR szCompatInfo[256]; +} WINVER_OS_INFO, *PWINVER_OS_INFO; + +extern HINSTANCE Winver_hInstance; + +BOOL +Winver_GetOSInfo( + _Out_ PWINVER_OS_INFO OSInfo);
3 weeks, 3 days
1
0
0
0
[reactos] 02/02: [WINDOWSCODECS][WINDOWSCODECSEXT] Sync to wine-10.0 (#7665)
by Mikhail Tyukin
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=197ed01e95f242af87a39…
commit 197ed01e95f242af87a3905d83c2cd22326a7668 Author: Mikhail Tyukin <mishakeys20(a)gmail.com> AuthorDate: Sun Jan 26 12:59:50 2025 -0500 Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> CommitDate: Fri Feb 7 16:57:02 2025 +0100 [WINDOWSCODECS][WINDOWSCODECSEXT] Sync to wine-10.0 (#7665) --- dll/win32/windowscodecs/CMakeLists.txt | 19 +- dll/win32/windowscodecs/bitmap.c | 55 +- dll/win32/windowscodecs/bmpdecode.c | 82 +- dll/win32/windowscodecs/bmpencode.c | 44 +- dll/win32/windowscodecs/clipper.c | 12 +- dll/win32/windowscodecs/clsfactory.c | 24 +- dll/win32/windowscodecs/colorcontext.c | 24 +- dll/win32/windowscodecs/colortransform.c | 10 +- dll/win32/windowscodecs/converter.c | 276 +- dll/win32/windowscodecs/ddsformat.c | 2162 +++++++++++++ dll/win32/windowscodecs/decoder.c | 811 +++++ dll/win32/windowscodecs/encoder.c | 903 ++++++ dll/win32/windowscodecs/fliprotate.c | 14 +- dll/win32/windowscodecs/gifformat.c | 521 ++-- dll/win32/windowscodecs/icnsformat.c | 743 ----- dll/win32/windowscodecs/icoformat.c | 40 +- dll/win32/windowscodecs/imgfactory.c | 470 ++- dll/win32/windowscodecs/info.c | 309 +- dll/win32/windowscodecs/jpegformat.c | 1562 ---------- dll/win32/windowscodecs/libjpeg.c | 662 ++++ dll/win32/windowscodecs/libpng.c | 842 +++++ dll/win32/windowscodecs/libtiff.c | 1352 +++++++++ dll/win32/windowscodecs/main.c | 230 +- dll/win32/windowscodecs/metadatahandler.c | 295 +- dll/win32/windowscodecs/metadataquery.c | 580 ++-- dll/win32/windowscodecs/palette.c | 56 +- dll/win32/windowscodecs/pngformat.c | 2093 +------------ dll/win32/windowscodecs/precomp.h | 3 +- dll/win32/windowscodecs/propertybag.c | 33 +- dll/win32/windowscodecs/proxy.c | 2 - dll/win32/windowscodecs/regsvr.c | 207 +- dll/win32/windowscodecs/scaler.c | 28 +- dll/win32/windowscodecs/stream.c | 108 +- dll/win32/windowscodecs/tgaformat.c | 34 +- dll/win32/windowscodecs/tiffformat.c | 2385 --------------- dll/win32/windowscodecs/ungif.c | 93 +- dll/win32/windowscodecs/ungif.h | 7 +- dll/win32/windowscodecs/uuid.c | 36 + dll/win32/windowscodecs/wincodecs_common.c | 211 ++ dll/win32/windowscodecs/wincodecs_common.h | 214 ++ dll/win32/windowscodecs/wincodecs_private.h | 325 +- dll/win32/windowscodecs/windowscodecs_wincodec.idl | 32 +- dll/win32/windowscodecsext/main.c | 18 - media/doc/WINESYNC.txt | 4 +- .../winetests/windowscodecs/CMakeLists.txt | 8 +- modules/rostests/winetests/windowscodecs/bitmap.c | 460 +-- .../rostests/winetests/windowscodecs/bmpformat.c | 647 +++- .../rostests/winetests/windowscodecs/converter.c | 578 ++-- .../rostests/winetests/windowscodecs/ddsformat.c | 1579 ++++++++++ .../rostests/winetests/windowscodecs/gifformat.c | 198 +- .../rostests/winetests/windowscodecs/icoformat.c | 20 +- modules/rostests/winetests/windowscodecs/info.c | 263 +- .../rostests/winetests/windowscodecs/jpegformat.c | 38 +- .../rostests/winetests/windowscodecs/metadata.c | 3204 ++++++++++++++------ modules/rostests/winetests/windowscodecs/palette.c | 154 +- .../rostests/winetests/windowscodecs/pngformat.c | 203 +- .../rostests/winetests/windowscodecs/propertybag.c | 56 +- modules/rostests/winetests/windowscodecs/stream.c | 438 +-- .../rostests/winetests/windowscodecs/testlist.c | 4 + .../rostests/winetests/windowscodecs/tiffformat.c | 344 ++- .../rostests/winetests/windowscodecs/wmpformat.c | 182 ++ .../winetests/windowscodecsext/CMakeLists.txt | 1 + .../winetests/windowscodecsext/transform.c | 12 +- sdk/include/psdk/CMakeLists.txt | 1 + sdk/include/psdk/dxgiformat.idl | 145 + sdk/include/psdk/wincodec.idl | 137 + sdk/include/psdk/wincodecsdk.idl | 82 + sdk/tools/winesync/windowscodecs.cfg | 10 + 68 files changed, 16270 insertions(+), 10425 deletions(-) diff --git a/dll/win32/windowscodecs/CMakeLists.txt b/dll/win32/windowscodecs/CMakeLists.txt index ee7ff716e3b..c8e043b4979 100644 --- a/dll/win32/windowscodecs/CMakeLists.txt +++ b/dll/win32/windowscodecs/CMakeLists.txt @@ -1,12 +1,12 @@ add_definitions( -D__WINESRC__ - -D__ROS_LONG64__ -DENTRY_PREFIX=WIC_ -DPROXY_DELEGATION -DWINE_REGISTER_DLL) remove_definitions(-D_WIN32_WINNT=0x502) +remove_definitions(-D_CRT_NON_CONFORMING_SWPRINTFS) add_definitions(-D_WIN32_WINNT=0x600) include_directories( @@ -27,13 +27,17 @@ list(APPEND SOURCE colorcontext.c colortransform.c converter.c + ddsformat.c + decoder.c + encoder.c fliprotate.c gifformat.c - icnsformat.c icoformat.c imgfactory.c info.c - jpegformat.c + libjpeg.c + libpng.c + libtiff.c main.c metadatahandler.c metadataquery.c @@ -45,8 +49,9 @@ list(APPEND SOURCE scaler.c stream.c tgaformat.c - tiffformat.c - ungif.c) + ungif.c + uuid.c + wincodecs_common.c) if(MSVC) if(ARCH STREQUAL "i386") @@ -79,7 +84,7 @@ if(MSVC) endif() set_module_type(windowscodecs win32dll) -target_link_libraries(windowscodecs wine uuid ${PSEH_LIB}) -add_importlibs(windowscodecs ole32 oleaut32 rpcrt4 shlwapi user32 gdi32 advapi32 advapi32_vista propsys msvcrt kernel32 ntdll) +target_link_libraries(windowscodecs wine uuid ${PSEH_LIB} oldnames) +add_importlibs(windowscodecs libjpeg libpng libtiff ole32 oleaut32 rpcrt4 shlwapi user32 gdi32 advapi32 advapi32_vista propsys msvcrt kernel32 ntdll) add_pch(windowscodecs precomp.h "${PCH_SKIP_SOURCE}") add_cd_file(TARGET windowscodecs DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/windowscodecs/bitmap.c b/dll/win32/windowscodecs/bitmap.c index 7959da6911d..dee3f28d5d7 100644 --- a/dll/win32/windowscodecs/bitmap.c +++ b/dll/win32/windowscodecs/bitmap.c @@ -17,10 +17,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __REACTOS__ -#include "config.h" -#endif - #include <stdarg.h> #define COBJMACROS @@ -34,6 +30,9 @@ #include "wine/asm.h" #include "wine/debug.h" +#include "initguid.h" +DEFINE_GUID(IID_CMetaBitmapRenderTarget, 0x0ccd7824,0xdc16,0x4d09,0xbc,0xa8,0x6b,0x09,0xc4,0xef,0x55,0x35); + WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); /* WARNING: .NET Media Integration Layer (MIL) directly dereferences @@ -82,11 +81,6 @@ static inline BitmapImpl *impl_from_IMILUnknown1(IMILUnknown1 *iface) return CONTAINING_RECORD(iface, BitmapImpl, IMILUnknown1_iface); } -static inline BitmapImpl *impl_from_IMILUnknown2(IMILUnknown2 *iface) -{ - return CONTAINING_RECORD(iface, BitmapImpl, IMILUnknown2_iface); -} - static inline BitmapLockImpl *impl_from_IWICBitmapLock(IWICBitmapLock *iface) { return CONTAINING_RECORD(iface, BitmapLockImpl, IWICBitmapLock_iface); @@ -155,7 +149,7 @@ static ULONG WINAPI BitmapLockImpl_AddRef(IWICBitmapLock *iface) BitmapLockImpl *This = impl_from_IWICBitmapLock(iface); ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); return ref; } @@ -165,13 +159,13 @@ static ULONG WINAPI BitmapLockImpl_Release(IWICBitmapLock *iface) BitmapLockImpl *This = impl_from_IWICBitmapLock(iface); ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); if (ref == 0) { BitmapImpl_ReleaseLock(This->parent); IWICBitmap_Release(&This->parent->IWICBitmap_iface); - HeapFree(GetProcessHeap(), 0, This); + free(This); } return ref; @@ -262,7 +256,10 @@ static HRESULT WINAPI BitmapImpl_QueryInterface(IWICBitmap *iface, REFIID iid, } else { - FIXME("unknown interface %s\n", debugstr_guid(iid)); + if (IsEqualIID(&IID_CMetaBitmapRenderTarget, iid)) + WARN("Ignoring interface %s\n", debugstr_guid(iid)); + else + FIXME("unknown interface %s\n", debugstr_guid(iid)); *ppv = NULL; return E_NOINTERFACE; } @@ -276,7 +273,7 @@ static ULONG WINAPI BitmapImpl_AddRef(IWICBitmap *iface) BitmapImpl *This = impl_from_IWICBitmap(iface); ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); return ref; } @@ -286,7 +283,7 @@ static ULONG WINAPI BitmapImpl_Release(IWICBitmap *iface) BitmapImpl *This = impl_from_IWICBitmap(iface); ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); if (ref == 0) { @@ -296,8 +293,8 @@ static ULONG WINAPI BitmapImpl_Release(IWICBitmap *iface) if (This->view) UnmapViewOfFile(This->view); else - HeapFree(GetProcessHeap(), 0, This->data); - HeapFree(GetProcessHeap(), 0, This); + free(This->data); + free(This); } return ref; @@ -378,7 +375,7 @@ static HRESULT WINAPI BitmapImpl_Lock(IWICBitmap *iface, const WICRect *prcLock, BitmapLockImpl *result; WICRect rc; - TRACE("(%p,%s,%x,%p)\n", iface, debug_wic_rect(prcLock), flags, ppILock); + TRACE("(%p,%s,%lx,%p)\n", iface, debug_wic_rect(prcLock), flags, ppILock); if (!(flags & (WICBitmapLockRead|WICBitmapLockWrite)) || !ppILock) return E_INVALIDARG; @@ -401,13 +398,13 @@ static HRESULT WINAPI BitmapImpl_Lock(IWICBitmap *iface, const WICRect *prcLock, return E_FAIL; } - result = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapLockImpl)); + result = malloc(sizeof(BitmapLockImpl)); if (!result) return E_OUTOFMEMORY; if (!BitmapImpl_AcquireLock(This, flags & WICBitmapLockWrite)) { - HeapFree(GetProcessHeap(), 0, result); + free(result); return WINCODEC_ERR_ALREADYLOCKED; } @@ -605,7 +602,7 @@ static HRESULT WINAPI IMILBitmapImpl_unknown1(IMILBitmap *iface, void **ppv) static HRESULT WINAPI IMILBitmapImpl_Lock(IMILBitmap *iface, const WICRect *rc, DWORD flags, IWICBitmapLock **lock) { BitmapImpl *This = impl_from_IMILBitmap(iface); - TRACE("(%p,%p,%08x,%p)\n", iface, rc, flags, lock); + TRACE("(%p,%p,%08lx,%p)\n", iface, rc, flags, lock); return IWICBitmap_Lock(&This->IWICBitmap_iface, rc, flags, lock); } @@ -675,7 +672,7 @@ static ULONG WINAPI IMILUnknown1Impl_Release(IMILUnknown1 *iface) return IWICBitmap_Release(&This->IWICBitmap_iface); } -DECLSPEC_HIDDEN void WINAPI IMILUnknown1Impl_unknown1(IMILUnknown1 *iface, void *arg) +void WINAPI IMILUnknown1Impl_unknown1(IMILUnknown1 *iface, void *arg) { FIXME("(%p,%p): stub\n", iface, arg); } @@ -686,7 +683,7 @@ static HRESULT WINAPI IMILUnknown1Impl_unknown2(IMILUnknown1 *iface, void *arg1, return E_NOTIMPL; } -DECLSPEC_HIDDEN HRESULT WINAPI IMILUnknown1Impl_unknown3(IMILUnknown1 *iface, void *arg) +HRESULT WINAPI IMILUnknown1Impl_unknown3(IMILUnknown1 *iface, void *arg) { FIXME("(%p,%p): stub\n", iface, arg); return E_NOTIMPL; @@ -716,7 +713,7 @@ static HRESULT WINAPI IMILUnknown1Impl_unknown7(IMILUnknown1 *iface, void *arg) return E_NOTIMPL; } -DECLSPEC_HIDDEN HRESULT WINAPI IMILUnknown1Impl_unknown8(IMILUnknown1 *iface) +HRESULT WINAPI IMILUnknown1Impl_unknown8(IMILUnknown1 *iface) { FIXME("(%p): stub\n", iface); return E_NOTIMPL; @@ -808,13 +805,13 @@ HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight, UINT stride, UINT datasiz if (datasize < stride * uiHeight) return WINCODEC_ERR_INSUFFICIENTBUFFER; if (stride < ((bpp*uiWidth)+7)/8) return E_INVALIDARG; - This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapImpl)); + This = malloc(sizeof(BitmapImpl)); if (!This) return E_OUTOFMEMORY; if (view) data = (BYTE *)view + offset; - else if (!(data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, datasize))) + else if (!(data = calloc(1, datasize))) { - HeapFree(GetProcessHeap(), 0, This); + free(This); return E_OUTOFMEMORY; } @@ -835,7 +832,11 @@ HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight, UINT stride, UINT datasiz This->bpp = bpp; memcpy(&This->pixelformat, pixelFormat, sizeof(GUID)); This->dpix = This->dpiy = 0.0; +#ifdef __REACTOS__ InitializeCriticalSection(&This->cs); +#else + InitializeCriticalSectionEx(&This->cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO); +#endif This->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BitmapImpl.lock"); *ppIBitmap = &This->IWICBitmap_iface; diff --git a/dll/win32/windowscodecs/bmpdecode.c b/dll/win32/windowscodecs/bmpdecode.c index 5ee4ac38ccb..9eb74b3d7cc 100644 --- a/dll/win32/windowscodecs/bmpdecode.c +++ b/dll/win32/windowscodecs/bmpdecode.c @@ -16,8 +16,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "config.h" - #include <assert.h> #include <stdarg.h> @@ -226,9 +224,9 @@ static HRESULT WINAPI BmpFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface, int i; count = 1 << bch->bcBitCount; - wiccolors = HeapAlloc(GetProcessHeap(), 0, sizeof(WICColor) * count); + wiccolors = malloc(sizeof(WICColor) * count); tablesize = sizeof(RGBTRIPLE) * count; - bgrcolors = HeapAlloc(GetProcessHeap(), 0, tablesize); + bgrcolors = malloc(tablesize); if (!wiccolors || !bgrcolors) { hr = E_OUTOFMEMORY; @@ -274,7 +272,7 @@ static HRESULT WINAPI BmpFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface, count = min(This->bih.bV5ClrUsed, 1 << This->bih.bV5BitCount); tablesize = sizeof(WICColor) * count; - wiccolors = HeapAlloc(GetProcessHeap(), 0, tablesize); + wiccolors = malloc(tablesize); if (!wiccolors) { hr = E_OUTOFMEMORY; @@ -310,8 +308,8 @@ end: if (SUCCEEDED(hr)) hr = IWICPalette_InitializeCustom(pIPalette, wiccolors, count); - HeapFree(GetProcessHeap(), 0, wiccolors); - HeapFree(GetProcessHeap(), 0, bgrcolors); + free(wiccolors); + free(bgrcolors); return hr; } @@ -388,7 +386,7 @@ static HRESULT BmpFrameDecode_ReadUncompressed(BmpDecoder* This) bytesperrow = (((width * This->bitsperpixel)+31)/32)*4; datasize = bytesperrow * height; - This->imagedata = HeapAlloc(GetProcessHeap(), 0, datasize); + This->imagedata = malloc(datasize); if (!This->imagedata) return E_OUTOFMEMORY; offbits.QuadPart = This->image_offset; @@ -411,12 +409,45 @@ static HRESULT BmpFrameDecode_ReadUncompressed(BmpDecoder* This) return S_OK; fail: - HeapFree(GetProcessHeap(), 0, This->imagedata); + free(This->imagedata); This->imagedata = NULL; if (SUCCEEDED(hr)) hr = E_FAIL; return hr; } +static HRESULT BmpFrameDecode_ReadABGRasBGR(BmpDecoder* This) +{ + UINT x, y, width, height; + BYTE *pixel; + HRESULT hr; + + hr = IWICBitmapFrameDecode_GetSize(&This->IWICBitmapFrameDecode_iface, &width, &height); + + if (SUCCEEDED(hr)) + { + hr = BmpFrameDecode_ReadUncompressed(This); + } + + if (SUCCEEDED(hr)) + { + for (y = 0; y < height; y++) + { + pixel = This->imagedatastart + This->stride * (INT)y; + + for (x = 0; x < width; x++) + { + pixel[0] = pixel[1]; + pixel[1] = pixel[2]; + pixel[2] = pixel[3]; + pixel[3] = 0; + pixel += 4; + } + } + } + + return hr; +} + static HRESULT BmpFrameDecode_ReadRGB8(BmpDecoder* This) { HRESULT hr; @@ -482,7 +513,7 @@ static HRESULT BmpFrameDecode_ReadRLE8(BmpDecoder* This) else palettesize = 4 * 256; - This->imagedata = HeapAlloc(GetProcessHeap(), 0, datasize); + This->imagedata = malloc(datasize); if (!This->imagedata) { hr = E_OUTOFMEMORY; @@ -578,7 +609,7 @@ end: return S_OK; fail: - HeapFree(GetProcessHeap(), 0, This->imagedata); + free(This->imagedata); This->imagedata = NULL; if (SUCCEEDED(hr)) hr = E_FAIL; return hr; @@ -606,7 +637,7 @@ static HRESULT BmpFrameDecode_ReadRLE4(BmpDecoder* This) else palettesize = 4 * 16; - This->imagedata = HeapAlloc(GetProcessHeap(), 0, datasize); + This->imagedata = malloc(datasize); if (!This->imagedata) { hr = E_OUTOFMEMORY; @@ -718,7 +749,7 @@ end: return S_OK; fail: - HeapFree(GetProcessHeap(), 0, This->imagedata); + free(This->imagedata); This->imagedata = NULL; if (SUCCEEDED(hr)) hr = E_FAIL; return hr; @@ -744,7 +775,7 @@ static const struct bitfields_format bitfields_formats[] = { {16,0xf800,0x7e0,0x1f,0,&GUID_WICPixelFormat16bppBGR565,BmpFrameDecode_ReadUncompressed}, {32,0xff0000,0xff00,0xff,0,&GUID_WICPixelFormat32bppBGR,BmpFrameDecode_ReadUncompressed}, {32,0xff0000,0xff00,0xff,0xff000000,&GUID_WICPixelFormat32bppBGRA,BmpFrameDecode_ReadUncompressed}, - {32,0xff000000,0xff0000,0xff00,0xff,&GUID_WICPixelFormat32bppRGBA,BmpFrameDecode_ReadUncompressed}, + {32,0xff000000,0xff0000,0xff00,0xff,&GUID_WICPixelFormat32bppBGR,BmpFrameDecode_ReadABGRasBGR}, {32,0xff,0xff00,0xff0000,0,&GUID_WICPixelFormat32bppBGR,BmpFrameDecode_ReadRGB8}, {0} }; @@ -861,7 +892,7 @@ static HRESULT BmpDecoder_ReadHeaders(BmpDecoder* This, IStream *stream) } else /* struct is compatible with BITMAPINFOHEADER */ { - TRACE("bitmap header=%i compression=%i depth=%i\n", This->bih.bV5Size, This->bih.bV5Compression, This->bih.bV5BitCount); + TRACE("bitmap header=%li compression=%li depth=%i\n", This->bih.bV5Size, This->bih.bV5Compression, This->bih.bV5BitCount); switch(This->bih.bV5Compression) { case BI_RGB: @@ -935,7 +966,7 @@ static HRESULT BmpDecoder_ReadHeaders(BmpDecoder* This, IStream *stream) { This->read_data_func = BmpFrameDecode_ReadUncompressed; This->pixelformat = &GUID_WICPixelFormatUndefined; - FIXME("unsupported bitfields type depth=%i red=%x green=%x blue=%x alpha=%x\n", + FIXME("unsupported bitfields type depth=%i red=%lx green=%lx blue=%lx alpha=%lx\n", This->bih.bV5BitCount, This->bih.bV5RedMask, This->bih.bV5GreenMask, This->bih.bV5BlueMask, This->bih.bV5AlphaMask); } break; @@ -944,7 +975,7 @@ static HRESULT BmpDecoder_ReadHeaders(BmpDecoder* This, IStream *stream) This->bitsperpixel = 0; This->read_data_func = BmpFrameDecode_ReadUnsupported; This->pixelformat = &GUID_WICPixelFormatUndefined; - FIXME("unsupported bitmap type header=%i compression=%i depth=%i\n", This->bih.bV5Size, This->bih.bV5Compression, This->bih.bV5BitCount); + FIXME("unsupported bitmap type header=%li compression=%li depth=%i\n", This->bih.bV5Size, This->bih.bV5Compression, This->bih.bV5BitCount); break; } } @@ -999,7 +1030,7 @@ static ULONG WINAPI BmpDecoder_AddRef(IWICBitmapDecoder *iface) BmpDecoder *This = impl_from_IWICBitmapDecoder(iface); ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); return ref; } @@ -1009,15 +1040,15 @@ static ULONG WINAPI BmpDecoder_Release(IWICBitmapDecoder *iface) BmpDecoder *This = impl_from_IWICBitmapDecoder(iface); ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); if (ref == 0) { if (This->stream) IStream_Release(This->stream); - HeapFree(GetProcessHeap(), 0, This->imagedata); + free(This->imagedata); This->lock.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->lock); - HeapFree(GetProcessHeap(), 0, This); + free(This); } return ref; @@ -1155,7 +1186,7 @@ static HRESULT BmpDecoder_Create(int packed, int icoframe, BmpDecoder **ppDecode { BmpDecoder *This; - This = HeapAlloc(GetProcessHeap(), 0, sizeof(BmpDecoder)); + This = malloc(sizeof(BmpDecoder)); if (!This) return E_OUTOFMEMORY; This->IWICBitmapDecoder_iface.lpVtbl = &BmpDecoder_Vtbl; @@ -1164,7 +1195,11 @@ static HRESULT BmpDecoder_Create(int packed, int icoframe, BmpDecoder **ppDecode This->initialized = FALSE; This->stream = NULL; This->imagedata = NULL; +#ifdef __REACTOS__ InitializeCriticalSection(&This->lock); +#else + InitializeCriticalSectionEx(&This->lock, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO); +#endif This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BmpDecoder.lock"); This->packed = packed; This->icoframe = icoframe; @@ -1220,7 +1255,8 @@ void BmpDecoder_FindIconMask(BmpDecoder *This, ULONG *mask_offset, int *topdown) if (This->read_data_func == BmpFrameDecode_ReadUncompressed) { /* RGB or BITFIELDS data */ - ULONG width, height, bytesperrow, datasize; + UINT width, height; + ULONG bytesperrow, datasize; IWICBitmapFrameDecode_GetSize(&This->IWICBitmapFrameDecode_iface, &width, &height); bytesperrow = (((width * This->bitsperpixel)+31)/32)*4; datasize = bytesperrow * height; diff --git a/dll/win32/windowscodecs/bmpencode.c b/dll/win32/windowscodecs/bmpencode.c index 3b77517a8d9..28da4a5e6d2 100644 --- a/dll/win32/windowscodecs/bmpencode.c +++ b/dll/win32/windowscodecs/bmpencode.c @@ -17,8 +17,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "config.h" - #include <stdarg.h> #define COBJMACROS @@ -56,10 +54,7 @@ static const struct bmp_pixelformat formats[] = { {&GUID_WICPixelFormat16bppBGR555, 16, 0, BI_RGB}, {&GUID_WICPixelFormat16bppBGR565, 16, 0, BI_BITFIELDS, 0xf800, 0x7e0, 0x1f, 0}, {&GUID_WICPixelFormat32bppBGR, 32, 0, BI_RGB}, -#if 0 - /* Windows doesn't seem to support this one. */ {&GUID_WICPixelFormat32bppBGRA, 32, 0, BI_BITFIELDS, 0xff0000, 0xff00, 0xff, 0xff000000}, -#endif {NULL} }; @@ -79,8 +74,6 @@ typedef struct BmpFrameEncode { BOOL committed; } BmpFrameEncode; -static const WCHAR wszEnableV5Header32bppBGRA[] = {'E','n','a','b','l','e','V','5','H','e','a','d','e','r','3','2','b','p','p','B','G','R','A',0}; - static inline BmpFrameEncode *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode *iface) { return CONTAINING_RECORD(iface, BmpFrameEncode, IWICBitmapFrameEncode_iface); @@ -114,7 +107,7 @@ static ULONG WINAPI BmpFrameEncode_AddRef(IWICBitmapFrameEncode *iface) BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); return ref; } @@ -124,13 +117,13 @@ static ULONG WINAPI BmpFrameEncode_Release(IWICBitmapFrameEncode *iface) BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); if (ref == 0) { if (This->stream) IStream_Release(This->stream); - HeapFree(GetProcessHeap(), 0, This->bits); - HeapFree(GetProcessHeap(), 0, This); + free(This->bits); + free(This); } return ref; @@ -253,7 +246,7 @@ static HRESULT BmpFrameEncode_AllocateBits(BmpFrameEncode *This) return WINCODEC_ERR_WRONGSTATE; This->stride = (((This->width * This->format->bpp)+31)/32)*4; - This->bits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->stride * This->height); + This->bits = calloc(This->stride, This->height); if (!This->bits) return E_OUTOFMEMORY; } @@ -316,7 +309,8 @@ static HRESULT WINAPI BmpFrameEncode_WriteSource(IWICBitmapFrameEncode *iface, if (SUCCEEDED(hr)) { hr = write_source(iface, pIBitmapSource, prc, - This->format->guid, This->format->bpp, This->width, This->height); + This->format->guid, This->format->bpp, !This->colors && This->format->colors, + This->width, This->height); } return hr; @@ -400,10 +394,16 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface) } static HRESULT WINAPI BmpFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode *iface, - IWICMetadataQueryWriter **ppIMetadataQueryWriter) + IWICMetadataQueryWriter **query_writer) { - FIXME("(%p, %p): stub\n", iface, ppIMetadataQueryWriter); - return E_NOTIMPL; + BmpFrameEncode *encoder = impl_from_IWICBitmapFrameEncode(iface); + + TRACE("iface %p, query_writer %p.\n", iface, query_writer); + + if (!encoder->initialized) + return WINCODEC_ERR_NOTINITIALIZED; + + return WINCODEC_ERR_UNSUPPORTEDOPERATION; } static const IWICBitmapFrameEncodeVtbl BmpFrameEncode_Vtbl = { @@ -463,7 +463,7 @@ static ULONG WINAPI BmpEncoder_AddRef(IWICBitmapEncoder *iface) BmpEncoder *This = impl_from_IWICBitmapEncoder(iface); ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); return ref; } @@ -473,13 +473,13 @@ static ULONG WINAPI BmpEncoder_Release(IWICBitmapEncoder *iface) BmpEncoder *This = impl_from_IWICBitmapEncoder(iface); ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); if (ref == 0) { if (This->stream) IStream_Release(This->stream); if (This->frame) IWICBitmapFrameEncode_Release(&This->frame->IWICBitmapFrameEncode_iface); - HeapFree(GetProcessHeap(), 0, This); + free(This); } return ref; @@ -563,7 +563,7 @@ static HRESULT WINAPI BmpEncoder_CreateNewFrame(IWICBitmapEncoder *iface, HRESULT hr; static const PROPBAG2 opts[1] = { - { PROPBAG2_TYPE_DATA, VT_BOOL, 0, 0, (LPOLESTR)wszEnableV5Header32bppBGRA }, + { PROPBAG2_TYPE_DATA, VT_BOOL, 0, 0, (LPOLESTR)L"EnableV5Header32bppBGRA" }, }; TRACE("(%p,%p,%p)\n", iface, ppIFrameEncode, ppIEncoderOptions); @@ -578,7 +578,7 @@ static HRESULT WINAPI BmpEncoder_CreateNewFrame(IWICBitmapEncoder *iface, if (FAILED(hr)) return hr; } - encode = HeapAlloc(GetProcessHeap(), 0, sizeof(BmpFrameEncode)); + encode = malloc(sizeof(BmpFrameEncode)); if (!encode) { IPropertyBag2_Release(*ppIEncoderOptions); @@ -648,7 +648,7 @@ HRESULT BmpEncoder_CreateInstance(REFIID iid, void** ppv) *ppv = NULL; - This = HeapAlloc(GetProcessHeap(), 0, sizeof(BmpEncoder)); + This = malloc(sizeof(BmpEncoder)); if (!This) return E_OUTOFMEMORY; This->IWICBitmapEncoder_iface.lpVtbl = &BmpEncoder_Vtbl; diff --git a/dll/win32/windowscodecs/clipper.c b/dll/win32/windowscodecs/clipper.c index 02e0d967f52..b4b2c23ee45 100644 --- a/dll/win32/windowscodecs/clipper.c +++ b/dll/win32/windowscodecs/clipper.c @@ -72,7 +72,7 @@ static ULONG WINAPI BitmapClipper_AddRef(IWICBitmapClipper *iface) BitmapClipper *This = impl_from_IWICBitmapClipper(iface); ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); return ref; } @@ -82,14 +82,14 @@ static ULONG WINAPI BitmapClipper_Release(IWICBitmapClipper *iface) BitmapClipper *This = impl_from_IWICBitmapClipper(iface); ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); if (ref == 0) { This->lock.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->lock); if (This->source) IWICBitmapSource_Release(This->source); - HeapFree(GetProcessHeap(), 0, This); + free(This); } return ref; @@ -244,13 +244,17 @@ HRESULT BitmapClipper_Create(IWICBitmapClipper **clipper) { BitmapClipper *This; - This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapClipper)); + This = malloc(sizeof(BitmapClipper)); if (!This) return E_OUTOFMEMORY; This->IWICBitmapClipper_iface.lpVtbl = &BitmapClipper_Vtbl; This->ref = 1; This->source = NULL; +#ifdef __REACTOS__ InitializeCriticalSection(&This->lock); +#else + InitializeCriticalSectionEx(&This->lock, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO); +#endif This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BitmapClipper.lock"); *clipper = &This->IWICBitmapClipper_iface; diff --git a/dll/win32/windowscodecs/clsfactory.c b/dll/win32/windowscodecs/clsfactory.c index 2de518a00c1..87b77c9c089 100644 --- a/dll/win32/windowscodecs/clsfactory.c +++ b/dll/win32/windowscodecs/clsfactory.c @@ -16,8 +16,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "config.h" - #include <stdarg.h> #define COBJMACROS @@ -27,6 +25,8 @@ #include "winreg.h" #include "objbase.h" #include "ocidl.h" +#include "wincodec.h" +#include "wincodecsdk.h" #include "initguid.h" #include "wincodecs_private.h" @@ -35,7 +35,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); -extern HRESULT WINAPI WIC_DllGetClassObject(REFCLSID, REFIID, LPVOID *) DECLSPEC_HIDDEN; +extern HRESULT WINAPI WIC_DllGetClassObject(REFCLSID, REFIID, LPVOID *); typedef struct { REFCLSID classid; @@ -47,6 +47,7 @@ static const classinfo wic_classes[] = { {&CLSID_WICImagingFactory2, ImagingFactory_CreateInstance}, {&CLSID_WICBmpDecoder, BmpDecoder_CreateInstance}, {&CLSID_WICPngDecoder, PngDecoder_CreateInstance}, + {&CLSID_WICPngDecoder2, PngDecoder_CreateInstance}, {&CLSID_WICPngEncoder, PngEncoder_CreateInstance}, {&CLSID_WICBmpEncoder, BmpEncoder_CreateInstance}, {&CLSID_WICGifDecoder, GifDecoder_CreateInstance}, @@ -56,14 +57,17 @@ static const classinfo wic_classes[] = { {&CLSID_WICJpegEncoder, JpegEncoder_CreateInstance}, {&CLSID_WICTiffDecoder, TiffDecoder_CreateInstance}, {&CLSID_WICTiffEncoder, TiffEncoder_CreateInstance}, - {&CLSID_WICIcnsEncoder, IcnsEncoder_CreateInstance}, + {&CLSID_WICDdsDecoder, DdsDecoder_CreateInstance}, + {&CLSID_WICDdsEncoder, DdsEncoder_CreateInstance}, {&CLSID_WICDefaultFormatConverter, FormatConverter_CreateInstance}, {&CLSID_WineTgaDecoder, TgaDecoder_CreateInstance}, {&CLSID_WICUnknownMetadataReader, UnknownMetadataReader_CreateInstance}, {&CLSID_WICIfdMetadataReader, IfdMetadataReader_CreateInstance}, {&CLSID_WICPngChrmMetadataReader, PngChrmReader_CreateInstance}, {&CLSID_WICPngGamaMetadataReader, PngGamaReader_CreateInstance}, + {&CLSID_WICPngHistMetadataReader, PngHistReader_CreateInstance}, {&CLSID_WICPngTextMetadataReader, PngTextReader_CreateInstance}, + {&CLSID_WICPngTimeMetadataReader, PngTimeReader_CreateInstance}, {&CLSID_WICLSDMetadataReader, LSDReader_CreateInstance}, {&CLSID_WICIMDMetadataReader, IMDReader_CreateInstance}, {&CLSID_WICGCEMetadataReader, GCEReader_CreateInstance}, @@ -110,7 +114,7 @@ static ULONG WINAPI ClassFactoryImpl_AddRef(IClassFactory *iface) ClassFactoryImpl *This = impl_from_IClassFactory(iface); ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); return ref; } @@ -120,10 +124,10 @@ static ULONG WINAPI ClassFactoryImpl_Release(IClassFactory *iface) ClassFactoryImpl *This = impl_from_IClassFactory(iface); ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); if (ref == 0) - HeapFree(GetProcessHeap(), 0, This); + free(This); return ref; } @@ -161,7 +165,7 @@ static HRESULT ClassFactoryImpl_Constructor(const classinfo *info, REFIID riid, *ppv = NULL; - This = HeapAlloc(GetProcessHeap(), 0, sizeof(ClassFactoryImpl)); + This = malloc(sizeof(ClassFactoryImpl)); if (!This) return E_OUTOFMEMORY; This->IClassFactory_iface.lpVtbl = &ClassFactoryImpl_Vtbl; @@ -201,11 +205,11 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) else ret = WIC_DllGetClassObject(rclsid, iid, ppv); - TRACE("<-- %08X\n", ret); + TRACE("<-- %08lX\n", ret); return ret; } -HRESULT create_instance(CLSID *clsid, const IID *iid, void **ppv) +HRESULT create_instance(const CLSID *clsid, const IID *iid, void **ppv) { int i; diff --git a/dll/win32/windowscodecs/colorcontext.c b/dll/win32/windowscodecs/colorcontext.c index eb13482cf43..a52e4e06eb7 100644 --- a/dll/win32/windowscodecs/colorcontext.c +++ b/dll/win32/windowscodecs/colorcontext.c @@ -16,8 +16,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "config.h" - #include <stdarg.h> #define COBJMACROS @@ -74,7 +72,7 @@ static ULONG WINAPI ColorContext_AddRef(IWICColorContext *iface) ColorContext *This = impl_from_IWICColorContext(iface); ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); return ref; } @@ -84,12 +82,12 @@ static ULONG WINAPI ColorContext_Release(IWICColorContext *iface) ColorContext *This = impl_from_IWICColorContext(iface); ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); if (ref == 0) { - HeapFree(GetProcessHeap(), 0, This->profile); - HeapFree(GetProcessHeap(), 0, This); + free(This->profile); + free(This); } return ref; @@ -118,7 +116,7 @@ static HRESULT load_profile(const WCHAR *filename, BYTE **profile, UINT *len) CloseHandle(handle); return E_FAIL; } - if (!(*profile = HeapAlloc(GetProcessHeap(), 0, size.u.LowPart))) + if (!(*profile = malloc(size.u.LowPart))) { CloseHandle(handle); return E_OUTOFMEMORY; @@ -126,12 +124,12 @@ static HRESULT load_profile(const WCHAR *filename, BYTE **profile, UINT *len) ret = ReadFile(handle, *profile, size.u.LowPart, &count, NULL); CloseHandle(handle); if (!ret) { - HeapFree (GetProcessHeap(),0,*profile); + free(*profile); *profile = NULL; return HRESULT_FROM_WIN32(GetLastError()); } if (count != size.u.LowPart) { - HeapFree (GetProcessHeap(),0,*profile); + free(*profile); *profile = NULL; return E_FAIL; } @@ -156,7 +154,7 @@ static HRESULT WINAPI ColorContext_InitializeFromFilename(IWICColorContext *ifac hr = load_profile(wzFilename, &profile, &len); if (FAILED(hr)) return hr; - HeapFree(GetProcessHeap(), 0, This->profile); + free(This->profile); This->profile = profile; This->profile_len = len; This->type = WICColorContextProfile; @@ -174,10 +172,10 @@ static HRESULT WINAPI ColorContext_InitializeFromMemory(IWICColorContext *iface, if (This->type != WICColorContextUninitialized && This->type != WICColorContextProfile) return WINCODEC_ERR_WRONGSTATE; - if (!(profile = HeapAlloc(GetProcessHeap(), 0, cbBufferSize))) return E_OUTOFMEMORY; + if (!(profile = malloc(cbBufferSize))) return E_OUTOFMEMORY; memcpy(profile, pbBuffer, cbBufferSize); - HeapFree(GetProcessHeap(), 0, This->profile); + free(This->profile); This->profile = profile; This->profile_len = cbBufferSize; This->type = WICColorContextProfile; @@ -261,7 +259,7 @@ HRESULT ColorContext_Create(IWICColorContext **colorcontext) if (!colorcontext) return E_INVALIDARG; - This = HeapAlloc(GetProcessHeap(), 0, sizeof(ColorContext)); + This = malloc(sizeof(ColorContext)); if (!This) return E_OUTOFMEMORY; This->IWICColorContext_iface.lpVtbl = &ColorContext_Vtbl; diff --git a/dll/win32/windowscodecs/colortransform.c b/dll/win32/windowscodecs/colortransform.c index af66c67443d..9a392d6dc0c 100644 --- a/dll/win32/windowscodecs/colortransform.c +++ b/dll/win32/windowscodecs/colortransform.c @@ -16,8 +16,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "config.h" - #include <stdarg.h> #define COBJMACROS @@ -72,7 +70,7 @@ static ULONG WINAPI ColorTransform_AddRef(IWICColorTransform *iface) ColorTransform *This = impl_from_IWICColorTransform(iface); ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); return ref; } @@ -82,12 +80,12 @@ static ULONG WINAPI ColorTransform_Release(IWICColorTransform *iface) ColorTransform *This = impl_from_IWICColorTransform(iface); ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); if (ref == 0) { if (This->dst) IWICBitmapSource_Release(This->dst); - HeapFree(GetProcessHeap(), 0, This); + free(This); } return ref; @@ -177,7 +175,7 @@ HRESULT ColorTransform_Create(IWICColorTransform **colortransform) if (!colortransform) return E_INVALIDARG; - This = HeapAlloc(GetProcessHeap(), 0, sizeof(ColorTransform)); + This = malloc(sizeof(ColorTransform)); if (!This) return E_OUTOFMEMORY; This->IWICColorTransform_iface.lpVtbl = &ColorTransform_Vtbl; diff --git a/dll/win32/windowscodecs/converter.c b/dll/win32/windowscodecs/converter.c index cac2ac1aa5a..2156e0aec8f 100644 --- a/dll/win32/windowscodecs/converter.c +++ b/dll/win32/windowscodecs/converter.c @@ -17,8 +17,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "config.h" - #include <stdarg.h> #include <math.h> @@ -30,7 +28,6 @@ #include "wincodecs_private.h" -#include "wine/heap.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); @@ -71,6 +68,7 @@ struct pixelformatinfo { enum pixelformat format; const WICPixelFormatGUID *guid; copyfunc copy_function; + BOOL is_indexed_format; }; typedef struct FormatConverter { @@ -176,7 +174,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe srcstride = (prc->Width+7)/8; srcdatasize = srcstride * prc->Height; - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + srcdata = malloc(srcdatasize); if (!srcdata) return E_OUTOFMEMORY; res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); @@ -205,7 +203,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe } } - HeapFree(GetProcessHeap(), 0, srcdata); + free(srcdata); return res; } @@ -243,7 +241,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe srcstride = (prc->Width+3)/4; srcdatasize = srcstride * prc->Height; - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + srcdata = malloc(srcdatasize); if (!srcdata) return E_OUTOFMEMORY; res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); @@ -268,7 +266,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe } } - HeapFree(GetProcessHeap(), 0, srcdata); + free(srcdata); return res; } @@ -306,7 +304,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe srcstride = (prc->Width+1)/2; srcdatasize = srcstride * prc->Height; - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + srcdata = malloc(srcdatasize); if (!srcdata) return E_OUTOFMEMORY; res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); @@ -329,7 +327,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe } } - HeapFree(GetProcessHeap(), 0, srcdata); + free(srcdata); return res; } @@ -349,7 +347,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe srcstride = prc->Width; srcdatasize = srcstride * prc->Height; - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + srcdata = malloc(srcdatasize); if (!srcdata) return E_OUTOFMEMORY; res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); @@ -371,7 +369,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe } } - HeapFree(GetProcessHeap(), 0, srcdata); + free(srcdata); return res; } @@ -405,7 +403,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe srcstride = prc->Width; srcdatasize = srcstride * prc->Height; - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + srcdata = malloc(srcdatasize); if (!srcdata) return E_OUTOFMEMORY; res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); @@ -424,7 +422,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe } } - HeapFree(GetProcessHeap(), 0, srcdata); + free(srcdata); return res; } @@ -444,7 +442,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe srcstride = prc->Width * 2; srcdatasize = srcstride * prc->Height; - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + srcdata = malloc(srcdatasize); if (!srcdata) return E_OUTOFMEMORY; res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); @@ -467,7 +465,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe } } - HeapFree(GetProcessHeap(), 0, srcdata); + free(srcdata); return res; } @@ -487,7 +485,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe srcstride = 2 * prc->Width; srcdatasize = srcstride * prc->Height; - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + srcdata = malloc(srcdatasize); if (!srcdata) return E_OUTOFMEMORY; res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); @@ -515,7 +513,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe } } - HeapFree(GetProcessHeap(), 0, srcdata); + free(srcdata); return res; } @@ -535,7 +533,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe srcstride = 2 * prc->Width; srcdatasize = srcstride * prc->Height; - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + srcdata = malloc(srcdatasize); if (!srcdata) return E_OUTOFMEMORY; res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); @@ -563,7 +561,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe } } - HeapFree(GetProcessHeap(), 0, srcdata); + free(srcdata); return res; } @@ -583,7 +581,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe srcstride = 2 * prc->Width; srcdatasize = srcstride * prc->Height; - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + srcdata = malloc(srcdatasize); if (!srcdata) return E_OUTOFMEMORY; res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); @@ -611,7 +609,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe } } - HeapFree(GetProcessHeap(), 0, srcdata); + free(srcdata); return res; } @@ -631,7 +629,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe srcstride = 3 * prc->Width; srcdatasize = srcstride * prc->Height; - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + srcdata = malloc(srcdatasize); if (!srcdata) return E_OUTOFMEMORY; res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); @@ -654,7 +652,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe } } - HeapFree(GetProcessHeap(), 0, srcdata); + free(srcdata); return res; } @@ -675,7 +673,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe srcstride = 3 * prc->Width; srcdatasize = srcstride * prc->Height; - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + srcdata = malloc(srcdatasize); if (!srcdata) return E_OUTOFMEMORY; res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); @@ -702,7 +700,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe } } - HeapFree(GetProcessHeap(), 0, srcdata); + free(srcdata); return res; } @@ -728,7 +726,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe HRESULT res; res = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); if (FAILED(res)) return res; - convert_rgba_to_bgra(4, pbBuffer, prc->Width, prc->Height, cbStride); + reverse_bgr8(4, pbBuffer, prc->Width, prc->Height, cbStride); } return S_OK; case format_32bppBGRA: @@ -772,7 +770,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe srcstride = 6 * prc->Width; srcdatasize = srcstride * prc->Height; - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + srcdata = malloc(srcdatasize); if (!srcdata) return E_OUTOFMEMORY; res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); @@ -796,7 +794,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe } } - HeapFree(GetProcessHeap(), 0, srcdata); + free(srcdata); return res; } @@ -816,7 +814,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe srcstride = 8 * prc->Width; srcdatasize = srcstride * prc->Height; - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + srcdata = malloc(srcdatasize); if (!srcdata) return E_OUTOFMEMORY; res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); @@ -841,7 +839,7 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe } } - HeapFree(GetProcessHeap(), 0, srcdata); + free(srcdata); return res; } @@ -985,9 +983,9 @@ static HRESULT copypixels_to_32bppPBGRA(struct FormatConverter *This, const WICR BYTE alpha = pbBuffer[cbStride*y+4*x+3]; if (alpha != 255) { - pbBuffer[cbStride*y+4*x] = pbBuffer[cbStride*y+4*x] * alpha / 255; - pbBuffer[cbStride*y+4*x+1] = pbBuffer[cbStride*y+4*x+1] * alpha / 255; - pbBuffer[cbStride*y+4*x+2] = pbBuffer[cbStride*y+4*x+2] * alpha / 255; + pbBuffer[cbStride*y+4*x] = (pbBuffer[cbStride*y+4*x] * alpha + 127) / 255; + pbBuffer[cbStride*y+4*x+1] = (pbBuffer[cbStride*y+4*x+1] * alpha + 127) / 255; + pbBuffer[cbStride*y+4*x+2] = (pbBuffer[cbStride*y+4*x+2] * alpha + 127) / 255; } } } @@ -1018,9 +1016,9 @@ static HRESULT copypixels_to_32bppPRGBA(struct FormatConverter *This, const WICR BYTE alpha = pbBuffer[cbStride*y+4*x+3]; if (alpha != 255) { - pbBuffer[cbStride*y+4*x] = pbBuffer[cbStride*y+4*x] * alpha / 255; - pbBuffer[cbStride*y+4*x+1] = pbBuffer[cbStride*y+4*x+1] * alpha / 255; - pbBuffer[cbStride*y+4*x+2] = pbBuffer[cbStride*y+4*x+2] * alpha / 255; + pbBuffer[cbStride*y+4*x] = (pbBuffer[cbStride*y+4*x] * alpha + 127) / 255; + pbBuffer[cbStride*y+4*x+1] = (pbBuffer[cbStride*y+4*x+1] * alpha + 127) / 255; + pbBuffer[cbStride*y+4*x+2] = (pbBuffer[cbStride*y+4*x+2] * alpha + 127) / 255; } } } @@ -1063,7 +1061,7 @@ static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This, const WICRec srcstride = 4 * prc->Width; srcdatasize = srcstride * prc->Height; - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + srcdata = malloc(srcdatasize); if (!srcdata) return E_OUTOFMEMORY; res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); @@ -1107,7 +1105,7 @@ static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This, const WICRec } } - HeapFree(GetProcessHeap(), 0, srcdata); + free(srcdata); return res; } @@ -1122,7 +1120,7 @@ static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This, const WICRec srcstride = 4 * prc->Width; srcdatasize = srcstride * prc->Height; - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + srcdata = malloc(srcdatasize); if (!srcdata) return E_OUTOFMEMORY; hr = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); @@ -1149,7 +1147,7 @@ static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This, const WICRec } } - HeapFree(GetProcessHeap(), 0, srcdata); + free(srcdata); return hr; } @@ -1164,7 +1162,7 @@ static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This, const WICRec srcstride = 4 * prc->Width; srcdatasize = srcstride * prc->Height; - srcdata = heap_alloc(srcdatasize); + srcdata = malloc(srcdatasize); if (!srcdata) return E_OUTOFMEMORY; hr = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); @@ -1192,7 +1190,7 @@ static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This, const WICRec } } - heap_free(srcdata); + free(srcdata); return hr; } return S_OK; @@ -1238,7 +1236,7 @@ static HRESULT copypixels_to_24bppRGB(struct FormatConverter *This, const WICRec srcstride = 4 * prc->Width; srcdatasize = srcstride * prc->Height; - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + srcdata = malloc(srcdatasize); if (!srcdata) return E_OUTOFMEMORY; res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); @@ -1265,7 +1263,7 @@ static HRESULT copypixels_to_24bppRGB(struct FormatConverter *This, const WICRec } } - HeapFree(GetProcessHeap(), 0, srcdata); + free(srcdata); return res; } @@ -1343,7 +1341,7 @@ static HRESULT copypixels_to_8bppGray(struct FormatConverter *This, const WICRec srcstride = 4 * prc->Width; srcdatasize = srcstride * prc->Height; - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + srcdata = malloc(srcdatasize); if (!srcdata) return E_OUTOFMEMORY; hr = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); @@ -1365,7 +1363,7 @@ static HRESULT copypixels_to_8bppGray(struct FormatConverter *This, const WICRec } } - HeapFree(GetProcessHeap(), 0, srcdata); + free(srcdata); } return hr; @@ -1377,7 +1375,7 @@ static HRESULT copypixels_to_8bppGray(struct FormatConverter *This, const WICRec srcstride = 3 * prc->Width; srcdatasize = srcstride * prc->Height; - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + srcdata = malloc(srcdatasize); if (!srcdata) return E_OUTOFMEMORY; hr = copypixels_to_24bppBGR(This, prc, srcstride, srcdatasize, srcdata, source_format); @@ -1403,7 +1401,7 @@ static HRESULT copypixels_to_8bppGray(struct FormatConverter *This, const WICRec } } - HeapFree(GetProcessHeap(), 0, srcdata); + free(srcdata); return hr; } @@ -1467,7 +1465,7 @@ static HRESULT copypixels_to_8bppIndexed(struct FormatConverter *This, const WIC srcstride = 3 * prc->Width; srcdatasize = srcstride * prc->Height; - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); + srcdata = malloc(srcdatasize); if (!srcdata) return E_OUTOFMEMORY; hr = copypixels_to_24bppBGR(This, prc, srcstride, srcdatasize, srcdata, source_format); @@ -1490,15 +1488,138 @@ static HRESULT copypixels_to_8bppIndexed(struct FormatConverter *This, const WIC } } - HeapFree(GetProcessHeap(), 0, srcdata); + free(srcdata); return hr; } +static HRESULT copypixels_to_16bppBGRA5551(struct FormatConverter *This, const WICRect *prc, + UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) +{ + switch (source_format) + { + case format_16bppBGRA5551: + if (prc) + return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); + return S_OK; + case format_32bppBGRA: + if(prc) + { + HRESULT res; + INT x, y; + BYTE *srcdata; + UINT srcstride, srcdatasize; + const BYTE *srcrow; + const DWORD *srcpixel; + BYTE *dstrow; + DWORD srcval = 0; + WORD *dstpixel; + + int a, r, g, b; + + srcstride = 4 * prc->Width; + srcdatasize = srcstride * prc->Height; + + srcdata = malloc(srcdatasize); + if (!srcdata) return E_OUTOFMEMORY; + + res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); + if(SUCCEEDED(res)) + { + srcrow = srcdata; + dstrow = pbBuffer; + for(y=0; y< prc->Height; y++) { + srcpixel = (const DWORD*)srcrow; + dstpixel = (WORD *)dstrow; + for(x=0; x<prc->Width; x++) { + srcval=*srcpixel++; + a = (srcval & 0xff000000) >> 24; + r = (srcval & 0x00ff0000) >> 16; + g = (srcval & 0x0000ff00) >> 8; + b = (srcval & 0x000000ff); + a = (a >> 7) << 15; + r = (r >> 3) << 10; + g = (g >> 3) << 5; + b = (b >> 3); + *dstpixel++ = (a|r|g|b); + } + srcrow += srcstride; + dstrow += cbStride; + } + } + free(srcdata); + } + return S_OK; + default: + FIXME("Unimplemented conversion path! %d\n", source_format); + return WINCODEC_ERR_UNSUPPORTEDOPERATION; + } +} + +static HRESULT copypixels_to_64bppRGBA(struct FormatConverter *This, const WICRect *prc, + UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) +{ + HRESULT hr; + + switch (source_format) + { + case format_64bppRGBA: + if (prc) + return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); + return S_OK; + + case format_48bppRGB: + { + UINT srcstride, srcdatasize; + const USHORT *srcpixel; + const BYTE *srcrow; + USHORT *dstpixel; + BYTE *srcdata; + BYTE *dstrow; + INT x, y; + + if (!prc) + return S_OK; + + srcstride = 6 * prc->Width; + srcdatasize = srcstride * prc->Height; + + srcdata = malloc(srcdatasize); + if (!srcdata) return E_OUTOFMEMORY; + + hr = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); + if (SUCCEEDED(hr)) + { + srcrow = srcdata; + dstrow = pbBuffer; + for (y = 0; y < prc->Height; y++) + { + srcpixel = (USHORT *)srcrow; + dstpixel= (USHORT *)dstrow; + for (x = 0; x < prc->Width; x++) + { + *dstpixel++ = *srcpixel++; + *dstpixel++ = *srcpixel++; + *dstpixel++ = *srcpixel++; + *dstpixel++ = 65535; + } + srcrow += srcstride; + dstrow += cbStride; + } + } + free(srcdata); + return hr; + } + default: + FIXME("Unimplemented conversion path %d.\n", source_format); + return WINCODEC_ERR_UNSUPPORTEDOPERATION; + } +} + static const struct pixelformatinfo supported_formats[] = { - {format_1bppIndexed, &GUID_WICPixelFormat1bppIndexed, NULL}, - {format_2bppIndexed, &GUID_WICPixelFormat2bppIndexed, NULL}, - {format_4bppIndexed, &GUID_WICPixelFormat4bppIndexed, NULL}, - {format_8bppIndexed, &GUID_WICPixelFormat8bppIndexed, copypixels_to_8bppIndexed}, + {format_1bppIndexed, &GUID_WICPixelFormat1bppIndexed, NULL, TRUE}, + {format_2bppIndexed, &GUID_WICPixelFormat2bppIndexed, NULL, TRUE}, + {format_4bppIndexed, &GUID_WICPixelFormat4bppIndexed, NULL, TRUE}, + {format_8bppIndexed, &GUID_WICPixelFormat8bppIndexed, copypixels_to_8bppIndexed, TRUE}, {format_BlackWhite, &GUID_WICPixelFormatBlackWhite, NULL}, {format_2bppGray, &GUID_WICPixelFormat2bppGray, NULL}, {format_4bppGray, &GUID_WICPixelFormat4bppGray, NULL}, @@ -1506,7 +1627,7 @@ static const struct pixelformatinfo supported_formats[] = { {format_16bppGray, &GUID_WICPixelFormat16bppGray, NULL}, {format_16bppBGR555, &GUID_WICPixelFormat16bppBGR555, NULL}, {format_16bppBGR565, &GUID_WICPixelFormat16bppBGR565, NULL}, - {format_16bppBGRA5551, &GUID_WICPixelFormat16bppBGRA5551, NULL}, + {format_16bppBGRA5551, &GUID_WICPixelFormat16bppBGRA5551, copypixels_to_16bppBGRA5551}, {format_24bppBGR, &GUID_WICPixelFormat24bppBGR, copypixels_to_24bppBGR}, {format_24bppRGB, &GUID_WICPixelFormat24bppRGB, copypixels_to_24bppRGB}, {format_32bppGrayFloat, &GUID_WICPixelFormat32bppGrayFloat, copypixels_to_32bppGrayFloat}, @@ -1517,7 +1638,7 @@ static const struct pixelformatinfo supported_formats[] = { {format_32bppPBGRA, &GUID_WICPixelFormat32bppPBGRA, copypixels_to_32bppPBGRA}, {format_32bppPRGBA, &GUID_WICPixelFormat32bppPRGBA, copypixels_to_32bppPRGBA}, {format_48bppRGB, &GUID_WICPixelFormat48bppRGB, NULL}, - {format_64bppRGBA, &GUID_WICPixelFormat64bppRGBA, NULL}, + {format_64bppRGBA, &GUID_WICPixelFormat64bppRGBA, copypixels_to_64bppRGBA}, {format_32bppCMYK, &GUID_WICPixelFormat32bppCMYK, NULL}, {0} }; @@ -1561,7 +1682,7 @@ static ULONG WINAPI FormatConverter_AddRef(IWICFormatConverter *iface) FormatConverter *This = impl_from_IWICFormatConverter(iface); ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); return ref; } @@ -1571,7 +1692,7 @@ static ULONG WINAPI FormatConverter_Release(IWICFormatConverter *iface) FormatConverter *This = impl_from_IWICFormatConverter(iface); ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p) refcount=%u\n", iface, ref); + TRACE("(%p) refcount=%lu\n", iface, ref); if (ref == 0) { @@ -1579,7 +1700,7 @@ static ULONG WINAPI FormatConverter_Release(IWICFormatConverter *iface) DeleteCriticalSection(&This->lock); if (This->source) IWICBitmapSource_Release(This->source); if (This->palette) IWICPalette_Release(This->palette); - HeapFree(GetProcessHeap(), 0, This); + free(This); } return ref; @@ -1638,12 +1759,7 @@ static HRESULT WINAPI FormatConverter_CopyPalette(IWICFormatConverter *iface, if (!This->palette) { - HRESULT hr; - UINT bpp; - - hr = get_pixelformat_bpp(This->dst_format->guid, &bpp); - if (hr != S_OK) return hr; - if (bpp <= 8) return WINCODEC_ERR_WRONGSTATE; + if (This->dst_format->is_indexed_format) return WINCODEC_ERR_WRONGSTATE; return IWICBitmapSource_CopyPalette(This->source, palette); } @@ -1691,6 +1807,13 @@ static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface, TRACE("(%p,%p,%s,%u,%p,%0.3f,%u)\n", iface, source, debugstr_guid(dstFormat), dither, palette, alpha_threshold, palette_type); + dstinfo = get_formatinfo(dstFormat); + if (!dstinfo) + { + FIXME("Unsupported destination format %s\n", debugstr_guid(dstFormat)); + return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT; + } + if (!palette) { UINT bpp; @@ -1705,18 +1828,21 @@ static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface, case WICBitmapPaletteTypeCustom: IWICPalette_Release(palette); palette = NULL; - if (bpp <= 8) return E_INVALIDARG; + + /* Indexed types require a palette */ + if (dstinfo->is_indexed_format) + return E_INVALIDARG; break; case WICBitmapPaletteTypeMedianCut: { - if (bpp <= 8) + if (dstinfo->is_indexed_format) res = IWICPalette_InitializeFromBitmap(palette, source, 1 << bpp, FALSE); break; } default: - if (bpp <= 8) + if (dstinfo->is_indexed_format) res = IWICPalette_InitializePredefined(palette, palette_type, FALSE); break; } @@ -1749,14 +1875,6 @@ static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface, goto end; } - dstinfo = get_formatinfo(dstFormat); - if (!dstinfo) - { - res = WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT; - FIXME("Unsupported destination format %s\n", debugstr_guid(dstFormat)); - goto end; - } - if (dstinfo->copy_function) { IWICBitmapSource_AddRef(source); @@ -1841,14 +1959,18 @@ HRESULT FormatConverter_CreateInstance(REFIID iid, void** ppv) *ppv = NULL; - This = HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter)); + This = malloc(sizeof(FormatConverter)); if (!This) return E_OUTOFMEMORY; This->IWICFormatConverter_iface.lpVtbl = &FormatConverter_Vtbl; This->ref = 1; This->source = NULL; This->palette = NULL; +#ifdef __REACTOS__ InitializeCriticalSection(&This->lock); +#else + InitializeCriticalSectionEx(&This->lock, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO); +#endif This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": FormatConverter.lock"); ret = IWICFormatConverter_QueryInterface(&This->IWICFormatConverter_iface, iid, ppv); diff --git a/dll/win32/windowscodecs/ddsformat.c b/dll/win32/windowscodecs/ddsformat.c new file mode 100644 index 00000000000..680febb0d93 --- /dev/null +++ b/dll/win32/windowscodecs/ddsformat.c @@ -0,0 +1,2162 @@ +/* + * Copyright 2020 Ziqing Hui + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + * + * Note: + * + * Uncompressed image: + * For uncompressed formats, a block is equivalent to a pixel. + * + * Cube map: + * A cube map is equivalent to a 2D texture array which has 6 textures. + * A cube map array is equivalent to a 2D texture array which has cubeCount*6 textures. + */ + +#include <stdarg.h> + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "objbase.h" + +#include "wincodecs_private.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); + +#define DDS_MAGIC 0x20534444 +#ifndef MAKEFOURCC +#define MAKEFOURCC(ch0, ch1, ch2, ch3) \ + ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \ + ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 )) +#endif + +#define GET_RGB565_R(color) ((BYTE)(((color) >> 11) & 0x1F)) +#define GET_RGB565_G(color) ((BYTE)(((color) >> 5) & 0x3F)) +#define GET_RGB565_B(color) ((BYTE)(((color) >> 0) & 0x1F)) +#define MAKE_RGB565(r, g, b) ((WORD)(((BYTE)(r) << 11) | ((BYTE)(g) << 5) | (BYTE)(b))) +#define MAKE_ARGB(a, r, g, b) (((DWORD)(a) << 24) | ((DWORD)(r) << 16) | ((DWORD)(g) << 8) | (DWORD)(b)) + +#define DDPF_ALPHAPIXELS 0x00000001 +#define DDPF_ALPHA 0x00000002 +#define DDPF_FOURCC 0x00000004 +#define DDPF_PALETTEINDEXED8 0x00000020 +#define DDPF_RGB 0x00000040 +#define DDPF_LUMINANCE 0x00020000 +#define DDPF_BUMPDUDV 0x00080000 + +#define DDSCAPS2_CUBEMAP 0x00000200 +#define DDSCAPS2_VOLUME 0x00200000 + +#define DDS_DIMENSION_TEXTURE1D 2 +#define DDS_DIMENSION_TEXTURE2D 3 +#define DDS_DIMENSION_TEXTURE3D 4 + +#define DDS_RESOURCE_MISC_TEXTURECUBE 0x00000004 + +#define DDS_BLOCK_WIDTH 4 +#define DDS_BLOCK_HEIGHT 4 + +typedef struct { + DWORD size; + DWORD flags; + DWORD fourCC; + DWORD rgbBitCount; + DWORD rBitMask; + DWORD gBitMask; + DWORD bBitMask; + DWORD aBitMask; +} DDS_PIXELFORMAT; + +typedef struct { + DWORD size; + DWORD flags; + DWORD height; + DWORD width; + DWORD pitchOrLinearSize; + DWORD depth; + DWORD mipMapCount; + DWORD reserved1[11]; + DDS_PIXELFORMAT ddspf; + DWORD caps; + DWORD caps2; + DWORD caps3; + DWORD caps4; + DWORD reserved2; +} DDS_HEADER; + +typedef struct { + DWORD dxgiFormat; + DWORD resourceDimension; + DWORD miscFlag; + DWORD arraySize; + DWORD miscFlags2; +} DDS_HEADER_DXT10; + +typedef struct dds_info { + UINT width; + UINT height; + UINT depth; + UINT mip_levels; + UINT array_size; + UINT frame_count; + UINT data_offset; + UINT bytes_per_block; /* for uncompressed format, this means bytes per pixel*/ + DXGI_FORMAT format; + WICDdsDimension dimension; + WICDdsAlphaMode alpha_mode; + const GUID *pixel_format; + UINT pixel_format_bpp; +} dds_info; + +typedef struct dds_frame_info { + UINT width; + UINT height; + DXGI_FORMAT format; + UINT bytes_per_block; /* for uncompressed format, this means bytes per pixel*/ + UINT block_width; + UINT block_height; + UINT width_in_blocks; + UINT height_in_blocks; + const GUID *pixel_format; + UINT pixel_format_bpp; +} dds_frame_info; + +typedef struct DdsDecoder { + IWICBitmapDecoder IWICBitmapDecoder_iface; + IWICDdsDecoder IWICDdsDecoder_iface; + IWICWineDecoder IWICWineDecoder_iface; + LONG ref; + BOOL initialized; + IStream *stream; + CRITICAL_SECTION lock; + dds_info info; +} DdsDecoder; + +typedef struct DdsFrameDecode { + IWICBitmapFrameDecode IWICBitmapFrameDecode_iface; + IWICDdsFrameDecode IWICDdsFrameDecode_iface; + LONG ref; + BYTE *block_data; + BYTE *pixel_data; + CRITICAL_SECTION lock; + dds_frame_info info; +} DdsFrameDecode; + +typedef struct DdsEncoder { + IWICBitmapEncoder IWICBitmapEncoder_iface; + IWICDdsEncoder IWICDdsEncoder_iface; + LONG ref; + CRITICAL_SECTION lock; + IStream *stream; + UINT frame_count; + UINT frame_index; + BOOL uncommitted_frame; + BOOL committed; + dds_info info; +} DdsEncoder; + +typedef struct DdsFrameEncode { + IWICBitmapFrameEncode IWICBitmapFrameEncode_iface; + LONG ref; + DdsEncoder *parent; + BOOL initialized; + BOOL frame_created; + UINT width; + UINT height; + double dpi_x; + double dpi_y; +} DdsFrameEncode; + +static struct dds_format { + DDS_PIXELFORMAT pixel_format; + const GUID *wic_format; + UINT wic_format_bpp; + DXGI_FORMAT dxgi_format; +} dds_format_table[] = { + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '1'), 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormat32bppPBGRA, 32, DXGI_FORMAT_BC1_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '2'), 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormat32bppPBGRA, 32, DXGI_FORMAT_BC2_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '3'), 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormat32bppBGRA, 32, DXGI_FORMAT_BC2_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '4'), 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormat32bppPBGRA, 32, DXGI_FORMAT_BC3_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', 'T', '5'), 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormat32bppBGRA, 32, DXGI_FORMAT_BC3_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('B', 'C', '4', 'U'), 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormat32bppBGRA, 32, DXGI_FORMAT_BC4_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('B', 'C', '4', 'S'), 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormat32bppBGRA, 32, DXGI_FORMAT_BC4_SNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('B', 'C', '5', 'U'), 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormat32bppBGRA, 32, DXGI_FORMAT_BC5_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('B', 'C', '5', 'S'), 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormat32bppBGRA, 32, DXGI_FORMAT_BC5_SNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('A', 'T', 'I', '1'), 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormat32bppBGRA, 32, DXGI_FORMAT_BC4_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('A', 'T', 'I', '2'), 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormat32bppBGRA, 32, DXGI_FORMAT_BC5_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('R', 'G', 'B', 'G'), 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormat32bpp4Channels, 32, DXGI_FORMAT_R8G8_B8G8_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('G', 'R', 'G', 'B'), 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormat32bpp4Channels, 32, DXGI_FORMAT_G8R8_G8B8_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, MAKEFOURCC('D', 'X', '1', '0'), 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormatUndefined, 0, DXGI_FORMAT_UNKNOWN }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x24, 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormat64bppRGBA, 64, DXGI_FORMAT_R16G16B16A16_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x6E, 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormat64bppRGBA, 64, DXGI_FORMAT_R16G16B16A16_SNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x6F, 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormat16bppGrayHalf, 16, DXGI_FORMAT_R16_FLOAT }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x70, 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormatUndefined, 0, DXGI_FORMAT_R16G16_FLOAT }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x71, 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormat64bppRGBAHalf, 64, DXGI_FORMAT_R16G16B16A16_FLOAT }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x72, 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormat32bppGrayFloat, 32, DXGI_FORMAT_R32_FLOAT }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x73, 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormatUndefined, 32, DXGI_FORMAT_R32G32_FLOAT }, + { { sizeof(DDS_PIXELFORMAT), DDPF_FOURCC, 0x74, 0, 0, 0, 0, 0 }, + &GUID_WICPixelFormat128bppRGBAFloat, 128, DXGI_FORMAT_R32G32B32A32_FLOAT }, + { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 32, 0xFF,0xFF00,0xFF0000,0xFF000000 }, + &GUID_WICPixelFormat32bppRGBA, 32, DXGI_FORMAT_R8G8B8A8_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 32, 0xFF,0xFF00,0xFF0000,0 }, + &GUID_WICPixelFormat32bppRGB, 32, DXGI_FORMAT_UNKNOWN }, + { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 32, 0xFF0000,0xFF00,0xFF,0xFF000000 }, + &GUID_WICPixelFormat32bppBGRA, 32, DXGI_FORMAT_B8G8R8A8_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 32, 0xFF0000,0xFF00,0xFF,0 }, + &GUID_WICPixelFormat32bppBGR, 32, DXGI_FORMAT_B8G8R8X8_UNORM }, + /* The red and blue masks are swapped for DXGI_FORMAT_R10G10B10A2_UNORM. + * For "correct" one, the RGB masks should be 0x3FF,0xFFC00,0x3FF00000. + * see:
https://walbourn.github.io/dds-update-and-1010102-problems
*/ + { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 32, 0x3FF00000,0xFFC00,0x3FF,0xC0000000 }, + &GUID_WICPixelFormat32bppR10G10B10A2, 32, DXGI_FORMAT_R10G10B10A2_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 32, 0x3FF,0xFFC00,0x3FF00000,0xC0000000 }, + &GUID_WICPixelFormat32bppRGBA1010102, 32, DXGI_FORMAT_R10G10B10A2_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_RGB , 0, 32, 0xFFFF,0xFFFF0000,0,0 }, + &GUID_WICPixelFormatUndefined, 0, DXGI_FORMAT_R16G16_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_RGB , 0, 32, 0xFFFFFFFF,0,0,0 }, + &GUID_WICPixelFormat32bppGrayFloat, 32, DXGI_FORMAT_R32_FLOAT }, + { { sizeof(DDS_PIXELFORMAT), DDPF_RGB , 0, 24, 0xFF0000,0x00FF00,0x0000FF,0 }, + &GUID_WICPixelFormat24bppBGR, 24, DXGI_FORMAT_UNKNOWN }, + { { sizeof(DDS_PIXELFORMAT), DDPF_RGB , 0, 24, 0x0000FF,0x00FF00,0xFF0000,0 }, + &GUID_WICPixelFormat24bppRGB, 24, DXGI_FORMAT_UNKNOWN }, + { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 16, 0xF800,0x7E0,0x1F,0 }, + &GUID_WICPixelFormat16bppBGR565, 16, DXGI_FORMAT_B5G6R5_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 16, 0x7C00,0x3E0,0x1F,0 }, + &GUID_WICPixelFormat16bppBGR555, 16, DXGI_FORMAT_UNKNOWN }, + { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 16, 0x7C00,0x3E0,0x1F,0x8000 }, + &GUID_WICPixelFormat16bppBGRA5551, 16, DXGI_FORMAT_B5G5R5A1_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_RGB, 0, 16, 0xF00,0xF0,0xF,0xF000 }, + &GUID_WICPixelFormatUndefined, 0, DXGI_FORMAT_B4G4R4A4_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_ALPHA, 0, 8, 0,0,0,0xFF }, + &GUID_WICPixelFormat8bppAlpha, 8, DXGI_FORMAT_A8_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_LUMINANCE, 0, 16, 0xFFFF,0,0,0 }, + &GUID_WICPixelFormat16bppGray, 16, DXGI_FORMAT_R16_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_LUMINANCE, 0, 16, 0xFF,0,0,0xFF00 }, + &GUID_WICPixelFormatUndefined, 0, DXGI_FORMAT_R8G8_UNORM }, + { { sizeof(DDS_PIXELFORMAT), DDPF_LUMINANCE, 0, 8, 0xFF,0,0,0 }, + &GUID_WICPixelFormat8bppGray, 8, DXGI_FORMAT_R8_UNORM }, + { { 0 }, &GUID_WICPixelFormat8bppAlpha, 8, DXGI_FORMAT_A8_UNORM }, + { { 0 }, &GUID_WICPixelFormat8bppGray, 8, DXGI_FORMAT_R8_UNORM }, + { { 0 }, &GUID_WICPixelFormat16bppGray, 16, DXGI_FORMAT_R16_UNORM }, + { { 0 }, &GUID_WICPixelFormat16bppGrayHalf, 16, DXGI_FORMAT_R16_FLOAT }, + { { 0 }, &GUID_WICPixelFormat16bppBGR565, 16, DXGI_FORMAT_B5G6R5_UNORM }, + { { 0 }, &GUID_WICPixelFormat16bppBGRA5551, 16, DXGI_FORMAT_B5G5R5A1_UNORM }, + { { 0 }, &GUID_WICPixelFormat32bppGrayFloat, 32, DXGI_FORMAT_R32_FLOAT }, + { { 0 }, &GUID_WICPixelFormat32bppRGBA, 32, DXGI_FORMAT_R8G8B8A8_UNORM }, + { { 0 }, &GUID_WICPixelFormat32bppBGRA, 32, DXGI_FORMAT_B8G8R8A8_UNORM }, + { { 0 }, &GUID_WICPixelFormat32bppBGR, 32, DXGI_FORMAT_B8G8R8X8_UNORM }, + { { 0 }, &GUID_WICPixelFormat32bppR10G10B10A2, 32, DXGI_FORMAT_R10G10B10A2_UNORM }, + { { 0 }, &GUID_WICPixelFormat32bppRGBE, 32, DXGI_FORMAT_R9G9B9E5_SHAREDEXP }, + { { 0 }, &GUID_WICPixelFormat32bppRGBA1010102XR, 32, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM }, + { { 0 }, &GUID_WICPixelFormat64bppRGBA, 64, DXGI_FORMAT_R16G16B16A16_UNORM }, + { { 0 }, &GUID_WICPixelFormat64bppRGBAHalf, 64, DXGI_FORMAT_R16G16B16A16_FLOAT }, + { { 0 }, &GUID_WICPixelFormat96bppRGBFloat, 96, DXGI_FORMAT_R32G32B32_FLOAT }, + { { 0 }, &GUID_WICPixelFormat128bppRGBAFloat, 128, DXGI_FORMAT_R32G32B32A32_FLOAT }, + { { 0 }, &GUID_WICPixelFormatUndefined, 0, DXGI_FORMAT_UNKNOWN } +}; + +static DXGI_FORMAT compressed_formats[] = { + DXGI_FORMAT_BC1_TYPELESS, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM_SRGB, + DXGI_FORMAT_BC2_TYPELESS, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM_SRGB, + DXGI_FORMAT_BC3_TYPELESS, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM_SRGB, + DXGI_FORMAT_BC4_TYPELESS, DXGI_FORMAT_BC4_UNORM, DXGI_FORMAT_BC4_SNORM, + DXGI_FORMAT_BC5_TYPELESS, DXGI_FORMAT_BC5_UNORM, DXGI_FORMAT_BC5_SNORM, + DXGI_FORMAT_BC6H_TYPELESS, DXGI_FORMAT_BC6H_UF16, DXGI_FORMAT_BC6H_SF16, + DXGI_FORMAT_BC7_TYPELESS, DXGI_FORMAT_BC7_UNORM, DXGI_FORMAT_BC7_UNORM_SRGB +}; + +static HRESULT WINAPI DdsDecoder_Dds_GetFrame(IWICDdsDecoder *, UINT, UINT, UINT, IWICBitmapFrameDecode **); + +static DWORD rgb565_to_argb(WORD color, BYTE alpha) +{ + return MAKE_ARGB(alpha, (GET_RGB565_R(color) * 0xFF + 0x0F) / 0x1F, + (GET_RGB565_G(color) * 0xFF + 0x1F) / 0x3F, + (GET_RGB565_B(color) * 0xFF + 0x0F) / 0x1F); +} + +static inline BOOL has_extended_header(DDS_HEADER *header) +{ + return (header->ddspf.flags & DDPF_FOURCC) && + (header->ddspf.fourCC == MAKEFOURCC('D', 'X', '1', '0')); +} + +static WICDdsDimension get_dimension(DDS_HEADER *header, DDS_HEADER_DXT10 *header_dxt10) +{ + if (header_dxt10) { + if (header_dxt10->miscFlag & DDS_RESOURCE_MISC_TEXTURECUBE) return WICDdsTextureCube; + switch (header_dxt10->resourceDimension) + { + case DDS_DIMENSION_TEXTURE1D: return WICDdsTexture1D; + case DDS_DIMENSION_TEXTURE2D: return WICDdsTexture2D; + case DDS_DIMENSION_TEXTURE3D: return WICDdsTexture3D; + default: return WICDdsTexture2D; + } + } else { + if (header->caps2 & DDSCAPS2_CUBEMAP) { + return WICDdsTextureCube; + } else if (header->caps2 & DDSCAPS2_VOLUME) { + return WICDdsTexture3D; + } else { + return WICDdsTexture2D; + } + } +} + +static struct dds_format *get_dds_format(DDS_PIXELFORMAT *pixel_format) +{ + UINT i; + + for (i = 0; i < ARRAY_SIZE(dds_format_table); i++) + { + if ((pixel_format->flags & dds_format_table[i].pixel_format.flags) && + (pixel_format->fourCC == dds_format_table[i].pixel_format.fourCC) && + (pixel_format->rgbBitCount == dds_format_table[i].pixel_format.rgbBitCount) && + (pixel_format->rBitMask == dds_format_table[i].pixel_format.rBitMask) && + (pixel_format->gBitMask == dds_format_table[i].pixel_format.gBitMask) && + (pixel_format->bBitMask == dds_format_table[i].pixel_format.bBitMask) && + (pixel_format->aBitMask == dds_format_table[i].pixel_format.aBitMask)) + return dds_format_table + i; + } + + return dds_format_table + ARRAY_SIZE(dds_format_table) - 1; +} + +static WICDdsAlphaMode get_alpha_mode_from_fourcc(DWORD fourcc) +{ + switch (fourcc) + { + case MAKEFOURCC('D', 'X', 'T', '1'): + case MAKEFOURCC('D', 'X', 'T', '2'): + case MAKEFOURCC('D', 'X', 'T', '4'): + return WICDdsAlphaModePremultiplied; + default: + return WICDdsAlphaModeUnknown; + } +} + +static UINT get_bytes_per_block_from_format(DXGI_FORMAT format) +{ + /* for uncompressed format, return bytes per pixel*/ + switch (format) + { + case DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_SINT: + case DXGI_FORMAT_A8_UNORM: + return 1; + case DXGI_FORMAT_R8G8_TYPELESS: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT_R8G8_SINT: + case DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R16_UINT: + case DXGI_FORMAT_R16_SNORM: + case DXGI_FORMAT_R16_SINT: + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + case DXGI_FORMAT_B4G4R4A4_UNORM: + return 2; + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + case DXGI_FORMAT_R16G16_TYPELESS: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R16G16_UINT: + case DXGI_FORMAT_R16G16_SNORM: + case DXGI_FORMAT_R16G16_SINT: + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R32_SINT: + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + return 4; + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM_SRGB: + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G32_SINT: + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + return 8; + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + return 12; + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM_SRGB: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM_SRGB: + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + return 16; + default: + WARN("DXGI format 0x%x is not supported in DDS decoder\n", format); + return 0; + } +} + +static UINT get_frame_count(UINT depth, UINT mip_levels, UINT array_size, WICDdsDimension dimension) +{ + UINT frame_count, i; + + if (depth == 1) + { + frame_count = mip_levels; + } + else + { + frame_count = 0; + for (i = 0; i < mip_levels; i++) + { + frame_count += depth; + if (depth > 1) depth /= 2; + } + } + + frame_count *= array_size; + if (dimension == WICDdsTextureCube) frame_count *= 6; + + return frame_count; +} + +static void get_frame_dds_index(UINT index, dds_info *info, UINT *array_index, UINT *mip_level, UINT *slice_index) +{ + UINT frame_per_texture, depth; + + if (info->dimension == WICDdsTextureCube) + frame_per_texture = info->mip_levels; + else + frame_per_texture = info->frame_count / info->array_size; + + *array_index = index / frame_per_texture; + *slice_index = index % frame_per_texture; + depth = info->depth; + *mip_level = 0; + while (*slice_index >= depth) + { + *slice_index -= depth; + (*mip_level)++; + if (depth > 1) depth /= 2; + } +} + +static const GUID *dxgi_format_to_wic_format(DXGI_FORMAT dxgi_format) +{ + UINT i; + for (i = 0; i < ARRAY_SIZE(dds_format_table); i++) + { + if (dds_format_table[i].pixel_format.size == 0 && + dds_format_table[i].dxgi_format == dxgi_format) + return dds_format_table[i].wic_format; + } + return &GUID_WICPixelFormatUndefined; +} + +static BOOL is_compressed(DXGI_FORMAT format) +{ + UINT i; + + for (i = 0; i < ARRAY_SIZE(compressed_formats); i++) + { + if (format == compressed_formats[i]) return TRUE; + } + return FALSE; +} + +static void get_dds_info(dds_info* info, DDS_HEADER *header, DDS_HEADER_DXT10 *header_dxt10) +{ + struct dds_format *format_info; + + info->width = header->width; + info->height = header->height; + info->depth = 1; + info->mip_levels = 1; + info->array_size = 1; + if (header->depth) info->depth = header->depth; + if (header->mipMapCount) info->mip_levels = header->mipMapCount; + + if (has_extended_header(header)) { + if (header_dxt10->arraySize) info->array_size = header_dxt10->arraySize; + info->format = header_dxt10->dxgiFormat; + info->dimension = get_dimension(NULL, header_dxt10); + info->alpha_mode = header_dxt10->miscFlags2 & 0x00000008; + info->data_offset = sizeof(DWORD) + sizeof(*header) + sizeof(*header_dxt10); + if (is_compressed(info->format)) { + info->pixel_format = (info->alpha_mode == WICDdsAlphaModePremultiplied) ? + &GUID_WICPixelFormat32bppPBGRA : &GUID_WICPixelFormat32bppBGRA; + info->pixel_format_bpp = 32; + } else { + info->pixel_format = dxgi_format_to_wic_format(info->format); + info->pixel_format_bpp = get_bytes_per_block_from_format(info->format) * 8; + } + } else { + format_info = get_dds_format(&header->ddspf); + info->format = format_info->dxgi_format; + info->dimension = get_dimension(header, NULL); + info->alpha_mode = get_alpha_mode_from_fourcc(header->ddspf.fourCC); + info->data_offset = sizeof(DWORD) + sizeof(*header); + info->pixel_format = format_info->wic_format; + info->pixel_format_bpp = format_info->wic_format_bpp; + } + + if (header->ddspf.flags & (DDPF_RGB | DDPF_ALPHA | DDPF_LUMINANCE)) { + info->bytes_per_block = header->ddspf.rgbBitCount / 8; + } else { + info->bytes_per_block = get_bytes_per_block_from_format(info->format); + } + + info->frame_count = get_frame_count(info->depth, info->mip_levels, info->array_size, info->dimension); +} + +static void decode_block(const BYTE *block_data, UINT block_count, DXGI_FORMAT format, + UINT width, UINT height, DWORD *buffer) +{ + const BYTE *block, *color_indices, *alpha_indices, *alpha_table; + int i, j, x, y, block_x, block_y, color_index, alpha_index; + int block_size, color_offset, color_indices_offset; + WORD color[4], color_value = 0; + BYTE alpha[8], alpha_value = 0; + + if (format == DXGI_FORMAT_BC1_UNORM) { + block_size = 8; + color_offset = 0; + color_indices_offset = 4; + } else { + block_size = 16; + color_offset = 8; + color_indices_offset = 12; + } + block_x = 0; + block_y = 0; + + for (i = 0; i < block_count; i++) + { + block = block_data + i * block_size; + + color[0] = *((WORD *)(block + color_offset)); + color[1] = *((WORD *)(block + color_offset + 2)); + color[2] = MAKE_RGB565(((GET_RGB565_R(color[0]) * 2 + GET_RGB565_R(color[1]) + 1) / 3), + ((GET_RGB565_G(color[0]) * 2 + GET_RGB565_G(color[1]) + 1) / 3), + ((GET_RGB565_B(color[0]) * 2 + GET_RGB565_B(color[1]) + 1) / 3)); + color[3] = MAKE_RGB565(((GET_RGB565_R(color[0]) + GET_RGB565_R(color[1]) * 2 + 1) / 3), + ((GET_RGB565_G(color[0]) + GET_RGB565_G(color[1]) * 2 + 1) / 3), + ((GET_RGB565_B(color[0]) + GET_RGB565_B(color[1]) * 2 + 1) / 3)); + + switch (format) + { + case DXGI_FORMAT_BC1_UNORM: + if (color[0] <= color[1]) { + color[2] = MAKE_RGB565(((GET_RGB565_R(color[0]) + GET_RGB565_R(color[1]) + 1) / 2), + ((GET_RGB565_G(color[0]) + GET_RGB565_G(color[1]) + 1) / 2), + ((GET_RGB565_B(color[0]) + GET_RGB565_B(color[1]) + 1) / 2)); + color[3] = 0; + } + break; + case DXGI_FORMAT_BC2_UNORM: + alpha_table = block; + break; + case DXGI_FORMAT_BC3_UNORM: + alpha[0] = *block; + alpha[1] = *(block + 1); + if (alpha[0] > alpha[1]) { + for (j = 2; j < 8; j++) + { + alpha[j] = (BYTE)((alpha[0] * (8 - j) + alpha[1] * (j - 1) + 3) / 7); + } + } else { + for (j = 2; j < 6; j++) + { + alpha[j] = (BYTE)((alpha[0] * (6 - j) + alpha[1] * (j - 1) + 2) / 5); + } + alpha[6] = 0; + alpha[7] = 0xFF; + } + alpha_indices = block + 2; + break; + default: + break; + } + + color_indices = block + color_indices_offset; + for (j = 0; j < 16; j++) + { + x = block_x + j % 4; + y = block_y + j / 4; + if (x >= width || y >= height) continue; + + color_index = (color_indices[j / 4] >> ((j % 4) * 2)) & 0x3; + color_value = color[color_index]; + + switch (format) + { + case DXGI_FORMAT_BC1_UNORM: + if ((color[0] <= color[1]) && !color_value) { + color_value = 0; + alpha_value = 0; + } else { + alpha_value = 0xFF; + } + break; + case DXGI_FORMAT_BC2_UNORM: + alpha_value = (alpha_table[j / 2] >> (j % 2) * 4) & 0xF; + alpha_value = (BYTE)((alpha_value * 0xFF + 0x7)/ 0xF); + break; + case DXGI_FORMAT_BC3_UNORM: + alpha_index = (*((DWORD *)(alpha_indices + (j / 8) * 3)) >> ((j % 8) * 3)) & 0x7; + alpha_value = alpha[alpha_index]; + break; + default: + break; + } + buffer[x + y * width] = rgb565_to_argb(color_value, alpha_value); + } + + block_x += DDS_BLOCK_WIDTH; + if (block_x >= width) { + block_x = 0; + block_y += DDS_BLOCK_HEIGHT; + } + } +} + +static inline DdsDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface) +{ + return CONTAINING_RECORD(iface, DdsDecoder, IWICBitmapDecoder_iface); +} + +static inline DdsDecoder *impl_from_IWICDdsDecoder(IWICDdsDecoder *iface) +{ + return CONTAINING_RECORD(iface, DdsDecoder, IWICDdsDecoder_iface); +} + +static inline DdsDecoder *impl_from_IWICWineDecoder(IWICWineDecoder *iface) +{ + return CONTAINING_RECORD(iface, DdsDecoder, IWICWineDecoder_iface); +} + +static inline DdsFrameDecode *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface) +{ + return CONTAINING_RECORD(iface, DdsFrameDecode, IWICBitmapFrameDecode_iface); +} + +static inline DdsFrameDecode *impl_from_IWICDdsFrameDecode(IWICDdsFrameDecode *iface) +{ + return CONTAINING_RECORD(iface, DdsFrameDecode, IWICDdsFrameDecode_iface); +} + +static inline DdsEncoder *impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface) +{ + return CONTAINING_RECORD(iface, DdsEncoder, IWICBitmapEncoder_iface); +} + +static inline DdsEncoder *impl_from_IWICDdsEncoder(IWICDdsEncoder *iface) +{ + return CONTAINING_RECORD(iface, DdsEncoder, IWICDdsEncoder_iface); +} + +static inline DdsFrameEncode *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode *iface) +{ + return CONTAINING_RECORD(iface, DdsFrameEncode, IWICBitmapFrameEncode_iface); +} + +static HRESULT WINAPI DdsFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid, + void **ppv) +{ + DdsFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface); + TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); + + if (!ppv) return E_INVALIDARG; + + if (IsEqualIID(&IID_IUnknown, iid) || + IsEqualIID(&IID_IWICBitmapSource, iid) || + IsEqualIID(&IID_IWICBitmapFrameDecode, iid)) { + *ppv = &This->IWICBitmapFrameDecode_iface; + } else if (IsEqualGUID(&IID_IWICDdsFrameDecode, iid)) { + *ppv = &This->IWICDdsFrameDecode_iface; + } else { + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI DdsFrameDecode_AddRef(IWICBitmapFrameDecode *iface) +{ + DdsFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) refcount=%lu\n", iface, ref); + + return ref; +} + +static ULONG WINAPI DdsFrameDecode_Release(IWICBitmapFrameDecode *iface) +{ + DdsFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) refcount=%lu\n", iface, ref); + + if (ref == 0) { + if (This->pixel_data != This->block_data) free(This->pixel_data); + free(This->block_data); + free(This); + } + + return ref; +} + +static HRESULT WINAPI DdsFrameDecode_GetSize(IWICBitmapFrameDecode *iface, + UINT *puiWidth, UINT *puiHeight) +{ + DdsFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface); + + if (!puiWidth || !puiHeight) return E_INVALIDARG; + + *puiWidth = This->info.width; + *puiHeight = This->info.height; + + TRACE("(%p) -> (%d,%d)\n", iface, *puiWidth, *puiHeight); + + return S_OK; +} + +static HRESULT WINAPI DdsFrameDecode_GetPixelFormat(IWICBitmapFrameDecode *iface, + WICPixelFormatGUID *pPixelFormat) +{ + DdsFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface); + + if (!pPixelFormat) return E_INVALIDARG; + + *pPixelFormat = *This->info.pixel_format; + + TRACE("(%p) -> %s\n", iface, debugstr_guid(pPixelFormat)); + + return S_OK; +} + +static HRESULT WINAPI DdsFrameDecode_GetResolution(IWICBitmapFrameDecode *iface, + double *pDpiX, double *pDpiY) +{ + FIXME("(%p,%p,%p): stub.\n", iface, pDpiX, pDpiY); + + return E_NOTIMPL; +} + +static HRESULT WINAPI DdsFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface, + IWICPalette *pIPalette) +{ + FIXME("(%p,%p): stub.\n", iface, pIPalette); + + return E_NOTIMPL; +} + +static HRESULT WINAPI DdsFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface, + const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer) +{ + DdsFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface); + UINT bpp, frame_stride, frame_size; + INT x, y, width, height; + HRESULT hr; + + TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer); + + if (!pbBuffer) return E_INVALIDARG; + + bpp = This->info.pixel_format_bpp; + if (!bpp) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT; + + frame_stride = This->info.width * bpp / 8; + frame_size = frame_stride * This->info.height; + if (!prc) { + if (cbStride < frame_stride) return E_INVALIDARG; + if (cbBufferSize < frame_size) return WINCODEC_ERR_INSUFFICIENTBUFFER; + } else { + x = prc->X; + y = prc->Y; + width = prc->Width; + height = prc->Height; + if (x < 0 || y < 0 || width <= 0 || height <= 0 || + x + width > This->info.width || + y + height > This->info.height) { + return E_INVALIDARG; + } + if (cbStride < width * bpp / 8) return E_INVALIDARG; + if (cbBufferSize < cbStride * height) return WINCODEC_ERR_INSUFFICIENTBUFFER; + } + + EnterCriticalSection(&This->lock); + + if (!This->pixel_data) { + if (is_compressed(This->info.format)) { + This->pixel_data = malloc(frame_size); + if (!This->pixel_data) { + hr = E_OUTOFMEMORY; + goto end; + } + decode_block(This->block_data, This->info.width_in_blocks * This->info.height_in_blocks, This->info.format, + This->info.width, This->info.height, (DWORD *)This->pixel_data); + } else { + This->pixel_data = This->block_data; + } + } + + hr = copy_pixels(bpp, This->pixel_data, This->info.width, This->info.height, frame_stride, + prc, cbStride, cbBufferSize, pbBuffer); + +end: + LeaveCriticalSection(&This->lock); + + return hr; +} + +static HRESULT WINAPI DdsFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode *iface, + IWICMetadataQueryReader **ppIMetadataQueryReader) +{ + FIXME("(%p,%p): stub.\n", iface, ppIMetadataQueryReader); + + return E_NOTIMPL; +} + +static HRESULT WINAPI DdsFrameDecode_GetColorContexts(IWICBitmapFrameDecode *iface, + UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount) +{ + FIXME("(%p,%u,%p,%p): stub.\n", iface, cCount, ppIColorContexts, pcActualCount); + + return E_NOTIMPL; +} + +static HRESULT WINAPI DdsFrameDecode_GetThumbnail(IWICBitmapFrameDecode *iface, + IWICBitmapSource **ppIThumbnail) +{ + FIXME("(%p,%p): stub.\n", iface, ppIThumbnail); + + return E_NOTIMPL; +} + +static const IWICBitmapFrameDecodeVtbl DdsFrameDecode_Vtbl = { + DdsFrameDecode_QueryInterface, + DdsFrameDecode_AddRef, + DdsFrameDecode_Release, + DdsFrameDecode_GetSize, + DdsFrameDecode_GetPixelFormat, + DdsFrameDecode_GetResolution, + DdsFrameDecode_CopyPalette, + DdsFrameDecode_CopyPixels, + DdsFrameDecode_GetMetadataQueryReader, + DdsFrameDecode_GetColorContexts, + DdsFrameDecode_GetThumbnail +}; + +static HRESULT WINAPI DdsFrameDecode_Dds_QueryInterface(IWICDdsFrameDecode *iface, + REFIID iid, void **ppv) +{ + DdsFrameDecode *This = impl_from_IWICDdsFrameDecode(iface); + return DdsFrameDecode_QueryInterface(&This->IWICBitmapFrameDecode_iface, iid, ppv); +} + +static ULONG WINAPI DdsFrameDecode_Dds_AddRef(IWICDdsFrameDecode *iface) +{ + DdsFrameDecode *This = impl_from_IWICDdsFrameDecode(iface); + return DdsFrameDecode_AddRef(&This->IWICBitmapFrameDecode_iface); +} + +static ULONG WINAPI DdsFrameDecode_Dds_Release(IWICDdsFrameDecode *iface) +{ + DdsFrameDecode *This = impl_from_IWICDdsFrameDecode(iface); + return DdsFrameDecode_Release(&This->IWICBitmapFrameDecode_iface); +} + +static HRESULT WINAPI DdsFrameDecode_Dds_GetSizeInBlocks(IWICDdsFrameDecode *iface, + UINT *widthInBlocks, UINT *heightInBlocks) +{ + DdsFrameDecode *This = impl_from_IWICDdsFrameDecode(iface); + + if (!widthInBlocks || !heightInBlocks) return E_INVALIDARG; + + *widthInBlocks = This->info.width_in_blocks; + *heightInBlocks = This->info.height_in_blocks; + + TRACE("(%p,%p,%p) -> (%d,%d)\n", iface, widthInBlocks, heightInBlocks, *widthInBlocks, *heightInBlocks); + + return S_OK; +} + +static HRESULT WINAPI DdsFrameDecode_Dds_GetFormatInfo(IWICDdsFrameDecode *iface, + WICDdsFormatInfo *formatInfo) +{ + DdsFrameDecode *This = impl_from_IWICDdsFrameDecode(iface); + + if (!formatInfo) return E_INVALIDARG; + + formatInfo->DxgiFormat = This->info.format; + formatInfo->BytesPerBlock = This->info.bytes_per_block; + formatInfo->BlockWidth = This->info.block_width; + formatInfo->BlockHeight = This->info.block_height; + + TRACE("(%p,%p) -> (0x%x,%d,%d,%d)\n", iface, formatInfo, + formatInfo->DxgiFormat, formatInfo->BytesPerBlock, formatInfo->BlockWidth, formatInfo->BlockHeight); + + return S_OK; +} + +static HRESULT WINAPI DdsFrameDecode_Dds_CopyBlocks(IWICDdsFrameDecode *iface, + const WICRect *boundsInBlocks, UINT stride, UINT bufferSize, + BYTE *buffer) +{ + DdsFrameDecode *This = impl_from_IWICDdsFrameDecode(iface); + int x, y, width, height; + UINT bytes_per_block, frame_stride, frame_size; + + TRACE("(%p,%p,%u,%u,%p)\n", iface, boundsInBlocks, stride, bufferSize, buffer); + + if (!buffer) return E_INVALIDARG; + + bytes_per_block = This->info.bytes_per_block; + frame_stride = This->info.width_in_blocks * bytes_per_block; + frame_size = frame_stride * This->info.height_in_blocks; + + if (!boundsInBlocks) { + if (stride < frame_stride) return E_INVALIDARG; + if (bufferSize < frame_size) return E_INVALIDARG; + } else { + x = boundsInBlocks->X; + y = boundsInBlocks->Y; + width = boundsInBlocks->Width; + height = boundsInBlocks->Height; + if (x < 0 || y < 0 || width <= 0 || height <= 0 || + x + width > This->info.width_in_blocks || + y + height > This->info.height_in_blocks) { + return E_INVALIDARG; + } + if (stride < width * bytes_per_block) return E_INVALIDARG; + if (bufferSize < stride * height) return E_INVALIDARG; + } + + return copy_pixels(This->info.bytes_per_block * 8, This->block_data, This->info.width_in_blocks, + This->info.height_in_blocks, frame_stride, boundsInBlocks, stride, bufferSize, buffer); +} + +static const IWICDdsFrameDecodeVtbl DdsFrameDecode_Dds_Vtbl = { + DdsFrameDecode_Dds_QueryInterface, + DdsFrameDecode_Dds_AddRef, + DdsFrameDecode_Dds_Release, + DdsFrameDecode_Dds_GetSizeInBlocks, + DdsFrameDecode_Dds_GetFormatInfo, + DdsFrameDecode_Dds_CopyBlocks +}; + +static HRESULT DdsFrameDecode_CreateInstance(DdsFrameDecode **frame_decode) +{ + DdsFrameDecode *result; + + result = malloc(sizeof(*result)); + if (!result) return E_OUTOFMEMORY; + + result->IWICBitmapFrameDecode_iface.lpVtbl = &DdsFrameDecode_Vtbl; + result->IWICDdsFrameDecode_iface.lpVtbl = &DdsFrameDecode_Dds_Vtbl; + result->ref = 1; +#ifdef __REACTOS__ + InitializeCriticalSection(&result->lock); +#else + InitializeCriticalSectionEx(&result->lock, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO); +#endif + result->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DdsFrameDecode.lock"); + + *frame_decode = result; + return S_OK; +} + +static HRESULT WINAPI DdsDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid, + void **ppv) +{ + DdsDecoder *This = impl_from_IWICBitmapDecoder(iface); + TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); + + if (!ppv) return E_INVALIDARG; + + if (IsEqualIID(&IID_IUnknown, iid) || + IsEqualIID(&IID_IWICBitmapDecoder, iid)) { + *ppv = &This->IWICBitmapDecoder_iface; + } else if (IsEqualIID(&IID_IWICDdsDecoder, iid)) { + *ppv = &This->IWICDdsDecoder_iface; + } else if (IsEqualIID(&IID_IWICWineDecoder, iid)) { + *ppv = &This->IWICWineDecoder_iface; + } else { + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI DdsDecoder_AddRef(IWICBitmapDecoder *iface) +{ + DdsDecoder *This = impl_from_IWICBitmapDecoder(iface); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) refcount=%lu\n", iface, ref); + + return ref; +} + +static ULONG WINAPI DdsDecoder_Release(IWICBitmapDecoder *iface) +{ + DdsDecoder *This = impl_from_IWICBitmapDecoder(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) refcount=%lu\n", iface, ref); + + if (ref == 0) + { + This->lock.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&This->lock); + if (This->stream) IStream_Release(This->stream); + free(This); + } + + return ref; +} + +static HRESULT WINAPI DdsDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *stream, + DWORD *capability) +{ + FIXME("(%p,%p,%p): stub.\n", iface, stream, capability); + + return E_NOTIMPL; +} + +static HRESULT WINAPI DdsDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream, + WICDecodeOptions cacheOptions) +{ + DdsDecoder *This = impl_from_IWICBitmapDecoder(iface); + HRESULT hr; + + TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions); + + EnterCriticalSection(&This->lock); + + hr = IWICWineDecoder_Initialize(&This->IWICWineDecoder_iface, pIStream, cacheOptions); + if (FAILED(hr)) goto end; + + if (This->info.dimension == WICDdsTextureCube || + (This->info.format != DXGI_FORMAT_BC1_UNORM && + This->info.format != DXGI_FORMAT_BC2_UNORM && + This->info.format != DXGI_FORMAT_BC3_UNORM)) { + IStream_Release(pIStream); + This->stream = NULL; + This->initialized = FALSE; + hr = WINCODEC_ERR_BADHEADER; + } + +end: + LeaveCriticalSection(&This->lock); + + return hr; +} + +static HRESULT WINAPI DdsDecoder_GetContainerFormat(IWICBitmapDecoder *iface, + GUID *pguidContainerFormat) +{ + TRACE("(%p,%p)\n", iface, pguidContainerFormat); + + memcpy(pguidContainerFormat, &GUID_ContainerFormatDds, sizeof(GUID)); + + return S_OK; +} + +static HRESULT WINAPI DdsDecoder_GetDecoderInfo(IWICBitmapDecoder *iface, + IWICBitmapDecoderInfo **ppIDecoderInfo) +{ + TRACE("(%p,%p)\n", iface, ppIDecoderInfo); + + return get_decoder_info(&CLSID_WICDdsDecoder, ppIDecoderInfo); +} + +static HRESULT WINAPI DdsDecoder_CopyPalette(IWICBitmapDecoder *iface, + IWICPalette *pIPalette) +{ + TRACE("(%p,%p)\n", iface, pIPalette); + + return WINCODEC_ERR_PALETTEUNAVAILABLE; +} + +static HRESULT WINAPI DdsDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface, + IWICMetadataQueryReader **ppIMetadataQueryReader) +{ + if (!ppIMetadataQueryReader) return E_INVALIDARG; + + FIXME("(%p,%p)\n", iface, ppIMetadataQueryReader); + + return E_NOTIMPL; +} + +static HRESULT WINAPI DdsDecoder_GetPreview(IWICBitmapDecoder *iface, + IWICBitmapSource **ppIBitmapSource) +{ + TRACE("(%p,%p)\n", iface, ppIBitmapSource); + + return WINCODEC_ERR_UNSUPPORTEDOPERATION; +} + +static HRESULT WINAPI DdsDecoder_GetColorContexts(IWICBitmapDecoder *iface, + UINT cCount, IWICColorContext **ppDdslorContexts, UINT *pcActualCount) +{ + TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppDdslorContexts, pcActualCount); + + return WINCODEC_ERR_UNSUPPORTEDOPERATION; +} + +static HRESULT WINAPI DdsDecoder_GetThumbnail(IWICBitmapDecoder *iface, + IWICBitmapSource **ppIThumbnail) +{ + TRACE("(%p,%p)\n", iface, ppIThumbnail); + + return WINCODEC_ERR_CODECNOTHUMBNAIL; +} + +static HRESULT WINAPI DdsDecoder_GetFrameCount(IWICBitmapDecoder *iface, + UINT *pCount) +{ + DdsDecoder *This = impl_from_IWICBitmapDecoder(iface); + + if (!pCount) return E_INVALIDARG; + if (!This->initialized) return WINCODEC_ERR_WRONGSTATE; + + EnterCriticalSection(&This->lock); + + *pCount = This->info.frame_count; + + LeaveCriticalSection(&This->lock); + + TRACE("(%p) -> %d\n", iface, *pCount); + + return S_OK; +} + +static HRESULT WINAPI DdsDecoder_GetFrame(IWICBitmapDecoder *iface, + UINT index, IWICBitmapFrameDecode **ppIBitmapFrame) +{ + DdsDecoder *This = impl_from_IWICBitmapDecoder(iface); + UINT array_index, mip_level, slice_index; + + TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame); + + if (!ppIBitmapFrame) return E_INVALIDARG; + + EnterCriticalSection(&This->lock); + + if (!This->initialized) { + LeaveCriticalSection(&This->lock); + return WINCODEC_ERR_WRONGSTATE; + } + + get_frame_dds_index(index, &This->info, &array_index, &mip_level, &slice_index); + + LeaveCriticalSection(&This->lock); + + return DdsDecoder_Dds_GetFrame(&This->IWICDdsDecoder_iface, array_index, mip_level, slice_index, ppIBitmapFrame); +} + +static const IWICBitmapDecoderVtbl DdsDecoder_Vtbl = { + DdsDecoder_QueryInterface, + DdsDecoder_AddRef, + DdsDecoder_Release, + DdsDecoder_QueryCapability, + DdsDecoder_Initialize, + DdsDecoder_GetContainerFormat, + DdsDecoder_GetDecoderInfo, + DdsDecoder_CopyPalette, + DdsDecoder_GetMetadataQueryReader, + DdsDecoder_GetPreview, + DdsDecoder_GetColorContexts, + DdsDecoder_GetThumbnail, + DdsDecoder_GetFrameCount, + DdsDecoder_GetFrame +}; + +static HRESULT WINAPI DdsDecoder_Dds_QueryInterface(IWICDdsDecoder *iface, + REFIID iid, void **ppv) +{ + DdsDecoder *This = impl_from_IWICDdsDecoder(iface); + return DdsDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv); +} + +static ULONG WINAPI DdsDecoder_Dds_AddRef(IWICDdsDecoder *iface) +{ + DdsDecoder *This = impl_from_IWICDdsDecoder(iface); + return DdsDecoder_AddRef(&This->IWICBitmapDecoder_iface); +} + +static ULONG WINAPI DdsDecoder_Dds_Release(IWICDdsDecoder *iface) +{ + DdsDecoder *This = impl_from_IWICDdsDecoder(iface); + return DdsDecoder_Release(&This->IWICBitmapDecoder_iface); +} + +static HRESULT WINAPI DdsDecoder_Dds_GetParameters(IWICDdsDecoder *iface, + WICDdsParameters *parameters) +{ + DdsDecoder *This = impl_from_IWICDdsDecoder(iface); + HRESULT hr; + + if (!parameters) return E_INVALIDARG; + + EnterCriticalSection(&This->lock); + + if (!This->initialized) { + hr = WINCODEC_ERR_WRONGSTATE; + goto end; + } + + parameters->Width = This->info.width; + parameters->Height = This->info.height; + parameters->Depth = This->info.depth; + parameters->MipLevels = This->info.mip_levels; + parameters->ArraySize = This->info.array_size; + parameters->DxgiFormat = This->info.format; + parameters->Dimension = This->info.dimension; + parameters->AlphaMode = This->info.alpha_mode; + + TRACE("(%p) -> (%dx%d depth=%d mipLevels=%d arraySize=%d dxgiFormat=0x%x dimension=0x%x alphaMode=0x%x)\n", + iface, parameters->Width, parameters->Height, parameters->Depth, parameters->MipLevels, + parameters->ArraySize, parameters->DxgiFormat, parameters->Dimension, parameters->AlphaMode); + + hr = S_OK; + +end: + LeaveCriticalSection(&This->lock); + + return hr; +} + +static HRESULT WINAPI DdsDecoder_Dds_GetFrame(IWICDdsDecoder *iface, + UINT arrayIndex, UINT mipLevel, UINT sliceIndex, + IWICBitmapFrameDecode **bitmapFrame) +{ + DdsDecoder *This = impl_from_IWICDdsDecoder(iface); + HRESULT hr; + LARGE_INTEGER seek; + UINT width, height, depth, block_width, block_height, width_in_blocks, height_in_blocks, size; + UINT frame_width = 0, frame_height = 0, frame_width_in_blocks = 0, frame_height_in_blocks = 0, frame_size = 0; + UINT bytes_per_block, i; + DWORD bytesread; + DdsFrameDecode *frame_decode = NULL; + + TRACE("(%p,%u,%u,%u,%p)\n", iface, arrayIndex, mipLevel, sliceIndex, bitmapFrame); + + if (!bitmapFrame) return E_INVALIDARG; + + EnterCriticalSection(&This->lock); + + if (!This->initialized) { + hr = WINCODEC_ERR_WRONGSTATE; + goto end; + } + + if ((arrayIndex >= This->info.array_size && This->info.dimension != WICDdsTextureCube) || + (arrayIndex >= This->info.array_size * 6) || + (mipLevel >= This->info.mip_levels) || + (sliceIndex >= This->info.depth)) { + hr = E_INVALIDARG; + goto end; + } + + if (is_compressed(This->info.format)) { + block_width = DDS_BLOCK_WIDTH; + block_height = DDS_BLOCK_HEIGHT; + } else { + block_width = 1; + block_height = 1; + } + bytes_per_block = This->info.bytes_per_block; + seek.QuadPart = This->info.data_offset; + + width = This->info.width; + height = This->info.height; + depth = This->info.depth; + for (i = 0; i < This->info.mip_levels; i++) + { + width_in_blocks = (width + block_width - 1) / block_width; + height_in_blocks = (height + block_height - 1) / block_height; + size = width_in_blocks * height_in_blocks * bytes_per_block; + + if (i < mipLevel) { + seek.QuadPart += size * depth; + } else if (i == mipLevel){ + seek.QuadPart += size * sliceIndex; + frame_width = width; + frame_height = height; + frame_width_in_blocks = width_in_blocks; + frame_height_in_blocks = height_in_blocks; + frame_size = frame_width_in_blocks * frame_height_in_blocks * bytes_per_block; + if (arrayIndex == 0) break; + } + seek.QuadPart += arrayIndex * size * depth; + + if (width > 1) width /= 2; + if (height > 1) height /= 2; + if (depth > 1) depth /= 2; + } + + hr = DdsFrameDecode_CreateInstance(&frame_decode); + if (hr != S_OK) goto end; + frame_decode->info.width = frame_width; + frame_decode->info.height = frame_height; + frame_decode->info.format = This->info.format; + frame_decode->info.bytes_per_block = bytes_per_block; + frame_decode->info.block_width = block_width; + frame_decode->info.block_height = block_height; + frame_decode->info.width_in_blocks = frame_width_in_blocks; + frame_decode->info.height_in_blocks = frame_height_in_blocks; + frame_decode->info.pixel_format = This->info.pixel_format; + frame_decode->info.pixel_format_bpp = This->info.pixel_format_bpp; + frame_decode->block_data = malloc(frame_size); + frame_decode->pixel_data = NULL; + hr = IStream_Seek(This->stream, seek, SEEK_SET, NULL); + if (hr != S_OK) goto end; + hr = IStream_Read(This->stream, frame_decode->block_data, frame_size, &bytesread); + if (hr != S_OK || bytesread != frame_size) { + hr = WINCODEC_ERR_STREAMREAD; + goto end; + } + *bitmapFrame = &frame_decode->IWICBitmapFrameDecode_iface; + + hr = S_OK; + +end: + LeaveCriticalSection(&This->lock); + + if (hr != S_OK && frame_decode) DdsFrameDecode_Release(&frame_decode->IWICBitmapFrameDecode_iface); + + return hr; +} + +static const IWICDdsDecoderVtbl DdsDecoder_Dds_Vtbl = { + DdsDecoder_Dds_QueryInterface, + DdsDecoder_Dds_AddRef, + DdsDecoder_Dds_Release, + DdsDecoder_Dds_GetParameters, + DdsDecoder_Dds_GetFrame +}; + +static HRESULT WINAPI DdsDecoder_Wine_QueryInterface(IWICWineDecoder *iface, REFIID iid, void **ppv) +{ + DdsDecoder *This = impl_from_IWICWineDecoder(iface); + return DdsDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv); +} + +static ULONG WINAPI DdsDecoder_Wine_AddRef(IWICWineDecoder *iface) +{ + DdsDecoder *This = impl_from_IWICWineDecoder(iface); + return DdsDecoder_AddRef(&This->IWICBitmapDecoder_iface); +} + +static ULONG WINAPI DdsDecoder_Wine_Release(IWICWineDecoder *iface) +{ + DdsDecoder *This = impl_from_IWICWineDecoder(iface); + return DdsDecoder_Release(&This->IWICBitmapDecoder_iface); +} + +static HRESULT WINAPI DdsDecoder_Wine_Initialize(IWICWineDecoder *iface, IStream *stream, WICDecodeOptions options) +{ + DdsDecoder *This = impl_from_IWICWineDecoder(iface); + DDS_HEADER_DXT10 header_dxt10; + LARGE_INTEGER seek; + DDS_HEADER header; + ULONG bytesread; + DWORD magic; + HRESULT hr; + + TRACE("(This %p, stream %p, options %#x)\n", iface, stream, options); + + EnterCriticalSection(&This->lock); + + if (This->initialized) { + hr = WINCODEC_ERR_WRONGSTATE; + goto end; + } + + seek.QuadPart = 0; + hr = IStream_Seek(stream, seek, SEEK_SET, NULL); + if (FAILED(hr)) goto end; + + hr = IStream_Read(stream, &magic, sizeof(magic), &bytesread); + if (FAILED(hr)) goto end; + if (bytesread != sizeof(magic)) { + hr = WINCODEC_ERR_STREAMREAD; + goto end; + } + if (magic != DDS_MAGIC) { + hr = WINCODEC_ERR_UNKNOWNIMAGEFORMAT; + goto end; + } + + hr = IStream_Read(stream, &header, sizeof(header), &bytesread); + if (FAILED(hr)) goto end; + if (bytesread != sizeof(header)) { + hr = WINCODEC_ERR_STREAMREAD; + goto end; + } + if (header.size != sizeof(header)) { + hr = WINCODEC_ERR_BADHEADER; + goto end; + } + + if (has_extended_header(&header)) { + hr = IStream_Read(stream, &header_dxt10, sizeof(header_dxt10), &bytesread); + if (FAILED(hr)) goto end; + if (bytesread != sizeof(header_dxt10)) { + hr = WINCODEC_ERR_STREAMREAD; + goto end; + } + } + + get_dds_info(&This->info, &header, &header_dxt10); + + This->initialized = TRUE; + This->stream = stream; + IStream_AddRef(stream); + +end: + LeaveCriticalSection(&This->lock); + + return hr; +} + +static const IWICWineDecoderVtbl DdsDecoder_Wine_Vtbl = { + DdsDecoder_Wine_QueryInterface, + DdsDecoder_Wine_AddRef, + DdsDecoder_Wine_Release, + DdsDecoder_Wine_Initialize +}; + +static HRESULT WINAPI DdsFrameEncode_QueryInterface(IWICBitmapFrameEncode *iface, REFIID iid, void **ppv) +{ + DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); + TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); + + if (!ppv) return E_INVALIDARG; + + if (IsEqualIID(&IID_IUnknown, iid) || + IsEqualIID(&IID_IWICBitmapFrameEncode, iid)) + { + *ppv = &This->IWICBitmapFrameEncode_iface; + } + else + { + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI DdsFrameEncode_AddRef(IWICBitmapFrameEncode *iface) +{ + DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) refcount=%lu\n", iface, ref); + + return ref; +} + +static ULONG WINAPI DdsFrameEncode_Release(IWICBitmapFrameEncode *iface) +{ + DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) refcount=%lu\n", iface, ref); + + if (ref == 0) + { + IWICBitmapEncoder_Release(&This->parent->IWICBitmapEncoder_iface); + free(This); + } + + return ref; +} + +static HRESULT WINAPI DdsFrameEncode_Initialize(IWICBitmapFrameEncode *iface, + IPropertyBag2 *encoderOptions) +{ + DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); + HRESULT hr; + + TRACE("(%p,%p)\n", iface, encoderOptions); + if (encoderOptions) FIXME("encoder options are not supported for DDS.\n"); + + EnterCriticalSection(&This->parent->lock); + + if (This->initialized) + { + hr = WINCODEC_ERR_WRONGSTATE; + } + else + { + This->initialized = TRUE; + hr = S_OK; + } + + LeaveCriticalSection(&This->parent->lock); + + return hr; +} + +static HRESULT WINAPI DdsFrameEncode_SetSize(IWICBitmapFrameEncode *iface, + UINT width, UINT height) +{ + DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); + HRESULT hr; + + TRACE("(%p,%u,%u)\n", iface, width, height); + + EnterCriticalSection(&This->parent->lock); + + if (!This->initialized || This->frame_created) + { + hr = WINCODEC_ERR_WRONGSTATE; + } + else + { + This->width = width; + This->height = height; + hr = S_OK; + } + + LeaveCriticalSection(&This->parent->lock); + + return hr; +} + +static HRESULT WINAPI DdsFrameEncode_SetResolution(IWICBitmapFrameEncode *iface, + double dpiX, double dpiY) +{ + DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); + HRESULT hr; + + TRACE("(%p,%0.2f,%0.2f)\n", iface, dpiX, dpiY); + + EnterCriticalSection(&This->parent->lock); + + if (!This->initialized || This->frame_created) + { + hr = WINCODEC_ERR_WRONGSTATE; + } + else + { + This->dpi_x = dpiX; + This->dpi_y = dpiY; + hr = S_OK; + } + + LeaveCriticalSection(&This->parent->lock); + + return hr; +} + +static HRESULT WINAPI DdsFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface, + WICPixelFormatGUID *pixelFormat) +{ + DdsFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); + HRESULT hr; + + TRACE("(%p,%s)\n", iface, debugstr_guid(pixelFormat)); + + EnterCriticalSection(&This->parent->lock); + + if (!This->initialized) + { + hr = WINCODEC_ERR_NOTINITIALIZED; + } + else if (This->frame_created) + { + hr = WINCODEC_ERR_WRONGSTATE; + } + else + { + *pixelFormat = GUID_WICPixelFormat32bppBGRA; + hr = S_OK; + } + + LeaveCriticalSection(&This->parent->lock); + + return hr; +} + +static HRESULT WINAPI DdsFrameEncode_SetColorContexts(IWICBitmapFrameEncode *iface, + UINT count, IWICColorContext **colorContext) +{ + FIXME("(%p,%u,%p): stub\n", iface, count, colorContext); + return E_NOTIMPL; +} + +static HRESULT WINAPI DdsFrameEncode_SetPalette(IWICBitmapFrameEncode *iface, + IWICPalette *palette) +{ + FIXME("(%p,%p): stub\n", iface, palette); + return E_NOTIMPL; +} + +static HRESULT WINAPI DdsFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface, + IWICBitmapSource *thumbnail) +{ + TRACE("(%p,%p)\n", iface, thumbnail); + return WINCODEC_ERR_UNSUPPORTEDOPERATION; +} + +static HRESULT WINAPI DdsFrameEncode_WritePixels(IWICBitmapFrameEncode *iface, + UINT lineCount, UINT stride, UINT bufferSize, BYTE *pixels) +{ + FIXME("(%p,%u,%u,%u,%p): stub\n", iface, lineCount, stride, bufferSize, pixels); + return E_NOTIMPL; +} + +static HRESULT WINAPI DdsFrameEncode_WriteSource(IWICBitmapFrameEncode *iface, + IWICBitmapSource *bitmapSource, WICRect *rc) +{ + FIXME("(%p,%p,%s): stub\n", iface, bitmapSource, debug_wic_rect(rc)); + return E_NOTIMPL; +} + +static HRESULT WINAPI DdsFrameEncode_Commit(IWICBitmapFrameEncode *iface) +{ + FIXME("(%p): stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI DdsFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode *iface, + IWICMetadataQueryWriter **metadataQueryWriter) +{ + FIXME("(%p,%p): stub\n", iface, metadataQueryWriter); + return E_NOTIMPL; +} + +static const IWICBitmapFrameEncodeVtbl DdsFrameEncode_Vtbl = { + DdsFrameEncode_QueryInterface, + DdsFrameEncode_AddRef, + DdsFrameEncode_Release, + DdsFrameEncode_Initialize, + DdsFrameEncode_SetSize, + DdsFrameEncode_SetResolution, + DdsFrameEncode_SetPixelFormat, + DdsFrameEncode_SetColorContexts, + DdsFrameEncode_SetPalette, + DdsFrameEncode_SetThumbnail, + DdsFrameEncode_WritePixels, + DdsFrameEncode_WriteSource, + DdsFrameEncode_Commit, + DdsFrameEncode_GetMetadataQueryWriter +}; + +HRESULT DdsDecoder_CreateInstance(REFIID iid, void** ppv) +{ + DdsDecoder *This; + HRESULT ret; + + TRACE("(%s,%p)\n", debugstr_guid(iid), ppv); + + *ppv = NULL; + + This = malloc(sizeof(DdsDecoder)); + if (!This) return E_OUTOFMEMORY; + + This->IWICBitmapDecoder_iface.lpVtbl = &DdsDecoder_Vtbl; + This->IWICDdsDecoder_iface.lpVtbl = &DdsDecoder_Dds_Vtbl; + This->IWICWineDecoder_iface.lpVtbl = &DdsDecoder_Wine_Vtbl; + This->ref = 1; + This->initialized = FALSE; + This->stream = NULL; +#ifdef __REACTOS__ + InitializeCriticalSection(&This->lock); +#else + InitializeCriticalSectionEx(&This->lock, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO); +#endif + This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DdsDecoder.lock"); + + ret = IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv); + IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface); + + return ret; +} + +static HRESULT WINAPI DdsEncoder_Dds_QueryInterface(IWICDdsEncoder *iface, REFIID iid, + void **ppv) +{ + DdsEncoder *This = impl_from_IWICDdsEncoder(iface); + return IWICBitmapEncoder_QueryInterface(&This->IWICBitmapEncoder_iface, iid, ppv); +} + +static ULONG WINAPI DdsEncoder_Dds_AddRef(IWICDdsEncoder *iface) +{ + DdsEncoder *This = impl_from_IWICDdsEncoder(iface); + return IWICBitmapEncoder_AddRef(&This->IWICBitmapEncoder_iface); +} + +static ULONG WINAPI DdsEncoder_Dds_Release(IWICDdsEncoder *iface) +{ + DdsEncoder *This = impl_from_IWICDdsEncoder(iface); + return IWICBitmapEncoder_Release(&This->IWICBitmapEncoder_iface); +} + +static HRESULT WINAPI DdsEncoder_Dds_SetParameters(IWICDdsEncoder *iface, + WICDdsParameters *parameters) +{ + DdsEncoder *This = impl_from_IWICDdsEncoder(iface); + HRESULT hr; + + TRACE("(%p,%p)\n", iface, parameters); + + if (!parameters) return E_INVALIDARG; + + EnterCriticalSection(&This->lock); + + if (!This->stream) + { + hr = WINCODEC_ERR_WRONGSTATE; + goto end; + } + + This->info.width = parameters->Width; + This->info.height = parameters->Height; + This->info.depth = parameters->Depth; + This->info.mip_levels = parameters->MipLevels; + This->info.array_size = parameters->ArraySize; + This->info.format = parameters->DxgiFormat; + This->info.dimension = parameters->Dimension; + This->info.alpha_mode = parameters->AlphaMode; + + This->info.bytes_per_block = get_bytes_per_block_from_format(This->info.format); + This->info.frame_count = get_frame_count(This->info.depth, This->info.mip_levels, + This->info.array_size, This->info.dimension); + + hr = S_OK; + +end: + LeaveCriticalSection(&This->lock); + return hr; +} + +static HRESULT WINAPI DdsEncoder_Dds_GetParameters(IWICDdsEncoder *iface, + WICDdsParameters *parameters) +{ + DdsEncoder *This = impl_from_IWICDdsEncoder(iface); + HRESULT hr; + + TRACE("(%p,%p)\n", iface, parameters); + + if (!parameters) return E_INVALIDARG; + + EnterCriticalSection(&This->lock); + + if (!This->stream) + { + hr = WINCODEC_ERR_WRONGSTATE; + goto end; + } + + parameters->Width = This->info.width; + parameters->Height = This->info.height; + parameters->Depth = This->info.depth; + parameters->MipLevels = This->info.mip_levels; + parameters->ArraySize = This->info.array_size; + parameters->DxgiFormat = This->info.format; + parameters->Dimension = This->info.dimension; + parameters->AlphaMode = This->info.alpha_mode; + + TRACE("(%p,%p) -> (%dx%d depth=%u mipLevels=%u arraySize=%u dxgiFormat=%#x dimension=%#x alphaMode=%#x)\n", + iface, parameters, parameters->Width, parameters->Height, parameters->Depth, parameters->MipLevels, + parameters->ArraySize, parameters->DxgiFormat, parameters->Dimension, parameters->AlphaMode); + + hr = S_OK; + +end: + LeaveCriticalSection(&This->lock); + return hr; +} + +static HRESULT WINAPI DdsEncoder_Dds_CreateNewFrame(IWICDdsEncoder *iface, + IWICBitmapFrameEncode **frameEncode, + UINT *arrayIndex, UINT *mipLevel, UINT *sliceIndex) +{ + DdsEncoder *This = impl_from_IWICDdsEncoder(iface); + UINT array_index, mip_level, slice_index; + DdsFrameEncode *result; + HRESULT hr; + + TRACE("(%p,%p,%p,%p,%p)\n", iface, frameEncode, arrayIndex, mipLevel, sliceIndex); + + EnterCriticalSection(&This->lock); + + if (!This->stream || This->committed || This->uncommitted_frame) + { + hr = WINCODEC_ERR_WRONGSTATE; + goto end; + } + + result = malloc(sizeof(*result)); + if (!result) + { + hr = E_OUTOFMEMORY; + goto end; + } + + get_frame_dds_index(This->frame_index, &This->info, &array_index, &mip_level, &slice_index); + if (arrayIndex) *arrayIndex = array_index; + if (mipLevel) *mipLevel = mip_level; + if (sliceIndex) *sliceIndex = slice_index; + + This->frame_index++; + result->IWICBitmapFrameEncode_iface.lpVtbl = &DdsFrameEncode_Vtbl; + result->ref = 1; + result->parent = This; + result->parent->uncommitted_frame = TRUE; + result->initialized = FALSE; + result->frame_created = FALSE; + IWICDdsEncoder_AddRef(iface); + + *frameEncode = &result->IWICBitmapFrameEncode_iface; + hr = S_OK; + +end: + LeaveCriticalSection(&This->lock); + return hr; +} + +static const IWICDdsEncoderVtbl DdsEncoder_Dds_Vtbl = +{ + DdsEncoder_Dds_QueryInterface, + DdsEncoder_Dds_AddRef, + DdsEncoder_Dds_Release, + DdsEncoder_Dds_SetParameters, + DdsEncoder_Dds_GetParameters, + DdsEncoder_Dds_CreateNewFrame +}; + +static HRESULT WINAPI DdsEncoder_QueryInterface(IWICBitmapEncoder *iface, REFIID iid, + void **ppv) +{ + DdsEncoder *This = impl_from_IWICBitmapEncoder(iface); + FIXME("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); + + if (!ppv) return E_INVALIDARG; + + if (IsEqualIID(&IID_IUnknown, iid) || + IsEqualIID(&IID_IWICBitmapEncoder, iid)) { + *ppv = &This->IWICBitmapEncoder_iface; + } else if (IsEqualIID(&IID_IWICDdsEncoder, iid)) { + *ppv = &This->IWICDdsEncoder_iface; + } else { + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI DdsEncoder_AddRef(IWICBitmapEncoder *iface) +{ + DdsEncoder *This = impl_from_IWICBitmapEncoder(iface); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) refcount=%lu\n", iface, ref); + + return ref; +} + +static ULONG WINAPI DdsEncoder_Release(IWICBitmapEncoder *iface) +{ + DdsEncoder *This = impl_from_IWICBitmapEncoder(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) refcount=%lu\n", iface, ref); + + if (ref == 0) { + This->lock.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&This->lock); + if (This->stream) IStream_Release(This->stream); + free(This); + } + + return ref; +} + +static HRESULT WINAPI DdsEncoder_Initialize(IWICBitmapEncoder *iface, + IStream *stream, WICBitmapEncoderCacheOption cacheOption) +{ + DdsEncoder *This = impl_from_IWICBitmapEncoder(iface); + HRESULT hr; + + TRACE("(%p,%p,%u)\n", iface, stream, cacheOption); + + if (cacheOption != WICBitmapEncoderNoCache) + FIXME("Cache option %#x is not supported.\n", cacheOption); + + if (!stream) return E_INVALIDARG; + + EnterCriticalSection(&This->lock); + + if (This->stream) + { + hr = WINCODEC_ERR_WRONGSTATE; + goto end; + } + + This->stream = stream; + IStream_AddRef(stream); + + This->info.width = 1; + This->info.height = 1; + This->info.depth = 1; + This->info.mip_levels = 1; + This->info.array_size = 1; + This->info.frame_count = 1; + This->info.data_offset = 0; + This->info.bytes_per_block = get_bytes_per_block_from_format(DXGI_FORMAT_BC3_UNORM); + This->info.format = DXGI_FORMAT_BC3_UNORM; + This->info.dimension = WICDdsTexture2D; + This->info.alpha_mode = WICDdsAlphaModeUnknown; + This->info.pixel_format = &GUID_WICPixelFormatUndefined; + This->info.pixel_format_bpp = 0; + + hr = S_OK; + +end: + LeaveCriticalSection(&This->lock); + + return hr; +} + +static HRESULT WINAPI DdsEncoder_GetContainerFormat(IWICBitmapEncoder *iface, GUID *format) +{ + TRACE("(%p,%p)\n", iface, format); + + if (!format) + return E_INVALIDARG; + + memcpy(format, &GUID_ContainerFormatDds, sizeof(*format)); + return S_OK; +} + +static HRESULT WINAPI DdsEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBitmapEncoderInfo **info) +{ + IWICComponentInfo *comp_info; + HRESULT hr; + + TRACE("%p,%p\n", iface, info); + + if (!info) return E_INVALIDARG; + + hr = CreateComponentInfo(&CLSID_WICDdsEncoder, &comp_info); + if (hr == S_OK) { + hr = IWICComponentInfo_QueryInterface(comp_info, &IID_IWICBitmapEncoderInfo, (void **)info); + IWICComponentInfo_Release(comp_info); + } + return hr; +} + +static HRESULT WINAPI DdsEncoder_SetColorContexts(IWICBitmapEncoder *iface, + UINT cCount, IWICColorContext **ppIColorContext) +{ + FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext); + return E_NOTIMPL; +} + +static HRESULT WINAPI DdsEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *palette) +{ + DdsEncoder *This = impl_from_IWICBitmapEncoder(iface); + HRESULT hr; + + TRACE("(%p,%p)\n", iface, palette); + + EnterCriticalSection(&This->lock); + + hr = This->stream ? WINCODEC_ERR_UNSUPPORTEDOPERATION : WINCODEC_ERR_NOTINITIALIZED; + + LeaveCriticalSection(&This->lock); + + return hr; +} + +static HRESULT WINAPI DdsEncoder_SetThumbnail(IWICBitmapEncoder *iface, IWICBitmapSource *pIThumbnail) +{ + TRACE("(%p,%p)\n", iface, pIThumbnail); + return WINCODEC_ERR_UNSUPPORTEDOPERATION; +} + +static HRESULT WINAPI DdsEncoder_SetPreview(IWICBitmapEncoder *iface, IWICBitmapSource *pIPreview) +{ + TRACE("(%p,%p)\n", iface, pIPreview); + return WINCODEC_ERR_UNSUPPORTEDOPERATION; +} + +static HRESULT WINAPI DdsEncoder_CreateNewFrame(IWICBitmapEncoder *iface, + IWICBitmapFrameEncode **frameEncode, IPropertyBag2 **encoderOptions) +{ + DdsEncoder *This = impl_from_IWICBitmapEncoder(iface); + + TRACE("(%p,%p,%p)\n", iface, frameEncode, encoderOptions); + + return IWICDdsEncoder_CreateNewFrame(&This->IWICDdsEncoder_iface, frameEncode, NULL, NULL, NULL); +} + +static HRESULT WINAPI DdsEncoder_Commit(IWICBitmapEncoder *iface) +{ + FIXME("(%p): stub\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI DdsEncoder_GetMetadataQueryWriter(IWICBitmapEncoder *iface, + IWICMetadataQueryWriter **ppIMetadataQueryWriter) +{ + FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryWriter); + return E_NOTIMPL; +} + +static const IWICBitmapEncoderVtbl DdsEncoder_Vtbl = { + DdsEncoder_QueryInterface, + DdsEncoder_AddRef, + DdsEncoder_Release, + DdsEncoder_Initialize, + DdsEncoder_GetContainerFormat, + DdsEncoder_GetEncoderInfo, + DdsEncoder_SetColorContexts, + DdsEncoder_SetPalette, + DdsEncoder_SetThumbnail, + DdsEncoder_SetPreview, + DdsEncoder_CreateNewFrame, + DdsEncoder_Commit, + DdsEncoder_GetMetadataQueryWriter +}; + +HRESULT DdsEncoder_CreateInstance( REFIID iid, void **ppv) +{ + DdsEncoder *This; + HRESULT ret; + + TRACE("(%s,%p)\n", debugstr_guid(iid), ppv); + + *ppv = NULL; + + This = malloc(sizeof(DdsEncoder)); + if (!This) return E_OUTOFMEMORY; + + This->IWICBitmapEncoder_iface.lpVtbl = &DdsEncoder_Vtbl; + This->IWICDdsEncoder_iface.lpVtbl = &DdsEncoder_Dds_Vtbl; + This->ref = 1; + This->stream = NULL; + This->frame_count = 0; + This->frame_index = 0; + This->uncommitted_frame = FALSE; + This->committed = FALSE; +#ifdef __REACTOS__ + InitializeCriticalSection(&This->lock); +#else + InitializeCriticalSectionEx(&This->lock, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO); +#endif + This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DdsEncoder.lock"); + + ret = IWICBitmapEncoder_QueryInterface(&This->IWICBitmapEncoder_iface, iid, ppv); + IWICBitmapEncoder_Release(&This->IWICBitmapEncoder_iface); + + return ret; +} diff --git a/dll/win32/windowscodecs/decoder.c b/dll/win32/windowscodecs/decoder.c new file mode 100644 index 00000000000..08fe23e1bf0 --- /dev/null +++ b/dll/win32/windowscodecs/decoder.c @@ -0,0 +1,811 @@ +/* + * Copyright 2020 Esme Povirk + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdarg.h> + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "objbase.h" + +#include "wincodecs_private.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); + +typedef struct { + IWICBitmapDecoder IWICBitmapDecoder_iface; + LONG ref; + CRITICAL_SECTION lock; /* must be held when stream or decoder is accessed */ + IStream *stream; + struct decoder *decoder; + struct decoder_info decoder_info; + struct decoder_stat file_info; + WICDecodeOptions cache_options; +} CommonDecoder; + +static inline CommonDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface) +{ + return CONTAINING_RECORD(iface, CommonDecoder, IWICBitmapDecoder_iface); +} + +static HRESULT WINAPI CommonDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid, + void **ppv) +{ + CommonDecoder *This = impl_from_IWICBitmapDecoder(iface); + TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); + + if (!ppv) return E_INVALIDARG; + + if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid)) + { + *ppv = &This->IWICBitmapDecoder_iface; + } + else + { + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI CommonDecoder_AddRef(IWICBitmapDecoder *iface) +{ + CommonDecoder *This = impl_from_IWICBitmapDecoder(iface); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) refcount=%lu\n", iface, ref); + + return ref; +} + +static ULONG WINAPI CommonDecoder_Release(IWICBitmapDecoder *iface) +{ + CommonDecoder *This = impl_from_IWICBitmapDecoder(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) refcount=%lu\n", iface, ref); + + if (ref == 0) + { + if (This->stream) + IStream_Release(This->stream); + This->lock.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&This->lock); + decoder_destroy(This->decoder); + free(This); + } + + return ref; +} + +static HRESULT WINAPI CommonDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *stream, + DWORD *capability) +{ + CommonDecoder *This = impl_from_IWICBitmapDecoder(iface); + HRESULT hr; + + TRACE("(%p,%p,%p)\n", iface, stream, capability); + + if (!stream || !capability) return E_INVALIDARG; + + hr = IWICBitmapDecoder_Initialize(iface, stream, WICDecodeMetadataCacheOnDemand); + if (hr != S_OK) return hr; + + *capability = (This->file_info.flags & DECODER_FLAGS_CAPABILITY_MASK); + return S_OK; +} + +static HRESULT WINAPI CommonDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream, + WICDecodeOptions cacheOptions) +{ + CommonDecoder *This = impl_from_IWICBitmapDecoder(iface); + HRESULT hr=S_OK; + + TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions); + + EnterCriticalSection(&This->lock); + + if (This->stream) + hr = WINCODEC_ERR_WRONGSTATE; + + if (SUCCEEDED(hr)) + hr = decoder_initialize(This->decoder, pIStream, &This->file_info); + + if (SUCCEEDED(hr)) + { + This->cache_options = cacheOptions; + This->stream = pIStream; + IStream_AddRef(This->stream); + } + + LeaveCriticalSection(&This->lock); + + return hr; +} + +static HRESULT WINAPI CommonDecoder_GetContainerFormat(IWICBitmapDecoder *iface, + GUID *pguidContainerFormat) +{ + CommonDecoder *This = impl_from_IWICBitmapDecoder(iface); + memcpy(pguidContainerFormat, &This->decoder_info.container_format, sizeof(GUID)); + return S_OK; +} + +static HRESULT WINAPI CommonDecoder_GetDecoderInfo(IWICBitmapDecoder *iface, + IWICBitmapDecoderInfo **ppIDecoderInfo) +{ + CommonDecoder *This = impl_from_IWICBitmapDecoder(iface); + TRACE("(%p,%p)\n", iface, ppIDecoderInfo); + + return get_decoder_info(&This->decoder_info.clsid, ppIDecoderInfo); +} + +static HRESULT WINAPI CommonDecoder_CopyPalette(IWICBitmapDecoder *iface, + IWICPalette *palette) +{ + TRACE("(%p,%p)\n", iface, palette); + return WINCODEC_ERR_PALETTEUNAVAILABLE; +} + +static HRESULT WINAPI CommonDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface, + IWICMetadataQueryReader **reader) +{ + TRACE("(%p,%p)\n", iface, reader); + + if (!reader) return E_INVALIDARG; + + *reader = NULL; + return WINCODEC_ERR_UNSUPPORTEDOPERATION; +} + +static HRESULT WINAPI CommonDecoder_GetPreview(IWICBitmapDecoder *iface, + IWICBitmapSource **ppIBitmapSource) +{ + TRACE("(%p,%p)\n", iface, ppIBitmapSource); + + if (!ppIBitmapSource) return E_INVALIDARG; + + *ppIBitmapSource = NULL; + return WINCODEC_ERR_UNSUPPORTEDOPERATION; +} + +static HRESULT WINAPI CommonDecoder_GetColorContexts(IWICBitmapDecoder *iface, + UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount) +{ + TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount); + return WINCODEC_ERR_UNSUPPORTEDOPERATION; +} + +static HRESULT WINAPI CommonDecoder_GetThumbnail(IWICBitmapDecoder *iface, + IWICBitmapSource **ppIThumbnail) +{ + TRACE("(%p,%p)\n", iface, ppIThumbnail); + + if (!ppIThumbnail) return E_INVALIDARG; + + *ppIThumbnail = NULL; + return WINCODEC_ERR_CODECNOTHUMBNAIL; +} + +static HRESULT WINAPI CommonDecoder_GetFrameCount(IWICBitmapDecoder *iface, + UINT *pCount) +{ + CommonDecoder *This = impl_from_IWICBitmapDecoder(iface); + if (!pCount) return E_INVALIDARG; + + if (This->stream) + *pCount = This->file_info.frame_count; + else + *pCount = 0; + + return S_OK; +} + +static HRESULT WINAPI CommonDecoder_GetFrame(IWICBitmapDecoder *iface, + UINT index, IWICBitmapFrameDecode **ppIBitmapFrame); + +static const IWICBitmapDecoderVtbl CommonDecoder_Vtbl = { + CommonDecoder_QueryInterface, + CommonDecoder_AddRef, + CommonDecoder_Release, + CommonDecoder_QueryCapability, + CommonDecoder_Initialize, + CommonDecoder_GetContainerFormat, + CommonDecoder_GetDecoderInfo, + CommonDecoder_CopyPalette, + CommonDecoder_GetMetadataQueryReader, + CommonDecoder_GetPreview, + CommonDecoder_GetColorContexts, + CommonDecoder_GetThumbnail, + CommonDecoder_GetFrameCount, + CommonDecoder_GetFrame +}; + +typedef struct { + IWICBitmapFrameDecode IWICBitmapFrameDecode_iface; + IWICMetadataBlockReader IWICMetadataBlockReader_iface; + LONG ref; + CommonDecoder *parent; + DWORD frame; + struct decoder_frame decoder_frame; + BOOL metadata_initialized; + UINT metadata_count; + struct decoder_block* metadata_blocks; +} CommonDecoderFrame; + +static inline CommonDecoderFrame *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface) +{ + return CONTAINING_RECORD(iface, CommonDecoderFrame, IWICBitmapFrameDecode_iface); +} + +static inline CommonDecoderFrame *impl_from_IWICMetadataBlockReader(IWICMetadataBlockReader *iface) +{ + return CONTAINING_RECORD(iface, CommonDecoderFrame, IWICMetadataBlockReader_iface); +} + +static HRESULT WINAPI CommonDecoderFrame_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid, + void **ppv) +{ + CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface); + if (!ppv) return E_INVALIDARG; + + if (IsEqualIID(&IID_IUnknown, iid) || + IsEqualIID(&IID_IWICBitmapSource, iid) || + IsEqualIID(&IID_IWICBitmapFrameDecode, iid)) + { + *ppv = &This->IWICBitmapFrameDecode_iface; + } + else if (IsEqualIID(&IID_IWICMetadataBlockReader, iid) && + (This->parent->file_info.flags & WICBitmapDecoderCapabilityCanEnumerateMetadata)) + { + *ppv = &This->IWICMetadataBlockReader_iface; + } + else + { + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI CommonDecoderFrame_AddRef(IWICBitmapFrameDecode *iface) +{ + CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) refcount=%lu\n", iface, ref); + + return ref; +} + +static ULONG WINAPI CommonDecoderFrame_Release(IWICBitmapFrameDecode *iface) +{ + CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) refcount=%lu\n", iface, ref); + + if (ref == 0) + { + IWICBitmapDecoder_Release(&This->parent->IWICBitmapDecoder_iface); + free(This->metadata_blocks); + free(This); + } + + return ref; +} + +static HRESULT WINAPI CommonDecoderFrame_GetSize(IWICBitmapFrameDecode *iface, + UINT *puiWidth, UINT *puiHeight) +{ + CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface); + + TRACE("(%p,%p,%p)\n", This, puiWidth, puiHeight); + + if (!puiWidth || !puiHeight) + return E_POINTER; + + *puiWidth = This->decoder_frame.width; + *puiHeight = This->decoder_frame.height; + return S_OK; +} + +static HRESULT WINAPI CommonDecoderFrame_GetPixelFormat(IWICBitmapFrameDecode *iface, + WICPixelFormatGUID *pPixelFormat) +{ + CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface); + + TRACE("(%p,%p)\n", This, pPixelFormat); + + if (!pPixelFormat) + return E_POINTER; + + *pPixelFormat = This->decoder_frame.pixel_format; + return S_OK; +} + +static HRESULT WINAPI CommonDecoderFrame_GetResolution(IWICBitmapFrameDecode *iface, + double *pDpiX, double *pDpiY) +{ + CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface); + + TRACE("(%p,%p,%p)\n", This, pDpiX, pDpiY); + + if (!pDpiX || !pDpiY) + return E_POINTER; + + *pDpiX = This->decoder_frame.dpix; + *pDpiY = This->decoder_frame.dpiy; + return S_OK; +} + +static HRESULT WINAPI CommonDecoderFrame_CopyPalette(IWICBitmapFrameDecode *iface, + IWICPalette *pIPalette) +{ + CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface); + HRESULT hr=S_OK; + + TRACE("(%p,%p)\n", iface, pIPalette); + + if (This->decoder_frame.num_colors) + { + hr = IWICPalette_InitializeCustom(pIPalette, This->decoder_frame.palette, This->decoder_frame.num_colors); + } + else + { + hr = WINCODEC_ERR_PALETTEUNAVAILABLE; + } + + return hr; +} + +static HRESULT WINAPI CommonDecoderFrame_CopyPixels(IWICBitmapFrameDecode *iface, + const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer) +{ + CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface); + HRESULT hr; + UINT bytesperrow; + WICRect rect; + + TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer); + + if (!pbBuffer) + return E_POINTER; + + if (!prc) + { + rect.X = 0; + rect.Y = 0; + rect.Width = This->decoder_frame.width; + rect.Height = This->decoder_frame.height; + prc = ▭ + } + else + { + if (prc->X < 0 || prc->Y < 0 || + prc->X+prc->Width > This->decoder_frame.width || + prc->Y+prc->Height > This->decoder_frame.height) + return E_INVALIDARG; + } + + bytesperrow = ((This->decoder_frame.bpp * prc->Width)+7)/8; + + if (cbStride < bytesperrow) + return E_INVALIDARG; + + if ((cbStride * (prc->Height-1)) + bytesperrow > cbBufferSize) + return E_INVALIDARG; + + EnterCriticalSection(&This->parent->lock); + + hr = decoder_copy_pixels(This->parent->decoder, This->frame, + prc, cbStride, cbBufferSize, pbBuffer); + + LeaveCriticalSection(&This->parent->lock); + + return hr; +} + +static HRESULT WINAPI CommonDecoderFrame_GetMetadataQueryReader(IWICBitmapFrameDecode *iface, + IWICMetadataQueryReader **ppIMetadataQueryReader) +{ + CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface); + IWICComponentFactory* factory; + HRESULT hr; + + TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader); + + if (!ppIMetadataQueryReader) + return E_INVALIDARG; + + if (!(This->parent->file_info.flags & WICBitmapDecoderCapabilityCanEnumerateMetadata)) + return WINCODEC_ERR_UNSUPPORTEDOPERATION; + + hr = create_instance(&CLSID_WICImagingFactory, &IID_IWICComponentFactory, (void**)&factory); + + if (SUCCEEDED(hr)) + { + hr = IWICComponentFactory_CreateQueryReaderFromBlockReader(factory, &This->IWICMetadataBlockReader_iface, ppIMetadataQueryReader); + IWICComponentFactory_Release(factory); + } + + if (FAILED(hr)) + *ppIMetadataQueryReader = NULL; + + return hr; +} + +static HRESULT WINAPI CommonDecoderFrame_GetColorContexts(IWICBitmapFrameDecode *iface, + UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount) +{ + CommonDecoderFrame *This = impl_from_IWICBitmapFrameDecode(iface); + HRESULT hr=S_OK; + UINT i; + BYTE *profile; + DWORD profile_len; + + TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount); + + if (!pcActualCount) return E_INVALIDARG; + + if (This->parent->file_info.flags & DECODER_FLAGS_UNSUPPORTED_COLOR_CONTEXT) + { + FIXME("not supported for %s\n", wine_dbgstr_guid(&This->parent->decoder_info.clsid)); + *pcActualCount = 0; + return WINCODEC_ERR_UNSUPPORTEDOPERATION; + } + + *pcActualCount = This->decoder_frame.num_color_contexts; + + if (This->decoder_frame.num_color_contexts && cCount && ppIColorContexts) + { + if (cCount >= This->decoder_frame.num_color_contexts) + { + EnterCriticalSection(&This->parent->lock); + + for (i=0; i<This->decoder_frame.num_color_contexts; i++) + { + hr = decoder_get_color_context(This->parent->decoder, This->frame, i, + &profile, &profile_len); + if (SUCCEEDED(hr)) + { + hr = IWICColorContext_InitializeFromMemory(ppIColorContexts[i], profile, profile_len); + + free(profile); + } + + if (FAILED(hr)) + break; + } + + LeaveCriticalSection(&This->parent->lock); + } + else + { + hr = E_INVALIDARG; + } + } + + return hr; +} + +static HRESULT WINAPI CommonDecoderFrame_GetThumbnail(IWICBitmapFrameDecode *iface, + IWICBitmapSource **ppIThumbnail) +{ + TRACE("(%p,%p)\n", iface, ppIThumbnail); + + if (!ppIThumbnail) return E_INVALIDARG; + + *ppIThumbnail = NULL; + return WINCODEC_ERR_CODECNOTHUMBNAIL; +} + +static const IWICBitmapFrameDecodeVtbl CommonDecoderFrameVtbl = { + CommonDecoderFrame_QueryInterface, + CommonDecoderFrame_AddRef, + CommonDecoderFrame_Release, + CommonDecoderFrame_GetSize, + CommonDecoderFrame_GetPixelFormat, + CommonDecoderFrame_GetResolution, + CommonDecoderFrame_CopyPalette, + CommonDecoderFrame_CopyPixels, + CommonDecoderFrame_GetMetadataQueryReader, + CommonDecoderFrame_GetColorContexts, + CommonDecoderFrame_GetThumbnail +}; + +static HRESULT WINAPI CommonDecoderFrame_Block_QueryInterface(IWICMetadataBlockReader *iface, REFIID iid, + void **ppv) +{ + CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface); + return IWICBitmapFrameDecode_QueryInterface(&This->IWICBitmapFrameDecode_iface, iid, ppv); +} + +static ULONG WINAPI CommonDecoderFrame_Block_AddRef(IWICMetadataBlockReader *iface) +{ + CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface); + return IWICBitmapFrameDecode_AddRef(&This->IWICBitmapFrameDecode_iface); +} + +static ULONG WINAPI CommonDecoderFrame_Block_Release(IWICMetadataBlockReader *iface) +{ + CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface); + return IWICBitmapFrameDecode_Release(&This->IWICBitmapFrameDecode_iface); +} + +static HRESULT WINAPI CommonDecoderFrame_Block_GetContainerFormat(IWICMetadataBlockReader *iface, + GUID *pguidContainerFormat) +{ + CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface); + if (!pguidContainerFormat) return E_INVALIDARG; + *pguidContainerFormat = This->parent->decoder_info.block_format; + return S_OK; +} + +static HRESULT CommonDecoderFrame_InitializeMetadata(CommonDecoderFrame *This) +{ + HRESULT hr=S_OK; + + if (This->metadata_initialized) + return S_OK; + + EnterCriticalSection(&This->parent->lock); + + if (!This->metadata_initialized) + { + hr = decoder_get_metadata_blocks(This->parent->decoder, This->frame, &This->metadata_count, &This->metadata_blocks); + if (SUCCEEDED(hr)) + This->metadata_initialized = TRUE; + } + + LeaveCriticalSection(&This->parent->lock); + + return hr; +} + +static HRESULT WINAPI CommonDecoderFrame_Block_GetCount(IWICMetadataBlockReader *iface, + UINT *pcCount) +{ + CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface); + HRESULT hr; + + TRACE("%p,%p\n", iface, pcCount); + + if (!pcCount) return E_INVALIDARG; + + hr = CommonDecoderFrame_InitializeMetadata(This); + if (SUCCEEDED(hr)) + *pcCount = This->metadata_count; + + return hr; +} + +static HRESULT WINAPI CommonDecoderFrame_Block_GetReaderByIndex(IWICMetadataBlockReader *iface, + UINT nIndex, IWICMetadataReader **ppIMetadataReader) +{ + CommonDecoderFrame *This = impl_from_IWICMetadataBlockReader(iface); + HRESULT hr; + IWICComponentFactory* factory = NULL; + IWICStream* stream; + + TRACE("%p,%d,%p\n", iface, nIndex, ppIMetadataReader); + + if (!ppIMetadataReader) + return E_INVALIDARG; + + hr = CommonDecoderFrame_InitializeMetadata(This); + + if (SUCCEEDED(hr) && nIndex >= This->metadata_count) + hr = E_INVALIDARG; + + if (SUCCEEDED(hr)) + hr = create_instance(&CLSID_WICImagingFactory, &IID_IWICComponentFactory, (void**)&factory); + + if (SUCCEEDED(hr)) + hr = IWICComponentFactory_CreateStream(factory, &stream); + + if (SUCCEEDED(hr)) + { + if (This->metadata_blocks[nIndex].options & DECODER_BLOCK_FULL_STREAM) + { + LARGE_INTEGER offset; + offset.QuadPart = This->metadata_blocks[nIndex].offset; + + hr = IWICStream_InitializeFromIStream(stream, This->parent->stream); + + if (SUCCEEDED(hr)) + hr = IWICStream_Seek(stream, offset, STREAM_SEEK_SET, NULL); + } + else + { + ULARGE_INTEGER offset, length; + + offset.QuadPart = This->metadata_blocks[nIndex].offset; + length.QuadPart = This->metadata_blocks[nIndex].length; + + hr = IWICStream_InitializeFromIStreamRegion(stream, This->parent->stream, + offset, length); + } + + if (This->metadata_blocks[nIndex].options & DECODER_BLOCK_READER_CLSID) + { + IWICMetadataReader *reader; + IWICPersistStream *persist; + if (SUCCEEDED(hr)) + { + hr = create_instance(&This->metadata_blocks[nIndex].reader_clsid, + &IID_IWICMetadataReader, (void**)&reader); + } + + if (SUCCEEDED(hr)) + { + hr = IWICMetadataReader_QueryInterface(reader, &IID_IWICPersistStream, (void**)&persist); + + if (SUCCEEDED(hr)) + { + hr = IWICPersistStream_LoadEx(persist, (IStream*)stream, NULL, + This->metadata_blocks[nIndex].options & DECODER_BLOCK_OPTION_MASK); + + IWICPersistStream_Release(persist); + } + + if (SUCCEEDED(hr)) + *ppIMetadataReader = reader; + else + IWICMetadataReader_Release(reader); + } + } + else + { + hr = IWICComponentFactory_CreateMetadataReaderFromContainer(factory, + &This->parent->decoder_info.block_format, NULL, + This->metadata_blocks[nIndex].options & DECODER_BLOCK_OPTION_MASK, + (IStream*)stream, ppIMetadataReader); + } + + IWICStream_Release(stream); + } + + if (factory) IWICComponentFactory_Release(factory); + + if (FAILED(hr)) + *ppIMetadataReader = NULL; + + return S_OK; +} + +static HRESULT WINAPI CommonDecoderFrame_Block_GetEnumerator(IWICMetadataBlockReader *iface, + IEnumUnknown **ppIEnumMetadata) +{ + FIXME("%p,%p\n", iface, ppIEnumMetadata); + return E_NOTIMPL; +} + +static const IWICMetadataBlockReaderVtbl CommonDecoderFrame_BlockVtbl = { + CommonDecoderFrame_Block_QueryInterface, + CommonDecoderFrame_Block_AddRef, + CommonDecoderFrame_Block_Release, + CommonDecoderFrame_Block_GetContainerFormat, + CommonDecoderFrame_Block_GetCount, + CommonDecoderFrame_Block_GetReaderByIndex, + CommonDecoderFrame_Block_GetEnumerator, +}; + +static HRESULT WINAPI CommonDecoder_GetFrame(IWICBitmapDecoder *iface, + UINT index, IWICBitmapFrameDecode **ppIBitmapFrame) +{ + CommonDecoder *This = impl_from_IWICBitmapDecoder(iface); + HRESULT hr=S_OK; + CommonDecoderFrame *result; + + TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame); + + if (!ppIBitmapFrame) + return E_INVALIDARG; + + EnterCriticalSection(&This->lock); + + if (!This->stream || index >= This->file_info.frame_count) + hr = WINCODEC_ERR_FRAMEMISSING; + + if (SUCCEEDED(hr)) + { + result = malloc(sizeof(*result)); + if (!result) + hr = E_OUTOFMEMORY; + } + + if (SUCCEEDED(hr)) + { + result->IWICBitmapFrameDecode_iface.lpVtbl = &CommonDecoderFrameVtbl; + result->IWICMetadataBlockReader_iface.lpVtbl = &CommonDecoderFrame_BlockVtbl; + result->ref = 1; + result->parent = This; + result->frame = index; + result->metadata_initialized = FALSE; + result->metadata_count = 0; + result->metadata_blocks = NULL; + + hr = decoder_get_frame_info(This->decoder, index, &result->decoder_frame); + + if (SUCCEEDED(hr) && This->cache_options == WICDecodeMetadataCacheOnLoad) + hr = CommonDecoderFrame_InitializeMetadata(result); + + if (FAILED(hr)) + free(result); + } + + LeaveCriticalSection(&This->lock); + + if (SUCCEEDED(hr)) + { + TRACE("-> %ux%u, %u-bit pixelformat=%s res=%f,%f colors=%lu contexts=%lu\n", + result->decoder_frame.width, result->decoder_frame.height, + result->decoder_frame.bpp, wine_dbgstr_guid(&result->decoder_frame.pixel_format), + result->decoder_frame.dpix, result->decoder_frame.dpiy, + result->decoder_frame.num_colors, result->decoder_frame.num_color_contexts); + IWICBitmapDecoder_AddRef(&This->IWICBitmapDecoder_iface); + *ppIBitmapFrame = &result->IWICBitmapFrameDecode_iface; + } + else + { + *ppIBitmapFrame = NULL; + } + + return hr; +} + +HRESULT CommonDecoder_CreateInstance(struct decoder *decoder, + const struct decoder_info *decoder_info, REFIID iid, void** ppv) +{ + CommonDecoder *This; + HRESULT hr; + + TRACE("(%s,%s,%p)\n", debugstr_guid(&decoder_info->clsid), debugstr_guid(iid), ppv); + + This = malloc(sizeof(*This)); + if (!This) + { + decoder_destroy(decoder); + return E_OUTOFMEMORY; + } + + This->IWICBitmapDecoder_iface.lpVtbl = &CommonDecoder_Vtbl; + This->ref = 1; + This->stream = NULL; + This->decoder = decoder; + This->decoder_info = *decoder_info; +#ifdef __REACTOS__ + InitializeCriticalSection(&This->lock); +#else + InitializeCriticalSectionEx(&This->lock, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO); +#endif + This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": CommonDecoder.lock"); + + hr = IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv); + IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface); + + return hr; +} diff --git a/dll/win32/windowscodecs/encoder.c b/dll/win32/windowscodecs/encoder.c new file mode 100644 index 00000000000..b2be1f12e1c --- /dev/null +++ b/dll/win32/windowscodecs/encoder.c @@ -0,0 +1,903 @@ +/* + * Copyright 2020 Esme Povirk + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdarg.h> + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "objbase.h" + +#include "wincodecs_private.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(wincodecs); + +static const PROPBAG2 encoder_option_properties[ENCODER_OPTION_END] = { + { PROPBAG2_TYPE_DATA, VT_BOOL, 0, 0, (LPOLESTR)L"InterlaceOption" }, + { PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)L"FilterOption" }, + { PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)L"TiffCompressionMethod" }, + { PROPBAG2_TYPE_DATA, VT_R4, 0, 0, (LPOLESTR)L"CompressionQuality" }, + { PROPBAG2_TYPE_DATA, VT_R4, 0, 0, (LPOLESTR)L"ImageQuality" }, + { PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)L"BitmapTransform" }, + { PROPBAG2_TYPE_DATA, VT_I4 | VT_ARRAY, 0, 0, (LPOLESTR)L"Luminance" }, + { PROPBAG2_TYPE_DATA, VT_I4 | VT_ARRAY, 0, 0, (LPOLESTR)L"Chrominance" }, + { PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)L"JpegYCrCbSubsampling" }, + { PROPBAG2_TYPE_DATA, VT_BOOL, 0, 0, (LPOLESTR)L"SuppressApp0" } +}; + +typedef struct CommonEncoder { + IWICBitmapEncoder IWICBitmapEncoder_iface; + LONG ref; + CRITICAL_SECTION lock; /* must be held when stream or encoder is accessed */ + IStream *stream; + struct encoder *encoder; + struct encoder_info encoder_info; + UINT frame_count; + BOOL uncommitted_frame; + BOOL committed; +} CommonEncoder; + +typedef struct CommonEncoderFrame { + IWICBitmapFrameEncode IWICBitmapFrameEncode_iface; + IWICMetadataBlockWriter IWICMetadataBlockWriter_iface; + LONG ref; + CommonEncoder *parent; + struct encoder_frame encoder_frame; + BOOL initialized; + BOOL frame_created; + UINT lines_written; + BOOL committed; +} CommonEncoderFrame; + +static inline CommonEncoder *impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface) +{ + return CONTAINING_RECORD(iface, CommonEncoder, IWICBitmapEncoder_iface); +} + +static inline CommonEncoderFrame *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode *iface) +{ + return CONTAINING_RECORD(iface, CommonEncoderFrame, IWICBitmapFrameEncode_iface); +} + +static inline CommonEncoderFrame *impl_from_IWICMetadataBlockWriter(IWICMetadataBlockWriter *iface) +{ + return CONTAINING_RECORD(iface, CommonEncoderFrame, IWICMetadataBlockWriter_iface); +} + +static HRESULT WINAPI CommonEncoderFrame_QueryInterface(IWICBitmapFrameEncode *iface, REFIID iid, + void **ppv) +{ + CommonEncoderFrame *object = impl_from_IWICBitmapFrameEncode(iface); + TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); + + if (!ppv) return E_INVALIDARG; + + if (IsEqualIID(&IID_IUnknown, iid) || + IsEqualIID(&IID_IWICBitmapFrameEncode, iid)) + { + *ppv = &object->IWICBitmapFrameEncode_iface; + } + else if (object->parent->encoder_info.flags & ENCODER_FLAGS_SUPPORTS_METADATA + && IsEqualIID(&IID_IWICMetadataBlockWriter, iid)) + { + *ppv = &object->IWICMetadataBlockWriter_iface; + } + else + { + *ppv = NULL; + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; +} + +static ULONG WINAPI CommonEncoderFrame_AddRef(IWICBitmapFrameEncode *iface) +{ + CommonEncoderFrame *This = impl_from_IWICBitmapFrameEncode(iface); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) refcount=%lu\n", iface, ref); + + return ref; +} + +static ULONG WINAPI CommonEncoderFrame_Release(IWICBitmapFrameEncode *iface) +{ + CommonEncoderFrame *This = impl_from_IWICBitmapFrameEncode(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) refcount=%lu\n", iface, ref); + + if (ref == 0) + { + IWICBitmapEncoder_Release(&This->parent->IWICBitmapEncoder_iface); + free(This); + } + + return ref; +} + +static HRESULT WINAPI CommonEncoderFrame_Initialize(IWICBitmapFrameEncode *iface, + IPropertyBag2 *pIEncoderOptions) +{ + CommonEncoderFrame *This = impl_from_IWICBitmapFrameEncode(iface); + HRESULT hr=S_OK; + struct encoder_frame options = {{0}}; + PROPBAG2 opts[7]= {{0}}; + VARIANT opt_values[7]; + HRESULT opt_hres[7]; + DWORD num_opts, i; + + TRACE("(%p,%p)\n", iface, pIEncoderOptions); + + if (pIEncoderOptions) + { + for (i=0; This->parent->encoder_info.encoder_options[i] != ENCODER_OPTION_END; i++) + opts[i] = encoder_option_properties[This->parent->encoder_info.encoder_options[i]]; + num_opts = i; + + hr = IPropertyBag2_Read(pIEncoderOptions, num_opts, opts, NULL, opt_values, opt_hres); + + if (FAILED(hr)) + return hr; + + for (i=0; This->parent->encoder_info.encoder_options[i] != ENCODER_OPTION_END; i++) + { + VARIANT *val = &opt_values[i]; + + switch (This->parent->encoder_info.encoder_options[i]) + { + case ENCODER_OPTION_INTERLACE: + if (V_VT(val) == VT_EMPTY) + options.interlace = FALSE; + else + options.interlace = (V_BOOL(val) != 0); + break; + case ENCODER_OPTION_FILTER: + options.filter = V_UI1(val); + if (options.filter > WICPngFilterAdaptive) + { + WARN("Unrecognized filter option value %lu.\n", options.filter); + options.filter = WICPngFilterUnspecified; + } + break; + default: + break; + } + } + } + else + { + options.interlace = FALSE; + options.filter = WICPngFilterUnspecified; + } + + EnterCriticalSection(&This->parent->lock); + + if (This->initialized) + hr = WINCODEC_ERR_WRONGSTATE; + else + { + This->encoder_frame = options; + This->initialized = TRUE; + } + + LeaveCriticalSection(&This->parent->lock); + + return hr; +} + +static HRESULT WINAPI CommonEncoderFrame_SetSize(IWICBitmapFrameEncode *iface, + UINT uiWidth, UINT uiHeight) +{ + CommonEncoderFrame *This = impl_from_IWICBitmapFrameEncode(iface); + HRESULT hr; + + TRACE("(%p,%u,%u)\n", iface, uiWidth, uiHeight); + + EnterCriticalSection(&This->parent->lock); + + if (This->parent->encoder_info.flags & ENCODER_FLAGS_ICNS_SIZE) + { + if (uiWidth != uiHeight) + { + WARN("cannot generate ICNS icon from %dx%d image\n", uiWidth, uiHeight); + hr = E_INVALIDARG; + goto end; + } + + switch (uiWidth) + { + case 16: + case 32: + case 48: + case 128: + case 256: + case 512: + break; + default: + WARN("cannot generate ICNS icon from %dx%d image\n", uiWidth, uiHeight); + hr = E_INVALIDARG; + goto end; + } + } + + if (!This->initialized || This->frame_created) + { + hr = WINCODEC_ERR_WRONGSTATE; + } + else + { + This->encoder_frame.width = uiWidth; + This->encoder_frame.height = uiHeight; + hr = S_OK; + } + +end: + LeaveCriticalSection(&This->parent->lock); + + return hr; +} + +static HRESULT WINAPI CommonEncoderFrame_SetResolution(IWICBitmapFrameEncode *iface, + double dpiX, double dpiY) +{ + CommonEncoderFrame *This = impl_from_IWICBitmapFrameEncode(iface); + HRESULT hr; + + TRACE("(%p,%0.2f,%0.2f)\n", iface, dpiX, dpiY); + + EnterCriticalSection(&This->parent->lock); + + if (!This->initialized || This->frame_created) + { + hr = WINCODEC_ERR_WRONGSTATE; + } + else + { + This->encoder_frame.dpix = dpiX; + This->encoder_frame.dpiy = dpiY; + hr = S_OK; + } + + LeaveCriticalSection(&This->parent->lock); + + return hr; +} + +static HRESULT WINAPI CommonEncoderFrame_SetPixelFormat(IWICBitmapFrameEncode *iface, + WICPixelFormatGUID *pPixelFormat) +{ + CommonEncoderFrame *This = impl_from_IWICBitmapFrameEncode(iface); + HRESULT hr; + GUID pixel_format; + DWORD bpp; + BOOL indexed; + + TRACE("(%p,%s)\n", iface, debugstr_guid(pPixelFormat)); + + EnterCriticalSection(&This->parent->lock); + + if (!This->initialized || This->frame_created) + { + hr = WINCODEC_ERR_WRONGSTATE; + } + else + { + pixel_format = *pPixelFormat; + hr = encoder_get_supported_format(This->parent->encoder, &pixel_format, &bpp, &indexed); + } + + if (SUCCEEDED(hr)) + { + TRACE("<-- %s bpp=%li indexed=%i\n", wine_dbgstr_guid(&pixel_format), bpp, indexed); + *pPixelFormat = pixel_format; ... 33002 lines suppressed ...
3 weeks, 3 days
1
0
0
0
[reactos] 01/02: [LIBJPEG][LIBPNG][LIBTIFF] Add .spec files (#7665)
by Mikhail Tyukin
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=41d1898fcd4ef53780e33…
commit 41d1898fcd4ef53780e33229e21dfee20a7d5de2 Author: Mikhail Tyukin <mishakeys20(a)gmail.com> AuthorDate: Sun Jan 26 12:57:27 2025 -0500 Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org> CommitDate: Fri Feb 7 16:57:01 2025 +0100 [LIBJPEG][LIBPNG][LIBTIFF] Add .spec files (#7665) --- dll/3rdparty/libjpeg/CMakeLists.txt | 4 +++- dll/3rdparty/libjpeg/libjpeg.spec | 14 +++++++++++++ dll/3rdparty/libpng/CMakeLists.txt | 4 +++- dll/3rdparty/libpng/libpng.spec | 40 +++++++++++++++++++++++++++++++++++++ dll/3rdparty/libtiff/CMakeLists.txt | 4 +++- dll/3rdparty/libtiff/libtiff.spec | 17 ++++++++++++++++ media/doc/3rd Party Files.txt | 3 +++ 7 files changed, 83 insertions(+), 3 deletions(-) diff --git a/dll/3rdparty/libjpeg/CMakeLists.txt b/dll/3rdparty/libjpeg/CMakeLists.txt index fefc3da850c..1b68ac71488 100644 --- a/dll/3rdparty/libjpeg/CMakeLists.txt +++ b/dll/3rdparty/libjpeg/CMakeLists.txt @@ -10,6 +10,8 @@ include_directories( ${REACTOS_SOURCE_DIR}/sdk/include/reactos/libs/libjpeg ${REACTOS_SOURCE_DIR}/sdk/include/reactos/libs/zlib) +spec2def(libjpeg.dll libjpeg.spec ADD_IMPORTLIB) + list(APPEND SOURCE jaricom.c jcapimin.c @@ -59,7 +61,7 @@ list(APPEND SOURCE jmemnobs.c precomp.h) -add_library(libjpeg MODULE ${SOURCE}) +add_library(libjpeg MODULE ${SOURCE} ${CMAKE_CURRENT_BINARY_DIR}/libjpeg.def) set_module_type(libjpeg win32dll) add_importlibs(libjpeg msvcrt kernel32) add_pch(libjpeg precomp.h SOURCE) diff --git a/dll/3rdparty/libjpeg/libjpeg.spec b/dll/3rdparty/libjpeg/libjpeg.spec new file mode 100644 index 00000000000..62eda3cbd0f --- /dev/null +++ b/dll/3rdparty/libjpeg/libjpeg.spec @@ -0,0 +1,14 @@ +@ cdecl jpeg_std_error(ptr) +@ cdecl jpeg_CreateCompress(ptr long) +@ cdecl jpeg_CreateDecompress(ptr long long) +@ cdecl jpeg_destroy_compress(ptr) +@ cdecl jpeg_destroy_decompress(ptr) +@ cdecl jpeg_set_defaults(ptr) +@ cdecl jpeg_start_compress(ptr long) +@ cdecl jpeg_write_scanlines(ptr ptr long) +@ cdecl jpeg_finish_compress(ptr) +@ cdecl jpeg_read_header(ptr long) +@ cdecl jpeg_start_decompress(ptr) +@ cdecl jpeg_read_scanlines(ptr ptr long) +@ cdecl jpeg_finish_decompress(ptr) +@ cdecl jpeg_resync_to_restart(ptr long) diff --git a/dll/3rdparty/libpng/CMakeLists.txt b/dll/3rdparty/libpng/CMakeLists.txt index e7599539562..a5b3849377f 100644 --- a/dll/3rdparty/libpng/CMakeLists.txt +++ b/dll/3rdparty/libpng/CMakeLists.txt @@ -9,6 +9,8 @@ include_directories( ${REACTOS_SOURCE_DIR}/sdk/include/reactos/libs/libpng ${REACTOS_SOURCE_DIR}/sdk/include/reactos/libs/zlib) +spec2def(libpng.dll libpng.spec ADD_IMPORTLIB) + list(APPEND SOURCE png.c pngerror.c @@ -27,7 +29,7 @@ list(APPEND SOURCE pngwutil.c pngpriv.h) -add_library(libpng MODULE ${SOURCE}) +add_library(libpng MODULE ${SOURCE} ${CMAKE_CURRENT_BINARY_DIR}/libpng.def) set_module_type(libpng win32dll) target_link_libraries(libpng zlib) add_importlibs(libpng msvcrt kernel32 ntdll) diff --git a/dll/3rdparty/libpng/libpng.spec b/dll/3rdparty/libpng/libpng.spec new file mode 100644 index 00000000000..b1b008b8ffc --- /dev/null +++ b/dll/3rdparty/libpng/libpng.spec @@ -0,0 +1,40 @@ +@ cdecl png_create_info_struct(ptr) +@ cdecl png_create_read_struct(ptr ptr ptr ptr) +@ cdecl png_create_write_struct(ptr ptr ptr ptr) +@ cdecl png_get_compression_buffer_size(ptr) +@ cdecl png_set_compression_buffer_size(ptr long) +@ cdecl png_set_longjmp_fn(ptr ptr long) +@ cdecl png_destroy_read_struct(ptr ptr ptr) +@ cdecl png_destroy_write_struct(ptr ptr) +@ cdecl png_error(ptr ptr) +@ cdecl png_get_bit_depth(ptr ptr) +@ cdecl png_get_color_type(ptr ptr) +@ cdecl png_get_error_ptr(ptr) +@ cdecl png_get_iCCP(ptr ptr ptr ptr ptr ptr) +@ cdecl png_get_image_height(ptr ptr) +@ cdecl png_get_image_width(ptr ptr) +@ cdecl png_get_io_ptr(ptr) +@ cdecl png_get_pHYs(ptr ptr ptr ptr) +@ cdecl png_get_PLTE(ptr ptr ptr ptr) +@ cdecl png_get_tRNS(ptr ptr ptr ptr ptr) +@ cdecl png_read_image(ptr ptr) +@ cdecl png_read_info(ptr ptr) +@ cdecl png_set_bgr(ptr) +@ cdecl png_set_crc_action(ptr long long) +@ cdecl png_set_filter(ptr long long) +@ cdecl png_set_error_fn(ptr ptr ptr ptr) +@ cdecl png_set_filler(ptr long long) +@ cdecl png_set_gray_to_rgb(ptr) +@ cdecl png_set_IHDR(ptr ptr long long long long long long long) +@ cdecl png_set_interlace_handling(ptr) +@ cdecl png_set_pHYs(ptr ptr ptr long long long) +@ cdecl png_set_PLTE(ptr ptr ptr long) +@ cdecl png_set_read_fn(ptr ptr ptr) +@ cdecl png_set_swap(ptr) +@ cdecl png_set_tRNS(ptr ptr ptr long ptr) +@ cdecl png_set_tRNS_to_alpha(ptr) +@ cdecl png_set_write_fn(ptr ptr ptr ptr) +@ cdecl png_set_chunk_malloc_max(ptr long) +@ cdecl png_write_end(ptr) +@ cdecl png_write_info(ptr ptr) +@ cdecl png_write_rows(ptr ptr long) diff --git a/dll/3rdparty/libtiff/CMakeLists.txt b/dll/3rdparty/libtiff/CMakeLists.txt index 2aff720a340..882d3b3971f 100644 --- a/dll/3rdparty/libtiff/CMakeLists.txt +++ b/dll/3rdparty/libtiff/CMakeLists.txt @@ -9,6 +9,8 @@ include_directories( ${REACTOS_SOURCE_DIR}/sdk/include/reactos/libs/libtiff ${REACTOS_SOURCE_DIR}/sdk/include/reactos/libs/zlib) +spec2def(libtiff.dll libtiff.spec ADD_IMPORTLIB) + list(APPEND SOURCE #mkg3states.c tif_aux.c @@ -54,7 +56,7 @@ list(APPEND SOURCE #tif_zstd.c precomp.h) -add_library(libtiff MODULE ${SOURCE} libtiff.def) +add_library(libtiff MODULE ${SOURCE} ${CMAKE_CURRENT_BINARY_DIR}/libtiff.def) set_module_type(libtiff win32dll) target_link_libraries(libtiff zlib getopt) diff --git a/dll/3rdparty/libtiff/libtiff.spec b/dll/3rdparty/libtiff/libtiff.spec new file mode 100644 index 00000000000..f774b2ac4a1 --- /dev/null +++ b/dll/3rdparty/libtiff/libtiff.spec @@ -0,0 +1,17 @@ +# TODO: add remaining exports +@ cdecl TIFFClose(ptr) +@ cdecl TIFFClientOpen(ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr) +@ cdecl TIFFCurrentDirOffset(ptr) +@ cdecl TIFFGetField(ptr long long long) +@ cdecl TIFFIsByteSwapped(ptr) +@ cdecl TIFFNumberOfDirectories(ptr) +@ cdecl TIFFReadEncodedStrip(ptr) +@ cdecl TIFFReadEncodedTile(ptr long ptr long) +@ cdecl TIFFSetDirectory(ptr long) +@ cdecl TIFFSetErrorHandler(ptr) +@ cdecl TIFFSetErrorHandlerExt(ptr) +@ cdecl TIFFSetWarningHandler(ptr) +@ cdecl TIFFSetWarningHandlerExt(ptr) +@ cdecl TIFFSetField(ptr long long long) +@ cdecl TIFFWriteDirectory(ptr) +@ cdecl TIFFWriteScanline(ptr ptr long long) diff --git a/media/doc/3rd Party Files.txt b/media/doc/3rd Party Files.txt index e8ae9ad70ad..617aac1cc4d 100644 --- a/media/doc/3rd Party Files.txt +++ b/media/doc/3rd Party Files.txt @@ -31,18 +31,21 @@ Path: dll/3rdparty/libjpeg Used Version: 9d License: custom, BSD-like URL:
http://www.ijg.org/
+Modifications: added .spec file Title: libpng Path: dll/3rdparty/libpng Used Version: 1.6.39 License: PNG Reference Library version 2 URL:
http://libpng.sourceforge.net/
+Modifications: added .spec file Title: libtiff Path: dll/3rdparty/libtiff Used Version: 4.1.0 License: libtiff (
https://spdx.org/licenses/libtiff.html
) URL:
http://www.simplesystems.org/libtiff/
+Modifications: added .spec file Title: Libxslt Path: dll/3rdparty/libxslt
3 weeks, 3 days
1
0
0
0
← Newer
1
2
3
4
5
6
7
8
Older →
Jump to page:
1
2
3
4
5
6
7
8
Results per page:
10
25
50
100
200