diff --git a/Readme.md b/Readme.md index 3b70b2a2..05303ebf 100644 --- a/Readme.md +++ b/Readme.md @@ -99,6 +99,17 @@ Compatible with all platforms. * All runtime modes are supported (such as: `/MD`, `/MT`, `/MDd`, `/MTd`). ### 3.2. Windows SDK Version Requirements +| Thunks Target | At Least Windows SDK Version is required +| ------------------ | ----------- +| Windows 2000 | SDK 6.0 (VS2008 built-in) +| Windows XP(2003) | SDK 6.0 (VS2008 built-in) +| Windows Vista | SDK 6.0 (VS2008 built-in) +| Windows 7 | SDK 7.0 +| Windows 8 | SDK 8.0 +| Windows 8.1 | SDK 8.1 +| Windows 10 10240 | SDK 10.0.10240 +| Windows 10 19041 | SDK 10.0.19041 + At least Windows SDK 6.0 is required. > Note: VC6.0 and VS2005 users should note that the SDK version that comes with these compilers by default is too low. diff --git a/Readme.osc.md b/Readme.osc.md index ab292931..f38322e3 100644 --- a/Readme.osc.md +++ b/Readme.osc.md @@ -101,7 +101,17 @@ ULONGLONG WINAPI GetTickCount64(VOID) * 所有运行库模式均支持(比如:`/MD`、`/MT`、`/MDd`、`/MTd`)。 ### 3.2. SDK版本要求 -至少需要SDK 6.0(VS2008默认附带) + +| Thunks等级 | 最低SDK要求 +| ------------------ | ----------- +| Windows 2000 | SDK 6.0(VS2008默认附带) +| Windows XP(2003) | SDK 6.0(VS2008默认附带) +| Windows Vista | SDK 6.0(VS2008默认附带) +| Windows 7 | SDK 7.0 +| Windows 8 | SDK 8.0 +| Windows 8.1 | SDK 8.1 +| Windows 10 10240 | SDK 10.0.10240 +| Windows 10 19041 | SDK 10.0.19041 > 温馨提示:VC6.0、VS2005用户请注意,由于这些编译器默认附带的SDK版本太低。请先将SDK升级到6.0或者更高版本,然后再使用YY-Thunks,否则将发生链接失败! 高版本的SDK不影响对老系统的兼容性,请坐和放宽,安心升级。 diff --git a/ThunksList.md b/ThunksList.md index d77bc4c3..f4d67bad 100644 --- a/ThunksList.md +++ b/ThunksList.md @@ -4,6 +4,11 @@ > 开头带`*`的函数并不建议使用,存在一些较大负面影响,仅用于编译通过处理,具体负面影响可参考注释内容。 +## api-ms-win-core-handle-l1-1-0.dll +| 函数 | Fallback +| ---- | ----------- +| CompareObjectHandles | 不存在时,调用NtQueryObject以及DuplicateHandle。 + ## api-ms-win-core-path-l1-1-0.dll | 函数 | Fallback | ---- | ----------- @@ -121,6 +126,7 @@ | EventWriteEx | 不存在时,调用EventWriteTransfer。 | EventWriteString | 不存在时,返回ERROR_NOT_SUPPORTED。 | GetDynamicTimeZoneInformationEffectiveYears| 不存在时,直接读取`Time Zones`注册表。 +| AddMandatoryAce | 不存在时,调用RtlCopySid。 ## bcrypt.dll | 函数 | Fallback @@ -159,6 +165,14 @@ | BluetoothGATTSetCharacteristicValue | 不存在时,返回ERROR_NOT_SUPPORTED。 | BluetoothGATTSetDescriptorValue | 不存在时,返回ERROR_NOT_SUPPORTED。 +## CfgMgr32.dll +| 函数 | Fallback +| ---- | ----------- +| CM_Get_DevNode_Property_ExW | 不存在时,调用CM_Get_DevNode_Registry_PropertyW。 +| CM_Set_DevNode_Property_ExW | 不存在时,调用CM_Set_DevNode_Registry_PropertyW。 +| CM_Get_DevNode_PropertyW | 不存在时,调用CM_Get_DevNode_Property_ExW。 +| CM_Set_DevNode_PropertyW | 不存在时,调用CM_Set_DevNode_Property_ExW。 + ## Crypt32.dll | 函数 | Fallback | ---- | ----------- @@ -175,6 +189,11 @@ | ---- | ----------- | D3D11CreateDevice | 不存在时,返回 `E_NOINTERFACE`。 +## d3d12.dll +| 函数 | Fallback +| ---- | ----------- +| D3D12CreateDevice | 不存在时,返回 `E_NOINTERFACE`。 + ## DbgHelp.dll | 函数 | Fallback | ---- | ----------- @@ -518,7 +537,14 @@ | CreateRemoteThreadEx | 不存在时,调用CreateRemoteThread。 | WerRegisterRuntimeExceptionModule | 不存在时,返回S_OK。 | WerUnregisterRuntimeExceptionModule | 不存在时,返回S_OK。 -| Wow64GetThreadContext | 不存在时,返回ERROR_INVALID_PARAMETER。 +| Wow64GetThreadContext | 不存在时,调用GetThreadContext或者返回ERROR_INVALID_PARAMETER。 +| SetDefaultDllDirectories | 不存在时,手工控制LoadLibrary加载顺序。 + +## mfplat.dll +| 函数 | Fallback +| ---- | ----------- +| MFCreateDeviceSource | 不存在时,返回E_NOTIMPL。 +| MFEnumDeviceSources | 不存在时,返回E_NOTIMPL。 ## mfplat.dll | 函数 | Fallback @@ -527,6 +553,36 @@ | MFCreateDXGISurfaceBuffer | 不存在时,返回E_NOTIMPL。 | MFLockDXGIDeviceManager | 不存在时,返回E_NOTIMPL。 | MFUnlockDXGIDeviceManager | 不存在时,返回E_NOTIMPL。 +| MFCreateAlignedMemoryBuffer | 不存在时,返回E_NOTIMPL。 +| MFCreateAsyncResult | 不存在时,返回E_NOTIMPL。 +| MFCreateAttributes | 不存在时,返回E_NOTIMPL。 +| MFCreateEventQueue | 不存在时,返回E_NOTIMPL。 +| MFCreateMediaBufferWrapper | 不存在时,返回E_NOTIMPL。 +| MFCreateMediaEvent | 不存在时,返回E_NOTIMPL。 +| MFCreateMediaType | 不存在时,返回E_NOTIMPL。 +| MFCreateMemoryBuffer | 不存在时,返回E_NOTIMPL。 +| MFCreatePresentationDescriptor | 不存在时,返回E_NOTIMPL。 +| MFCreateSample | 不存在时,返回E_NOTIMPL。 +| MFCreateStreamDescriptor | 不存在时,返回E_NOTIMPL。 +| MFCreateWaveFormatExFromMFMediaType | 不存在时,返回E_NOTIMPL。 +| MFFrameRateToAverageTimePerFrame | 不存在时,返回E_NOTIMPL。 +| MFGetSystemTime | 不存在时,调用GetSystemTimeAsFileTime。 +| MFInitMediaTypeFromWaveFormatEx | 不存在时,返回E_NOTIMPL。 +| MFShutdown | 不存在时,返回E_NOTIMPL。 +| MFStartup | 不存在时,返回E_NOTIMPL。 +| MFTEnumEx | 不存在时,返回E_NOTIMPL。 + +## mfreadwrite.dll +| 函数 | Fallback +| ---- | ----------- +| MFCreateSourceReaderFromMediaSource | 不存在时,返回E_NOTIMPL。 + +## ndfapi.dll +| 函数 | Fallback +| ---- | ----------- +| NdfCreateWebIncident | 不存在时,返回一个伪句柄假装成功。 +| NdfCloseIncident | 不存在时,假装成功关闭句柄。 +| NdfExecuteDiagnosis | 不存在时,假装什么问题也没有发现。 ## netapi32.dll | 函数 | Fallback @@ -538,6 +594,7 @@ | 函数 | Fallback | ---- | ----------- | NtCancelIoFileEx | 不存在时,调用 NtCancelIoFile。注意:将取消此文件的所有IO请求。 +| NtOpenKeyEx | 不存在时,调用 NtOpenKey 或者 NtCreateKey。 ## ole32.dll | 函数 | Fallback @@ -557,6 +614,14 @@ | PowerRegisterSuspendResumeNotification | 不存在时,使用窗口模拟。 | PowerUnregisterSuspendResumeNotification | 内部实现。 +## PropSys.dll +| 函数 | Fallback +| ---- | ----------- +| InitPropVariantFromCLSID | 不存在时,CoTaskMemAlloc分配内存。 +| PSGetPropertyKeyFromName | 不存在时,返回 TYPE_E_ELEMENTNOTFOUND(属性不存在)。 +| PSCreateMemoryPropertyStore | 不存在时,返回 E_NOTIMPL。 +| VariantCompare | 不存在时,内部实现。 + ## psapi.dll | 函数 | Fallback | ---- | ----------- @@ -617,6 +682,7 @@ | UiaGetReservedMixedAttributeValue | 不存在时,报告错误 E_NOTIMPL。 | UiaGetReservedNotSupportedValue | 不存在时,报告错误 E_NOTIMPL。 | UiaRaiseStructureChangedEvent | 不存在时,报告错误 E_NOTIMPL。 +| UiaRaiseNotificationEvent | 不存在时,假装成功。 ## user32.dll | 函数 | Fallback @@ -649,6 +715,11 @@ | DisplayConfigGetDeviceInfo | 不存在时,报告没有安装驱动。 | GetDisplayConfigBufferSizes | 不存在时,报告没有安装驱动。 | QueryDisplayConfig | 不存在时,报告没有安装驱动。 +| RegisterPointerDeviceNotifications | 不存在时,假装成功。 +| GetPointerDevices | 不存在时,假装没有触摸设备。 +| GetPointerDevice | 不存在时,假装没有触摸设备。 +| GetPointerPenInfo | 不存在时,假装没有触摸设备。 +| GetPointerType | 不存在时,假装没有触摸设备。 ## userenv.dll | 函数 | Fallback @@ -689,6 +760,18 @@ | WinHttpGetProxyResult | 不存在时,内部实现。 | WinHttpFreeProxyResult | 不存在时,内部实现。 +## WinUsb.dll +| 函数 | Fallback +| ---- | ----------- +| WinUsb_Free | 不存在时,报告ERROR_INVALID_HANDLE。 +| WinUsb_GetAssociatedInterface | 不存在时,报告ERROR_INVALID_HANDLE。 +| WinUsb_GetOverlappedResult | 不存在时,报告ERROR_INVALID_HANDLE。 +| WinUsb_Initialize | 不存在时,报告ERROR_INVALID_HANDLE。 +| WinUsb_ReadPipe | 不存在时,报告ERROR_INVALID_HANDLE。 +| WinUsb_ResetPipe | 不存在时,报告ERROR_INVALID_HANDLE。 +| WinUsb_SetCurrentAlternateSetting | 不存在时,报告ERROR_INVALID_HANDLE。 +| WinUsb_WritePipe | 不存在时,报告ERROR_INVALID_HANDLE。 + ## ws2_32.dll | 函数 | Fallback | ---- | ----------- diff --git a/src/Build.cmd b/src/Build.cmd index 5e4ec351..c496c596 100644 --- a/src/Build.cmd +++ b/src/Build.cmd @@ -26,7 +26,7 @@ goto:eof :BuildObj echo BuildObj %1 %2 %3 -cl /O1 /Os /Oi /GS- /std:c++17 /arch:IA32 /Z7 /MT /Fo"objs\\%Platform%\\%1" /Zl /c /D "NDEBUG" /D "YY_Thunks_Support_Version=%2" "%~dp0Thunks\YY_Thunks.cpp" +cl /O1 /Os /Oi /GS- /std:c++17 /execution-charset:utf-8 /arch:IA32 /Z7 /MT /Fo"objs\\%Platform%\\%1" /Zl /c /D "NDEBUG" /D "YY_Thunks_Support_Version=%2" "%~dp0Thunks\YY_Thunks.cpp" if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% ::weakţһЩDZŰΪweakԱʧ @@ -52,7 +52,7 @@ echo BuildLib %1 %2 %3 md "Lib\\%1\\%Platform%" -cl /O1 /Os /Oi /GS- /std:c++17 /arch:IA32 /Z7 /MT /Fo"Lib\\%1\\%Platform%\\YY_Thunks_for_%1.obj" /Zl /c /D "NDEBUG" /D "YY_Thunks_Support_Version=%2" /D "__FALLBACK_PREFIX=YY_Thunks_" "%~dp0Thunks\YY_Thunks.cpp" +cl /O1 /Os /Oi /GS- /std:c++17 /execution-charset:utf-8 /arch:IA32 /Z7 /MT /Fo"Lib\\%1\\%Platform%\\YY_Thunks_for_%1.obj" /Zl /c /D "__APPLY_CHROMIUM_WORKAROUNDS" /D "__USING_NTDLL_LIB" /D "NDEBUG" /D "YY_Thunks_Support_Version=%2" /D "__FALLBACK_PREFIX=YY_Thunks_" "%~dp0Thunks\YY_Thunks.cpp" if %ErrorLevel% NEQ 0 exit /b %ErrorLevel% diff --git a/src/Shared/km.h b/src/Shared/km.h index ca3d4080..28b6303e 100644 --- a/src/Shared/km.h +++ b/src/Shared/km.h @@ -106,6 +106,8 @@ #define NtGetCurrentProcess() (HANDLE)-1 +#define NtGetCurrentThread() (HANDLE)-2 + // begin_access #define DUPLICATE_CLOSE_SOURCE 0x00000001 #define DUPLICATE_SAME_ACCESS 0x00000002 @@ -1580,6 +1582,21 @@ NtQueryDirectoryFile ( }; + typedef struct _OBJECT_BASIC_INFORMATION + { + ULONG Attributes; + ACCESS_MASK GrantedAccess; + ULONG HandleCount; + ULONG PointerCount; + ULONG PagedPoolCharge; + ULONG NonPagedPoolCharge; + ULONG Reserved[3]; + ULONG NameInfoSize; + ULONG TypeInfoSize; + ULONG SecurityDescriptorSize; + LARGE_INTEGER CreationTime; + } OBJECT_BASIC_INFORMATION, * POBJECT_BASIC_INFORMATION; + typedef struct _OBJECT_NAME_INFORMATION { UNICODE_STRING Name; @@ -5205,6 +5222,21 @@ typedef struct _KUSER_SHARED_DATA #define KI_USER_SHARED_DATA 0x7ffe0000 const auto SharedUserData = reinterpret_cast(KI_USER_SHARED_DATA); +EXTERN_C NTSYSAPI BOOLEAN NTAPI RtlValidSid(_In_ PSID Sid); + +EXTERN_C NTSYSAPI BOOLEAN NTAPI RtlValidAcl(IN PACL Acl); + +EXTERN_C NTSYSAPI BOOLEAN NTAPI RtlFirstFreeAce( + IN PACL Acl, + OUT PVOID* FirstFree + ); + +EXTERN_C NTSYSAPI NTSTATUS NTAPI RtlCopySid( + IN ULONG DestinationSidLength, + OUT PSID DestinationSid, + IN PSID SourceSid + ); + #pragma warning(pop) #if defined __cplusplus && !defined _Disallow_YY_KM_Namespace } //namespace YY diff --git a/src/Thunks/CfgMgr32.hpp b/src/Thunks/CfgMgr32.hpp new file mode 100644 index 00000000..d240b175 --- /dev/null +++ b/src/Thunks/CfgMgr32.hpp @@ -0,0 +1,417 @@ +#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#include +#include +#endif + +#if (YY_Thunks_Support_Version < NTDDI_WIN7) && !defined(__Comment_Lib_setupapi) +#define __Comment_Lib_setupapi +#pragma comment(lib, "SetupAPI.Lib") +#endif + +#if (YY_Thunks_Support_Version < NTDDI_WIN7) && __YY_Thunks_libs && !defined(__Comment_Lib_cfgmgr32) +#define __Comment_Lib_cfgmgr32 +#pragma comment(lib, "cfgmgr32.Lib") +#endif + +#ifdef YY_Thunks_Implemented +namespace YY::Thunks::Fallback +{ + namespace + { +#if (YY_Thunks_Support_Version < NTDDI_WIN7) + struct DevNodeTempPropertyBufffer + { + wchar_t szId[39]; + DWORD uValue; + + static bool __fastcall HasTransform(DEVPROPTYPE PropertyType) noexcept + { + return PropertyType == DEVPROP_TYPE_BOOLEAN || PropertyType == DEVPROP_TYPE_GUID; + } + + bool __fastcall TryTransformSetBuffer(DEVPROPTYPE PropertyType, _Inout_ PBYTE* _ppPropertyBuffer, _Inout_ ULONG* _pcbPropertyBufferSize) noexcept + { + if (PropertyType == DEVPROP_TYPE_BOOLEAN) + { + if (*_pcbPropertyBufferSize < sizeof(DEVPROP_BOOLEAN)) + { + return false; + } + + uValue = *(DEVPROP_BOOLEAN*)*_ppPropertyBuffer ? 1 : 0; + *_ppPropertyBuffer = PBYTE(&uValue); + *_pcbPropertyBufferSize = sizeof(uValue); + } + else if (PropertyType == DEVPROP_TYPE_GUID) + { + if (*_pcbPropertyBufferSize < sizeof(GUID)) + { + return false; + } + internal::StringBuffer _StringBuild(szId, _countof(szId)); + _StringBuild.AppendChar(L'{'); + _StringBuild.AppendGUID(*(GUID*)*_ppPropertyBuffer); + _StringBuild.AppendChar(L'}'); + + *_ppPropertyBuffer = PBYTE(&szId); + *_pcbPropertyBufferSize = sizeof(szId); + } + + return true; + } + + bool __fastcall TryTransformGetBuffer(DEVPROPTYPE PropertyType, _Out_writes_bytes_to_opt_(*_pcbPropertyBufferSize, *_pcbPropertyBufferSize) PBYTE PropertyBuffer, _Inout_ ULONG* _pcbPropertyBufferSize) noexcept + { + if (DEVPROP_TYPE_BOOLEAN == PropertyType) + { + auto _bRet = true; + if (PropertyBuffer) + { + _bRet = *_pcbPropertyBufferSize >= sizeof(DEVPROP_BOOLEAN); + if (_bRet) + { + *(DEVPROP_BOOLEAN*)PropertyBuffer = uValue ? DEVPROP_TRUE : DEVPROP_FALSE; + } + } + + *_pcbPropertyBufferSize = sizeof(DEVPROP_BOOLEAN); + return _bRet; + } + else if (DEVPROP_TYPE_GUID == PropertyType) + { + auto _bRet = true; + if (PropertyBuffer) + { + _bRet = *_pcbPropertyBufferSize >= sizeof(GUID); + if (_bRet) + { + internal::StringToGuid(szId, (GUID*)PropertyBuffer); + } + } + + *_pcbPropertyBufferSize = sizeof(GUID); + return _bRet; + } + else + { + return true; + } + } + }; + + struct DevicePropertyToDeviceRegistryPropertyItem + { + ULONG CM_DeviceRegistryProperty; + ULONG SP_DeviceRegistryProperty; + DEVPROPTYPE PropertyType; + }; + + static const DevicePropertyToDeviceRegistryPropertyItem* __fastcall DevicePropertyToDeviceRegistryProperty(_In_ const DEVPROPKEY* PropertyKey) noexcept + { + static const GUID s_BaseId = { 0xa45c254e, 0xdf1c, 0x4efd, { 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0 } }; + constexpr auto kBaseIndex = 2; + + static const DevicePropertyToDeviceRegistryPropertyItem s_Map[] = + { + { CM_DRP_DEVICEDESC, SPDRP_DEVICEDESC, DEVPROP_TYPE_STRING }, // 2 DEVPKEY_Device_DeviceDesc + { CM_DRP_HARDWAREID, SPDRP_HARDWAREID, DEVPROP_TYPE_STRING_LIST }, // 3 DEVPKEY_Device_HardwareIds + { CM_DRP_COMPATIBLEIDS, SPDRP_COMPATIBLEIDS, DEVPROP_TYPE_STRING_LIST }, // 4 DEVPKEY_Device_CompatibleIds + {}, //5 + { CM_DRP_SERVICE, SPDRP_SERVICE, DEVPROP_TYPE_STRING }, // 6 DEVPKEY_Device_Service + {}, // 7 + {}, // 8 + { CM_DRP_CLASS, SPDRP_CLASS, DEVPROP_TYPE_STRING }, // 9 DEVPKEY_Device_Class + { CM_DRP_CLASSGUID, SPDRP_CLASSGUID, DEVPROP_TYPE_GUID }, // 10 DEVPKEY_Device_ClassGuid + { CM_DRP_DRIVER, SPDRP_DRIVER, DEVPROP_TYPE_STRING }, // 11 DEVPKEY_Device_Driver + { CM_DRP_CONFIGFLAGS, SPDRP_CONFIGFLAGS, DEVPROP_TYPE_UINT32 }, // 12 DEVPKEY_Device_ConfigFlags + { CM_DRP_MFG, SPDRP_MFG, DEVPROP_TYPE_STRING }, // 13 DEVPKEY_Device_Manufacturer + { CM_DRP_FRIENDLYNAME, SPDRP_FRIENDLYNAME, DEVPROP_TYPE_STRING }, // 14 DEVPKEY_Device_FriendlyName + { CM_DRP_LOCATION_INFORMATION, SPDRP_LOCATION_INFORMATION, DEVPROP_TYPE_STRING }, // 15 DEVPKEY_Device_LocationInfo + { CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME, SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, DEVPROP_TYPE_STRING }, // 16 DEVPKEY_Device_PDOName + { CM_DRP_CAPABILITIES, SPDRP_CAPABILITIES, DEVPROP_TYPE_UINT32 }, // 17 DEVPKEY_Device_Capabilities + { CM_DRP_UI_NUMBER, SPDRP_UI_NUMBER, DEVPROP_TYPE_UINT32 }, // 18 DEVPKEY_Device_UINumber + { CM_DRP_UPPERFILTERS, SPDRP_UPPERFILTERS, DEVPROP_TYPE_STRING_LIST }, // 19 DEVPKEY_Device_UpperFilters + { CM_DRP_LOWERFILTERS, SPDRP_LOWERFILTERS, DEVPROP_TYPE_STRING_LIST }, // 20 DEVPKEY_Device_LowerFilters + { CM_DRP_BUSTYPEGUID, SPDRP_BUSTYPEGUID, DEVPROP_TYPE_GUID }, // 21 DEVPKEY_Device_BusTypeGuid + { CM_DRP_LEGACYBUSTYPE, SPDRP_LEGACYBUSTYPE, DEVPROP_TYPE_UINT32 }, // 22 DEVPKEY_Device_LegacyBusType + { CM_DRP_BUSNUMBER, SPDRP_BUSNUMBER, DEVPROP_TYPE_UINT32 }, // 23 DEVPKEY_Device_BusNumber + { CM_DRP_ENUMERATOR_NAME, SPDRP_ENUMERATOR_NAME, DEVPROP_TYPE_STRING }, // 24 DEVPKEY_Device_EnumeratorName + { CM_DRP_SECURITY, SPDRP_SECURITY, DEVPROP_TYPE_SECURITY_DESCRIPTOR }, // 25 DEVPKEY_Device_Security + { CM_DRP_SECURITY_SDS, SPDRP_SECURITY_SDS, DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING }, // 26 DEVPKEY_Device_SecuritySDS + { CM_DRP_DEVTYPE, SPDRP_DEVTYPE, DEVPROP_TYPE_UINT32 }, // 27 DEVPKEY_Device_DevType + { CM_DRP_EXCLUSIVE, SPDRP_EXCLUSIVE, DEVPROP_TYPE_BOOLEAN }, // 28 DEVPKEY_Device_Exclusive + { CM_DRP_CHARACTERISTICS, SPDRP_CHARACTERISTICS, DEVPROP_TYPE_UINT32 }, // 29 DEVPKEY_Device_Characteristics + { CM_DRP_ADDRESS, SPDRP_ADDRESS, DEVPROP_TYPE_UINT32 }, // 30 DEVPKEY_Device_Address + { CM_DRP_UI_NUMBER_DESC_FORMAT, SPDRP_UI_NUMBER_DESC_FORMAT, DEVPROP_TYPE_STRING }, // 31 DEVPKEY_Device_UINumberDescFormat + { CM_DRP_DEVICE_POWER_DATA, SPDRP_DEVICE_POWER_DATA, DEVPROP_TYPE_BINARY }, // 32 DEVPKEY_Device_PowerData + { CM_DRP_REMOVAL_POLICY, SPDRP_REMOVAL_POLICY, DEVPROP_TYPE_UINT32 }, // 33 DEVPKEY_Device_RemovalPolicy + { CM_DRP_REMOVAL_POLICY_HW_DEFAULT, SPDRP_REMOVAL_POLICY_HW_DEFAULT, DEVPROP_TYPE_UINT32 }, // 34 DEVPKEY_Device_RemovalPolicyDefault + { CM_DRP_REMOVAL_POLICY_OVERRIDE, SPDRP_REMOVAL_POLICY_OVERRIDE, DEVPROP_TYPE_UINT32 }, // 35 DEVPKEY_Device_RemovalPolicyOverride + { CM_DRP_INSTALL_STATE, SPDRP_INSTALL_STATE, DEVPROP_TYPE_UINT32 }, // 36 DEVPKEY_Device_InstallState + { CM_DRP_LOCATION_PATHS, SPDRP_LOCATION_PATHS, DEVPROP_TYPE_STRING_LIST }, // 37 DEVPKEY_Device_LocationPaths + // { CM_DRP_BASE_CONTAINERID, SPDRP_BASE_CONTAINERID, DEVPROP_TYPE_GUID }, // 38 DEVPKEY_Device_BaseContainerId Windows 7才支持 + }; + + if (PropertyKey == nullptr || PropertyKey->pid < kBaseIndex || PropertyKey->pid >= (kBaseIndex + _countof(s_Map)) || IsEqualGUID(PropertyKey->fmtid, s_BaseId) == false) + return nullptr; + + auto& _Item = s_Map[PropertyKey->pid]; + if (_Item.PropertyType == DEVPROP_TYPE_EMPTY) + return nullptr; + + return &_Item; + } + + struct ClassPropertyToClassRegistryPropertyItem + { + ULONG CM_ClassRegistryProperty; + ULONG SP_ClassRegistryProperty; + DEVPROPTYPE PropertyType; + }; + + static const ClassPropertyToClassRegistryPropertyItem* __fastcall ClassPropertyToClassRegistryProperty(_In_ const DEVPROPKEY* PropertyKey) noexcept + { + static const GUID s_BaseId = { 0x4321918b, 0xf69e, 0x470d, { 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b } }; + constexpr auto kBaseIndex = 19; + + static const ClassPropertyToClassRegistryPropertyItem s_Map[] = + { + { CM_CRP_UPPERFILTERS, SPCRP_UPPERFILTERS, DEVPROP_TYPE_STRING_LIST }, // 19 DEVPKEY_DeviceClass_UpperFilters Vista开始才支持 + { CM_CRP_LOWERFILTERS, SPCRP_LOWERFILTERS, DEVPROP_TYPE_STRING_LIST }, // 20 DEVPKEY_DeviceClass_LowerFilters Vista开始才支持 + {}, // 21 + {}, // 22 + {}, // 23 + {}, // 24 + { CM_CRP_SECURITY, SPCRP_SECURITY, DEVPROP_TYPE_SECURITY_DESCRIPTOR }, // 25 DEVPKEY_DeviceClass_Security + { CM_CRP_SECURITY_SDS, SPCRP_SECURITY_SDS, DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING }, // 26 DEVPKEY_DeviceClass_SecuritySDS + { CM_CRP_DEVTYPE, SPCRP_DEVTYPE, DEVPROP_TYPE_UINT32 }, // 27 DEVPKEY_DeviceClass_DevType + { CM_CRP_EXCLUSIVE, SPCRP_EXCLUSIVE, DEVPROP_TYPE_BOOLEAN }, // 28 DEVPKEY_DeviceClass_Exclusive + { CM_CRP_CHARACTERISTICS, SPCRP_CHARACTERISTICS, DEVPROP_TYPE_UINT32 }, // 29 DEVPKEY_DeviceClass_Characteristics + }; + + if (PropertyKey == nullptr || PropertyKey->pid < kBaseIndex || PropertyKey->pid >= (kBaseIndex + _countof(s_Map)) || IsEqualGUID(PropertyKey->fmtid, s_BaseId) == false) + return nullptr; + + auto& _Item = s_Map[PropertyKey->pid]; + if (_Item.PropertyType == DEVPROP_TYPE_EMPTY) + return nullptr; + + return &_Item; + } + + void* __fastcall try_get_CM_Get_DevNode_Property_ExW(const ProcInfo& _ProcInfo) + { + auto _pProc = try_get_proc_address_from_dll(_ProcInfo); + if (_pProc) + return _pProc; + + static constexpr const ProcOffsetInfo kProcInfo[] = + { +#if defined(_X86_) + { 0x4549BDB0ul, 0x7427B681ul - 0x74270000ul }, // 6.0.6000.16386 (Windows Vista RTM) + { 0x4791A754ul, 0x738DB93Dul - 0x738D0000ul }, // 6.0.6002.18000 (Windows Vista SP1) + { 0x49E037E9ul, 0x744DED36ul - 0x744D0000ul }, // 6.0.6002.18005 (Windows Vista SP2) +#elif defined(_AMD64_) + { 0x4549D318ul, 0x000007FF7C006400ull - 0x7FF7C000000ull }, // 6.0.6000.16386 (Windows Vista RTM) + { 0x4791ADA3ul, 0x000007FF7BC06E00ull - 0x7FF7BC00000ull }, // 6.0.6002.18000 (Windows Vista SP1) + { 0x49E041EDul, 0x000007FF7C007090ull - 0x7FF7C000000ull }, // 6.0.6002.18005 (Windows Vista SP2) +#endif + }; + + __WarningMessage__("try_get_CM_Get_DevNode_Property_ExW 可能遗漏Vista/2008某些补丁中的setupapi.dll,如果你知道详细可以提交PR。"); + return try_get_proc_address_from_offset(try_get_module_setupapi(), kProcInfo); + } + + void* __fastcall try_get_CM_Set_DevNode_Property_ExW(const ProcInfo& _ProcInfo) + { + auto _pProc = try_get_proc_address_from_dll(_ProcInfo); + if (_pProc) + return _pProc; + + static constexpr const ProcOffsetInfo kProcInfo[] = + { +#if defined(_X86_) + { 0x4549BDB0ul, 0x7433C705ul - 0x74270000ul }, // 6.0.6000.16386 (Windows Vista RTM) + { 0x4791A754ul, 0x7399D7ADul - 0x738D0000ul }, // 6.0.6002.18000 (Windows Vista SP1) + { 0x49E037E9ul, 0x7459DC1Dul - 0x744D0000ul }, // 6.0.6002.18005 (Windows Vista SP2) +#elif defined(_AMD64_) + { 0x4549D318ul, 0x000007FF7C0FDD70ull - 0x7FF7C000000ull }, // 6.0.6000.16386 (Windows Vista RTM) + { 0x4791ADA3ul, 0x000007FF7BCE1E08ull - 0x7FF7BC00000ull }, // 6.0.6002.18000 (Windows Vista SP1) + { 0x49E041EDul, 0x000007FF7C0E2550ull - 0x7FF7C000000ull }, // 6.0.6002.18005 (Windows Vista SP2) +#endif + }; + + __WarningMessage__("try_get_CM_Set_DevNode_Property_ExW 可能遗漏Vista/2008某些补丁中的setupapi.dll,如果你知道详细可以提交PR。"); + return try_get_proc_address_from_offset(try_get_module_setupapi(), kProcInfo); + } +#endif + } +} +#endif + +namespace YY::Thunks +{ +#if (YY_Thunks_Support_Version < NTDDI_WIN7) + + // Windows 7 RTM 导出 + // Windows Vista有这个函数但是没有导出 + __DEFINE_THUNK( + cfgmgr32, + 28, + CONFIGRET, + WINAPI, + CM_Get_DevNode_Property_ExW, + _In_ DEVINST dnDevInst, + _In_ CONST DEVPROPKEY* PropertyKey, + _Out_ DEVPROPTYPE* PropertyType, + _Out_writes_bytes_opt_(*PropertyBufferSize) PBYTE PropertyBuffer, + _Inout_ PULONG PropertyBufferSize, + _In_ ULONG ulFlags, + _In_opt_ HMACHINE hMachine + ) + { + if (const auto _pfnCM_Get_DevNode_Property_ExW = try_get_CM_Get_DevNode_Property_ExW()) + { + return _pfnCM_Get_DevNode_Property_ExW(dnDevInst, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, ulFlags, hMachine); + } + + if (!PropertyKey) + return CR_INVALID_DEVINST; + + if (PropertyKey == nullptr || PropertyType == nullptr || PropertyBufferSize == nullptr) + return CR_INVALID_POINTER; + + if (ulFlags != 0) + return CR_INVALID_FLAG; + + const auto _pProperty = Fallback::DevicePropertyToDeviceRegistryProperty(PropertyKey); + if (!_pProperty) + return CR_INVALID_PROPERTY; + + *PropertyType = _pProperty->PropertyType; + + if (!Fallback::DevNodeTempPropertyBufffer::HasTransform(_pProperty->PropertyType)) + { + return CM_Get_DevNode_Registry_Property_ExW(dnDevInst, _pProperty->CM_DeviceRegistryProperty, nullptr, PropertyBuffer, PropertyBufferSize, ulFlags, hMachine); + } + + Fallback::DevNodeTempPropertyBufffer TempBuffer = {}; + ULONG _cbTempBuffer = sizeof(TempBuffer); + auto _Error = CM_Get_DevNode_Registry_Property_ExW(dnDevInst, _pProperty->CM_DeviceRegistryProperty, nullptr, &TempBuffer, &_cbTempBuffer, ulFlags, hMachine); + if (CR_SUCCESS != _Error) + { + return _Error; + } + + if (!TempBuffer.TryTransformGetBuffer(_pProperty->PropertyType, PropertyBuffer, PropertyBufferSize)) + return CR_BUFFER_SMALL; + + return CR_SUCCESS; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN7) + + // Windows 7 RTM 导出 + // Windows Vista有这个函数但是没有导出 + __DEFINE_THUNK( + cfgmgr32, + 28, + CONFIGRET, + WINAPI, + CM_Set_DevNode_Property_ExW, + _In_ DEVINST dnDevInst, + _In_ CONST DEVPROPKEY* PropertyKey, + _In_ DEVPROPTYPE PropertyType, + _In_reads_bytes_opt_(PropertyBufferSize) PBYTE PropertyBuffer, + _In_ ULONG PropertyBufferSize, + _In_ ULONG ulFlags, + _In_opt_ HMACHINE hMachine + ) + { + if (const auto _pfnCM_Set_DevNode_Property_ExW = try_get_CM_Set_DevNode_Property_ExW()) + { + return _pfnCM_Set_DevNode_Property_ExW(dnDevInst, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, ulFlags, hMachine); + } + + if (!PropertyKey) + return CR_INVALID_DEVINST; + + if (PropertyKey == nullptr || (PropertyBuffer == nullptr && PropertyBufferSize)) + return CR_INVALID_POINTER; + + if (ulFlags != 0) + return CR_INVALID_FLAG; + + const auto _pProperty = Fallback::DevicePropertyToDeviceRegistryProperty(PropertyKey); + if (!_pProperty) + return CR_INVALID_PROPERTY; + + if (_pProperty->PropertyType != PropertyType) + return CR_WRONG_TYPE; + + Fallback::DevNodeTempPropertyBufffer TempBuffer; + if (!TempBuffer.TryTransformSetBuffer(PropertyType, &PropertyBuffer, &PropertyBufferSize)) + return CR_BUFFER_SMALL; + + return CM_Set_DevNode_Registry_Property_ExW(dnDevInst, _pProperty->CM_DeviceRegistryProperty, PropertyBuffer, PropertyBufferSize, ulFlags, hMachine); + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN7) + + // 最低受支持的客户端 在 Microsoft Windows Vista 和更高版本的 Windows 中可用。 + // 实际Windows Vista RTM根本就没有这个接口 + __DEFINE_THUNK( + cfgmgr32, + 24, + CONFIGRET, + WINAPI, + CM_Get_DevNode_PropertyW, + _In_ DEVINST dnDevInst, + _In_ CONST DEVPROPKEY* PropertyKey, + _Out_ DEVPROPTYPE* PropertyType, + _Out_writes_bytes_opt_(*PropertyBufferSize) PBYTE PropertyBuffer, + _Inout_ PULONG PropertyBufferSize, + _In_ ULONG ulFlags + ) + { + if (const auto _pfnCM_Get_DevNode_PropertyW = try_get_CM_Get_DevNode_PropertyW()) + { + return _pfnCM_Get_DevNode_PropertyW(dnDevInst, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, ulFlags); + } + + return ::CM_Get_DevNode_Property_ExW(dnDevInst, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, ulFlags, nullptr); + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN7) + + // 最低受支持的客户端 在 Microsoft Windows Vista 和更高版本的 Windows 中可用。 + // 实际Windows Vista RTM根本就没有这个接口 + __DEFINE_THUNK( + cfgmgr32, + 24, + CONFIGRET, + WINAPI, + CM_Set_DevNode_PropertyW, + _In_ DEVINST dnDevInst, + _In_ CONST DEVPROPKEY *PropertyKey, + _In_ DEVPROPTYPE PropertyType, + _In_reads_bytes_opt_(PropertyBufferSize) PBYTE PropertyBuffer, + _In_ ULONG PropertyBufferSize, + _In_ ULONG ulFlags + ) + { + if (const auto _pfnCM_Set_DevNode_PropertyW = try_get_CM_Set_DevNode_PropertyW()) + { + return _pfnCM_Set_DevNode_PropertyW(dnDevInst, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, ulFlags); + } + + return ::CM_Set_DevNode_Property_ExW(dnDevInst, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, ulFlags, nullptr); + } +#endif +} diff --git a/src/Thunks/DllMainCRTStartup.hpp b/src/Thunks/DllMainCRTStartup.hpp index f543f3cb..235e51bb 100644 --- a/src/Thunks/DllMainCRTStartup.hpp +++ b/src/Thunks/DllMainCRTStartup.hpp @@ -64,7 +64,7 @@ namespace YY::Thunks::internal static volatile LONG uStatus = 0; static TlsRawItem* volatile pRoot = nullptr; - static ULONG __fastcall GetTlsIndexBufferCount(TEB* _pTeb) + static SIZE_T __fastcall GetTlsIndexBufferCount(TEB* _pTeb) { auto _ppThreadLocalStoragePointer = (void**)_pTeb->ThreadLocalStoragePointer; if (!_ppThreadLocalStoragePointer) @@ -72,22 +72,6 @@ namespace YY::Thunks::internal return HeapSize(_pTeb->ProcessEnvironmentBlock->ProcessHeap, 0, _ppThreadLocalStoragePointer) / sizeof(void*); } - static PVOID NTAPI RtlImageDirectoryEntryToData( - __in PVOID pBaseAddress, - __in ULONG dwDirectory, - __out PULONG pSize - ) - { - auto _pDosHeader = (PIMAGE_DOS_HEADER)pBaseAddress; - auto _pNtHerder = reinterpret_cast(PBYTE(pBaseAddress) + _pDosHeader->e_lfanew); - auto& _DataDirectory = _pNtHerder->OptionalHeader.DataDirectory[dwDirectory]; - - *pSize = _DataDirectory.Size; - if (_DataDirectory.Size == 0 || _DataDirectory.VirtualAddress == 0) - return nullptr; - - return PBYTE(pBaseAddress) + _DataDirectory.VirtualAddress; - } static ULONG __fastcall GetMaxTlsIndex() noexcept { @@ -106,7 +90,7 @@ namespace YY::Thunks::internal /*if (!_pEntry->TlsIndex) continue;*/ ULONG TlsSize; - auto pTlsImage = (PIMAGE_TLS_DIRECTORY)RtlImageDirectoryEntryToData( + auto pTlsImage = (PIMAGE_TLS_DIRECTORY)YY_ImageDirectoryEntryToData( _pEntry->BaseAddress, IMAGE_DIRECTORY_ENTRY_TLS, &TlsSize); @@ -135,7 +119,7 @@ namespace YY::Thunks::internal if (!_pfnNtQuerySystemInformation) return nullptr; - ULONG _cbBuffer = max(4096, _szBuffer.uBufferLength); + auto _cbBuffer = max(4096, _szBuffer.uBufferLength); ULONG _cbRet = 0; for (;;) { @@ -157,7 +141,7 @@ namespace YY::Thunks::internal auto _pInfo = (SYSTEM_PROCESS_INFORMATION*)_szBuffer.GetBuffer(0); for (;;) { - if (_pInfo->ProcessId == (HANDLE)_uCurrentProcessId) + if (static_cast(reinterpret_cast(_pInfo->ProcessId)) == _uCurrentProcessId) return _pInfo; if (_pInfo->NextEntryDelta == 0) @@ -316,10 +300,10 @@ namespace YY::Thunks::internal { auto& _Thread = _pProcessInfo->Threads[i]; - if (_uCurrentThreadId == (DWORD)_Thread.ClientId.UniqueThread) + if (_uCurrentThreadId == static_cast(reinterpret_cast(_Thread.ClientId.UniqueThread))) continue; - auto _hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, (DWORD)_Thread.ClientId.UniqueThread); + auto _hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, static_cast(reinterpret_cast(_Thread.ClientId.UniqueThread))); if (!_hThread) { continue; diff --git a/src/Thunks/PropSys.hpp b/src/Thunks/PropSys.hpp new file mode 100644 index 00000000..5e5fe090 --- /dev/null +++ b/src/Thunks/PropSys.hpp @@ -0,0 +1,508 @@ +#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#include +#endif + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) && !defined(__Comment_Lib_oleaut32) +#define __Comment_Lib_oleaut32 +// SafeArrayGetElement、SafeArrayGetLBound、SafeArrayGetUBound、VariantClear、VarCmp +#pragma comment(lib, "OleAut32.lib") +#endif + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) && !defined(__Comment_Lib_ole32) +#define __Comment_Lib_ole32 +// CoTaskMemAlloc +#pragma comment(lib, "ole32.lib") +#endif + +#ifdef YY_Thunks_Implemented +namespace YY::Thunks::internal +{ + namespace + { +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + static HRESULT __fastcall SafeArrayGetCount(SAFEARRAY* _pArray, LONG* _pnLbound) + { + *_pnLbound = 0; + if (SafeArrayGetDim(_pArray) != 1) + return 0x80028CA0; + + LONG _nLBound = 0; + auto _hr = SafeArrayGetLBound(_pArray, 1u, &_nLBound); + if (FAILED(_hr)) + return _hr; + + LONG _nUBound = 0; + _hr = SafeArrayGetUBound(_pArray, 1u, &_nUBound); + if (FAILED(_hr)) + return _hr; + + if (_nUBound >= _nLBound) + *_pnLbound = _nUBound - _nLBound + 1; + + return S_OK; + } + + static constexpr DWORD __fastcall MakeVarTypePair(VARTYPE _eLeft, VARTYPE _eRigth) + { + return (DWORD(UINT16(_eRigth)) << 16) | UINT16(_eLeft); + } + + struct FastValue + { + union + { + ULONGLONG ullVal; + LONGLONG llVal; + DOUBLE dblVal; + }; + + VARTYPE vt; + }; + + static FastValue TryGetFastValue(const VARIANT& _Value) + { + FastValue _Resutl = {}; + switch (_Value.vt) + { + case VT_UI1: + _Resutl.vt = VT_UI8; + _Resutl.ullVal = _Value.bVal; + break; + case VT_UI2: + _Resutl.vt = VT_UI8; + _Resutl.ullVal = _Value.uiVal; + break; + case VT_UI4: + _Resutl.vt = VT_UI8; + _Resutl.ullVal = _Value.ulVal; + break; + case VT_UI8: + _Resutl.vt = VT_UI8; + _Resutl.ullVal = _Value.ulVal; + break; + case VT_UINT: + _Resutl.vt = VT_UI8; + _Resutl.ullVal = _Value.uintVal; + break; + case VT_I1: + _Resutl.vt = VT_I8; + _Resutl.llVal = _Value.cVal; + break; + case VT_I2: + _Resutl.vt = VT_I8; + _Resutl.llVal = _Value.iVal; + break; + case VT_I4: + _Resutl.vt = VT_I8; + _Resutl.llVal = _Value.lVal; + break; + case VT_I8: + _Resutl.vt = VT_I8; + _Resutl.llVal = _Value.lVal; + break; + case VT_INT: + _Resutl.vt = VT_I8; + _Resutl.llVal = _Value.intVal; + break; + case VT_R4: + _Resutl.vt = VT_R8; + _Resutl.dblVal = _Value.fltVal; + break; + case VT_R8: + _Resutl.vt = VT_R8; + _Resutl.dblVal = _Value.dblVal; + break; + } + + return _Resutl; + } + + static int CompareFastValue(const FastValue& _Left, const FastValue& _Rigth) + { + // 虽然这里有比较浮点,但是微软原版就是直接==比较浮点 + // 我们也不引入浮点误差。 + if (_Left.vt == VT_UI8) + { + switch (_Rigth.vt) + { + case VT_I8: + if (_Rigth.llVal < 0ll) + return 1; + case VT_UI8: + if (_Left.ullVal < _Rigth.ullVal) + { + return -1; + } + else if (_Left.ullVal > _Rigth.ullVal) + { + return 1; + } + else + { + return 0; + } + break; + case VT_R8: + if (_Rigth.dblVal < 0.0) + { + return 1; + } + else + { + auto _uTmp = ULONG64(_Rigth.dblVal); + if (_Left.ullVal < _uTmp) + { + return -1; + } + else if (_Left.ullVal > _uTmp) + { + return 1; + } + else + { + return double(_Left.ullVal) == _Rigth.dblVal ? 0 : -1; + } + } + break; + } + } + else if (_Left.vt == VT_I8) + { + switch (_Rigth.vt) + { + case VT_I8: + if (_Left.llVal < _Rigth.llVal) + { + return -1; + } + else if (_Left.llVal > _Rigth.llVal) + { + return 1; + } + else + { + return 0; + } + break; + case VT_UI8: + if (_Left.llVal < 0) + return -1; + + if (_Left.ullVal < _Rigth.ullVal) + { + return -1; + } + else if (_Left.ullVal > _Rigth.ullVal) + { + return 1; + } + else + { + return 0; + } + break; + case VT_R8: + { + auto _uTmp = LONG64(_Rigth.dblVal); + if (_Left.llVal < _uTmp) + { + return -1; + } + else if (_Left.llVal > _uTmp) + { + return 1; + } + else + { + return double(_Left.llVal) == _Rigth.dblVal ? 0 : -1; + } + break; + } + } + } + else if (_Left.vt == VT_R8) + { + switch (_Rigth.vt) + { + case VT_I8: + { + LONG64 _Tmp = LONG64(_Left.dblVal); + if (_Tmp < _Rigth.llVal) + { + return -1; + } + else if (_Tmp > _Rigth.llVal) + { + return 1; + } + else + { + return _Left.dblVal == double(_Rigth.llVal) ? 0 : 1; + } + break; + } + case VT_UI8: + if (_Left.dblVal < 0.0) + { + return -1; + } + else + { + ULONG64 _Tmp = LONG64(_Left.dblVal); + if (_Tmp < _Rigth.ullVal) + { + return -1; + } + else if (_Tmp > _Rigth.ullVal) + { + return 1; + } + else + { + return _Left.dblVal == double(_Rigth.ullVal) ? 0 : 1; + } + } + break; + case VT_R8: + if (_Left.dblVal < _Rigth.dblVal) + { + return -1; + } + else if (_Left.dblVal > _Rigth.dblVal) + { + return 1; + } + else + { + return 0; + } + break; + } + } + + return 0; + } +#endif + } +} +#endif + +namespace YY::Thunks +{ +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // 最低受支持的客户端 Windows XP SP2、Windows Vista [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2003 SP1[仅限桌面应用] + // XP、2003需要安装Windows 桌面搜索 (WDS) 3.0 + __DEFINE_THUNK( + propsys, + 8, + HRESULT, + STDAPICALLTYPE, + InitPropVariantFromCLSID, + _In_ REFCLSID _ClsId, + _Out_ PROPVARIANT* _pPropVar + ) + { + if (const auto _pfnInitPropVariantFromCLSID = try_get_InitPropVariantFromCLSID()) + { + return _pfnInitPropVariantFromCLSID(_ClsId, _pPropVar); + } + + _pPropVar->vt = VT_EMPTY; + auto _pId = (GUID*)CoTaskMemAlloc(sizeof(_ClsId)); + if (!_pId) + return E_OUTOFMEMORY; + + *_pId = _ClsId; + _pPropVar->vt = VT_CLSID; + _pPropVar->puuid = _pId; + return S_OK; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // 最低受支持的客户端 Windows XP SP2、Windows Vista [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2003 SP1[仅限桌面应用] + // XP、2003需要安装Windows 桌面搜索 (WDS) 3.0 + __DEFINE_THUNK( + propsys, + 8, + HRESULT, + STDAPICALLTYPE, + PSGetPropertyKeyFromName, + _In_ PCWSTR _szName, + _Out_ PROPERTYKEY* _pPropKey + ) + { + if (const auto _pfnPSGetPropertyKeyFromName = try_get_PSGetPropertyKeyFromName()) + { + return _pfnPSGetPropertyKeyFromName(_szName, _pPropKey); + } + + if (_szName == nullptr) + return E_INVALIDARG; + + return TYPE_E_ELEMENTNOTFOUND; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // 最低受支持的客户端 Windows XP SP2、Windows Vista [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2003 SP1[仅限桌面应用] + // XP、2003需要安装Windows 桌面搜索 (WDS) 3.0 + __DEFINE_THUNK( + propsys, + 8, + HRESULT, + STDAPICALLTYPE, + PSCreateMemoryPropertyStore, + _In_ REFIID riid, + _Outptr_ void** ppv + ) + { + if (const auto _pfnPSCreateMemoryPropertyStore = try_get_PSCreateMemoryPropertyStore()) + { + return _pfnPSCreateMemoryPropertyStore(riid, ppv); + } + + if (!ppv) + return E_POINTER; + *ppv = nullptr; + return E_NOTIMPL; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // 最低受支持的客户端 Windows XP SP2、Windows Vista [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2003 SP1[仅限桌面应用] + // XP、2003需要安装Windows 桌面搜索 (WDS) 3.0 + __DEFINE_THUNK( + propsys, + 8, + int, + WINAPI, + VariantCompare, + _In_ REFVARIANT _Left, + _In_ REFVARIANT _Rigth + ) + { + if (const auto _pfnVariantCompare = try_get_VariantCompare()) + { + return _pfnVariantCompare(_Left, _Rigth); + } + + // VT_EMPTY VT_NULL小于任何类型 + if (_Left.vt == VT_EMPTY || _Left.vt == VT_NULL) + { + if (_Rigth.vt == VT_EMPTY || _Rigth.vt == VT_NULL) + return 0; + + return -1; + } + else + { + if (_Rigth.vt == VT_EMPTY || _Rigth.vt == VT_NULL) + return 1; + } + + if ((_Left.vt & VT_ARRAY) && (_Rigth.vt & VT_ARRAY)) + { + LONG _nLeftCount; + internal::SafeArrayGetCount(_Left.parray, &_nLeftCount); + LONG _nRigthCount; + internal::SafeArrayGetCount(_Rigth.parray, &_nRigthCount); + + const auto _nCount = min(_nLeftCount, _nRigthCount); + for (LONG i = 0; i != _nCount; ++i) + { + VARIANT _LeftItem = {}; + if (FAILED(SafeArrayGetElement(_Left.parray, &i, &_LeftItem))) + continue; + + VARIANT _RightItem = {}; + int _nResult = 0; + if (SUCCEEDED(SafeArrayGetElement(_Rigth.parray, &i, &_RightItem))) + { + _nResult = _CRT_CONCATENATE(__FALLBACK_PREFIX, VariantCompare)(_LeftItem, _RightItem); + VariantClear(&_RightItem); + } + VariantClear(&_LeftItem); + if (_nResult) + return _nResult; + } + + if (_nLeftCount < _nRigthCount) + { + return -1; + } + else if (_nLeftCount > _nRigthCount) + { + return 1; + } + else + { + return 0; + } + } + + switch (internal::MakeVarTypePair(_Left.vt, _Rigth.vt)) + { + // BOOL + case internal::MakeVarTypePair(VT_BOOL, VT_BOOL): + if (_Left.boolVal) + { + return _Rigth.boolVal ? 0 : 1; + } + else + { + return _Rigth.boolVal ? -1 : 0; + } + // 字符串 + case internal::MakeVarTypePair(VT_BSTR, VT_BSTR): + return StrCmpLogicalW(_Left.bstrVal ? _Left.bstrVal : L"", _Rigth.bstrVal ? _Rigth.bstrVal : L""); + case internal::MakeVarTypePair(VT_ERROR, VT_ERROR): + return _Left.scode - _Rigth.scode; + case internal::MakeVarTypePair(VT_DATE, VT_DATE): + if (_Left.date < _Rigth.date) + { + return -1; + } + else if (_Left.date > _Rigth.date) + { + return 1; + } + else + { + return 0; + } + //case internal::MakeVarTypePair(VT_CY, VT_CY): VarCmp完成 + default: + { + auto _LeftValue = internal::TryGetFastValue(_Left); + if (_LeftValue.vt != VT_EMPTY) + { + auto _RightValue = internal::TryGetFastValue(_Rigth); + if (_RightValue.vt != VT_EMPTY) + { + return internal::CompareFastValue(_LeftValue, _RightValue); + } + } + + // 微软的保底逻辑 + const auto _hr = VarCmp(const_cast(&_Left), const_cast(&_Rigth), GetUserDefaultLCID(), 0); + if (SUCCEEDED(_hr)) + return _hr - VARCMP_EQ; + + return 0; + } + } + } +#endif +} diff --git a/src/Thunks/SetupAPI.hpp b/src/Thunks/SetupAPI.hpp index bac0f490..77827c18 100644 --- a/src/Thunks/SetupAPI.hpp +++ b/src/Thunks/SetupAPI.hpp @@ -7,111 +7,6 @@ #pragma comment(lib, "Setupapi.lib") #endif -#ifdef YY_Thunks_Implemented -namespace YY::Thunks::internal -{ - namespace - { -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - static int __fastcall DevicePropertyKeyToPropertyType(CONST DEVPROPKEY* PropertyKey, _Out_ DEVPROPTYPE* pPropertyType) - { - static constexpr const GUID PropertyId = { 0xa45c254e, 0xdf1c, 0x4efd, { 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0 } }; - - constexpr int IndexStart = 2; - - static constexpr const DEVPROPTYPE PropertyIdTypeIndex[] = - { - DEVPROP_TYPE_STRING, //2 - DEVPROP_TYPE_STRING_LIST, //3 - DEVPROP_TYPE_STRING_LIST, //4 - -1, //5 - DEVPROP_TYPE_STRING, //6 - -1, //7 - -1, //8 - DEVPROP_TYPE_STRING, //9 - DEVPROP_TYPE_GUID, //10 - DEVPROP_TYPE_STRING, //11 - DEVPROP_TYPE_UINT32, //12 - DEVPROP_TYPE_STRING, //13 - DEVPROP_TYPE_STRING, //14 - DEVPROP_TYPE_STRING, //15 - DEVPROP_TYPE_STRING, //16 - DEVPROP_TYPE_UINT32, //17 - DEVPROP_TYPE_UINT32, //18 - DEVPROP_TYPE_STRING_LIST, //19, - DEVPROP_TYPE_STRING_LIST, //20 - DEVPROP_TYPE_GUID, //21 - DEVPROP_TYPE_UINT32, //22 - DEVPROP_TYPE_UINT32, //23 - DEVPROP_TYPE_STRING, //24 - DEVPROP_TYPE_SECURITY_DESCRIPTOR, //25 - DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING, //26 - DEVPROP_TYPE_UINT32, //27 - DEVPROP_TYPE_BOOLEAN, //28 - DEVPROP_TYPE_UINT32, //29 - DEVPROP_TYPE_UINT32, //30 - DEVPROP_TYPE_STRING, //31 - DEVPROP_TYPE_BINARY, //32 - DEVPROP_TYPE_UINT32, //33 - DEVPROP_TYPE_UINT32, //34 - DEVPROP_TYPE_UINT32, //35 - DEVPROP_TYPE_UINT32, //36 - DEVPROP_TYPE_STRING_LIST, //37 - DEVPROP_TYPE_GUID, //38 - }; - - if ( memcmp(&PropertyKey->fmtid, &PropertyId, sizeof(PropertyId)) != 0 - || PropertyKey->pid < IndexStart || PropertyKey->pid >= _countof(PropertyIdTypeIndex) + IndexStart) - { - return -1; - } - - const auto Property = PropertyKey->pid - IndexStart; - auto PropertyType = PropertyIdTypeIndex[Property]; - - if (PropertyType == -1) - return -1; - - *pPropertyType = PropertyType; - - return Property; - } - - - static int __fastcall ClassPropertyKeyToPropertyType(CONST DEVPROPKEY* PropertyKey, _Out_ DEVPROPTYPE* PropertyType) - { - static constexpr const GUID PropertyId = { 0x4321918b, 0xf69e, 0x470d, { 0xa5, 0xde, 0x4d, 0x88, 0xc7, 0x5a, 0xd2, 0x4b } }; - - constexpr int IndexStart = 19; - - static constexpr const DEVPROPTYPE PropertyIdTypeIndex[] = - { - DEVPROP_TYPE_STRING_LIST, - DEVPROP_TYPE_STRING_LIST, - DEVPROP_TYPE_SECURITY_DESCRIPTOR, - DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING, - DEVPROP_TYPE_UINT32, - DEVPROP_TYPE_BOOLEAN, - DEVPROP_TYPE_UINT32, - }; - - if (memcmp(&PropertyKey->fmtid, &PropertyId, sizeof(PropertyId)) != 0 - || PropertyKey->pid < IndexStart || PropertyKey->pid >= _countof(PropertyIdTypeIndex) + IndexStart) - { - return -1; - } - - auto Property = PropertyKey->pid - IndexStart; - - *PropertyType = PropertyIdTypeIndex[Property]; - - return Property + 0x11; - }; -#endif - } -} -#endif - namespace YY::Thunks { #if (YY_Thunks_Support_Version < NTDDI_WIN6) @@ -134,44 +29,66 @@ namespace YY::Thunks _In_ DWORD Flags ) { - if(const auto pSetupDiGetDevicePropertyW = try_get_SetupDiGetDevicePropertyW()) + if(const auto _pfnSetupDiGetDevicePropertyW = try_get_SetupDiGetDevicePropertyW()) { - return pSetupDiGetDevicePropertyW(DeviceInfoSet, DeviceInfoData, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, RequiredSize, Flags); + return _pfnSetupDiGetDevicePropertyW(DeviceInfoSet, DeviceInfoData, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, RequiredSize, Flags); } - if(Flags != 0) + if (!DeviceInfoSet) { - SetLastError(ERROR_INVALID_FLAGS); + SetLastError(ERROR_INVALID_HANDLE); return FALSE; } + if (DeviceInfoData == nullptr || PropertyKey == nullptr || PropertyType == nullptr) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } - DEVPROPTYPE Type; - - const auto Property = internal::DevicePropertyKeyToPropertyType(PropertyKey, &Type); - - if (Property == -1) + if(Flags != 0) { - SetLastError(ERROR_NOT_FOUND); + SetLastError(ERROR_INVALID_FLAGS); return FALSE; } - if (!SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet, DeviceInfoData, Property, NULL, PropertyBuffer, PropertyBufferSize, RequiredSize)) + if (PropertyBuffer == nullptr && (PropertyBufferSize || RequiredSize == nullptr)) + { + SetLastError(ERROR_INVALID_USER_BUFFER); return FALSE; + } - if(PropertyType) + const auto _pProperty = Fallback::DevicePropertyToDeviceRegistryProperty(PropertyKey); + if (!_pProperty) { - *PropertyType = Type; + SetLastError(ERROR_INVALID_REG_PROPERTY); + return FALSE; } - return TRUE; + *PropertyType = _pProperty->PropertyType; + if (!Fallback::DevNodeTempPropertyBufffer::HasTransform(_pProperty->PropertyType)) + return SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet, DeviceInfoData, _pProperty->SP_DeviceRegistryProperty, NULL, PropertyBuffer, PropertyBufferSize, RequiredSize); + + Fallback::DevNodeTempPropertyBufffer TempBuffer = {}; + ULONG _cbTempBuffer = sizeof(TempBuffer); + if (!SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet, DeviceInfoData, _pProperty->SP_DeviceRegistryProperty, NULL, PBYTE(&TempBuffer), _cbTempBuffer, &_cbTempBuffer)) + return FALSE; + + const auto _bRet = TempBuffer.TryTransformGetBuffer(_pProperty->PropertyType, PropertyBuffer, &PropertyBufferSize); + if (RequiredSize) + *RequiredSize = PropertyBufferSize; + + if(!_bRet) + SetLastError(ERROR_INSUFFICIENT_BUFFER); + + return _bRet; } #endif //!YY_Thunks_Support_Version < NTDDI_WIN6 #if (YY_Thunks_Support_Version < NTDDI_WIN6) - //Available in Windows Vista and later versions of Windows. + // Available in Windows Vista and later versions of Windows. __DEFINE_THUNK( setupapi, 28, @@ -182,14 +99,26 @@ namespace YY::Thunks _In_ PSP_DEVINFO_DATA DeviceInfoData, _In_ CONST DEVPROPKEY *PropertyKey, _In_ DEVPROPTYPE PropertyType, - _In_reads_bytes_opt_(PropertyBufferSize) CONST PBYTE PropertyBuffer, + _In_reads_bytes_opt_(PropertyBufferSize) PBYTE PropertyBuffer, _In_ DWORD PropertyBufferSize, _In_ DWORD Flags ) { - if (const auto pSetupDiSetDevicePropertyW = try_get_SetupDiSetDevicePropertyW()) + if (const auto _pfnSetupDiSetDevicePropertyW = try_get_SetupDiSetDevicePropertyW()) + { + return _pfnSetupDiSetDevicePropertyW(DeviceInfoSet, DeviceInfoData, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, Flags); + } + + if (!DeviceInfoSet) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + if (DeviceInfoData == nullptr || PropertyKey == nullptr) { - return pSetupDiSetDevicePropertyW(DeviceInfoSet, DeviceInfoData, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, Flags); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; } if (Flags != 0) @@ -198,30 +127,40 @@ namespace YY::Thunks return FALSE; } - DEVPROPTYPE Type; - - const auto Property = internal::DevicePropertyKeyToPropertyType(PropertyKey, &Type); + if (PropertyBuffer == nullptr && PropertyBufferSize) + { + SetLastError(ERROR_INVALID_USER_BUFFER); + return FALSE; + } - if (Property == -1) + const auto _pProperty = Fallback::DevicePropertyToDeviceRegistryProperty(PropertyKey); + if (!_pProperty) { - SetLastError(ERROR_NOT_FOUND); + SetLastError(ERROR_INVALID_REG_PROPERTY); return FALSE; } - if(Type == PropertyType) + if(_pProperty->PropertyType != PropertyType) { SetLastError(ERROR_INVALID_DATA); return FALSE; } - return SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet, DeviceInfoData, Property, PropertyBuffer, PropertyBufferSize); + Fallback::DevNodeTempPropertyBufffer TempBuffer; + if (!TempBuffer.TryTransformSetBuffer(PropertyType, &PropertyBuffer, &PropertyBufferSize)) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + + return SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet, DeviceInfoData, PropertyType, PropertyBuffer, PropertyBufferSize); } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN6) - //Available in Windows Vista and later versions of Windows. + // Available in Windows Vista and later versions of Windows. __DEFINE_THUNK( setupapi, 28, @@ -238,32 +177,47 @@ namespace YY::Thunks _In_ DWORD Flags ) { - if(const auto pSetupDiGetClassPropertyW = try_get_SetupDiGetClassPropertyW()) + if(const auto _pfnSetupDiGetClassPropertyW = try_get_SetupDiGetClassPropertyW()) { - return pSetupDiGetClassPropertyW(ClassGuid, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, RequiredSize, Flags); + return _pfnSetupDiGetClassPropertyW(ClassGuid, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, RequiredSize, Flags); } - DEVPROPTYPE Type; - - const auto Property = internal::ClassPropertyKeyToPropertyType(PropertyKey, &Type); - - if (Property == -1) + if (ClassGuid == nullptr || PropertyType == nullptr || PropertyKey == nullptr) { - SetLastError(ERROR_NOT_FOUND); + SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - if(!SetupDiGetClassRegistryPropertyW(ClassGuid, Property, nullptr, PropertyBuffer, PropertyBufferSize, RequiredSize, nullptr, nullptr)) + if (PropertyBuffer == nullptr && (PropertyBufferSize || RequiredSize == nullptr)) { + SetLastError(ERROR_INVALID_USER_BUFFER); return FALSE; } - if (PropertyType) + const auto _pProperty = Fallback::ClassPropertyToClassRegistryProperty(PropertyKey); + if (!_pProperty) { - *PropertyType = Type; + SetLastError(ERROR_INVALID_REG_PROPERTY); + return FALSE; } - return TRUE; + *PropertyType = _pProperty->PropertyType; + if (!Fallback::DevNodeTempPropertyBufffer::HasTransform(_pProperty->PropertyType)) + return SetupDiGetClassRegistryPropertyW(ClassGuid, _pProperty->SP_ClassRegistryProperty, nullptr, PropertyBuffer, PropertyBufferSize, RequiredSize, nullptr, nullptr); + + Fallback::DevNodeTempPropertyBufffer TempBuffer = {}; + ULONG _cbTempBuffer = sizeof(TempBuffer); + if (!SetupDiGetClassRegistryPropertyW(ClassGuid, _pProperty->SP_ClassRegistryProperty, nullptr, PBYTE(&TempBuffer), _cbTempBuffer, &_cbTempBuffer, nullptr, nullptr)) + return FALSE; + + const auto _bRet = TempBuffer.TryTransformGetBuffer(_pProperty->PropertyType, PropertyBuffer, &PropertyBufferSize); + if (RequiredSize) + *RequiredSize = PropertyBufferSize; + + if (!_bRet) + SetLastError(ERROR_INSUFFICIENT_BUFFER); + + return _bRet; } #endif @@ -288,32 +242,47 @@ namespace YY::Thunks _Reserved_ PVOID Reserved ) { - if (const auto pSetupDiGetClassPropertyExW = try_get_SetupDiGetClassPropertyExW()) + if (const auto _pfnSetupDiGetClassPropertyExW = try_get_SetupDiGetClassPropertyExW()) { - return pSetupDiGetClassPropertyExW(ClassGuid, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, RequiredSize, Flags, MachineName, Reserved); + return _pfnSetupDiGetClassPropertyExW(ClassGuid, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, RequiredSize, Flags, MachineName, Reserved); } - DEVPROPTYPE Type; - - const auto Property = internal::ClassPropertyKeyToPropertyType(PropertyKey, &Type); - - if (Property == -1) + if (ClassGuid == nullptr || PropertyType == nullptr || PropertyKey == nullptr) { - SetLastError(ERROR_NOT_FOUND); + SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - if (!SetupDiGetClassRegistryPropertyW(ClassGuid, Property, nullptr, PropertyBuffer, PropertyBufferSize, RequiredSize, MachineName, Reserved)) + if (PropertyBuffer == nullptr && (PropertyBufferSize || RequiredSize == nullptr)) { + SetLastError(ERROR_INVALID_USER_BUFFER); return FALSE; } - if (PropertyType) + const auto _pProperty = Fallback::ClassPropertyToClassRegistryProperty(PropertyKey); + if (!_pProperty) { - *PropertyType = Type; + SetLastError(ERROR_INVALID_REG_PROPERTY); + return FALSE; } - return TRUE; + *PropertyType = _pProperty->PropertyType; + if(!Fallback::DevNodeTempPropertyBufffer::HasTransform(_pProperty->PropertyType)) + return SetupDiGetClassRegistryPropertyW(ClassGuid, _pProperty->SP_ClassRegistryProperty, nullptr, PropertyBuffer, PropertyBufferSize, RequiredSize, MachineName, Reserved); + + Fallback::DevNodeTempPropertyBufffer TempBuffer = {}; + ULONG _cbTempBuffer = sizeof(TempBuffer); + if (!SetupDiGetClassRegistryPropertyW(ClassGuid, _pProperty->SP_ClassRegistryProperty, nullptr, PBYTE(&TempBuffer), _cbTempBuffer, &_cbTempBuffer, MachineName, Reserved)) + return FALSE; + + const auto _bRet = TempBuffer.TryTransformGetBuffer(_pProperty->PropertyType, PropertyBuffer, &PropertyBufferSize); + if (RequiredSize) + *RequiredSize = PropertyBufferSize; + + if (!_bRet) + SetLastError(ERROR_INSUFFICIENT_BUFFER); + + return _bRet; } #endif @@ -330,33 +299,49 @@ namespace YY::Thunks _In_ CONST GUID *ClassGuid, _In_ CONST DEVPROPKEY *PropertyKey, _In_ DEVPROPTYPE PropertyType, - _In_reads_bytes_opt_(PropertyBufferSize) CONST PBYTE PropertyBuffer, + _In_reads_bytes_opt_(PropertyBufferSize) PBYTE PropertyBuffer, _In_ DWORD PropertyBufferSize, _In_ DWORD Flags ) { - if (const auto pSetupDiSetClassPropertyW = try_get_SetupDiSetClassPropertyW()) + if (const auto _pfnSetupDiSetClassPropertyW = try_get_SetupDiSetClassPropertyW()) { - return pSetupDiSetClassPropertyW(ClassGuid, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, Flags); + return _pfnSetupDiSetClassPropertyW(ClassGuid, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, Flags); } - DEVPROPTYPE Type; + if (ClassGuid == nullptr || PropertyKey == nullptr) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } - const auto Property = internal::ClassPropertyKeyToPropertyType(PropertyKey, &Type); + if (PropertyBuffer == nullptr && PropertyBufferSize) + { + SetLastError(ERROR_INVALID_USER_BUFFER); + return FALSE; + } - if (Property == -1) + const auto _pProperty = Fallback::ClassPropertyToClassRegistryProperty(PropertyKey); + if (!_pProperty) { - SetLastError(ERROR_NOT_FOUND); + SetLastError(ERROR_INVALID_REG_PROPERTY); return FALSE; } - if (Type != PropertyType) + if (_pProperty->PropertyType != PropertyType) { SetLastError(ERROR_INVALID_DATA); return FALSE; } - return SetupDiSetClassRegistryPropertyW(ClassGuid, Property, PropertyBuffer, PropertyBufferSize, nullptr, nullptr); + Fallback::DevNodeTempPropertyBufffer TempBuffer; + if (!TempBuffer.TryTransformSetBuffer(PropertyType, &PropertyBuffer, &PropertyBufferSize)) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + + return SetupDiSetClassRegistryPropertyW(ClassGuid, PropertyType, PropertyBuffer, PropertyBufferSize, nullptr, nullptr); } #endif @@ -373,35 +358,51 @@ namespace YY::Thunks _In_ CONST GUID *ClassGuid, _In_ CONST DEVPROPKEY *PropertyKey, _In_ DEVPROPTYPE PropertyType, - _In_reads_bytes_opt_(PropertyBufferSize) CONST PBYTE PropertyBuffer, + _In_reads_bytes_opt_(PropertyBufferSize) PBYTE PropertyBuffer, _In_ DWORD PropertyBufferSize, _In_ DWORD Flags, _In_opt_ PCWSTR MachineName, _Reserved_ PVOID Reserved ) { - if (const auto pSetupDiSetClassPropertyExW = try_get_SetupDiSetClassPropertyExW()) + if (const auto _pfnSetupDiSetClassPropertyExW = try_get_SetupDiSetClassPropertyExW()) { - return pSetupDiSetClassPropertyExW(ClassGuid, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, Flags, MachineName, Reserved); + return _pfnSetupDiSetClassPropertyExW(ClassGuid, PropertyKey, PropertyType, PropertyBuffer, PropertyBufferSize, Flags, MachineName, Reserved); } - DEVPROPTYPE Type; + if (ClassGuid == nullptr || PropertyKey == nullptr) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } - const auto Property = internal::ClassPropertyKeyToPropertyType(PropertyKey, &Type); + if (PropertyBuffer == nullptr && PropertyBufferSize) + { + SetLastError(ERROR_INVALID_USER_BUFFER); + return FALSE; + } - if (Property == -1) + const auto _pProperty = Fallback::ClassPropertyToClassRegistryProperty(PropertyKey); + if (!_pProperty) { - SetLastError(ERROR_NOT_FOUND); + SetLastError(ERROR_INVALID_REG_PROPERTY); return FALSE; } - if(Type != PropertyType) + if (_pProperty->PropertyType != PropertyType) { SetLastError(ERROR_INVALID_DATA); return FALSE; } - return SetupDiSetClassRegistryPropertyW(ClassGuid, Property, PropertyBuffer, PropertyBufferSize, MachineName, Reserved); + Fallback::DevNodeTempPropertyBufffer TempBuffer; + if (!TempBuffer.TryTransformSetBuffer(PropertyType, &PropertyBuffer, &PropertyBufferSize)) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + + return SetupDiSetClassRegistryPropertyW(ClassGuid, PropertyType, PropertyBuffer, PropertyBufferSize, MachineName, Reserved); } #endif } diff --git a/src/Thunks/UIAutomationCore.hpp b/src/Thunks/UIAutomationCore.hpp index c3d9e63a..0d96394e 100644 --- a/src/Thunks/UIAutomationCore.hpp +++ b/src/Thunks/UIAutomationCore.hpp @@ -201,4 +201,31 @@ namespace YY::Thunks return E_NOTIMPL; } #endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN10_RS3) + + // 最低受支持的客户端 Windows 10版本 1709 [桌面应用 |UWP 应用] + // 最低受支持的服务器 Windows Server 2016[桌面应用 | UWP 应用] + __DEFINE_THUNK( + uiautomationcore, + 20, + HRESULT, + WINAPI, + UiaRaiseNotificationEvent, + _In_ IRawElementProviderSimple* _pProvider, + enum NotificationKind _eNotificationKind, + enum NotificationProcessing _eNotificationProcessing, + _In_opt_ BSTR _szDisplayString, + _In_ BSTR _szActivityId + ) + { + if (auto const _pfnUiaRaiseNotificationEvent = try_get_UiaRaiseNotificationEvent()) + { + return _pfnUiaRaiseNotificationEvent(_pProvider, _eNotificationKind, _eNotificationProcessing, _szDisplayString, _szActivityId); + } + + return S_OK; + } +#endif } diff --git a/src/Thunks/WinUsb.hpp b/src/Thunks/WinUsb.hpp new file mode 100644 index 00000000..11aea0fa --- /dev/null +++ b/src/Thunks/WinUsb.hpp @@ -0,0 +1,235 @@ +#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#include +#endif + +namespace YY::Thunks +{ +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // 最低受支持XP,但是XP需要打补丁,Vista开始直接内置 + __DEFINE_THUNK( + winusb, + 28, + BOOL, + __stdcall, + WinUsb_ControlTransfer, + _In_ WINUSB_INTERFACE_HANDLE InterfaceHandle, + _In_ WINUSB_SETUP_PACKET SetupPacket, + _Out_writes_bytes_to_opt_(BufferLength, *LengthTransferred) PUCHAR Buffer, + _In_ ULONG BufferLength, + _Out_opt_ PULONG LengthTransferred, + _In_opt_ LPOVERLAPPED Overlapped + ) + { + if (const auto _pfnWinUsb_ControlTransfer = try_get_WinUsb_ControlTransfer()) + { + return _pfnWinUsb_ControlTransfer(InterfaceHandle, SetupPacket, Buffer, BufferLength, LengthTransferred, Overlapped); + } + + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // 最低受支持XP,但是XP需要打补丁,Vista开始直接内置 + __DEFINE_THUNK( + winusb, + 4, + BOOL, + __stdcall, + WinUsb_Free, + _In_ WINUSB_INTERFACE_HANDLE InterfaceHandle + ) + { + if (const auto _pfnWinUsb_Free = try_get_WinUsb_Free()) + { + return _pfnWinUsb_Free(InterfaceHandle); + } + + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // 最低受支持XP,但是XP需要打补丁,Vista开始直接内置 + __DEFINE_THUNK( + winusb, + 12, + BOOL, + __stdcall, + WinUsb_GetAssociatedInterface, + _In_ WINUSB_INTERFACE_HANDLE InterfaceHandle, + _In_ UCHAR AssociatedInterfaceIndex, + _Out_ PWINUSB_INTERFACE_HANDLE AssociatedInterfaceHandle + ) + { + if (const auto _pfnWinUsb_GetAssociatedInterface = try_get_WinUsb_GetAssociatedInterface()) + { + return _pfnWinUsb_GetAssociatedInterface(InterfaceHandle, AssociatedInterfaceIndex, AssociatedInterfaceHandle); + } + + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // 最低受支持XP,但是XP需要打补丁,Vista开始直接内置 + __DEFINE_THUNK( + winusb, + 16, + BOOL, + __stdcall, + WinUsb_GetOverlappedResult, + _In_ WINUSB_INTERFACE_HANDLE InterfaceHandle, + _In_ LPOVERLAPPED lpOverlapped, + _Out_ LPDWORD lpNumberOfBytesTransferred, + _In_ BOOL bWait + ) + { + if (const auto _pfnWinUsb_GetOverlappedResult = try_get_WinUsb_GetOverlappedResult()) + { + return _pfnWinUsb_GetOverlappedResult(InterfaceHandle, lpOverlapped, lpNumberOfBytesTransferred, bWait); + } + + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // 最低受支持XP,但是XP需要打补丁,Vista开始直接内置 + __DEFINE_THUNK( + winusb, + 8, + BOOL, + __stdcall, + WinUsb_Initialize, + _In_ HANDLE DeviceHandle, + _Out_ PWINUSB_INTERFACE_HANDLE InterfaceHandle + ) + { + if (const auto _pfnWinUsb_Initialize = try_get_WinUsb_Initialize()) + { + return _pfnWinUsb_Initialize(DeviceHandle, InterfaceHandle); + } + + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // 最低受支持XP,但是XP需要打补丁,Vista开始直接内置 + __DEFINE_THUNK( + winusb, + 24, + BOOL, + __stdcall, + WinUsb_ReadPipe, + _In_ WINUSB_INTERFACE_HANDLE InterfaceHandle, + _In_ UCHAR PipeID, + _Out_writes_bytes_to_opt_(BufferLength,*LengthTransferred) PUCHAR Buffer, + _In_ ULONG BufferLength, + _Out_opt_ PULONG LengthTransferred, + _In_opt_ LPOVERLAPPED Overlapped + ) + { + if (const auto _pfnWinUsb_ReadPipe = try_get_WinUsb_ReadPipe()) + { + return _pfnWinUsb_ReadPipe(InterfaceHandle, PipeID, Buffer, BufferLength, LengthTransferred, Overlapped); + } + + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // 最低受支持XP,但是XP需要打补丁,Vista开始直接内置 + __DEFINE_THUNK( + winusb, + 24, + BOOL, + __stdcall, + WinUsb_ResetPipe, + _In_ WINUSB_INTERFACE_HANDLE InterfaceHandle, + _In_ UCHAR PipeID + ) + { + if (const auto _pfnWinUsb_ResetPipe = try_get_WinUsb_ResetPipe()) + { + return _pfnWinUsb_ResetPipe(InterfaceHandle, PipeID); + } + + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // 最低受支持XP,但是XP需要打补丁,Vista开始直接内置 + __DEFINE_THUNK( + winusb, + 8, + BOOL, + __stdcall, + WinUsb_SetCurrentAlternateSetting, + _In_ WINUSB_INTERFACE_HANDLE InterfaceHandle, + _In_ UCHAR SettingNumber + ) + { + if (const auto _pfnWinUsb_SetCurrentAlternateSetting = try_get_WinUsb_SetCurrentAlternateSetting()) + { + return _pfnWinUsb_SetCurrentAlternateSetting(InterfaceHandle, SettingNumber); + } + + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // 最低受支持XP,但是XP需要打补丁,Vista开始直接内置 + __DEFINE_THUNK( + winusb, + 8, + BOOL, + __stdcall, + WinUsb_WritePipe, + _In_ WINUSB_INTERFACE_HANDLE InterfaceHandle, + _In_ UCHAR PipeID, + _In_reads_bytes_(BufferLength) PUCHAR Buffer, + _In_ ULONG BufferLength, + _Out_opt_ PULONG LengthTransferred, + _In_opt_ LPOVERLAPPED Overlapped + ) + { + if (const auto _pfnWinUsb_WritePipe = try_get_WinUsb_WritePipe()) + { + return _pfnWinUsb_WritePipe(InterfaceHandle, PipeID, Buffer, BufferLength, LengthTransferred, Overlapped); + } + + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } +#endif +} diff --git a/src/Thunks/YY_Thunks.cpp b/src/Thunks/YY_Thunks.cpp index 65a41ca1..7e71ccea 100644 --- a/src/Thunks/YY_Thunks.cpp +++ b/src/Thunks/YY_Thunks.cpp @@ -1,14 +1,38 @@ -// 忽略非标准的 0 数组警告。 +/* +YY-Thunks支持的控制宏: +1. __FALLBACK_PREFIX:编译Lib库模式使用的API前缀修饰。一般来说只能为空或者传递 "YY_Thunks_"。 +2. __USING_NTDLL_LIB:假定构建环境存在ntdll.lib,这可以减少一些NTDLL相关函数的动态加载。 + +特殊支持的变通方案: +1. __ENABLE_WORKAROUND_ALL +启用所有兼容方案,即__ENABLE_WORKAROUND_1 ~ __ENABLE_WORKAROUND_N,全部开启。 + +2. __ENABLE_WORKAROUND_1_GetProcAddress_ProcessPrng +兼容方案1:让GetProcAddress也能取到ProcessPrng函数地址。某些代码可能强制依赖ProcessPrng。 + +3. __ENABLE_WORKAROUND_2_UNNAME_OBJECT_DACL +兼容方案2:Windows 8.1以前的版本对于匿名对象无法生效DACL。就会导致Chrome的CheckPlatformHandlePermissionsCorrespondToMode判断不准确。 +修复方案通过给匿名对象创建一个名字解决该问题。 + +特定项目的兼容方案: +1. __APPLY_CHROMIUM_WORKAROUNDS +开启Chrome项目的兼容能力,等效于同时指定__ENABLE_WORKAROUND_1_GetProcAddress_ProcessPrng、__ENABLE_WORKAROUND_2_UNNAME_OBJECT_DACL。 + +*/ + +// 忽略非标准的 0 数组警告。 #pragma warning(disable:4200) #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #define _YY_APPLY_TO_LATE_BOUND_MODULES(_APPLY) \ - _APPLY(ntdll, "ntdll" , USING_UNSAFE_LOAD ) \ - _APPLY(kernel32, "kernel32" , USING_UNSAFE_LOAD ) \ + _APPLY(ntdll, "ntdll" , USING_GET_MODULE_HANDLE ) \ + _APPLY(kernel32, "kernel32" , USING_GET_MODULE_HANDLE ) \ + _APPLY(cfgmgr32, "cfgmgr32" , 0 ) \ _APPLY(crypt32, "crypt32" , 0 ) \ _APPLY(dwmapi, "dwmapi" , 0 ) \ _APPLY(d3d9, "d3d9" , 0 ) \ _APPLY(d3d11, "d3d11" , 0 ) \ + _APPLY(d3d12, "d3d12" , 0 ) \ _APPLY(dbghelp, "dbghelp" , USING_UNSAFE_LOAD ) \ _APPLY(dxgi, "dxgi" , 0 ) \ _APPLY(dwrite, "dwrite" , 0 ) \ @@ -31,13 +55,19 @@ _APPLY(ole32, "ole32" , 0 ) \ _APPLY(iphlpapi, "iphlpapi" , 0 ) \ _APPLY(userenv, "userenv" , 0 ) \ + _APPLY(mf, "mf" , 0 ) \ _APPLY(mfplat, "mfplat" , 0 ) \ + _APPLY(mfreadwrite, "mfreadwrite" , 0 ) \ + _APPLY(ndfapi, "ndfapi" , 0 ) \ _APPLY(bluetoothapis, "bluetoothapis" , 0 ) \ _APPLY(netapi32, "netapi32" , 0 ) \ _APPLY(powrprof, "powrprof" , 0 ) \ + _APPLY(propsys, "propsys" , 0 ) \ _APPLY(wevtapi, "wevtapi" , 0 ) \ _APPLY(winhttp, "winhttp" , 0 ) \ + _APPLY(winusb, "winusb" , 0 ) \ _APPLY(zipfldr, "zipfldr" , LOAD_AS_DATA_FILE ) \ + _APPLY(api_ms_win_core_handle_l1_1_0, "api-ms-win-core-handle-l1-1-0" , 0 ) \ _APPLY(api_ms_win_core_realtime_l1_1_1, "api-ms-win-core-realtime-l1-1-1" , 0 ) \ _APPLY(api_ms_win_core_winrt_l1_1_0, "api-ms-win-core-winrt-l1-1-0" , 0 ) \ _APPLY(api_ms_win_core_winrt_string_l1_1_0, "api-ms-win-core-winrt-string-l1-1-0", 0 ) \ @@ -64,6 +94,9 @@ _APPLY(NtSetInformationThread, ntdll ) \ _APPLY(NtQueryInformationProcess, ntdll ) \ _APPLY(NtSetInformationProcess, ntdll ) \ + _APPLY(NtDeleteKey, ntdll ) \ + _APPLY(NtCreateKey, ntdll ) \ + _APPLY(NtOpenKey, ntdll ) \ _APPLY(NtOpenKeyedEvent, ntdll ) \ _APPLY(NtWaitForKeyedEvent, ntdll ) \ _APPLY(NtReleaseKeyedEvent, ntdll ) \ @@ -76,6 +109,10 @@ _APPLY(RtlCutoverTimeToSystemTime, ntdll ) \ _APPLY(NtCancelIoFile, ntdll ) \ _APPLY(NtWow64ReadVirtualMemory64, ntdll ) \ + _APPLY(RtlValidSid, ntdll ) \ + _APPLY(RtlValidAcl, ntdll ) \ + _APPLY(RtlFirstFreeAce, ntdll ) \ + _APPLY(RtlCopySid, ntdll ) \ _APPLY(AddDllDirectory, kernel32 ) \ _APPLY(SystemFunction036, advapi32 ) @@ -103,6 +140,26 @@ #define __WarningMessage__(msg) __pragma(message (__FILE__ "(" STRING(__LINE__) "): warning Thunks: " # msg)) #endif +#if !defined(__ENABLE_WORKAROUND_1_GetProcAddress_ProcessPrng) && (defined(__ENABLE_WORKAROUND_ALL) || defined(__APPLY_CHROMIUM_WORKAROUNDS)) +#define __ENABLE_WORKAROUND_1_GetProcAddress_ProcessPrng 1 +#endif + +#if !defined(__ENABLE_WORKAROUND_2_UNNAME_OBJECT_DACL) && (defined(__ENABLE_WORKAROUND_ALL) || defined(__APPLY_CHROMIUM_WORKAROUNDS)) +#define __ENABLE_WORKAROUND_2_UNNAME_OBJECT_DACL 1 +#endif + +#ifndef __FALLBACK_PREFIX +#define __FALLBACK_PREFIX +#define __YY_Thunks_libs 0 +#else +#define __YY_Thunks_libs 1 +#endif + +#if !defined(__USING_NTDLL_LIB) && (__YY_Thunks_libs || YY_Thunks_Support_Version >= NTDDI_WIN10) +// lib模式下必然存在 ntdll.lib,此外最小支持Windows 10时,我们因为强制依赖Windows 10 SDK,所以也必然存在ntdll.lib。 +#define __USING_NTDLL_LIB 1 +#endif + #define _Disallow_YY_KM_Namespace #include "km.h" #include @@ -184,15 +241,12 @@ RtlCutoverTimeToSystemTime( #pragma comment(lib, "User32.lib") #endif -#include - -#ifndef __FALLBACK_PREFIX -#define __FALLBACK_PREFIX -#define __YY_Thunks_libs 0 -#else -#define __YY_Thunks_libs 1 +#if defined(__USING_NTDLL_LIB) +#pragma comment(lib, "ntdll.lib") #endif +#include + //展开函数的所有的 声明 以及 try_get_ 函数 #define __DEFINE_THUNK_EXTERN_PREFIX(_PREFIX, _MODULE, _SIZE, _RETURN_, _CONVENTION_, _FUNCTION, ...) \ __APPLY_UNIT_TEST_BOOL(_FUNCTION); \ @@ -252,6 +306,34 @@ namespace YY::Thunks::internal return internal::MakeVersion(_pPeb->OSMajorVersion, _pPeb->OSMinorVersion); } + const SYSTEM_INFO& GetNativeSystemInfo() + { + static SYSTEM_INFO s_SystemInfo; + // 0: 尚未初始化 + // 1:正在初始化 + // 2:已经初始化完成 + static volatile LONG s_InitOnce; + + auto _nResult = InterlockedCompareExchange(&s_InitOnce, 1, 0); + if (_nResult == 0) + { + // 成功锁定 + ::GetNativeSystemInfo(&s_SystemInfo); + InterlockedExchange(&s_InitOnce, 2); + } + else if (_nResult == 1) + { + // 其他线程正在初始化 + do + { + YieldProcessor(); + + } while (s_InitOnce == 1); + } + + return s_SystemInfo; + } + _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(_cbBytes) @@ -569,6 +651,28 @@ namespace YY::Thunks::internal } + /// + /// 计算字符串长度,某些场景我们特意不依赖wcslen之类的,防止发生死锁。 + /// + /// + /// + /// + /// + template + constexpr size_t StringLength(_In_z_ const Char* _szString, size_t _cchMaxLength = -1) + { + if (!_szString) + return 0; + + size_t _cchString = 0; + for (;_cchMaxLength && *_szString;--_cchMaxLength, ++_szString) + { + ++_cchString; + } + + return _cchString; + } + template class StringBuffer { @@ -715,12 +819,13 @@ namespace YY::Thunks::internal if (!bCanFree) return nullptr; - auto _szNewBuffer = (Char*)internal::ReAlloc(szBuffer, _cNewBufferLength); + auto _szNewBuffer = (Char*)internal::ReAlloc(szBuffer, _cNewBufferLength * sizeof(Char)); if (!_szNewBuffer) return nullptr; szBuffer = _szNewBuffer; uBufferLength = _cNewBufferLength; + szBuffer[uLength] = 0; return _szNewBuffer; } @@ -751,6 +856,64 @@ namespace YY::Thunks::internal GetBuffer(max(uBufferLength * 2, _uNew)); } } + + bool __fastcall AppendGUID(_In_ const GUID& _Id) + { + TryBuy(36); + + const auto _uLengthNew = uLength + 36; + if (_uLengthNew >= uBufferLength) + { + return false; + } + + // C0F8B35B-3CA6-4E57-9B65-B654B33AE583 + auto _szHexChar = "0123456789abcdef"; + auto _pBuffer = szBuffer + uLength; + *_pBuffer++ = _szHexChar[_Id.Data1 >> 28]; + *_pBuffer++ = _szHexChar[(_Id.Data1 >> 24) & 0xF]; + *_pBuffer++ = _szHexChar[(_Id.Data1 >> 20) & 0xF]; + *_pBuffer++ = _szHexChar[(_Id.Data1 >> 16) & 0xF]; + *_pBuffer++ = _szHexChar[(_Id.Data1 >> 12) & 0xF]; + *_pBuffer++ = _szHexChar[(_Id.Data1 >> 8) & 0xF]; + *_pBuffer++ = _szHexChar[(_Id.Data1 >> 4) & 0xF]; + *_pBuffer++ = _szHexChar[_Id.Data1 & 0xF]; + + *_pBuffer++ = '-'; + *_pBuffer++ = _szHexChar[(_Id.Data2 >> 12) & 0xF]; + *_pBuffer++ = _szHexChar[(_Id.Data2 >> 8) & 0xF]; + *_pBuffer++ = _szHexChar[(_Id.Data2 >> 4) & 0xF]; + *_pBuffer++ = _szHexChar[_Id.Data2 & 0xF]; + + *_pBuffer++ = '-'; + *_pBuffer++ = _szHexChar[(_Id.Data3 >> 12) & 0xF]; + *_pBuffer++ = _szHexChar[(_Id.Data3 >> 8) & 0xF]; + *_pBuffer++ = _szHexChar[(_Id.Data3 >> 4) & 0xF]; + *_pBuffer++ = _szHexChar[_Id.Data3 & 0xF]; + + *_pBuffer++ = '-'; + *_pBuffer++ = _szHexChar[(_Id.Data4[0] >> 4) & 0xF]; + *_pBuffer++ = _szHexChar[_Id.Data4[0] & 0xF]; + *_pBuffer++ = _szHexChar[(_Id.Data4[1] >> 4) & 0xF]; + *_pBuffer++ = _szHexChar[_Id.Data4[1] & 0xF]; + + *_pBuffer++ = '-'; + *_pBuffer++ = _szHexChar[(_Id.Data4[2] >> 4) & 0xF]; + *_pBuffer++ = _szHexChar[_Id.Data4[2] & 0xF]; + *_pBuffer++ = _szHexChar[(_Id.Data4[3] >> 4) & 0xF]; + *_pBuffer++ = _szHexChar[_Id.Data4[3] & 0xF]; + *_pBuffer++ = _szHexChar[(_Id.Data4[4] >> 4) & 0xF]; + *_pBuffer++ = _szHexChar[_Id.Data4[4] & 0xF]; + *_pBuffer++ = _szHexChar[(_Id.Data4[5] >> 4) & 0xF]; + *_pBuffer++ = _szHexChar[_Id.Data4[5] & 0xF]; + *_pBuffer++ = _szHexChar[(_Id.Data4[6] >> 4) & 0xF]; + *_pBuffer++ = _szHexChar[_Id.Data4[6] & 0xF]; + *_pBuffer++ = _szHexChar[(_Id.Data4[7] >> 4) & 0xF]; + *_pBuffer++ = _szHexChar[_Id.Data4[7] & 0xF]; + *_pBuffer = 0; + uLength = _uLengthNew; + return true; + } }; static LSTATUS Convert(_In_NLS_string_(_cchSrc) LPCWSTR _szSrc, _In_ int _cchSrc, StringBuffer* _pBuffer) @@ -783,6 +946,43 @@ namespace YY::Thunks::internal return ERROR_SUCCESS; } + static bool __fastcall IsEqualI(const UNICODE_STRING& _Left, const UNICODE_STRING& _Right) + { + if (_Left.Length != _Right.Length) + return false; + + return StringCompareIgnoreCaseByAscii(_Left.Buffer, _Right.Buffer, _Left.Length / 2) == 0; + } + + static bool __fastcall IsEqual(const UNICODE_STRING& _Left, const UNICODE_STRING& _Right) + { + if (_Left.Length != _Right.Length) + return false; + + return memcmp(_Left.Buffer, _Right.Buffer, _Left.Length) == 0; + } + + static constexpr UNICODE_STRING __fastcall MakeNtString(_In_z_ const wchar_t* _szString) + { + const auto _cbString = StringLength(_szString) * sizeof(_szString[0]); + UNICODE_STRING _Result = { (USHORT)max(UINT16_MAX, _cbString), (USHORT)max(UINT16_MAX, _cbString + sizeof(_szString[0])), const_cast(_szString) }; + return _Result; + } + + static constexpr ANSI_STRING __fastcall MakeNtString(_In_z_ const char* _szString) + { + const auto _cbString = StringLength(_szString) * sizeof(_szString[0]); + + ANSI_STRING _Result = { (USHORT)max(UINT16_MAX, _cbString), (USHORT)max(UINT16_MAX, _cbString + sizeof(_szString[0])), const_cast(_szString)}; + return _Result; + } + + template + static constexpr UNICODE_STRING __fastcall MakeStaticUnicodeString(const wchar_t (&_Right)[kLength]) + { + UNICODE_STRING _Result = { (kLength - 1)* sizeof(_Right[0]), kLength * sizeof(_Right[0]), const_cast(_Right) }; + return _Result; + } } } //namespace YY @@ -826,3 +1026,143 @@ __if_exists(YY::Thunks::Fallback::_CRT_CONCATENATE(try_get_, _FUNCTION)) #undef __DEFINE_THUNK #undef YY_Thunks_Implemented + +static HMODULE __fastcall try_get_module(volatile HMODULE* pModule, const wchar_t* module_name, int Flags) noexcept +{ + // First check to see if we've cached the module handle: + if (HMODULE const cached_handle = __crt_interlocked_read_pointer(pModule)) + { + if (cached_handle == INVALID_HANDLE_VALUE) + { + return nullptr; + } + + return cached_handle; + } + + // If we haven't yet cached the module handle, try to load the library. If + // this fails, cache the sentinel handle value INVALID_HANDLE_VALUE so that + // we don't attempt to load the module again: + HMODULE new_handle = NULL; + if (Flags & USING_GET_MODULE_HANDLE) + { + new_handle = GetModuleHandleW(module_name); + } + else + { + // 我们不能直接使用 LoadLibraryExW,因为它可能被Thunk。 + __if_exists(YY::Thunks::try_get_LoadLibraryExW) + { + const auto LoadLibraryExW = YY::Thunks::try_get_LoadLibraryExW(); + if (!LoadLibraryExW) + return nullptr; + } + + if (Flags & LOAD_AS_DATA_FILE) + { + new_handle = LoadLibraryExW(module_name, NULL, LOAD_LIBRARY_AS_DATAFILE); + } + else if (Flags & USING_UNSAFE_LOAD) + { + new_handle = LoadLibraryExW(module_name, nullptr, 0); + } + else + { + // 使用DLL安全加载 +#if (YY_Thunks_Support_Version < NTDDI_WIN8) + if (!try_get_AddDllDirectory()) + { +#if !defined(__USING_NTDLL_LIB) + const auto LdrLoadDll = try_get_LdrLoadDll(); + if (!LdrLoadDll) + return nullptr; +#endif + wchar_t szFilePathBuffer[MAX_PATH] = {}; + const auto _cchSystemPath = GetSystemDirectoryW(szFilePathBuffer, _countof(szFilePathBuffer)); + if (_cchSystemPath == 0 || _cchSystemPath >= _countof(szFilePathBuffer)) + { + // 回落普通加载,按理说 GetSystemDirectoryW不应该发生这样的失败。 + new_handle = LoadLibraryExW(module_name, nullptr, 0); + } + else + { + auto _sModuleName = YY::Thunks::internal::MakeNtString(module_name); + LdrLoadDll(szFilePathBuffer, nullptr, &_sModuleName, &new_handle); + } + } + else +#endif + { + new_handle = LoadLibraryExW(module_name, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); + } + } + } + + if (!new_handle) + { + if (HMODULE const cached_handle = __crt_interlocked_exchange_pointer(pModule, INVALID_HANDLE_VALUE)) + { + _ASSERTE(cached_handle == INVALID_HANDLE_VALUE); + } + + return nullptr; + } + + // Swap the new handle into the cache. If the cache no longer contained a + // null handle, then some other thread loaded the module and cached the + // handle while we were doing the same. In that case, we free the handle + // once to maintain the reference count: + if (HMODULE const cached_handle = __crt_interlocked_exchange_pointer(pModule, new_handle)) + { + _ASSERTE(cached_handle == new_handle); + FreeLibrary(new_handle); + } + + return new_handle; +} + +static __forceinline void* __fastcall try_get_proc_address_from_dll( + const ProcInfo& _ProcInfo + ) noexcept +{ + HMODULE const module_handle = _ProcInfo.pfnGetModule(); + if (!module_handle) + { + return nullptr; + } + + // 无法直接调用GetProcAddress,因为GetProcAddress可能被Thunk + // 我们需要严格判断,避免发生死锁。 +#if defined(__USING_NTDLL_LIB) + void* _pProc = nullptr; + if (uintptr_t(_ProcInfo.szProcName) > UINT16_MAX) + { + ANSI_STRING _sFunctionName = YY::Thunks::internal::MakeNtString(_ProcInfo.szProcName); + LdrGetProcedureAddress(module_handle, &_sFunctionName, 0, &_pProc); + } + else + { + LdrGetProcedureAddress(module_handle, nullptr, (WORD)uintptr_t(_ProcInfo.szProcName), &_pProc); + } + return _pProc; +#else // !defined(__USING_NTDLL_LIB) + __if_exists(YY::Thunks::try_get_GetProcAddress) + { + const auto GetProcAddress = YY::Thunks::try_get_GetProcAddress(); + } + + return reinterpret_cast(GetProcAddress(module_handle, _ProcInfo.szProcName)); +#endif // defined(__USING_NTDLL_LIB) +} + +static __forceinline void* __fastcall try_get_proc_address_from_first_available_module( + const ProcInfo& _ProcInfo + ) noexcept +{ + if (_ProcInfo.pfnCustomGetProcAddress) + { + return _ProcInfo.pfnCustomGetProcAddress(_ProcInfo); + } + + return try_get_proc_address_from_dll(_ProcInfo); +} diff --git a/src/Thunks/YY_Thunks.h b/src/Thunks/YY_Thunks.h index f4862d13..e9c193eb 100644 --- a/src/Thunks/YY_Thunks.h +++ b/src/Thunks/YY_Thunks.h @@ -135,7 +135,8 @@ static uintptr_t __security_cookie_yy_thunks; // Implements wcsncpmp for ASCII chars only. // NOTE: We can't use wcsncmp in this context because we may end up trying to modify // locale data structs or even calling the same function in NLS code. -static int _fastcall __wcsnicmp_ascii(const wchar_t* string1, const wchar_t* string2, size_t count) noexcept +template +static int _fastcall StringCompareIgnoreCaseByAscii(const Char1* string1, const Char2* string2, size_t count) noexcept { wchar_t f, l; int result = 0; @@ -156,6 +157,55 @@ static int _fastcall __wcsnicmp_ascii(const wchar_t* string1, const wchar_t* str return result; } +template +static int _fastcall StringCompare(const Char1* string1, const Char2* string2, size_t count) noexcept +{ + wchar_t f, l; + int result = 0; + + if (count) + { + /* validation section */ + do { + f = *string1; + l = *string2; + string1++; + string2++; + } while ((--count) && f && (f == l)); + + result = (int)(f - l); + } + + return result; +} + +static PVOID __fastcall YY_ImageDirectoryEntryToData( + __in PVOID pBaseAddress, + __in ULONG dwDirectory, + __out PULONG pSize + ) +{ + auto _pDosHeader = (PIMAGE_DOS_HEADER)pBaseAddress; + auto _pNtHerder = reinterpret_cast(PBYTE(pBaseAddress) + _pDosHeader->e_lfanew); + auto& _DataDirectory = _pNtHerder->OptionalHeader.DataDirectory[dwDirectory]; + + *pSize = _DataDirectory.Size; + if (_DataDirectory.Size == 0 || _DataDirectory.VirtualAddress == 0) + return nullptr; + + return PBYTE(pBaseAddress) + _DataDirectory.VirtualAddress; +} + +static DWORD __fastcall GetDllTimeDateStamp(_In_ HMODULE _hModule) +{ + if (!_hModule) + return 0; + + auto _pDosHeader = (PIMAGE_DOS_HEADER)_hModule; + auto _pNtHerder = reinterpret_cast(PBYTE(_hModule) + _pDosHeader->e_lfanew); + return _pNtHerder->FileHeader.TimeDateStamp; +} + enum : int { __crt_maximum_pointer_shift = sizeof(uintptr_t) * 8 @@ -257,69 +307,13 @@ static __forceinline T* __fastcall __crt_interlocked_read_pointer(T* const volat return __crt_interlocked_compare_exchange_pointer(target, nullptr, nullptr); } - - -static HMODULE __fastcall try_load_library_from_system_directory(wchar_t const* const name) noexcept -{ - return LoadLibraryExW(name, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); -} - - -#define USING_UNSAFE_LOAD 0x00000001 +// 改选项非常危险,只调用GetModuleHandleW!!! +#define USING_GET_MODULE_HANDLE 0x00000001 #define LOAD_AS_DATA_FILE 0x00000002 +// 该加载模式存在劫持风险,使用前请确认。 +#define USING_UNSAFE_LOAD 0x00000004 -static HMODULE __fastcall try_get_module(volatile HMODULE* pModule, const wchar_t* module_name, int Flags) noexcept -{ - // First check to see if we've cached the module handle: - if (HMODULE const cached_handle = __crt_interlocked_read_pointer(pModule)) - { - if (cached_handle == INVALID_HANDLE_VALUE) - { - return nullptr; - } - - return cached_handle; - } - - // If we haven't yet cached the module handle, try to load the library. If - // this fails, cache the sentinel handle value INVALID_HANDLE_VALUE so that - // we don't attempt to load the module again: - HMODULE new_handle = NULL; - if (Flags & LOAD_AS_DATA_FILE) - { - new_handle = LoadLibraryExW(module_name, NULL, LOAD_LIBRARY_AS_DATAFILE); - } - else if (Flags & USING_UNSAFE_LOAD) - { - new_handle = LoadLibraryW(module_name); - } - else - { - new_handle = try_load_library_from_system_directory(module_name); - } - - if (!new_handle) - { - if (HMODULE const cached_handle = __crt_interlocked_exchange_pointer(pModule, INVALID_HANDLE_VALUE)) - { - _ASSERTE(cached_handle == INVALID_HANDLE_VALUE); - } - - return nullptr; - } - - // Swap the new handle into the cache. If the cache no longer contained a - // null handle, then some other thread loaded the module and cached the - // handle while we were doing the same. In that case, we free the handle - // once to maintain the reference count: - if (HMODULE const cached_handle = __crt_interlocked_exchange_pointer(pModule, new_handle)) - { - _ASSERTE(cached_handle == new_handle); - FreeLibrary(new_handle); - } - - return new_handle; -} +static HMODULE __fastcall try_get_module(volatile HMODULE* pModule, const wchar_t* module_name, int Flags) noexcept; #define _APPLY(_MODULE, _NAME, _FLAGS) \ static HMODULE __fastcall _CRT_CONCATENATE(try_get_module_, _MODULE)() noexcept \ @@ -330,34 +324,62 @@ static HMODULE __fastcall try_get_module(volatile HMODULE* pModule, const wchar_ _YY_APPLY_TO_LATE_BOUND_MODULES(_APPLY) #undef _APPLY +struct ProcInfo; typedef HMODULE (__fastcall* try_get_module_fun)(); -typedef void*(__fastcall* try_get_proc_fallback_fun)(); +typedef void*(__fastcall* custom_try_get_proc_fun)(const ProcInfo& _ProcInfo); struct ProcInfo { char const* const szProcName; try_get_module_fun pfnGetModule; - try_get_proc_fallback_fun pfnGetProcFallback; + custom_try_get_proc_fun pfnCustomGetProcAddress; }; static __forceinline void* __fastcall try_get_proc_address_from_first_available_module( const ProcInfo& _ProcInfo - ) noexcept + ) noexcept; + +static __forceinline void* __fastcall try_get_proc_address_from_dll( + const ProcInfo& _ProcInfo + ) noexcept; + +struct ProcOffsetInfo { - HMODULE const module_handle = _ProcInfo.pfnGetModule(); - if (!module_handle) - { - return nullptr; - } + DWORD uTimeDateStamp; + DWORD uProcOffset; +}; - auto _pProc = reinterpret_cast(GetProcAddress(module_handle, _ProcInfo.szProcName)); - if (_pProc || _ProcInfo.pfnGetProcFallback == nullptr) - return _pProc; +template +static __forceinline void* __fastcall try_get_proc_address_from_offset( + HMODULE _hModule, + const ProcOffsetInfo (&_ProcOffsetInfos)[kLength] + ) noexcept +{ + if (_hModule) + { + __try + { + const auto _uTimeDateStamp = GetDllTimeDateStamp(_hModule); + if (_uTimeDateStamp) + { + for (auto& _ProcOffsetInfo : _ProcOffsetInfos) + { + if (_ProcOffsetInfo.uTimeDateStamp == _uTimeDateStamp) + { + return PBYTE(_hModule) + _ProcOffsetInfo.uProcOffset; + } + } + } + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + // 避免遇到畸形DLL而触发异常。 + } + } - return _ProcInfo.pfnGetProcFallback(); + return nullptr; } - static __forceinline void* __cdecl invalid_function_sentinel() noexcept { return reinterpret_cast(static_cast(-1)); diff --git a/src/Thunks/api-ms-win-core-handle.hpp b/src/Thunks/api-ms-win-core-handle.hpp new file mode 100644 index 00000000..a673a108 --- /dev/null +++ b/src/Thunks/api-ms-win-core-handle.hpp @@ -0,0 +1,570 @@ + +#if (YY_Thunks_Support_Version < NTDDI_WIN10) && !defined(__Comment_Lib_advapi32) +#define __Comment_Lib_advapi32 +#pragma comment(lib, "Advapi32.lib") +#endif + +#if defined(YY_Thunks_Implemented) +namespace YY::Thunks +{ + namespace + { +#if (YY_Thunks_Support_Version < NTDDI_WIN10) + static SRWLOCK g_CompareObjectHandles; + + union ObjectStaticBuffer + { + wchar_t Buffer[1024]; + OBJECT_TYPE_INFORMATION TypeInfo; + OBJECT_BASIC_INFORMATION BaseInfo; + OBJECT_NAME_INFORMATION NameInfo; + BY_HANDLE_FILE_INFORMATION FileInformation; + TOKEN_STATISTICS TokenStatistics; + }; + + typedef bool(__fastcall* CompareObjectFunType)(HANDLE _hLeft, ObjectStaticBuffer& _LeftBuffer, HANDLE _hRigth, ObjectStaticBuffer& _RightBuffer); + + struct CompareObjectItem + { + UNICODE_STRING TypeName; + CompareObjectFunType pfnCompareObject; + + template + constexpr CompareObjectItem(const wchar_t(&_szTypeName)[kLength], CompareObjectFunType _pfnCompareObject) + : TypeName(internal::MakeStaticUnicodeString(_szTypeName)) + , pfnCompareObject(_pfnCompareObject) + { + } + }; + + bool __fastcall CompareObjectRef(HANDLE _hFirstObjectHandle, ObjectStaticBuffer& _FirstObjectBuffer, HANDLE _hSecondObjectHandle, ObjectStaticBuffer& _SecondObjectBuffer) noexcept + { + const auto _pfnNtQueryObject = try_get_NtQueryObject(); + if (!_pfnNtQueryObject) + return false; + + const auto _pfnDuplicateHandle = try_get_DuplicateHandle(); + const auto _pfnCloseHandle = try_get_CloseHandle(); + if (_pfnDuplicateHandle == nullptr || _pfnCloseHandle == nullptr) + return false; + + HANDLE _hFirstTmp = NULL; + BOOL _bHandleIsSame = FALSE; + + ::AcquireSRWLockExclusive(&g_CompareObjectHandles); + + do + { + if (!_pfnDuplicateHandle(NtGetCurrentProcess(), _hFirstObjectHandle, NtGetCurrentProcess(), &_hFirstTmp, 0, FALSE, 0)) + { + break; + } + + LONG _Status = _pfnNtQueryObject(_hFirstObjectHandle, ObjectBasicInformation, &_FirstObjectBuffer, sizeof(_FirstObjectBuffer.BaseInfo), nullptr); + + // 实际测试,ObjectBasicInformation 只出现无效句柄错误 + if (_Status < 0) + { + break; + } + + if (_FirstObjectBuffer.BaseInfo.HandleCount == 1) + { + // 引用计数为 1,这肯定不可能与另外一个句柄是同一个内核对象 + break; + } + + _Status = _pfnNtQueryObject(_hSecondObjectHandle, ObjectBasicInformation, &_SecondObjectBuffer, sizeof(_SecondObjectBuffer.BaseInfo), nullptr); + if (_Status < 0) + { + break; + } + + if (_SecondObjectBuffer.BaseInfo.HandleCount != _FirstObjectBuffer.BaseInfo.HandleCount) + { + // 引用计数为 1,这肯定不可能与另外一个句柄是同一个内核对象 + break; + } + + _pfnCloseHandle(_hFirstTmp); + _hFirstTmp = NULL; + + _Status = _pfnNtQueryObject(_hFirstObjectHandle, ObjectBasicInformation, &_FirstObjectBuffer, sizeof(_FirstObjectBuffer.BaseInfo), nullptr); + + // 实际测试,ObjectBasicInformation 只出现无效句柄错误 + if (_Status < 0) + { + break; + } + + if (_FirstObjectBuffer.BaseInfo.HandleCount == 1) + { + // 引用计数为 1,这肯定不可能与另外一个句柄是同一个内核对象 + break; + } + + _Status = _pfnNtQueryObject(_hSecondObjectHandle, ObjectBasicInformation, &_SecondObjectBuffer, sizeof(_SecondObjectBuffer.BaseInfo), nullptr); + if (_Status < 0) + { + break; + } + + if (_SecondObjectBuffer.BaseInfo.HandleCount != _FirstObjectBuffer.BaseInfo.HandleCount) + { + // 引用计数为 1,这肯定不可能与另外一个句柄是同一个内核对象 + break; + } + + _bHandleIsSame = TRUE; + break; + } while (false); + + ::ReleaseSRWLockExclusive(&g_CompareObjectHandles); + + if (_hFirstTmp) + _pfnCloseHandle(_hFirstTmp); + + return _bHandleIsSame; + } + + bool __fastcall CompareObjectName(HANDLE _hLeft, ObjectStaticBuffer& _LeftBuffer, HANDLE _hRigth, ObjectStaticBuffer& _RightBuffer) noexcept + { + const auto _pfnNtQueryObject = try_get_NtQueryObject(); + if (!_pfnNtQueryObject) + return false; + + LONG _Status = _pfnNtQueryObject(_hLeft, ObjectNameInformation, &_LeftBuffer, sizeof(_LeftBuffer), nullptr); + if (_Status < 0) + return false; + + _Status = _pfnNtQueryObject(_hRigth, ObjectNameInformation, &_RightBuffer, sizeof(_RightBuffer), nullptr); + if (_Status < 0) + return false; + + if (_LeftBuffer.NameInfo.Name.Length == 0 && _RightBuffer.NameInfo.Name.Length == 0) + { + // 这是一个匿名对象,只能比较句柄的引用计数了。 + return CompareObjectRef(_hLeft, _LeftBuffer, _hRigth, _RightBuffer); + } + + return internal::IsEqual(_LeftBuffer.NameInfo.Name, _RightBuffer.NameInfo.Name); + } + + bool __fastcall CompareProcessHandle(HANDLE _hLeft, ObjectStaticBuffer& _LeftBuffer, HANDLE _hRigth, ObjectStaticBuffer& _RightBuffer) noexcept + { + decltype(DuplicateHandle)* _pfnDuplicateHandle = nullptr; + decltype(CloseHandle)* _pfnCloseHandle = nullptr; + + auto _uFirstProcessId = GetProcessId(_hLeft); + if (_uFirstProcessId == 0) + { + if (GetLastError() != ERROR_ACCESS_DENIED) + return false; + + _pfnDuplicateHandle = try_get_DuplicateHandle(); + _pfnCloseHandle = try_get_CloseHandle(); + if (_pfnDuplicateHandle == nullptr || _pfnCloseHandle == nullptr) + return false; + + HANDLE _hProcessTmp; + if (!_pfnDuplicateHandle(NtGetCurrentProcess(), _hLeft, NtGetCurrentProcess(), &_hProcessTmp, PROCESS_QUERY_INFORMATION, FALSE, 0)) + return false; + + _uFirstProcessId = GetProcessId(_hProcessTmp); + _pfnCloseHandle(_hProcessTmp); + if (_uFirstProcessId == 0) + return false; + } + + auto _uSecondProcessId = GetProcessId(_hRigth); + if (_uSecondProcessId == 0) + { + if (GetLastError() != ERROR_ACCESS_DENIED) + return false; + + if (!_pfnDuplicateHandle) + { + _pfnDuplicateHandle = try_get_DuplicateHandle(); + _pfnCloseHandle = try_get_CloseHandle(); + + if (_pfnDuplicateHandle == nullptr || _pfnCloseHandle == nullptr) + return false; + } + + HANDLE _hProcessTmp; + if (!_pfnDuplicateHandle(NtGetCurrentProcess(), _hRigth, NtGetCurrentProcess(), &_hProcessTmp, PROCESS_QUERY_INFORMATION, FALSE, 0)) + return false; + + _uSecondProcessId = GetProcessId(_hProcessTmp); + _pfnCloseHandle(_hProcessTmp); + if (_uSecondProcessId == 0) + return false; + } + + return _uFirstProcessId == _uSecondProcessId; + } + + bool __fastcall CompareThreadHandle(HANDLE _hLeft, ObjectStaticBuffer& _LeftBuffer, HANDLE _hRigth, ObjectStaticBuffer& _RightBuffer) noexcept + { + decltype(DuplicateHandle)* _pfnDuplicateHandle = nullptr; + decltype(CloseHandle)* _pfnCloseHandle = nullptr; + + auto _uFirstThreadId = GetThreadId(_hLeft); + if (_uFirstThreadId == 0) + { + if (GetLastError() != ERROR_ACCESS_DENIED) + return false; + + _pfnDuplicateHandle = try_get_DuplicateHandle(); + _pfnCloseHandle = try_get_CloseHandle(); + if (_pfnDuplicateHandle == nullptr || _pfnCloseHandle == nullptr) + return false; + + HANDLE _hHandleTmp; + if (!_pfnDuplicateHandle(NtGetCurrentProcess(), _hLeft, NtGetCurrentProcess(), &_hHandleTmp, THREAD_QUERY_INFORMATION, FALSE, 0)) + return false; + + _uFirstThreadId = GetThreadId(_hHandleTmp); + _pfnCloseHandle(_hHandleTmp); + if (_uFirstThreadId == 0) + return false; + } + + auto _uSecondThreadId = GetThreadId(_hRigth); + if (_uSecondThreadId == 0) + { + if (GetLastError() != ERROR_ACCESS_DENIED) + return false; + + if (!_pfnDuplicateHandle) + { + _pfnDuplicateHandle = try_get_DuplicateHandle(); + _pfnCloseHandle = try_get_CloseHandle(); + + if (_pfnDuplicateHandle == nullptr || _pfnCloseHandle == nullptr) + return false; + } + + HANDLE _hHandleTmp; + if (!_pfnDuplicateHandle(NtGetCurrentProcess(), _hRigth, NtGetCurrentProcess(), &_hHandleTmp, THREAD_QUERY_INFORMATION, FALSE, 0)) + { + return false; + } + + _uSecondThreadId = GetThreadId(_hHandleTmp); + _pfnCloseHandle(_hHandleTmp); + if (_uSecondThreadId == 0) + return false; + } + + return _uFirstThreadId == _uSecondThreadId; + } + + bool __fastcall CompareFileHandle(HANDLE _hFirstObjectHandle, ObjectStaticBuffer& _FirstObjectBuffer, HANDLE _hSecondObjectHandle, ObjectStaticBuffer& _SecondObjectBuffer) noexcept + { + // 提高判断效率,因为CompareObjectRef存在阻塞。 + // 如果是同一个对象,那么必然是同一个文件。当然是同一个文件不一定就是同一个对象。 + const auto _bRet1 = GetFileInformationByHandle(_hFirstObjectHandle, &_FirstObjectBuffer.FileInformation); + const auto _bRet2 = GetFileInformationByHandle(_hSecondObjectHandle, &_SecondObjectBuffer.FileInformation); + + if (_bRet1 != _bRet2) + return false; + + if (_bRet1) + { + if (_FirstObjectBuffer.FileInformation.dwVolumeSerialNumber != _SecondObjectBuffer.FileInformation.dwVolumeSerialNumber + || _FirstObjectBuffer.FileInformation.nFileIndexHigh != _SecondObjectBuffer.FileInformation.nFileIndexHigh + || _FirstObjectBuffer.FileInformation.nFileIndexLow != _SecondObjectBuffer.FileInformation.nFileIndexLow) + { + return false; + } + } + + return CompareObjectRef(_hFirstObjectHandle, _FirstObjectBuffer, _hSecondObjectHandle, _SecondObjectBuffer); + } + + bool __fastcall CompareTokenHandle(HANDLE _hFirstObjectHandle, ObjectStaticBuffer& _FirstObjectBuffer, HANDLE _hSecondObjectHandle, ObjectStaticBuffer& _SecondObjectBuffer) noexcept + { + decltype(DuplicateHandle)* _pfnDuplicateHandle = nullptr; + decltype(CloseHandle)* _pfnCloseHandle = nullptr; + + DWORD _uResultLength; + if (!GetTokenInformation(_hFirstObjectHandle, TokenStatistics, &_FirstObjectBuffer.TokenStatistics, sizeof(_FirstObjectBuffer.TokenStatistics), &_uResultLength)) + { + if (GetLastError() != ERROR_ACCESS_DENIED) + return false; + + _pfnDuplicateHandle = try_get_DuplicateHandle(); + _pfnCloseHandle = try_get_CloseHandle(); + if (_pfnDuplicateHandle == nullptr || _pfnCloseHandle == nullptr) + return false; + + HANDLE _hTmp; + if (!_pfnDuplicateHandle(NtCurrentProcess(), _hFirstObjectHandle, NtCurrentProcess(), &_hTmp, TOKEN_QUERY, FALSE, 0)) + return false; + + const auto _bRet = GetTokenInformation(_hTmp, TokenStatistics, &_FirstObjectBuffer.TokenStatistics, sizeof(_FirstObjectBuffer.TokenStatistics), &_uResultLength); + _pfnCloseHandle(_hTmp); + if (!_bRet) + return false; + } + + if (!GetTokenInformation(_hSecondObjectHandle, TokenStatistics, &_SecondObjectBuffer.TokenStatistics, sizeof(_SecondObjectBuffer.TokenStatistics), &_uResultLength)) + { + if (GetLastError() != ERROR_ACCESS_DENIED) + return false; + + if (!_pfnDuplicateHandle) + { + _pfnDuplicateHandle = try_get_DuplicateHandle(); + _pfnCloseHandle = try_get_CloseHandle(); + if (_pfnDuplicateHandle == nullptr || _pfnCloseHandle == nullptr) + return false; + } + HANDLE _hTmp; + if (!_pfnDuplicateHandle(NtCurrentProcess(), _hSecondObjectHandle, NtCurrentProcess(), &_hTmp, TOKEN_QUERY, FALSE, 0)) + return false; + + const auto _bRet = GetTokenInformation(_hTmp, TokenStatistics, &_SecondObjectBuffer.TokenStatistics, sizeof(_SecondObjectBuffer.TokenStatistics), &_uResultLength); + _pfnCloseHandle(_hTmp); + if (!_bRet) + return false; + } + + return _FirstObjectBuffer.TokenStatistics.TokenId.LowPart == _SecondObjectBuffer.TokenStatistics.TokenId.LowPart + && _FirstObjectBuffer.TokenStatistics.TokenId.HighPart == _SecondObjectBuffer.TokenStatistics.TokenId.HighPart; + } +#endif + } +} +#endif + +namespace YY::Thunks +{ + +#if (YY_Thunks_Support_Version < NTDDI_WIN10) + + // 最低受支持的客户端 Windows 2000 专业版 [桌面应用 |UWP 应用] + // 最低受支持的服务器 Windows 2000 Server[桌面应用 | UWP 应用] + // 虽然2000就支持,但是为了实现CompareObjectHandles,目前需要处理一下关闭。 + __DEFINE_THUNK( + kernel32, + 4, + BOOL, + WINAPI, + CloseHandle, + _In_ _Post_ptr_invalid_ HANDLE _hObject + ) + { + const auto _pfnCloseHandle = try_get_CloseHandle(); + const auto _pfnCompareObjectHandles = try_get_CompareObjectHandles(); + + if (_pfnCompareObjectHandles == nullptr && _hObject && _hObject != INVALID_HANDLE_VALUE) + { + ::AcquireSRWLockShared(&g_CompareObjectHandles); + } + // 空指针故意崩溃 + auto _bRet = _pfnCloseHandle(_hObject); + + if (_pfnCompareObjectHandles == nullptr && _hObject && _hObject != INVALID_HANDLE_VALUE) + { + auto _lStatus = GetLastError(); + ::ReleaseSRWLockShared(&g_CompareObjectHandles); + SetLastError(_lStatus); + } + + return _bRet; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN10) + + // 最低受支持的客户端 Windows 2000 专业版 [桌面应用 |UWP 应用] + // 最低受支持的服务器 Windows 2000 Server[桌面应用 | UWP 应用] + // 虽然2000就支持,但是为了实现CompareObjectHandles,目前需要处理一下关闭。 + __DEFINE_THUNK( + kernel32, + 28, + BOOL, + WINAPI, + DuplicateHandle, + _In_ HANDLE _hSourceProcessHandle, + _In_ HANDLE _hSourceHandle, + _In_ HANDLE _hTargetProcessHandle, + _Outptr_ LPHANDLE _phTargetHandle, + _In_ DWORD _fDesiredAccess, + _In_ BOOL _bInheritHandle, + _In_ DWORD _uOptions + ) + { + const auto _pfnDuplicateHandle = try_get_DuplicateHandle(); + const auto _pfnCompareObjectHandles = try_get_CompareObjectHandles(); + + bool _bNeedLock = false; + if (_pfnCompareObjectHandles) + { + // 无须加锁 + } + if (_hTargetProcessHandle == NtGetCurrentProcess() || GetProcessId(_hTargetProcessHandle) == GetCurrentProcessId()) + { + _bNeedLock = true; + } + else if ((DUPLICATE_CLOSE_SOURCE & _uOptions) + && (_hSourceProcessHandle == NtGetCurrentProcess() || GetProcessId(_hSourceProcessHandle) == GetCurrentProcessId())) + { + _bNeedLock = true; + } + + if (_bNeedLock) + { + ::AcquireSRWLockShared(&g_CompareObjectHandles); + } + + // 空指针故意崩溃 + auto _bRet = _pfnDuplicateHandle(_hSourceProcessHandle, _hSourceHandle, _hTargetProcessHandle, _phTargetHandle, _fDesiredAccess, _bInheritHandle, _uOptions); + + if (_bNeedLock) + { + auto _lStatus = GetLastError(); + ::ReleaseSRWLockShared(&g_CompareObjectHandles); + SetLastError(_lStatus); + } + return _bRet; + } +#endif + +#if (YY_Thunks_Support_Version < NTDDI_WIN10) + + // 最低受支持的客户端 Windows 10 [桌面应用 |UWP 应用] + // 最低受支持的服务器 Windows Server 2016[桌面应用 | UWP 应用] + __DEFINE_THUNK( + api_ms_win_core_handle_l1_1_0, + 8, + BOOL, + WINAPI, + CompareObjectHandles, + _In_ HANDLE _hFirstObjectHandle, + _In_ HANDLE _hSecondObjectHandle + ) + { + if (const auto _pfnCompareObjectHandles = try_get_CompareObjectHandles()) + { + return _pfnCompareObjectHandles(_hFirstObjectHandle, _hSecondObjectHandle); + } + + ObjectStaticBuffer _FirstObjectBuffer; + ObjectStaticBuffer _SecondObjectBuffer; + + if (_hFirstObjectHandle == _hSecondObjectHandle) + { + if (NtGetCurrentProcess() == _hFirstObjectHandle + || NtGetCurrentThread() == _hFirstObjectHandle) + { + return TRUE; + } + + const auto _pfnNtQueryObject = try_get_NtQueryObject(); + if (!_pfnNtQueryObject) + return FALSE; + + // 用来检测句柄是否合法 + LONG _Status = _pfnNtQueryObject(_hFirstObjectHandle, ObjectBasicInformation, &_FirstObjectBuffer, sizeof(_FirstObjectBuffer.BaseInfo), nullptr); + if (_Status < 0) + { + return FALSE; + } + return TRUE; + } + + const auto _pfnNtQueryObject = try_get_NtQueryObject(); + if (!_pfnNtQueryObject) + return FALSE; + + + LONG _Status = _pfnNtQueryObject(_hFirstObjectHandle, ObjectBasicInformation, &_FirstObjectBuffer, sizeof(_FirstObjectBuffer.BaseInfo), nullptr); + + // 实际测试,ObjectBasicInformation 只出现无效句柄错误 + if (_Status < 0) + { + return FALSE; + } + + if (_FirstObjectBuffer.BaseInfo.HandleCount == 1) + { + // 引用计数为 1,这肯定不可能与另外一个句柄是同一个内核对象 + return FALSE; + } + + _Status = _pfnNtQueryObject(_hSecondObjectHandle, ObjectBasicInformation, &_SecondObjectBuffer, sizeof(_SecondObjectBuffer.BaseInfo), nullptr); + if (_Status < 0) + { + return FALSE; + } + + if (_SecondObjectBuffer.BaseInfo.HandleCount == 1) + { + // 引用计数为 1,这肯定不可能与另外一个句柄是同一个内核对象 + return FALSE; + } + + if (_FirstObjectBuffer.BaseInfo.NameInfoSize != _SecondObjectBuffer.BaseInfo.NameInfoSize + || _FirstObjectBuffer.BaseInfo.TypeInfoSize != _SecondObjectBuffer.BaseInfo.TypeInfoSize) + { + return FALSE; + } + + _Status = _pfnNtQueryObject(_hFirstObjectHandle, ObjectTypeInformation, &_FirstObjectBuffer, sizeof(_FirstObjectBuffer), nullptr); + if (_Status < 0) + { + return FALSE; + } + _Status = _pfnNtQueryObject(_hSecondObjectHandle, ObjectTypeInformation, &_SecondObjectBuffer, sizeof(_SecondObjectBuffer), nullptr); + if (_Status < 0) + { + return FALSE; + } + + // 同一个内核句柄,必然拥有相同的TypeName。 + if (!internal::IsEqual(_FirstObjectBuffer.TypeInfo.TypeName, _SecondObjectBuffer.TypeInfo.TypeName)) + { + return FALSE; + } + + // 我们不直接比较句柄的Name,因为某些句柄获取Name会导致阻塞,而比如文件,文件相同也并非意味着是同一对象。 + // 我们也不能无脑判断ObjectRef,因为它也带有锁,而且无法完全保证其他代码不复制句柄。 + // 下面这个表格存储了所有已知的内核对象快速判断是否同一对象的方法。 + static const CompareObjectItem s_CompareObjectTable[] = + { + { L"Event", &CompareObjectName }, + { L"Process", &CompareProcessHandle }, + { L"Thread", &CompareThreadHandle }, + { L"Section", &CompareObjectName }, + { L"Mutant", &CompareObjectName }, + { L"Semaphore", &CompareObjectName }, + { L"File", &CompareFileHandle }, + { L"WindowStation", &CompareObjectName }, + { L"Desktop", &CompareObjectName }, + { L"Directory", &CompareObjectName }, + { L"Timer", &CompareObjectName }, + { L"KeyedEvent", &CompareObjectName }, + { L"Token", &CompareTokenHandle }, + { L"ALPC Port", &CompareObjectName }, + }; + + for (auto& _CompareObject : s_CompareObjectTable) + { + if (internal::IsEqualI(_FirstObjectBuffer.TypeInfo.TypeName, _CompareObject.TypeName)) + { + return _CompareObject.pfnCompareObject(_hFirstObjectHandle, _FirstObjectBuffer, _hSecondObjectHandle, _SecondObjectBuffer); + } + } + + // 保底逻辑,判断二个句柄的引用计数是否同步。但是需要注意的是该方法比较缓慢,因为需要加锁!如果这里有更好方案,欢迎PR。 + // Key : 重复打开时不是同一个内核对象 + // CreateIoCompletionPort : 无法获取名称 + // TmTx : 无法获取名称 + return CompareObjectRef(_hFirstObjectHandle, _FirstObjectBuffer, _hSecondObjectHandle, _SecondObjectBuffer); + } +#endif +} diff --git a/src/Thunks/api-ms-win-core-libraryloader.hpp b/src/Thunks/api-ms-win-core-libraryloader.hpp index bf5ff407..cc1a0c2a 100644 --- a/src/Thunks/api-ms-win-core-libraryloader.hpp +++ b/src/Thunks/api-ms-win-core-libraryloader.hpp @@ -1,9 +1,13 @@  #ifdef YY_Thunks_Implemented -namespace YY::Thunks::internal +namespace YY::Thunks::Fallback { namespace { +#if YY_Thunks_Support_Version < NTDDI_WIN8 + static DWORD s_DirectoryFlags/* = 0*/; +#endif + /*LSTATUS __fastcall BasepGetModuleHandleExParameterValidation( _In_ DWORD dwFlags, _In_opt_ LPCSTR lpModuleName, @@ -30,11 +34,101 @@ namespace YY::Thunks::internal SetLastError(ERROR_INVALID_PARAMETER); \ return FALSE; \ } + +#define __FORWARD_DLL_MODULE HMODULE(((TEB*)NtCurrentTeb())->ProcessEnvironmentBlock->ImageBaseAddress) + + template + HMODULE __fastcall ForwardDll(_In_z_ const Char* _szLibFileName) + { +#if defined(__ENABLE_WORKAROUND_1_GetProcAddress_ProcessPrng) && (YY_Thunks_Support_Version < NTDDI_WIN7) + if (_szLibFileName == nullptr || *_szLibFileName == L'\0') + return nullptr; + + auto _szFileName = _szLibFileName; + for (; *_szLibFileName; ) + { + if (*_szLibFileName == Char('\\') || *_szLibFileName == Char('/')) + { + ++_szLibFileName; + _szFileName = _szLibFileName; + } + else + { + ++_szLibFileName; + } + } + +#if defined(__ENABLE_WORKAROUND_1_GetProcAddress_ProcessPrng) && (YY_Thunks_Support_Version < NTDDI_WIN7) + if (internal::GetSystemVersion() < internal::MakeVersion(6, 1) + && StringCompareIgnoreCaseByAscii(_szFileName, L"bcryptprimitives", 16) == 0) + { + _szFileName += 16; + if (*_szFileName == L'\0' || StringCompareIgnoreCaseByAscii(_szFileName, ".dll", -1) == 0) + { + // Windows 7以下平台没有这个DLL,用进程模块句柄伪装一下。 + return __FORWARD_DLL_MODULE; + } + } +#endif +#endif + return nullptr; + } + +#if defined(__ENABLE_WORKAROUND_1_GetProcAddress_ProcessPrng) && YY_Thunks_Support_Version < NTDDI_WIN8 + void* __fastcall try_get_GetProcAddress(const ProcInfo& _ProcInfo) + { + auto _hModule = _ProcInfo.pfnGetModule(); + if (!_hModule) + return nullptr; + +#if defined(__USING_NTDLL_LIB) + void* _pProc = nullptr; + ANSI_STRING _sFunctionName = YY::Thunks::internal::MakeNtString(_ProcInfo.szProcName); + const LONG _Status = LdrGetProcedureAddress(_hModule, &_sFunctionName, 0, &_pProc); + return _Status >= 0 ? _pProc : nullptr; +#else // !defined(__USING_NTDLL_LIB) + + // 防止遇到畸形的DLL,抓个异常 + __try + { + ULONG _uSize; + auto _pExport = (_IMAGE_EXPORT_DIRECTORY*)YY_ImageDirectoryEntryToData(_hModule, IMAGE_DIRECTORY_ENTRY_EXPORT, &_uSize); + if (!_pExport) + return nullptr; + + if (_pExport->AddressOfNames == 0 || _pExport->AddressOfFunctions == 0 || _pExport->AddressOfNameOrdinals == 0) + return nullptr; + + auto _puFunctions = (const DWORD*)(PBYTE(_hModule) + _pExport->AddressOfFunctions); + auto _puNames = (const DWORD*)(PBYTE(_hModule) + _pExport->AddressOfNames); + auto _puNameOrdinals = (const WORD*)(PBYTE(_hModule) + _pExport->AddressOfNameOrdinals); + + for (DWORD i = 0; i != _pExport->NumberOfNames; ++i) + { + auto _uName = _puNames[i]; + if (_uName == 0) + continue; + + auto _szName = (char*)(PBYTE(_hModule) + _uName); + + if (StringCompare(_szName, _ProcInfo.szProcName, -1) == 0) + { + auto _pfn = PBYTE(_hModule) + _puFunctions[_puNameOrdinals[i]]; + return _pfn; + } + } + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + } + return nullptr; +#endif // defined(__USING_NTDLL_LIB) + } +#endif } } #endif - namespace YY::Thunks { #if (YY_Thunks_Support_Version < NTDDI_WINXP) @@ -259,11 +353,15 @@ namespace YY::Thunks } - if (try_get_AddDllDirectory() != nullptr) + if (dwFlags == 0 || try_get_AddDllDirectory() != nullptr) { //存在AddDllDirectory说明支持 LOAD_LIBRARY_SEARCH_SYSTEM32 等功能,直接调用pLoadLibraryExW即可。 - return pLoadLibraryExW(lpLibFileName, hFile, dwFlags); + auto _hModule = pLoadLibraryExW(lpLibFileName, hFile, dwFlags); + if (_hModule) + return _hModule; + + return Fallback::ForwardDll(lpLibFileName); } #if (YY_Thunks_Support_Version < NTDDI_WIN6) @@ -612,7 +710,10 @@ namespace YY::Thunks YY::Thunks::internal::BaseSetLastNTError(Status); } - return hModule; + if (hModule) + return hModule; + + return Fallback::ForwardDll(lpLibFileName); } while (false); #if defined(_X86_) || defined(_M_IX86) @@ -633,7 +734,10 @@ namespace YY::Thunks SetLastError(lStatus); } #endif - return hModule; + if(hModule) + return hModule; + + return Fallback::ForwardDll(lpLibFileName); } #endif @@ -662,11 +766,15 @@ namespace YY::Thunks } - if (try_get_AddDllDirectory() != nullptr) + if (dwFlags == 0 || try_get_AddDllDirectory() != nullptr) { //存在AddDllDirectory说明支持 LOAD_LIBRARY_SEARCH_SYSTEM32 等功能,直接调用pLoadLibraryExW即可。 - return pLoadLibraryExA(lpLibFileName, hFile, dwFlags); + auto _hModule = pLoadLibraryExA(lpLibFileName, hFile, dwFlags); + if (_hModule) + return _hModule; + + return Fallback::ForwardDll(lpLibFileName); } wchar_t szLibFileNameUnicode[512]; @@ -870,4 +978,149 @@ namespace YY::Thunks return TRUE; } #endif + + +#if defined(__ENABLE_WORKAROUND_1_GetProcAddress_ProcessPrng) && YY_Thunks_Support_Version < NTDDI_WIN8 + + // 所有系统都支持,但是这个函数的存在是为了能顺利取到 ProcessPrng,Windows 8开始原生支持ProcessPrng + __DEFINE_THUNK( + kernel32, + 8, + FARPROC, + WINAPI, + GetProcAddress, + _In_ HMODULE hModule, + _In_ LPCSTR lpProcName + ) + { +#if defined(__ENABLE_WORKAROUND_1_GetProcAddress_ProcessPrng) && YY_Thunks_Support_Version < NTDDI_WIN8 + if (uintptr_t(lpProcName) > UINT16_MAX) + { + if (StringCompare(lpProcName, "ProcessPrng", -1) == 0) + { + if (hModule == __FORWARD_DLL_MODULE || hModule == try_get_module_bcryptprimitives()) + { + const auto _pfn = try_get_ProcessPrng(); + return reinterpret_cast(_pfn ? _pfn : &ProcessPrng); + } + } + } +#endif + const auto _pfnGetProcAddress = try_get_GetProcAddress(); + if (!_pfnGetProcAddress) + { + SetLastError(ERROR_PROC_NOT_FOUND); + return nullptr; + } + + return _pfnGetProcAddress(hModule, lpProcName); + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN8) + + // 所有系统都支持,但是现在为了支持 SetDefaultDllDirectories就Thunk下 + __DEFINE_THUNK( + kernel32, + 4, + HMODULE, + WINAPI, + LoadLibraryW, + _In_ LPCWSTR _szLibFileName + ) + { + if (Fallback::s_DirectoryFlags == 0 || try_get_AddDllDirectory()) + { + const auto _pfnLoadLibraryW = try_get_LoadLibraryW(); + if (!_pfnLoadLibraryW) + { + SetLastError(ERROR_PROC_NOT_FOUND); + return nullptr; + } + + auto _hModule = _pfnLoadLibraryW(_szLibFileName); + if (_hModule) + return _hModule; + + return Fallback::ForwardDll(_szLibFileName); + } + else + { + return LoadLibraryExW(_szLibFileName, NULL, Fallback::s_DirectoryFlags); + } + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN8) + + // 所有系统都支持,但是现在为了支持 SetDefaultDllDirectories + __DEFINE_THUNK( + kernel32, + 4, + HMODULE, + WINAPI, + LoadLibraryA, + _In_ LPCSTR _szLibFileName + ) + { + if (Fallback::s_DirectoryFlags == 0 || try_get_AddDllDirectory()) + { + const auto _pfnLoadLibraryA = try_get_LoadLibraryA(); + if (!_pfnLoadLibraryA) + { + SetLastError(ERROR_PROC_NOT_FOUND); + return nullptr; + } + + auto _hModule = _pfnLoadLibraryA(_szLibFileName); + if (_hModule) + return _hModule; + + return Fallback::ForwardDll(_szLibFileName); + } + else + { + return LoadLibraryExA(_szLibFileName, NULL, Fallback::s_DirectoryFlags); + } + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN8) + + // 最低受支持的客户端 Windows 8 [仅限桌面应用],在 Windows 7、Windows Server 2008 R2、Windows Vista 和 Windows Server 2008 上KB2533623 + // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] + __DEFINE_THUNK( + kernel32, + 4, + BOOL, + WINAPI, + SetDefaultDllDirectories, + _In_ DWORD _fDirectoryFlags + ) + { + if (const auto _pfnSetDefaultDllDirectories = try_get_SetDefaultDllDirectories()) + { + return _pfnSetDefaultDllDirectories(_fDirectoryFlags); + } + + if (_fDirectoryFlags & LOAD_LIBRARY_SEARCH_DEFAULT_DIRS) + { + _fDirectoryFlags &= ~LOAD_LIBRARY_SEARCH_DEFAULT_DIRS; + _fDirectoryFlags |= LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32 | LOAD_LIBRARY_SEARCH_USER_DIRS; + } + + if (_fDirectoryFlags & ~(LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32 | LOAD_LIBRARY_SEARCH_USER_DIRS)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + Fallback::s_DirectoryFlags = _fDirectoryFlags; + return TRUE; + } +#endif + } diff --git a/src/Thunks/api-ms-win-core-localization.hpp b/src/Thunks/api-ms-win-core-localization.hpp index 993e0cd6..f285ec80 100644 --- a/src/Thunks/api-ms-win-core-localization.hpp +++ b/src/Thunks/api-ms-win-core-localization.hpp @@ -444,7 +444,7 @@ while (bottom <= top) { int middle = (bottom + top) / 2; - int testIndex = __wcsnicmp_ascii(szLocaleName, NeutralToSpecificMap[middle].szNeutralLocale, LOCALE_NAME_MAX_LENGTH); + int testIndex = StringCompareIgnoreCaseByAscii(szLocaleName, NeutralToSpecificMap[middle].szNeutralLocale, LOCALE_NAME_MAX_LENGTH); if (testIndex == 0) return NeutralToSpecificMap[middle].szSpecificLocale; @@ -908,7 +908,7 @@ { return GetUserDefaultLCID(); } - else if (__wcsnicmp_ascii(lpName, LOCALE_NAME_SYSTEM_DEFAULT, _countof(LOCALE_NAME_SYSTEM_DEFAULT)) == 0) + else if (StringCompareIgnoreCaseByAscii(lpName, LOCALE_NAME_SYSTEM_DEFAULT, _countof(LOCALE_NAME_SYSTEM_DEFAULT)) == 0) { return GetSystemDefaultLCID(); } @@ -1308,7 +1308,7 @@ while (bottom <= top) { int middle = (bottom + top) / 2; - int testIndex = __wcsnicmp_ascii(lpName, LocaleNameToLcidTable[middle].localeName, LOCALE_NAME_MAX_LENGTH); + int testIndex = StringCompareIgnoreCaseByAscii(lpName, LocaleNameToLcidTable[middle].localeName, LOCALE_NAME_MAX_LENGTH); if (testIndex == 0) return LocaleNameToLcidTable[middle].lcid; diff --git a/src/Thunks/api-ms-win-core-memory.hpp b/src/Thunks/api-ms-win-core-memory.hpp index 7aaa86d3..bad5079b 100644 --- a/src/Thunks/api-ms-win-core-memory.hpp +++ b/src/Thunks/api-ms-win-core-memory.hpp @@ -1,630 +1,670 @@  -namespace YY +namespace YY::Thunks { - namespace Thunks - { #if (YY_Thunks_Support_Version < NTDDI_WIN7) - //Minimum supported client Windows 8 [desktop apps only] - //Minimum supported server Windows Server 2012 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 4, - BOOL, - WINAPI, - GetMemoryErrorHandlingCapabilities, - _Out_ PULONG Capabilities - ) + //Minimum supported client Windows 8 [desktop apps only] + //Minimum supported server Windows Server 2012 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 4, + BOOL, + WINAPI, + GetMemoryErrorHandlingCapabilities, + _Out_ PULONG Capabilities + ) + { + if (auto pGetMemoryErrorHandlingCapabilities = try_get_GetMemoryErrorHandlingCapabilities()) { - if (auto pGetMemoryErrorHandlingCapabilities = try_get_GetMemoryErrorHandlingCapabilities()) - { - return pGetMemoryErrorHandlingCapabilities(Capabilities); - } - - //别怪我,我们什么特性都不支持…… - *Capabilities = 0; - return TRUE; + return pGetMemoryErrorHandlingCapabilities(Capabilities); } + + //别怪我,我们什么特性都不支持…… + *Capabilities = 0; + return TRUE; + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN6) - //Minimum supported client Windows Vista [desktop apps only] - //Minimum supported server Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 16, - _Success_(return != FALSE) - BOOL, - WINAPI, - AllocateUserPhysicalPagesNuma, - _In_ HANDLE hProcess, - _Inout_ PULONG_PTR NumberOfPages, - _Out_writes_to_(*NumberOfPages,*NumberOfPages) PULONG_PTR PageArray, - _In_ DWORD nndPreferred - ) + //Minimum supported client Windows Vista [desktop apps only] + //Minimum supported server Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 16, + _Success_(return != FALSE) + BOOL, + WINAPI, + AllocateUserPhysicalPagesNuma, + _In_ HANDLE hProcess, + _Inout_ PULONG_PTR NumberOfPages, + _Out_writes_to_(*NumberOfPages,*NumberOfPages) PULONG_PTR PageArray, + _In_ DWORD nndPreferred + ) + { + if (const auto pAllocateUserPhysicalPagesNuma = try_get_AllocateUserPhysicalPagesNuma()) { - if (const auto pAllocateUserPhysicalPagesNuma = try_get_AllocateUserPhysicalPagesNuma()) - { - return pAllocateUserPhysicalPagesNuma(hProcess, NumberOfPages, PageArray, nndPreferred); - } - - return AllocateUserPhysicalPages(hProcess, NumberOfPages, PageArray); + return pAllocateUserPhysicalPagesNuma(hProcess, NumberOfPages, PageArray, nndPreferred); } + + return AllocateUserPhysicalPages(hProcess, NumberOfPages, PageArray); + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN10) - //Minimum supported client Windows 10 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2016 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 16, - PVOID, - WINAPI, - VirtualAllocFromApp, - _In_opt_ PVOID BaseAddress, - _In_ SIZE_T Size, - _In_ ULONG AllocationType, - _In_ ULONG Protection - ) + //Minimum supported client Windows 10 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2016 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 16, + PVOID, + WINAPI, + VirtualAllocFromApp, + _In_opt_ PVOID BaseAddress, + _In_ SIZE_T Size, + _In_ ULONG AllocationType, + _In_ ULONG Protection + ) + { + if (const auto pVirtualAllocFromApp = try_get_VirtualAllocFromApp()) { - if (const auto pVirtualAllocFromApp = try_get_VirtualAllocFromApp()) - { - return pVirtualAllocFromApp(BaseAddress, Size, AllocationType, Protection); - } + return pVirtualAllocFromApp(BaseAddress, Size, AllocationType, Protection); + } - return VirtualAlloc(BaseAddress, Size, AllocationType, Protection); - } + return VirtualAlloc(BaseAddress, Size, AllocationType, Protection); + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN6) - //Minimum supported client Windows Vista [desktop apps only] - //Minimum supported server Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 24, - LPVOID, - WINAPI, - VirtualAllocExNuma, - _In_ HANDLE hProcess, - _In_opt_ LPVOID lpAddress, - _In_ SIZE_T dwSize, - _In_ DWORD flAllocationType, - _In_ DWORD flProtect, - _In_ DWORD nndPreferred - ) + //Minimum supported client Windows Vista [desktop apps only] + //Minimum supported server Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 24, + LPVOID, + WINAPI, + VirtualAllocExNuma, + _In_ HANDLE hProcess, + _In_opt_ LPVOID lpAddress, + _In_ SIZE_T dwSize, + _In_ DWORD flAllocationType, + _In_ DWORD flProtect, + _In_ DWORD nndPreferred + ) + { + if (const auto pVirtualAllocExNuma = try_get_VirtualAllocExNuma()) { - if (const auto pVirtualAllocExNuma = try_get_VirtualAllocExNuma()) - { - return pVirtualAllocExNuma(hProcess, lpAddress, dwSize, flAllocationType, flProtect, nndPreferred); - } - - return VirtualAllocEx(hProcess, lpAddress, dwSize, flAllocationType, flProtect); + return pVirtualAllocExNuma(hProcess, lpAddress, dwSize, flAllocationType, flProtect, nndPreferred); } + + return VirtualAllocEx(hProcess, lpAddress, dwSize, flAllocationType, flProtect); + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN10) - //Minimum supported client Windows 10 [desktop apps only] - //Minimum supported server Windows Server 2016 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 28, - PVOID, - WINAPI, - VirtualAlloc2, - _In_opt_ HANDLE Process, - _In_opt_ PVOID BaseAddress, - _In_ SIZE_T Size, - _In_ ULONG AllocationType, - _In_ ULONG PageProtection, - _Inout_updates_opt_(ParameterCount) MEM_EXTENDED_PARAMETER* ExtendedParameters, - _In_ ULONG ParameterCount - ) + //Minimum supported client Windows 10 [desktop apps only] + //Minimum supported server Windows Server 2016 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 28, + PVOID, + WINAPI, + VirtualAlloc2, + _In_opt_ HANDLE Process, + _In_opt_ PVOID BaseAddress, + _In_ SIZE_T Size, + _In_ ULONG AllocationType, + _In_ ULONG PageProtection, + _Inout_updates_opt_(ParameterCount) MEM_EXTENDED_PARAMETER* ExtendedParameters, + _In_ ULONG ParameterCount + ) + { + if (const auto pVirtualAlloc2 = try_get_VirtualAlloc2()) { - if (const auto pVirtualAlloc2 = try_get_VirtualAlloc2()) - { - return pVirtualAlloc2(Process, BaseAddress, Size, AllocationType, PageProtection, ExtendedParameters, ParameterCount); - } + return pVirtualAlloc2(Process, BaseAddress, Size, AllocationType, PageProtection, ExtendedParameters, ParameterCount); + } - //尝试搜索 MemExtendedParameterNumaNode - if (ExtendedParameters && ParameterCount) + //尝试搜索 MemExtendedParameterNumaNode + if (ExtendedParameters && ParameterCount) + { + for (ULONG i = 0; i != ParameterCount; ++i) { - for (ULONG i = 0; i != ParameterCount; ++i) + if (ExtendedParameters[i].Type == MemExtendedParameterNumaNode) { - if (ExtendedParameters[i].Type == MemExtendedParameterNumaNode) - { - return VirtualAllocExNuma(Process, BaseAddress, Size, AllocationType, PageProtection, ExtendedParameters[i].ULong); - } + return VirtualAllocExNuma(Process, BaseAddress, Size, AllocationType, PageProtection, ExtendedParameters[i].ULong); } } - - //尽力了,只能调用VirtualAllocEx。 - return VirtualAllocEx(Process, BaseAddress, Size, AllocationType, PageProtection); } + + //尽力了,只能调用VirtualAllocEx。 + return VirtualAllocEx(Process, BaseAddress, Size, AllocationType, PageProtection); + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN10) - //Minimum supported client Windows 10 [desktop apps only] - //Minimum supported server Windows Server 2016 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 28, - PVOID, - WINAPI, - VirtualAlloc2FromApp, - _In_opt_ HANDLE Process, - _In_opt_ PVOID BaseAddress, - _In_ SIZE_T Size, - _In_ ULONG AllocationType, - _In_ ULONG PageProtection, - _Inout_updates_opt_(ParameterCount) MEM_EXTENDED_PARAMETER* ExtendedParameters, - _In_ ULONG ParameterCount - ) + //Minimum supported client Windows 10 [desktop apps only] + //Minimum supported server Windows Server 2016 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 28, + PVOID, + WINAPI, + VirtualAlloc2FromApp, + _In_opt_ HANDLE Process, + _In_opt_ PVOID BaseAddress, + _In_ SIZE_T Size, + _In_ ULONG AllocationType, + _In_ ULONG PageProtection, + _Inout_updates_opt_(ParameterCount) MEM_EXTENDED_PARAMETER* ExtendedParameters, + _In_ ULONG ParameterCount + ) + { + if (const auto pVirtualAlloc2FromApp = try_get_VirtualAlloc2FromApp()) { - if (const auto pVirtualAlloc2FromApp = try_get_VirtualAlloc2FromApp()) - { - return pVirtualAlloc2FromApp(Process, BaseAddress, Size, AllocationType, PageProtection, ExtendedParameters, ParameterCount); - } + return pVirtualAlloc2FromApp(Process, BaseAddress, Size, AllocationType, PageProtection, ExtendedParameters, ParameterCount); + } - //尝试搜索 MemExtendedParameterNumaNode - if (ExtendedParameters && ParameterCount) + //尝试搜索 MemExtendedParameterNumaNode + if (ExtendedParameters && ParameterCount) + { + for (ULONG i = 0; i != ParameterCount; ++i) { - for (ULONG i = 0; i != ParameterCount; ++i) + if (ExtendedParameters[i].Type == MemExtendedParameterNumaNode) { - if (ExtendedParameters[i].Type == MemExtendedParameterNumaNode) - { - return VirtualAllocExNuma(Process, BaseAddress, Size, AllocationType, PageProtection, ExtendedParameters[i].ULong); - } + return VirtualAllocExNuma(Process, BaseAddress, Size, AllocationType, PageProtection, ExtendedParameters[i].ULong); } } - - return VirtualAllocEx(Process, BaseAddress, Size, AllocationType, PageProtection); } + + return VirtualAllocEx(Process, BaseAddress, Size, AllocationType, PageProtection); + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN6) - //Minimum supported client Windows Vista [desktop apps only] - //Minimum supported server Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 28, - HANDLE, - WINAPI, - CreateFileMappingNumaW, - _In_ HANDLE hFile, - _In_opt_ LPSECURITY_ATTRIBUTES lpFileMappingAttributes, - _In_ DWORD flProtect, - _In_ DWORD dwMaximumSizeHigh, - _In_ DWORD dwMaximumSizeLow, - _In_opt_ LPCWSTR lpName, - _In_ DWORD nndPreferred - ) + //Minimum supported client Windows Vista [desktop apps only] + //Minimum supported server Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 28, + HANDLE, + WINAPI, + CreateFileMappingNumaW, + _In_ HANDLE hFile, + _In_opt_ LPSECURITY_ATTRIBUTES lpFileMappingAttributes, + _In_ DWORD flProtect, + _In_ DWORD dwMaximumSizeHigh, + _In_ DWORD dwMaximumSizeLow, + _In_opt_ LPCWSTR lpName, + _In_ DWORD nndPreferred + ) + { + if (const auto pCreateFileMappingNumaW = try_get_CreateFileMappingNumaW()) { - if (const auto pCreateFileMappingNumaW = try_get_CreateFileMappingNumaW()) - { - return pCreateFileMappingNumaW(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName, nndPreferred); - } - - return CreateFileMappingW(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName); + return pCreateFileMappingNumaW(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName, nndPreferred); } + + return CreateFileMappingW(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName); + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN6) - //Minimum supported client Windows Vista [desktop apps only] - //Minimum supported server Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - kernel32, - 28, - HANDLE, - WINAPI, - CreateFileMappingNumaA, - _In_ HANDLE hFile, - _In_opt_ LPSECURITY_ATTRIBUTES lpFileMappingAttributes, - _In_ DWORD flProtect, - _In_ DWORD dwMaximumSizeHigh, - _In_ DWORD dwMaximumSizeLow, - _In_opt_ LPCSTR lpName, - _In_ DWORD nndPreferred - ) + //Minimum supported client Windows Vista [desktop apps only] + //Minimum supported server Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + kernel32, + 28, + HANDLE, + WINAPI, + CreateFileMappingNumaA, + _In_ HANDLE hFile, + _In_opt_ LPSECURITY_ATTRIBUTES lpFileMappingAttributes, + _In_ DWORD flProtect, + _In_ DWORD dwMaximumSizeHigh, + _In_ DWORD dwMaximumSizeLow, + _In_opt_ LPCSTR lpName, + _In_ DWORD nndPreferred + ) + { + if (const auto pCreateFileMappingNumaA = try_get_CreateFileMappingNumaA()) { - if (const auto pCreateFileMappingNumaA = try_get_CreateFileMappingNumaA()) - { - return pCreateFileMappingNumaA(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName, nndPreferred); - } - - return CreateFileMappingA(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName); + return pCreateFileMappingNumaA(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName, nndPreferred); } + + return CreateFileMappingA(hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName); + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN8) - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 24, - HANDLE, - WINAPI, - CreateFileMappingFromApp, - _In_ HANDLE hFile, - _In_opt_ PSECURITY_ATTRIBUTES SecurityAttributes, - _In_ ULONG PageProtection, - _In_ ULONG64 MaximumSize, - _In_opt_ PCWSTR Name - ) + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 24, + HANDLE, + WINAPI, + CreateFileMappingFromApp, + _In_ HANDLE hFile, + _In_opt_ PSECURITY_ATTRIBUTES SecurityAttributes, + _In_ ULONG PageProtection, + _In_ ULONG64 MaximumSize, + _In_opt_ PCWSTR Name + ) + { + if (const auto pVirtualAllocExNuma = try_get_CreateFileMappingFromApp()) { - if (const auto pVirtualAllocExNuma = try_get_CreateFileMappingFromApp()) - { - return pVirtualAllocExNuma(hFile, SecurityAttributes, PageProtection, MaximumSize, Name); - } + return pVirtualAllocExNuma(hFile, SecurityAttributes, PageProtection, MaximumSize, Name); + } - return CreateFileMappingW(hFile, SecurityAttributes, PageProtection, MaximumSize >> 32, MaximumSize & 0xFFFFFFFF, Name); - } + return CreateFileMappingW(hFile, SecurityAttributes, PageProtection, MaximumSize >> 32, MaximumSize & 0xFFFFFFFF, Name); + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN8) - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 40, - HANDLE, - WINAPI, - CreateFileMapping2, - _In_ HANDLE File, - _In_opt_ SECURITY_ATTRIBUTES* SecurityAttributes, - _In_ ULONG DesiredAccess, - _In_ ULONG PageProtection, - _In_ ULONG AllocationAttributes, - _In_ ULONG64 MaximumSize, - _In_opt_ PCWSTR Name, - _Inout_updates_opt_(ParameterCount) MEM_EXTENDED_PARAMETER* ExtendedParameters, - _In_ ULONG ParameterCount - ) + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 40, + HANDLE, + WINAPI, + CreateFileMapping2, + _In_ HANDLE File, + _In_opt_ SECURITY_ATTRIBUTES* SecurityAttributes, + _In_ ULONG DesiredAccess, + _In_ ULONG PageProtection, + _In_ ULONG AllocationAttributes, + _In_ ULONG64 MaximumSize, + _In_opt_ PCWSTR Name, + _Inout_updates_opt_(ParameterCount) MEM_EXTENDED_PARAMETER* ExtendedParameters, + _In_ ULONG ParameterCount + ) + { + if (const auto pCreateFileMapping2 = try_get_CreateFileMapping2()) { - if (const auto pCreateFileMapping2 = try_get_CreateFileMapping2()) - { - return pCreateFileMapping2(File, SecurityAttributes, DesiredAccess, PageProtection, AllocationAttributes, MaximumSize, Name, ExtendedParameters, ParameterCount); - } + return pCreateFileMapping2(File, SecurityAttributes, DesiredAccess, PageProtection, AllocationAttributes, MaximumSize, Name, ExtendedParameters, ParameterCount); + } - //尝试搜索 MemExtendedParameterNumaNode - if (ExtendedParameters && ParameterCount) + //尝试搜索 MemExtendedParameterNumaNode + if (ExtendedParameters && ParameterCount) + { + for (ULONG i = 0; i != ParameterCount; ++i) { - for (ULONG i = 0; i != ParameterCount; ++i) + if (ExtendedParameters[i].Type == MemExtendedParameterNumaNode) { - if (ExtendedParameters[i].Type == MemExtendedParameterNumaNode) - { - return CreateFileMappingNumaW(File, SecurityAttributes, PageProtection | AllocationAttributes, MaximumSize >> 32, MaximumSize & 0xFFFFFFFF, Name, ExtendedParameters[i].ULong); - } + return CreateFileMappingNumaW(File, SecurityAttributes, PageProtection | AllocationAttributes, MaximumSize >> 32, MaximumSize & 0xFFFFFFFF, Name, ExtendedParameters[i].ULong); } } - - return CreateFileMappingW(File, SecurityAttributes, PageProtection | AllocationAttributes, MaximumSize >> 32, MaximumSize & 0xFFFFFFFF, Name); } + + return CreateFileMappingW(File, SecurityAttributes, PageProtection | AllocationAttributes, MaximumSize >> 32, MaximumSize & 0xFFFFFFFF, Name); + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN8) - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 20, - PVOID, - WINAPI, - MapViewOfFileFromApp, - _In_ HANDLE hFileMappingObject, - _In_ ULONG DesiredAccess, - _In_ ULONG64 FileOffset, - _In_ SIZE_T NumberOfBytesToMap - ) + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 20, + PVOID, + WINAPI, + MapViewOfFileFromApp, + _In_ HANDLE hFileMappingObject, + _In_ ULONG DesiredAccess, + _In_ ULONG64 FileOffset, + _In_ SIZE_T NumberOfBytesToMap + ) + { + if (const auto pMapViewOfFileFromApp = try_get_MapViewOfFileFromApp()) { - if (const auto pMapViewOfFileFromApp = try_get_MapViewOfFileFromApp()) - { - return pMapViewOfFileFromApp(hFileMappingObject, DesiredAccess, FileOffset, NumberOfBytesToMap); - } - - return MapViewOfFile(hFileMappingObject, DesiredAccess, FileOffset >> 32, FileOffset & 0xFFFFFFFF, NumberOfBytesToMap); + return pMapViewOfFileFromApp(hFileMappingObject, DesiredAccess, FileOffset, NumberOfBytesToMap); } + + return MapViewOfFile(hFileMappingObject, DesiredAccess, FileOffset >> 32, FileOffset & 0xFFFFFFFF, NumberOfBytesToMap); + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN8) - //Minimum supported client Windows 8 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 8, - BOOL, - WINAPI, - UnmapViewOfFileEx, - _In_ PVOID BaseAddress, - _In_ ULONG UnmapFlags - ) + //Minimum supported client Windows 8 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2012 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 8, + BOOL, + WINAPI, + UnmapViewOfFileEx, + _In_ PVOID BaseAddress, + _In_ ULONG UnmapFlags + ) + { + if (const auto pUnmapViewOfFileEx = try_get_UnmapViewOfFileEx()) { - if (const auto pUnmapViewOfFileEx = try_get_UnmapViewOfFileEx()) - { - return pUnmapViewOfFileEx(BaseAddress, UnmapFlags); - } - - return UnmapViewOfFile(BaseAddress); + return pUnmapViewOfFileEx(BaseAddress, UnmapFlags); } + + return UnmapViewOfFile(BaseAddress); + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN10) - //Minimum supported client Windows 10 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2016 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 16, - BOOL, - WINAPI, - VirtualProtectFromApp, - _In_ PVOID Address, - _In_ SIZE_T Size, - _In_ ULONG NewProtection, - _Out_ PULONG OldProtection - ) + //Minimum supported client Windows 10 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2016 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + VirtualProtectFromApp, + _In_ PVOID Address, + _In_ SIZE_T Size, + _In_ ULONG NewProtection, + _Out_ PULONG OldProtection + ) + { + if (const auto pVirtualProtectFromApp = try_get_VirtualProtectFromApp()) { - if (const auto pVirtualProtectFromApp = try_get_VirtualProtectFromApp()) - { - return pVirtualProtectFromApp(Address, Size, NewProtection, OldProtection); - } - - return VirtualProtect(Address, Size, NewProtection, OldProtection); + return pVirtualProtectFromApp(Address, Size, NewProtection, OldProtection); } + + return VirtualProtect(Address, Size, NewProtection, OldProtection); + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN10) - //Minimum supported client Windows 10 [desktop apps | UWP apps] - //Minimum supported server Windows Server 2016 [desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 12, - HANDLE, - WINAPI, - OpenFileMappingFromApp, - _In_ ULONG DesiredAccess, - _In_ BOOL InheritHandle, - _In_ PCWSTR Name - ) + //Minimum supported client Windows 10 [desktop apps | UWP apps] + //Minimum supported server Windows Server 2016 [desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 12, + HANDLE, + WINAPI, + OpenFileMappingFromApp, + _In_ ULONG DesiredAccess, + _In_ BOOL InheritHandle, + _In_ PCWSTR Name + ) + { + if (const auto pOpenFileMappingFromApp = try_get_OpenFileMappingFromApp()) { - if (const auto pOpenFileMappingFromApp = try_get_OpenFileMappingFromApp()) - { - return pOpenFileMappingFromApp(DesiredAccess, InheritHandle, Name); - } - - return OpenFileMappingW(DesiredAccess, InheritHandle, Name); + return pOpenFileMappingFromApp(DesiredAccess, InheritHandle, Name); } + + return OpenFileMappingW(DesiredAccess, InheritHandle, Name); + } #endif #if (YY_Thunks_Support_Version < NTDDI_WS03) - //Minimum supported client Windows Vista[desktop apps | UWP apps] - //Minimum supported server Windows Server 2003[desktop apps | UWP apps] - __DEFINE_THUNK( - kernel32, - 0, - SIZE_T, - WINAPI, - GetLargePageMinimum, - VOID - ) + //Minimum supported client Windows Vista[desktop apps | UWP apps] + //Minimum supported server Windows Server 2003[desktop apps | UWP apps] + __DEFINE_THUNK( + kernel32, + 0, + SIZE_T, + WINAPI, + GetLargePageMinimum, + VOID + ) + { + if (const auto pGetLargePageMinimum = try_get_GetLargePageMinimum()) { - if (const auto pGetLargePageMinimum = try_get_GetLargePageMinimum()) - { - return pGetLargePageMinimum(); - } - - return 0; + return pGetLargePageMinimum(); } + + return 0; + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN10) - // 最低受支持的客户端 Windows 8.1 更新[桌面应用 | UWP 应用] - // 最低受支持的服务器 Windows Server 2012 R2 更新[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 8, - DWORD, - WINAPI, - DiscardVirtualMemory, - _Inout_updates_(_uSize) PVOID _pVirtualAddress, - _In_ SIZE_T _uSize - ) + // 最低受支持的客户端 Windows 8.1 更新[桌面应用 | UWP 应用] + // 最低受支持的服务器 Windows Server 2012 R2 更新[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 8, + DWORD, + WINAPI, + DiscardVirtualMemory, + _Inout_updates_(_uSize) PVOID _pVirtualAddress, + _In_ SIZE_T _uSize + ) + { + if (const auto _pfnDiscardVirtualMemory = try_get_DiscardVirtualMemory()) { - if (const auto _pfnDiscardVirtualMemory = try_get_DiscardVirtualMemory()) - { - return _pfnDiscardVirtualMemory(_pVirtualAddress, _uSize); - } + return _pfnDiscardVirtualMemory(_pVirtualAddress, _uSize); + } - if (!VirtualAlloc(_pVirtualAddress, _uSize, MEM_RESET, PAGE_NOACCESS)) - return GetLastError(); + if (!VirtualAlloc(_pVirtualAddress, _uSize, MEM_RESET, PAGE_NOACCESS)) + return GetLastError(); - return ERROR_SUCCESS; - } + return ERROR_SUCCESS; + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN10) - // 最低受支持的客户端 Windows 8.1 更新[桌面应用 | UWP 应用] - // 最低受支持的服务器 Windows Server 2012 R2 更新[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 12, - DWORD, - WINAPI, - OfferVirtualMemory, - _Inout_updates_(_uSize) PVOID _pVirtualAddress, - _In_ SIZE_T _uSize, - _In_ OFFER_PRIORITY _ePriority - ) + // 最低受支持的客户端 Windows 8.1 更新[桌面应用 | UWP 应用] + // 最低受支持的服务器 Windows Server 2012 R2 更新[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 12, + DWORD, + WINAPI, + OfferVirtualMemory, + _Inout_updates_(_uSize) PVOID _pVirtualAddress, + _In_ SIZE_T _uSize, + _In_ OFFER_PRIORITY _ePriority + ) + { + if (const auto _pfnOfferVirtualMemory = try_get_OfferVirtualMemory()) { - if (const auto _pfnOfferVirtualMemory = try_get_OfferVirtualMemory()) - { - return _pfnOfferVirtualMemory(_pVirtualAddress, _uSize, _ePriority); - } + return _pfnOfferVirtualMemory(_pVirtualAddress, _uSize, _ePriority); + } - // 低版本系统不支持这个机制,所以暂时假装内存充足,不触发回收 - UNREFERENCED_PARAMETER(_ePriority); + // 低版本系统不支持这个机制,所以暂时假装内存充足,不触发回收 + UNREFERENCED_PARAMETER(_ePriority); - MEMORY_BASIC_INFORMATION _Info; - if (VirtualQuery(_pVirtualAddress, &_Info, sizeof(_Info)) == 0) - return GetLastError(); + MEMORY_BASIC_INFORMATION _Info; + if (VirtualQuery(_pVirtualAddress, &_Info, sizeof(_Info)) == 0) + return GetLastError(); - if (_Info.State != MEM_COMMIT) - return ERROR_INVALID_PARAMETER; + if (_Info.State != MEM_COMMIT) + return ERROR_INVALID_PARAMETER; - if ((char*)_pVirtualAddress + _uSize > (char*)_Info.BaseAddress + _Info.RegionSize) - return ERROR_INVALID_PARAMETER; + if ((char*)_pVirtualAddress + _uSize > (char*)_Info.BaseAddress + _Info.RegionSize) + return ERROR_INVALID_PARAMETER; - return ERROR_SUCCESS; - } + return ERROR_SUCCESS; + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN10) - // 最低受支持的客户端 Windows 8.1 更新[桌面应用 | UWP 应用] - // 最低受支持的服务器 Windows Server 2012 R2 更新[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 8, - DWORD, - WINAPI, - ReclaimVirtualMemory, - _In_reads_(_uSize) void const* _pVirtualAddress, - _In_ SIZE_T _uSize - ) + // 最低受支持的客户端 Windows 8.1 更新[桌面应用 | UWP 应用] + // 最低受支持的服务器 Windows Server 2012 R2 更新[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 8, + DWORD, + WINAPI, + ReclaimVirtualMemory, + _In_reads_(_uSize) void const* _pVirtualAddress, + _In_ SIZE_T _uSize + ) + { + if (const auto _pfnReclaimVirtualMemory = try_get_ReclaimVirtualMemory()) { - if (const auto _pfnReclaimVirtualMemory = try_get_ReclaimVirtualMemory()) - { - return _pfnReclaimVirtualMemory(_pVirtualAddress, _uSize); - } + return _pfnReclaimVirtualMemory(_pVirtualAddress, _uSize); + } - MEMORY_BASIC_INFORMATION _Info; - if (VirtualQuery(_pVirtualAddress, &_Info, sizeof(_Info)) == 0) - return GetLastError(); + MEMORY_BASIC_INFORMATION _Info; + if (VirtualQuery(_pVirtualAddress, &_Info, sizeof(_Info)) == 0) + return GetLastError(); - if (_Info.State != MEM_COMMIT) - return ERROR_INVALID_PARAMETER; + if (_Info.State != MEM_COMMIT) + return ERROR_INVALID_PARAMETER; - if ((char*)_pVirtualAddress + _uSize > (char*)_Info.BaseAddress + _Info.RegionSize) - return ERROR_INVALID_PARAMETER; + if ((char*)_pVirtualAddress + _uSize > (char*)_Info.BaseAddress + _Info.RegionSize) + return ERROR_INVALID_PARAMETER; - return ERROR_SUCCESS; - } + return ERROR_SUCCESS; + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN10) - // 最低受支持的客户端 Windows 8 [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] - __DEFINE_THUNK( - kernel32, - 16, - BOOL, - WINAPI, - PrefetchVirtualMemory, - _In_ HANDLE _hProcess, - _In_ ULONG_PTR _uNumberOfEntries, - _In_reads_(_uNumberOfEntries) PWIN32_MEMORY_RANGE_ENTRY _pVirtualAddresses, - _In_ ULONG _fFlags - ) + // 最低受支持的客户端 Windows 8 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + PrefetchVirtualMemory, + _In_ HANDLE _hProcess, + _In_ ULONG_PTR _uNumberOfEntries, + _In_reads_(_uNumberOfEntries) PWIN32_MEMORY_RANGE_ENTRY _pVirtualAddresses, + _In_ ULONG _fFlags + ) + { + if (const auto _pfnPrefetchVirtualMemory = try_get_PrefetchVirtualMemory()) { - if (const auto _pfnPrefetchVirtualMemory = try_get_PrefetchVirtualMemory()) - { - return _pfnPrefetchVirtualMemory(_hProcess, _uNumberOfEntries, _pVirtualAddresses, _fFlags); - } + return _pfnPrefetchVirtualMemory(_hProcess, _uNumberOfEntries, _pVirtualAddresses, _fFlags); + } - UNREFERENCED_PARAMETER(_hProcess); - UNREFERENCED_PARAMETER(_uNumberOfEntries); - UNREFERENCED_PARAMETER(_pVirtualAddresses); - UNREFERENCED_PARAMETER(_fFlags); + UNREFERENCED_PARAMETER(_hProcess); + UNREFERENCED_PARAMETER(_uNumberOfEntries); + UNREFERENCED_PARAMETER(_pVirtualAddresses); + UNREFERENCED_PARAMETER(_fFlags); - // 假装自己预取成功 - return TRUE; - } + // 假装自己预取成功 + return TRUE; + } #endif #if (YY_Thunks_Support_Version < NTDDI_WS03) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] - // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 16, - BOOL, - WINAPI, - SetProcessWorkingSetSizeEx, - _In_ HANDLE _hProcess, - _In_ SIZE_T _uMinimumWorkingSetSize, - _In_ SIZE_T _uMaximumWorkingSetSize, - _In_ DWORD _fFlags - ) + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + SetProcessWorkingSetSizeEx, + _In_ HANDLE _hProcess, + _In_ SIZE_T _uMinimumWorkingSetSize, + _In_ SIZE_T _uMaximumWorkingSetSize, + _In_ DWORD _fFlags + ) + { + if (const auto _pfnSetProcessWorkingSetSizeEx = try_get_SetProcessWorkingSetSizeEx()) { - if (const auto _pfnSetProcessWorkingSetSizeEx = try_get_SetProcessWorkingSetSizeEx()) - { - return _pfnSetProcessWorkingSetSizeEx(_hProcess, _uMinimumWorkingSetSize, _uMaximumWorkingSetSize, _fFlags); - } - - return SetProcessWorkingSetSize(_hProcess, _uMinimumWorkingSetSize, _uMaximumWorkingSetSize); + return _pfnSetProcessWorkingSetSizeEx(_hProcess, _uMinimumWorkingSetSize, _uMaximumWorkingSetSize, _fFlags); } + + return SetProcessWorkingSetSize(_hProcess, _uMinimumWorkingSetSize, _uMaximumWorkingSetSize); + } #endif #if (YY_Thunks_Support_Version < NTDDI_WS03) - // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] - // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 16, - BOOL, - WINAPI, - GetProcessWorkingSetSizeEx, - _In_ HANDLE _hProcess, - _Out_ PSIZE_T _puMinimumWorkingSetSize, - _Out_ PSIZE_T _puMaximumWorkingSetSize, - _Out_ PDWORD _pfFlags - ) + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的服务器 Windows Server 2003[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + GetProcessWorkingSetSizeEx, + _In_ HANDLE _hProcess, + _Out_ PSIZE_T _puMinimumWorkingSetSize, + _Out_ PSIZE_T _puMaximumWorkingSetSize, + _Out_ PDWORD _pfFlags + ) + { + if (const auto _pfnGetProcessWorkingSetSizeEx = try_get_GetProcessWorkingSetSizeEx()) { - if (const auto _pfnGetProcessWorkingSetSizeEx = try_get_GetProcessWorkingSetSizeEx()) - { - return _pfnGetProcessWorkingSetSizeEx(_hProcess, _puMinimumWorkingSetSize, _puMaximumWorkingSetSize, _pfFlags); - } - - *_pfFlags = 0; - return GetProcessWorkingSetSize(_hProcess, _puMinimumWorkingSetSize, _puMaximumWorkingSetSize); + return _pfnGetProcessWorkingSetSizeEx(_hProcess, _puMinimumWorkingSetSize, _puMaximumWorkingSetSize, _pfFlags); } + + *_pfFlags = 0; + return GetProcessWorkingSetSize(_hProcess, _puMinimumWorkingSetSize, _puMaximumWorkingSetSize); + } +#endif + + +#if defined(__ENABLE_WORKAROUND_2_UNNAME_OBJECT_DACL) && (YY_Thunks_Support_Version < NTDDI_WINBLUE) + + __DEFINE_THUNK( + kernel32, + 24, + HANDLE, + WINAPI, + CreateFileMappingW, + _In_ HANDLE _hFile, + _In_opt_ LPSECURITY_ATTRIBUTES _pFileMappingAttributes, + _In_ DWORD _flProtect, + _In_ DWORD _uMaximumSizeHigh, + _In_ DWORD _uMaximumSizeLow, + _In_opt_ LPCWSTR _szName + ) + { + const auto _pfnCreateFileMappingW = try_get_CreateFileMappingW(); + if (!_pfnCreateFileMappingW) + { + SetLastError(ERROR_FUNCTION_FAILED); + return NULL; + } + +#if (YY_Thunks_Support_Version < NTDDI_WINBLUE) + wchar_t _szTmpMapName[256]; + if (_pFileMappingAttributes && (_szName == nullptr || *_szName == L'\0') && internal::GetSystemVersion() < internal::MakeVersion(6, 3)) + { + internal::StringBuffer _TmpBuild(_szTmpMapName, _countof(_szTmpMapName)); + _TmpBuild.AppendString(L"YY_Thunks_Unnamed_Section_"); + GUID _Id; + const auto _pfnRtlGenRandom = try_get_SystemFunction036(); + _pfnRtlGenRandom(&_Id, sizeof(_Id)); + _TmpBuild.AppendGUID(_Id); + + _szName = _szTmpMapName; + } #endif + + return _pfnCreateFileMappingW(_hFile, _pFileMappingAttributes, _flProtect, _uMaximumSizeHigh, _uMaximumSizeLow, _szName); } +#endif } diff --git a/src/Thunks/api-ms-win-core-registry.hpp b/src/Thunks/api-ms-win-core-registry.hpp index b9563529..648000fc 100644 --- a/src/Thunks/api-ms-win-core-registry.hpp +++ b/src/Thunks/api-ms-win-core-registry.hpp @@ -1,396 +1,349 @@  -namespace YY +namespace YY::Thunks { - namespace Thunks - { - #if (YY_Thunks_Support_Version < NTDDI_WS03SP1) - //Windows XP Professional x64 Edition, Windows Server 2003 with SP1 - __DEFINE_THUNK( - advapi32, - 16, - LSTATUS, - APIENTRY, - RegDeleteKeyExW, - _In_ HKEY hKey, - _In_ LPCWSTR lpSubKey, - _In_ REGSAM samDesired, - _Reserved_ DWORD Reserved - ) + //Windows XP Professional x64 Edition, Windows Server 2003 with SP1 + __DEFINE_THUNK( + advapi32, + 16, + LSTATUS, + APIENTRY, + RegDeleteKeyExW, + _In_ HKEY hKey, + _In_ LPCWSTR lpSubKey, + _In_ REGSAM samDesired, + _Reserved_ DWORD Reserved + ) + { + if(auto const pRegDeleteKeyExW = try_get_RegDeleteKeyExW()) { - if(auto const pRegDeleteKeyExW = try_get_RegDeleteKeyExW()) - { - return pRegDeleteKeyExW(hKey, lpSubKey, samDesired, Reserved); - } + return pRegDeleteKeyExW(hKey, lpSubKey, samDesired, Reserved); + } - return RegDeleteKeyW(hKey, lpSubKey); - } + return RegDeleteKeyW(hKey, lpSubKey); + } #endif #if (YY_Thunks_Support_Version < NTDDI_WS03SP1) - //Windows XP Professional x64 Edition, Windows Server 2003 with SP1 - __DEFINE_THUNK( - advapi32, - 16, - LSTATUS, - APIENTRY, - RegDeleteKeyExA, - _In_ HKEY hKey, - _In_ LPCSTR lpSubKey, - _In_ REGSAM samDesired, - _Reserved_ DWORD Reserved - ) + //Windows XP Professional x64 Edition, Windows Server 2003 with SP1 + __DEFINE_THUNK( + advapi32, + 16, + LSTATUS, + APIENTRY, + RegDeleteKeyExA, + _In_ HKEY hKey, + _In_ LPCSTR lpSubKey, + _In_ REGSAM samDesired, + _Reserved_ DWORD Reserved + ) + { + if (auto const pRegDeleteKeyExA = try_get_RegDeleteKeyExA()) { - if (auto const pRegDeleteKeyExA = try_get_RegDeleteKeyExA()) - { - return pRegDeleteKeyExA(hKey, lpSubKey, samDesired, Reserved); - } - - return RegDeleteKeyA(hKey, lpSubKey); + return pRegDeleteKeyExA(hKey, lpSubKey, samDesired, Reserved); } -#endif - - -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - advapi32, - 24, - LSTATUS, - APIENTRY, - RegSetKeyValueW, - _In_ HKEY hKey, - _In_opt_ LPCWSTR lpSubKey, - _In_opt_ LPCWSTR lpValueName, - _In_ DWORD dwType, - _In_reads_bytes_opt_(cbData) LPCVOID lpData, - _In_ DWORD cbData - ) - { - //Empty? - if (lpSubKey == nullptr || *lpSubKey == L'\0') - { - return RegSetValueExW(hKey, lpValueName, 0, dwType, (const BYTE*)lpData, cbData); - } - else - { - HKEY hSubKey; - auto lStatus = RegCreateKeyExW(hKey, lpSubKey, 0, nullptr, 0, KEY_SET_VALUE, nullptr, &hSubKey, nullptr); - - if (lStatus == ERROR_SUCCESS) - { - lStatus = RegSetValueExW(hSubKey, lpValueName, 0, dwType, (const BYTE*)lpData, cbData); - - RegCloseKey(hSubKey); - } - return lStatus; - } - } + return RegDeleteKeyA(hKey, lpSubKey); + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN6) - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - advapi32, - 24, - LSTATUS, - APIENTRY, - RegSetKeyValueA, - _In_ HKEY hKey, - _In_opt_ LPCSTR lpSubKey, - _In_opt_ LPCSTR lpValueName, - _In_ DWORD dwType, - _In_reads_bytes_opt_(cbData) LPCVOID lpData, - _In_ DWORD cbData - ) + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + advapi32, + 24, + LSTATUS, + APIENTRY, + RegSetKeyValueW, + _In_ HKEY hKey, + _In_opt_ LPCWSTR lpSubKey, + _In_opt_ LPCWSTR lpValueName, + _In_ DWORD dwType, + _In_reads_bytes_opt_(cbData) LPCVOID lpData, + _In_ DWORD cbData + ) + { + //Empty? + if (lpSubKey == nullptr || *lpSubKey == L'\0') { - //Empty? - if (lpSubKey == nullptr || *lpSubKey == '\0') - { - return RegSetValueExA(hKey, lpValueName, 0, dwType, (const BYTE*)lpData, cbData); - } - else - { - HKEY hSubKey; - auto lStatus = RegCreateKeyExA(hKey, lpSubKey, 0, nullptr, 0, KEY_SET_VALUE, nullptr, &hSubKey, nullptr); - - if (lStatus == ERROR_SUCCESS) - { - lStatus = RegSetValueExA(hSubKey, lpValueName, 0, dwType, (const BYTE*)lpData, cbData); - - RegCloseKey(hSubKey); - } - - return lStatus; - } + return RegSetValueExW(hKey, lpValueName, 0, dwType, (const BYTE*)lpData, cbData); } -#endif - - -#if (YY_Thunks_Support_Version < NTDDI_WIN6) - - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - advapi32, - 12, - LSTATUS, - APIENTRY, - RegDeleteKeyValueW, - _In_ HKEY hKey, - _In_opt_ LPCWSTR lpSubKey, - _In_opt_ LPCWSTR lpValueName - ) + else { HKEY hSubKey; - auto lStatus = RegOpenKeyExW(hKey, lpSubKey, 0, KEY_SET_VALUE, &hSubKey); + auto lStatus = RegCreateKeyExW(hKey, lpSubKey, 0, nullptr, 0, KEY_SET_VALUE, nullptr, &hSubKey, nullptr); if (lStatus == ERROR_SUCCESS) { - lStatus = RegDeleteValueW(hSubKey, lpValueName); + lStatus = RegSetValueExW(hSubKey, lpValueName, 0, dwType, (const BYTE*)lpData, cbData); + RegCloseKey(hSubKey); } return lStatus; } + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN6) - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - advapi32, - 12, - LSTATUS, - APIENTRY, - RegDeleteKeyValueA, - _In_ HKEY hKey, - _In_opt_ LPCSTR lpSubKey, - _In_opt_ LPCSTR lpValueName - ) + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + advapi32, + 24, + LSTATUS, + APIENTRY, + RegSetKeyValueA, + _In_ HKEY hKey, + _In_opt_ LPCSTR lpSubKey, + _In_opt_ LPCSTR lpValueName, + _In_ DWORD dwType, + _In_reads_bytes_opt_(cbData) LPCVOID lpData, + _In_ DWORD cbData + ) + { + //Empty? + if (lpSubKey == nullptr || *lpSubKey == '\0') + { + return RegSetValueExA(hKey, lpValueName, 0, dwType, (const BYTE*)lpData, cbData); + } + else { HKEY hSubKey; - auto lStatus = RegOpenKeyExA(hKey, lpSubKey, 0, KEY_SET_VALUE, &hSubKey); + auto lStatus = RegCreateKeyExA(hKey, lpSubKey, 0, nullptr, 0, KEY_SET_VALUE, nullptr, &hSubKey, nullptr); if (lStatus == ERROR_SUCCESS) { - lStatus = RegDeleteValueA(hSubKey, lpValueName); + lStatus = RegSetValueExA(hSubKey, lpValueName, 0, dwType, (const BYTE*)lpData, cbData); + RegCloseKey(hSubKey); } return lStatus; } + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN6) - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - advapi32, - 8, - LSTATUS, - APIENTRY, - RegDeleteTreeW, - _In_ HKEY hKey, - _In_opt_ LPCWSTR lpSubKey - ) + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + advapi32, + 12, + LSTATUS, + APIENTRY, + RegDeleteKeyValueW, + _In_ HKEY hKey, + _In_opt_ LPCWSTR lpSubKey, + _In_opt_ LPCWSTR lpValueName + ) + { + HKEY hSubKey; + auto lStatus = RegOpenKeyExW(hKey, lpSubKey, 0, KEY_SET_VALUE, &hSubKey); + + if (lStatus == ERROR_SUCCESS) { - return SHDeleteKeyW(hKey, lpSubKey); + lStatus = RegDeleteValueW(hSubKey, lpValueName); + RegCloseKey(hSubKey); } + + return lStatus; + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN6) - //Windows Vista, Windows Server 2008 - __DEFINE_THUNK( - advapi32, - 8, - LSTATUS, - APIENTRY, - RegDeleteTreeA, - _In_ HKEY hKey, - _In_opt_ LPCSTR lpSubKey - ) + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + advapi32, + 12, + LSTATUS, + APIENTRY, + RegDeleteKeyValueA, + _In_ HKEY hKey, + _In_opt_ LPCSTR lpSubKey, + _In_opt_ LPCSTR lpValueName + ) + { + HKEY hSubKey; + auto lStatus = RegOpenKeyExA(hKey, lpSubKey, 0, KEY_SET_VALUE, &hSubKey); + + if (lStatus == ERROR_SUCCESS) { - return SHDeleteKeyA(hKey, lpSubKey); + lStatus = RegDeleteValueA(hSubKey, lpValueName); + RegCloseKey(hSubKey); } + + return lStatus; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + advapi32, + 8, + LSTATUS, + APIENTRY, + RegDeleteTreeW, + _In_ HKEY hKey, + _In_opt_ LPCWSTR lpSubKey + ) + { + return SHDeleteKeyW(hKey, lpSubKey); + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + //Windows Vista, Windows Server 2008 + __DEFINE_THUNK( + advapi32, + 8, + LSTATUS, + APIENTRY, + RegDeleteTreeA, + _In_ HKEY hKey, + _In_opt_ LPCSTR lpSubKey + ) + { + return SHDeleteKeyA(hKey, lpSubKey); + } #endif #if (YY_Thunks_Support_Version < NTDDI_WS03SP1) - //Windows Vista, Windows XP Professional x64 Edition, Windows Server 2008, Windows Server 2003 with SP1 - __DEFINE_THUNK( - advapi32, - 28, - LSTATUS, - APIENTRY, - RegGetValueW, - HKEY hkey, - LPCWSTR lpSubKey, - LPCWSTR lpValue, - DWORD dwFlags, - LPDWORD pdwType, - PVOID pvData, - LPDWORD pcbData - ) - { + //Windows Vista, Windows XP Professional x64 Edition, Windows Server 2008, Windows Server 2003 with SP1 + __DEFINE_THUNK( + advapi32, + 28, + LSTATUS, + APIENTRY, + RegGetValueW, + HKEY hkey, + LPCWSTR lpSubKey, + LPCWSTR lpValue, + DWORD dwFlags, + LPDWORD pdwType, + PVOID pvData, + LPDWORD pcbData + ) + { #if (YY_Thunks_Support_Version >= NTDDI_WINXPSP2) - return SHRegGetValueW(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); + return SHRegGetValueW(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); #else - if (auto const pRegGetValueW = try_get_RegGetValueW()) - { - return pRegGetValueW(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); - } + if (auto const pRegGetValueW = try_get_RegGetValueW()) + { + return pRegGetValueW(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); + } - if (pvData && pcbData == nullptr - || (dwFlags & RRF_RT_ANY) == 0) - { - return ERROR_INVALID_PARAMETER; - } + if (pvData && pcbData == nullptr + || (dwFlags & RRF_RT_ANY) == 0) + { + return ERROR_INVALID_PARAMETER; + } - LSTATUS lStatus; + LSTATUS lStatus; - if (lpSubKey&&*lpSubKey) - { - lStatus = RegOpenKeyExW(hkey, lpSubKey, 0, KEY_QUERY_VALUE, &hkey); - if (lStatus != ERROR_SUCCESS) - return lStatus; - } + if (lpSubKey&&*lpSubKey) + { + lStatus = RegOpenKeyExW(hkey, lpSubKey, 0, KEY_QUERY_VALUE, &hkey); + if (lStatus != ERROR_SUCCESS) + return lStatus; + } - DWORD dwType; - DWORD cbData = pvData && pcbData ? *pcbData : 0; - const auto cbDataBackup = cbData; + DWORD dwType; + DWORD cbData = pvData && pcbData ? *pcbData : 0; + const auto cbDataBackup = cbData; - lStatus = RegQueryValueExW(hkey, lpValue, nullptr, &dwType, (LPBYTE)pvData, &cbData); + lStatus = RegQueryValueExW(hkey, lpValue, nullptr, &dwType, (LPBYTE)pvData, &cbData); - DWORD cbDataFix; - if (lStatus == ERROR_SUCCESS - || lStatus == ERROR_MORE_DATA) + DWORD cbDataFix; + if (lStatus == ERROR_SUCCESS + || lStatus == ERROR_MORE_DATA) + { + if (dwType == REG_MULTI_SZ) { - if (dwType == REG_MULTI_SZ) - { - //连续2个 null 结尾 - cbDataFix = cbData + sizeof(*lpValue) * 2; - } - else if (dwType == REG_SZ) + //连续2个 null 结尾 + cbDataFix = cbData + sizeof(*lpValue) * 2; + } + else if (dwType == REG_SZ) + { + //一个null 结尾 + cbDataFix = cbData + sizeof(*lpValue); + } + else if (dwType == REG_EXPAND_SZ) + { + if (dwFlags & RRF_NOEXPAND) { //一个null 结尾 cbDataFix = cbData + sizeof(*lpValue); } - else if (dwType == REG_EXPAND_SZ) + else { - if (dwFlags & RRF_NOEXPAND) - { - //一个null 结尾 - cbDataFix = cbData + sizeof(*lpValue); - } - else - { - //需要展开 - cbDataFix = pvData && pcbData ? *pcbData : 0; - lStatus = SHQueryValueExW(hkey, lpValue, nullptr, &dwType, pvData, &cbDataFix); + //需要展开 + cbDataFix = pvData && pcbData ? *pcbData : 0; + lStatus = SHQueryValueExW(hkey, lpValue, nullptr, &dwType, pvData, &cbDataFix); - if (lStatus == ERROR_SUCCESS - || lStatus == ERROR_MORE_DATA) - { - cbData = cbDataFix; - } + if (lStatus == ERROR_SUCCESS + || lStatus == ERROR_MORE_DATA) + { + cbData = cbDataFix; } } - else - { - cbDataFix = cbData; - } } - - if (lpSubKey&&*lpSubKey) + else { - RegCloseKey(hkey); + cbDataFix = cbData; } + } + if (lpSubKey&&*lpSubKey) + { + RegCloseKey(hkey); + } - if (lStatus == ERROR_SUCCESS - || lStatus == ERROR_MORE_DATA) - { - if (pdwType) - *pdwType = dwType; - - //检测类型是否支持 - switch (dwType) - { - case REG_NONE: - case REG_SZ: - case REG_EXPAND_SZ: - case REG_BINARY: - case REG_DWORD: - if ((dwFlags & (1 << dwType)) == 0) - { - lStatus = ERROR_UNSUPPORTED_TYPE; - break; - } - else if (pvData && lStatus == ERROR_SUCCESS) - { - //当函数成功时,保证字符串正常 NULL 结尾 - if (REG_SZ == dwType || REG_EXPAND_SZ == dwType) - { - //保证1个 NULL 结尾 - - - //sizeof(wchar_t) 边界对齐 - if (cbData % sizeof(*lpValue)) - { - if (cbData >= cbDataBackup) - { - lStatus = ERROR_MORE_DATA; - break; - } - - ((byte*)pvData)[cbData] = 0; - - ++cbData; - } - - - auto cStringMin = cbData / sizeof(*lpValue); - - - auto pString = (wchar_t*)pvData; - - if (cStringMin == 0 || pString[cStringMin - 1]) - { - if (cbData + sizeof(*lpValue) > cbDataBackup) - { - lStatus = ERROR_MORE_DATA; - break; - } - pString[cStringMin++] = L'\0'; - } + if (lStatus == ERROR_SUCCESS + || lStatus == ERROR_MORE_DATA) + { + if (pdwType) + *pdwType = dwType; - cbDataFix = cStringMin * sizeof(*lpValue); - } - } + //检测类型是否支持 + switch (dwType) + { + case REG_NONE: + case REG_SZ: + case REG_EXPAND_SZ: + case REG_BINARY: + case REG_DWORD: + if ((dwFlags & (1 << dwType)) == 0) + { + lStatus = ERROR_UNSUPPORTED_TYPE; break; - case REG_MULTI_SZ: - if ((dwFlags & RRF_RT_REG_MULTI_SZ) == 0) - { - lStatus = ERROR_UNSUPPORTED_TYPE; - } - else if (pvData && lStatus == ERROR_SUCCESS) + } + else if (pvData && lStatus == ERROR_SUCCESS) + { + //当函数成功时,保证字符串正常 NULL 结尾 + if (REG_SZ == dwType || REG_EXPAND_SZ == dwType) { - //保证最后一个字符串 NULL 结尾 并且 包含 NULL 结束符 + //保证1个 NULL 结尾 + //sizeof(wchar_t) 边界对齐 if (cbData % sizeof(*lpValue)) @@ -406,11 +359,13 @@ namespace YY ++cbData; } + auto cStringMin = cbData / sizeof(*lpValue); + auto pString = (wchar_t*)pvData; - if (cStringMin == 0) + if (cStringMin == 0 || pString[cStringMin - 1]) { if (cbData + sizeof(*lpValue) > cbDataBackup) { @@ -420,217 +375,231 @@ namespace YY pString[cStringMin++] = L'\0'; } - else if (pString[cStringMin - 1]) - { - if (cbData + sizeof(*lpValue) * 2 > cbDataBackup) - { - lStatus = ERROR_MORE_DATA; - break; - } - pString[cStringMin++] = L'\0'; + cbDataFix = cStringMin * sizeof(*lpValue); + } + } + break; + case REG_MULTI_SZ: + if ((dwFlags & RRF_RT_REG_MULTI_SZ) == 0) + { + lStatus = ERROR_UNSUPPORTED_TYPE; + } + else if (pvData && lStatus == ERROR_SUCCESS) + { + //保证最后一个字符串 NULL 结尾 并且 包含 NULL 结束符 - pString[cStringMin++] = L'\0'; + //sizeof(wchar_t) 边界对齐 + if (cbData % sizeof(*lpValue)) + { + if (cbData >= cbDataBackup) + { + lStatus = ERROR_MORE_DATA; + break; } - else if (cStringMin >= 2 && pString[cStringMin - 2]) + + ((byte*)pvData)[cbData] = 0; + + ++cbData; + } + + auto cStringMin = cbData / sizeof(*lpValue); + + auto pString = (wchar_t*)pvData; + + if (cStringMin == 0) + { + if (cbData + sizeof(*lpValue) > cbDataBackup) { - if (cbData + sizeof(*lpValue) > cbDataBackup) - { - lStatus = ERROR_MORE_DATA; - break; - } + lStatus = ERROR_MORE_DATA; + break; + } - pString[cStringMin++] = L'\0'; + pString[cStringMin++] = L'\0'; + } + else if (pString[cStringMin - 1]) + { + if (cbData + sizeof(*lpValue) * 2 > cbDataBackup) + { + lStatus = ERROR_MORE_DATA; + break; } - cbDataFix = cStringMin * sizeof(*lpValue); + pString[cStringMin++] = L'\0'; + + pString[cStringMin++] = L'\0'; } - break; - case REG_QWORD: - if ((dwFlags & RRF_RT_REG_QWORD) == 0) + else if (cStringMin >= 2 && pString[cStringMin - 2]) { - lStatus = ERROR_UNSUPPORTED_TYPE; + if (cbData + sizeof(*lpValue) > cbDataBackup) + { + lStatus = ERROR_MORE_DATA; + break; + } + + pString[cStringMin++] = L'\0'; } - break; - default: - if((dwFlags & RRF_RT_ANY) != RRF_RT_ANY) - lStatus = ERROR_UNSUPPORTED_TYPE; - break; + + cbDataFix = cStringMin * sizeof(*lpValue); + } + break; + case REG_QWORD: + if ((dwFlags & RRF_RT_REG_QWORD) == 0) + { + lStatus = ERROR_UNSUPPORTED_TYPE; } + break; + default: + if((dwFlags & RRF_RT_ANY) != RRF_RT_ANY) + lStatus = ERROR_UNSUPPORTED_TYPE; + break; + } - if (pcbData) - *pcbData = cbDataFix; + if (pcbData) + *pcbData = cbDataFix; - } + } - if ((RRF_ZEROONFAILURE & dwFlags) != 0 && lStatus) + if ((RRF_ZEROONFAILURE & dwFlags) != 0 && lStatus) + { + //全0填充 + if (pvData && cbDataBackup) { - //全0填充 - if (pvData && cbDataBackup) - { - memset(pvData, 0, cbDataBackup); - } + memset(pvData, 0, cbDataBackup); } + } - return lStatus; + return lStatus; #endif - } + } #endif #if (YY_Thunks_Support_Version < NTDDI_WS03SP1) - //Windows Vista, Windows XP Professional x64 Edition, Windows Server 2008, Windows Server 2003 with SP1 - __DEFINE_THUNK( - advapi32, - 28, - LSTATUS, - APIENTRY, - RegGetValueA, - HKEY hkey, - LPCSTR lpSubKey, - LPCSTR lpValue, - DWORD dwFlags, - LPDWORD pdwType, - PVOID pvData, - LPDWORD pcbData - ) - { + //Windows Vista, Windows XP Professional x64 Edition, Windows Server 2008, Windows Server 2003 with SP1 + __DEFINE_THUNK( + advapi32, + 28, + LSTATUS, + APIENTRY, + RegGetValueA, + HKEY hkey, + LPCSTR lpSubKey, + LPCSTR lpValue, + DWORD dwFlags, + LPDWORD pdwType, + PVOID pvData, + LPDWORD pcbData + ) + { #if (YY_Thunks_Support_Version >= NTDDI_WINXPSP2) - return SHRegGetValueA(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); + return SHRegGetValueA(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); #else - if (auto const pRegGetValueA = try_get_RegGetValueA()) - { - return pRegGetValueA(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); - } + if (auto const pRegGetValueA = try_get_RegGetValueA()) + { + return pRegGetValueA(hkey, lpSubKey, lpValue, dwFlags, pdwType, pvData, pcbData); + } - if (pvData && pcbData == nullptr - || (dwFlags & RRF_RT_ANY) == 0) - { - return ERROR_INVALID_PARAMETER; - } + if (pvData && pcbData == nullptr + || (dwFlags & RRF_RT_ANY) == 0) + { + return ERROR_INVALID_PARAMETER; + } - LSTATUS lStatus; + LSTATUS lStatus; - if (lpSubKey&&*lpSubKey) - { - lStatus = RegOpenKeyExA(hkey, lpSubKey, 0, KEY_QUERY_VALUE, &hkey); - if (lStatus != ERROR_SUCCESS) - return lStatus; - } + if (lpSubKey&&*lpSubKey) + { + lStatus = RegOpenKeyExA(hkey, lpSubKey, 0, KEY_QUERY_VALUE, &hkey); + if (lStatus != ERROR_SUCCESS) + return lStatus; + } - DWORD dwType; - DWORD cbData = pvData && pcbData ? *pcbData : 0; - const auto cbDataBackup = cbData; + DWORD dwType; + DWORD cbData = pvData && pcbData ? *pcbData : 0; + const auto cbDataBackup = cbData; - lStatus = RegQueryValueExA(hkey, lpValue, nullptr, &dwType, (LPBYTE)pvData, &cbData); + lStatus = RegQueryValueExA(hkey, lpValue, nullptr, &dwType, (LPBYTE)pvData, &cbData); - DWORD cbDataFix; - if (lStatus == ERROR_SUCCESS - || lStatus == ERROR_MORE_DATA) + DWORD cbDataFix; + if (lStatus == ERROR_SUCCESS + || lStatus == ERROR_MORE_DATA) + { + if (dwType == REG_MULTI_SZ) { - if (dwType == REG_MULTI_SZ) - { - //连续2个 null 结尾 - cbDataFix = cbData + sizeof(*lpValue) * 2; - } - else if (dwType == REG_SZ) + //连续2个 null 结尾 + cbDataFix = cbData + sizeof(*lpValue) * 2; + } + else if (dwType == REG_SZ) + { + //一个null 结尾 + cbDataFix = cbData + sizeof(*lpValue); + } + else if (dwType == REG_EXPAND_SZ) + { + if (dwFlags & RRF_NOEXPAND) { //一个null 结尾 cbDataFix = cbData + sizeof(*lpValue); } - else if (dwType == REG_EXPAND_SZ) + else { - if (dwFlags & RRF_NOEXPAND) - { - //一个null 结尾 - cbDataFix = cbData + sizeof(*lpValue); - } - else - { - //需要展开 - cbDataFix = pvData && pcbData ? *pcbData : 0; - lStatus = SHQueryValueExA(hkey, lpValue, nullptr, &dwType, pvData, &cbDataFix); + //需要展开 + cbDataFix = pvData && pcbData ? *pcbData : 0; + lStatus = SHQueryValueExA(hkey, lpValue, nullptr, &dwType, pvData, &cbDataFix); - if (lStatus == ERROR_SUCCESS - || lStatus == ERROR_MORE_DATA) - { - cbData = cbDataFix; - } + if (lStatus == ERROR_SUCCESS + || lStatus == ERROR_MORE_DATA) + { + cbData = cbDataFix; } } - else - { - cbDataFix = cbData; - } } - - if (lpSubKey&&*lpSubKey) + else { - RegCloseKey(hkey); + cbDataFix = cbData; } + } + if (lpSubKey&&*lpSubKey) + { + RegCloseKey(hkey); + } - if (lStatus == ERROR_SUCCESS - || lStatus == ERROR_MORE_DATA) - { - if (pdwType) - *pdwType = dwType; - - //检测类型是否支持 - switch (dwType) - { - case REG_NONE: - case REG_SZ: - case REG_EXPAND_SZ: - case REG_BINARY: - case REG_DWORD: - if ((dwFlags & (1<< dwType)) == 0) - { - lStatus = ERROR_UNSUPPORTED_TYPE; - } - else if (pvData && lStatus == ERROR_SUCCESS) - { - //当函数成功时,保证字符串正常 NULL 结尾 - if (REG_SZ == dwType || REG_EXPAND_SZ == dwType) - { - //保证1个 NULL 结尾 - auto cStringMin = cbData; - - - auto pString = (char*)pvData; - - if (cStringMin == 0 || pString[cStringMin - 1]) - { - if (cbData + sizeof(*lpValue) > cbDataBackup) - { - lStatus = ERROR_MORE_DATA; - break; - } - pString[cStringMin++] = '\0'; - } + if (lStatus == ERROR_SUCCESS + || lStatus == ERROR_MORE_DATA) + { + if (pdwType) + *pdwType = dwType; - cbDataFix = cStringMin * sizeof(*lpValue); - } - } - break; - case REG_MULTI_SZ: - if ((dwFlags & RRF_RT_REG_MULTI_SZ) == 0) - { - lStatus = ERROR_UNSUPPORTED_TYPE; - } - else + //检测类型是否支持 + switch (dwType) + { + case REG_NONE: + case REG_SZ: + case REG_EXPAND_SZ: + case REG_BINARY: + case REG_DWORD: + if ((dwFlags & (1<< dwType)) == 0) + { + lStatus = ERROR_UNSUPPORTED_TYPE; + } + else if (pvData && lStatus == ERROR_SUCCESS) + { + //当函数成功时,保证字符串正常 NULL 结尾 + if (REG_SZ == dwType || REG_EXPAND_SZ == dwType) { - //保证最后一个字符串 NULL 结尾 并且 包含 NULL 结束符 - + //保证1个 NULL 结尾 auto cStringMin = cbData; + auto pString = (char*)pvData; - if (cStringMin == 0) + if (cStringMin == 0 || pString[cStringMin - 1]) { if (cbData + sizeof(*lpValue) > cbDataBackup) { @@ -640,114 +609,175 @@ namespace YY pString[cStringMin++] = '\0'; } - else if (pString[cStringMin - 1]) - { - if (cbData + sizeof(*lpValue) * 2 > cbDataBackup) - { - lStatus = ERROR_MORE_DATA; - break; - } - pString[cStringMin++] = '\0'; + cbDataFix = cStringMin * sizeof(*lpValue); + } + } + break; + case REG_MULTI_SZ: + if ((dwFlags & RRF_RT_REG_MULTI_SZ) == 0) + { + lStatus = ERROR_UNSUPPORTED_TYPE; + } + else + { + //保证最后一个字符串 NULL 结尾 并且 包含 NULL 结束符 - pString[cStringMin++] = '\0'; - } - else if (cStringMin >= 2 && pString[cStringMin - 2]) + auto cStringMin = cbData; + + auto pString = (char*)pvData; + + if (cStringMin == 0) + { + if (cbData + sizeof(*lpValue) > cbDataBackup) { - if (cbData + sizeof(*lpValue) > cbDataBackup) - { - lStatus = ERROR_MORE_DATA; - break; - } + lStatus = ERROR_MORE_DATA; + break; + } - pString[cStringMin++] = '\0'; + pString[cStringMin++] = '\0'; + } + else if (pString[cStringMin - 1]) + { + if (cbData + sizeof(*lpValue) * 2 > cbDataBackup) + { + lStatus = ERROR_MORE_DATA; + break; } - cbDataFix = cStringMin * sizeof(*lpValue); + pString[cStringMin++] = '\0'; + + pString[cStringMin++] = '\0'; } - break; - case REG_QWORD: - if ((dwFlags & RRF_RT_REG_QWORD) == 0) + else if (cStringMin >= 2 && pString[cStringMin - 2]) { - lStatus = ERROR_UNSUPPORTED_TYPE; + if (cbData + sizeof(*lpValue) > cbDataBackup) + { + lStatus = ERROR_MORE_DATA; + break; + } + + pString[cStringMin++] = '\0'; } - break; - default: - if((dwFlags & RRF_RT_ANY) != RRF_RT_ANY) - lStatus = ERROR_UNSUPPORTED_TYPE; - break; + + cbDataFix = cStringMin * sizeof(*lpValue); + } + break; + case REG_QWORD: + if ((dwFlags & RRF_RT_REG_QWORD) == 0) + { + lStatus = ERROR_UNSUPPORTED_TYPE; } + break; + default: + if((dwFlags & RRF_RT_ANY) != RRF_RT_ANY) + lStatus = ERROR_UNSUPPORTED_TYPE; + break; + } - if (pcbData) - *pcbData = cbDataFix; + if (pcbData) + *pcbData = cbDataFix; - } + } - if ((RRF_ZEROONFAILURE & dwFlags) != 0 && lStatus) + if ((RRF_ZEROONFAILURE & dwFlags) != 0 && lStatus) + { + //全0填充 + if (pvData && cbDataBackup) { - //全0填充 - if (pvData && cbDataBackup) - { - memset(pvData, 0, cbDataBackup); - } + memset(pvData, 0, cbDataBackup); } + } - return lStatus; + return lStatus; #endif - } + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN6) - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - advapi32, - 12, - LSTATUS, - APIENTRY, - RegCopyTreeW, - _In_ HKEY hKeySrc, - _In_opt_ LPCWSTR lpSubKey, - _In_ HKEY hKeyDest - ) + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + advapi32, + 12, + LSTATUS, + APIENTRY, + RegCopyTreeW, + _In_ HKEY hKeySrc, + _In_opt_ LPCWSTR lpSubKey, + _In_ HKEY hKeyDest + ) + { + if (auto const pRegCopyTreeW = try_get_RegCopyTreeW()) { - if (auto const pRegCopyTreeW = try_get_RegCopyTreeW()) - { - return pRegCopyTreeW(hKeySrc, lpSubKey, hKeyDest); - } - - return SHCopyKeyW(hKeySrc, lpSubKey, hKeyDest, 0); + return pRegCopyTreeW(hKeySrc, lpSubKey, hKeyDest); } + + return SHCopyKeyW(hKeySrc, lpSubKey, hKeyDest, 0); + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN6) - //Windows Vista [desktop apps only] - //Windows Server 2008 [desktop apps only] - __DEFINE_THUNK( - advapi32, - 12, - LSTATUS, - APIENTRY, - RegCopyTreeA, - _In_ HKEY hKeySrc, - _In_opt_ LPCSTR lpSubKey, - _In_ HKEY hKeyDest - ) + //Windows Vista [desktop apps only] + //Windows Server 2008 [desktop apps only] + __DEFINE_THUNK( + advapi32, + 12, + LSTATUS, + APIENTRY, + RegCopyTreeA, + _In_ HKEY hKeySrc, + _In_opt_ LPCSTR lpSubKey, + _In_ HKEY hKeyDest + ) + { + if (auto const pRegCopyTreeA = try_get_RegCopyTreeA()) { - if (auto const pRegCopyTreeA = try_get_RegCopyTreeA()) - { - return pRegCopyTreeA(hKeySrc, lpSubKey, hKeyDest); - } - - return SHCopyKeyA(hKeySrc, lpSubKey, hKeyDest, 0); + return pRegCopyTreeA(hKeySrc, lpSubKey, hKeyDest); } + + return SHCopyKeyA(hKeySrc, lpSubKey, hKeyDest, 0); + } #endif - }//namespace Thunks -} //namespace YY \ No newline at end of file +#if (YY_Thunks_Support_Version < NTDDI_WIN10) + + // 最低受支持的客户端 Windows 2000 Professional [仅限桌面应用] + // 最低受支持的服务器 Windows 2000 Server[仅限桌面应用] + // 虽然2000就支持,但是为了实现CompareObjectHandles,目前需要处理一下关闭。 + __DEFINE_THUNK( + advapi32, + 4, + LSTATUS, + APIENTRY, + RegCloseKey, + _In_ HKEY _hKey + ) + { + auto const _pfnRegCloseKey = try_get_RegCloseKey(); + const auto _pfnCompareObjectHandles = try_get_CompareObjectHandles(); + + // 伪句柄不用加锁 + if (_pfnCompareObjectHandles == nullptr && _hKey && (uintptr_t(_hKey) & uintptr_t(0x80000000)) == 0) + { + ::AcquireSRWLockShared(&g_CompareObjectHandles); + } + + // 空指针故意崩溃 + auto _lStatus = _pfnRegCloseKey(_hKey); + + if (_pfnCompareObjectHandles == nullptr && _hKey && (uintptr_t(_hKey) & uintptr_t(0x80000000)) == 0) + { + ::ReleaseSRWLockShared(&g_CompareObjectHandles); + } + + return _lStatus; + } +#endif +} //namespace YY::Thunks diff --git a/src/Thunks/api-ms-win-core-timezone.hpp b/src/Thunks/api-ms-win-core-timezone.hpp index 26a1ef57..42f4ab20 100644 --- a/src/Thunks/api-ms-win-core-timezone.hpp +++ b/src/Thunks/api-ms-win-core-timezone.hpp @@ -70,7 +70,7 @@ namespace YY::Thunks //始终保持 0 截断 StandardName[_countof(StandardName) - 1] = L'\0'; - if (__wcsnicmp_ascii(StandardName, pTimeZoneInformation->StandardName, _countof(pTimeZoneInformation->StandardName)) == 0) + if (StringCompareIgnoreCaseByAscii(StandardName, pTimeZoneInformation->StandardName, _countof(pTimeZoneInformation->StandardName)) == 0) { memcpy(pTimeZoneInformation->TimeZoneKeyName, szTimeZoneKeyName, sizeof(szTimeZoneKeyName)); diff --git a/src/Thunks/api-ms-win-core-wow64.hpp b/src/Thunks/api-ms-win-core-wow64.hpp index b26064de..b5970b9a 100644 --- a/src/Thunks/api-ms-win-core-wow64.hpp +++ b/src/Thunks/api-ms-win-core-wow64.hpp @@ -202,9 +202,9 @@ namespace YY::Thunks #endif -#if (YY_Thunks_Support_Version < NTDDI_WS03) +#if (YY_Thunks_Support_Version < NTDDI_WIN6) - // 实际看到Vista就有,推测这个接口是x64系统时代添加的。 + // Windows XP x64确认没有这个接口 __DEFINE_THUNK( kernel32, 8, @@ -220,8 +220,291 @@ namespace YY::Thunks return _pfnWow64GetThreadContext(_hThread, _pContext); } - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; + /* + | 系统 | 线程类型 | 结果 + | ------ | -------- | --- + | x86 | x86 | ERROR_INVALID_PARAMETER + | x64 | x86 | ERROR_SUCCESS + | x64 | x64 | ERROR_INVALID_PARAMETER + */ + +#if defined(_X86_) + // 如果系统也是 x86这必然不可能处于Wow64 + if (internal::GetNativeSystemInfo().wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + static_assert(sizeof(CONTEXT) == sizeof(*_pContext)); + return GetThreadContext(_hThread, (CONTEXT*)_pContext); +#elif defined(_AMD64_) + if (!_pContext) + { + SetLastError(ERROR_NOACCESS); + return FALSE; + } + + if ((_pContext->ContextFlags & (~(WOW64_CONTEXT_ALL | WOW64_CONTEXT_XSTATE))) != 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // 判断线程是否是 WOW64线程 + const auto _pfnNtQueryInformationThread = try_get_NtQueryInformationThread(); + if (!_pfnNtQueryInformationThread) + { + SetLastError(ERROR_FUNCTION_FAILED); + return FALSE; + } + + THREAD_BASIC_INFORMATION ThreadBasicInfo; + LONG Status = _pfnNtQueryInformationThread(_hThread, ThreadBasicInformation, &ThreadBasicInfo, sizeof(ThreadBasicInfo), nullptr); + if (Status < 0) + { + internal::BaseSetLastNTError(Status); + return FALSE; + } + + // 当前进程肯定不是Wow64 + if (static_cast(reinterpret_cast(ThreadBasicInfo.ClientId.UniqueProcess)) == GetCurrentProcessId()) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + union + { + struct + { + DWORD Unknow; + WOW64_CONTEXT ThreadContext; + } RemoteWow64ThreadContext; + + CONTEXT Context64; + } ContextBuffer = {}; + + CONTEXT& _Context64 = ContextBuffer.Context64; + _Context64.ContextFlags = CONTEXT_CONTROL | (_pContext->ContextFlags & 0x1F /*WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS | WOW64_CONTEXT_FLOATING_POINT | WOW64_CONTEXT_DEBUG_REGISTERS*/); + + if (_pContext->ContextFlags & 0x20 /*WOW64_CONTEXT_EXTENDED_REGISTERS*/) + { + _Context64.ContextFlags |= CONTEXT_FLOATING_POINT; + } + + // 这里忽略Windows XP必然不支持 WOW64_CONTEXT_XSTATE + if (!GetThreadContext(_hThread, &_Context64)) + { + return FALSE; + } + + if (_Context64.SegCs == 0x23u) + { + // 当前正处于WOW64执行中,这时取到的上下文就是 WOW64上下文 + // 我们可以直接将 CONTEXT 转换到 WOW64_CONTEXT + if ((_pContext->ContextFlags & WOW64_CONTEXT_DEBUG_REGISTERS) == WOW64_CONTEXT_DEBUG_REGISTERS) + { + _pContext->Dr0 = static_cast(_Context64.Dr0); + _pContext->Dr1 = static_cast(_Context64.Dr1); + _pContext->Dr2 = static_cast(_Context64.Dr2); + _pContext->Dr3 = static_cast(_Context64.Dr3); + _pContext->Dr6 = static_cast(_Context64.Dr6); + _pContext->Dr7 = static_cast(_Context64.Dr7); + } + + if ((_pContext->ContextFlags & WOW64_CONTEXT_FLOATING_POINT) == WOW64_CONTEXT_FLOATING_POINT) + { + _pContext->FloatSave.ControlWord = _Context64.FltSave.ControlWord; + _pContext->FloatSave.StatusWord = _Context64.FltSave.StatusWord; + _pContext->FloatSave.TagWord = _Context64.FltSave.TagWord; + _pContext->FloatSave.ErrorOffset = _Context64.FltSave.ErrorOffset; + _pContext->FloatSave.ErrorSelector = _Context64.FltSave.ErrorSelector; + _pContext->FloatSave.DataOffset = _Context64.FltSave.DataOffset; + _pContext->FloatSave.DataSelector = _Context64.FltSave.DataSelector; + _pContext->FloatSave.Cr0NpxState = 0; + + constexpr auto kFloatRegisterByteSize = sizeof(_pContext->FloatSave.RegisterArea) / _countof(_Context64.FltSave.FloatRegisters); + for (size_t i = 0; i != _countof(_Context64.FltSave.FloatRegisters); ++i) + { + memcpy(_pContext->FloatSave.RegisterArea + i * kFloatRegisterByteSize, &_Context64.FltSave.FloatRegisters[i], kFloatRegisterByteSize); + } + } + + if ((_pContext->ContextFlags & WOW64_CONTEXT_SEGMENTS) == WOW64_CONTEXT_SEGMENTS) + { + _pContext->SegGs = 0x2Bu; + _pContext->SegFs = 0x53u; + _pContext->SegEs = 0x2Bu; + _pContext->SegDs = 0x2Bu; + } + + if ((_pContext->ContextFlags & WOW64_CONTEXT_INTEGER) == WOW64_CONTEXT_INTEGER) + { + _pContext->Edi = static_cast(_Context64.Rdi); + _pContext->Esi = static_cast(_Context64.Rsi); + _pContext->Ebx = static_cast(_Context64.Rbx); + _pContext->Edx = static_cast(_Context64.Rdx); + _pContext->Ecx = static_cast(_Context64.Rcx); + _pContext->Eax = static_cast(_Context64.Rax); + } + + if ((_pContext->ContextFlags & WOW64_CONTEXT_CONTROL) == WOW64_CONTEXT_CONTROL) + { + _pContext->Ebp = static_cast(_Context64.Rbp); + _pContext->Eip = static_cast(_Context64.Rip); + _pContext->SegCs = 0x23u; + _pContext->EFlags = _Context64.EFlags & 0x3F0DD5u | 0x202u; + _pContext->Esp = static_cast(_Context64.Rsp); + _pContext->SegSs = 0x2Bu; + } + + if ((_pContext->ContextFlags & WOW64_CONTEXT_EXTENDED_REGISTERS) == WOW64_CONTEXT_EXTENDED_REGISTERS) + { + struct DECLSPEC_ALIGN(16) _XSAVE_FORMAT_WOW64 + { + WORD ControlWord; + WORD StatusWord; + BYTE TagWord; + BYTE Reserved1; + WORD ErrorOpcode; + DWORD ErrorOffset; + WORD ErrorSelector; + WORD Reserved2; + DWORD DataOffset; + WORD DataSelector; + WORD Reserved3; + DWORD MxCsr; + DWORD MxCsr_Mask; + M128A FloatRegisters[8]; + + M128A XmmRegisters[8]; + }; + + memcpy(_pContext->ExtendedRegisters, &_Context64.FltSave, sizeof(_XSAVE_FORMAT_WOW64)); + } + + return TRUE; + } + else if (_Context64.SegCs == 0x33u) + { + // 虽然大多数 x86程序地址最大只有2G,但是开启大地址时也可以达到接近4G + // 如果RSP大于32位上限,那么这明显就是一个64位程序。 + if (_Context64.Rsp > 0xffff0000ull) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + auto _hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, static_cast(reinterpret_cast(ThreadBasicInfo.ClientId.UniqueProcess))); + if (_hProcess == NULL) + { + return FALSE; + } + + LSTATUS _lStatus = ERROR_SUCCESS; + + do + { + void* _pRemoteThreadWow64Context = nullptr; + + auto _pRemoteThreadTeb = (TEB*)ThreadBasicInfo.TebBaseAddress; + // TEB->TlsSlots[1](TEB + 0x1488)指向一个 WOW64_CONTEXT,具体可以参考 wow64cpu.dll!CpuGetContext + static_assert((UFIELD_OFFSET(TEB, TlsSlots) + 1 * sizeof(TEB::TlsSlots[0])) == 0x1488, ""); + if (!ReadProcessMemory(_hProcess, &_pRemoteThreadTeb->TlsSlots[1], &_pRemoteThreadWow64Context, sizeof(_pRemoteThreadWow64Context), nullptr)) + { + _lStatus = ERROR_FUNCTION_FAILED; + break; + } + if (!_pRemoteThreadWow64Context) + { + _lStatus = ERROR_INVALID_PARAMETER; + break; + } + + memset(&ContextBuffer.RemoteWow64ThreadContext, 0, sizeof(ContextBuffer.RemoteWow64ThreadContext)); + if (!ReadProcessMemory(_hProcess, _pRemoteThreadWow64Context, &ContextBuffer.RemoteWow64ThreadContext, sizeof(ContextBuffer.RemoteWow64ThreadContext), nullptr)) + { + _lStatus = ERROR_FUNCTION_FAILED; + break; + } + + auto& _Wow64ThreadContext = ContextBuffer.RemoteWow64ThreadContext.ThreadContext; + if ((_Wow64ThreadContext.ContextFlags & WOW64_CONTEXT_i386) == 0) + { + _lStatus = ERROR_INVALID_PARAMETER; + break; + } + + if ((_pContext->ContextFlags & WOW64_CONTEXT_DEBUG_REGISTERS) == WOW64_CONTEXT_DEBUG_REGISTERS) + { + _pContext->Dr0 = _Wow64ThreadContext.Dr0; + _pContext->Dr1 = _Wow64ThreadContext.Dr1; + _pContext->Dr2 = _Wow64ThreadContext.Dr2; + _pContext->Dr3 = _Wow64ThreadContext.Dr3; + _pContext->Dr6 = _Wow64ThreadContext.Dr6; + _pContext->Dr7 = _Wow64ThreadContext.Dr7; + } + + if ((_pContext->ContextFlags & WOW64_CONTEXT_FLOATING_POINT) == WOW64_CONTEXT_FLOATING_POINT) + { + memcpy(&_pContext->FloatSave, &_Wow64ThreadContext.FloatSave, sizeof(_Wow64ThreadContext.FloatSave)); + } + + if ((_pContext->ContextFlags & WOW64_CONTEXT_SEGMENTS) == WOW64_CONTEXT_SEGMENTS) + { + _pContext->SegGs = 0x2Bu; + _pContext->SegFs = 0x53u; + _pContext->SegEs = 0x2Bu; + _pContext->SegDs = 0x2Bu; + } + + if ((_pContext->ContextFlags & WOW64_CONTEXT_INTEGER) == WOW64_CONTEXT_INTEGER) + { + _pContext->Edi = _Wow64ThreadContext.Edi; + _pContext->Esi = _Wow64ThreadContext.Esi; + _pContext->Ebx = _Wow64ThreadContext.Ebx; + _pContext->Edx = _Wow64ThreadContext.Edx; + _pContext->Ecx = _Wow64ThreadContext.Ecx; + _pContext->Eax = _Wow64ThreadContext.Eax; + } + + if ((_pContext->ContextFlags & WOW64_CONTEXT_CONTROL) == WOW64_CONTEXT_CONTROL) + { + _pContext->Ebp = _Wow64ThreadContext.Ebp; + _pContext->Eip = _Wow64ThreadContext.Eip; + _pContext->SegCs = 0x23u; + _pContext->EFlags = _Wow64ThreadContext.EFlags & 0x3F0DD5u | 0x202u; + _pContext->Esp = _Wow64ThreadContext.Esp; + _pContext->SegSs = 0x2Bu; + } + + if ((_pContext->ContextFlags & WOW64_CONTEXT_EXTENDED_REGISTERS) == WOW64_CONTEXT_EXTENDED_REGISTERS) + { + memcpy(_pContext->ExtendedRegisters, _Wow64ThreadContext.ExtendedRegisters, sizeof(_Wow64ThreadContext.ExtendedRegisters)); + } + + } while (false); + CloseHandle(_hProcess); + + if (_lStatus) + { + SetLastError(_lStatus); + return FALSE; + } + else + { + return TRUE; + } + } + else + { + // 非预期值。 + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } +#else +#error ???? +#endif } #endif } //namespace YY::Thunks diff --git a/src/Thunks/api-ms-win-core-xstate.hpp b/src/Thunks/api-ms-win-core-xstate.hpp index 00f02995..cd10e0fb 100644 --- a/src/Thunks/api-ms-win-core-xstate.hpp +++ b/src/Thunks/api-ms-win-core-xstate.hpp @@ -1,347 +1,350 @@ -namespace YY +namespace YY::Thunks { - namespace Thunks - { #if (YY_Thunks_Support_Version < NTDDI_WIN6SP1) - // 最低受支持的客户端 Windows 7 SP1[桌面应用 | UWP 应用] - // 最低受支持的服务器 Windows Server 2008 R2 SP1[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 0, - DWORD64, - WINAPI, - GetEnabledXStateFeatures, - VOID - ) + // 最低受支持的客户端 Windows 7 SP1[桌面应用 | UWP 应用] + // 最低受支持的服务器 Windows Server 2008 R2 SP1[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 0, + DWORD64, + WINAPI, + GetEnabledXStateFeatures, + VOID + ) + { + if (auto const _pfnGetEnabledXStateFeatures = try_get_GetEnabledXStateFeatures()) { - if (auto const _pfnGetEnabledXStateFeatures = try_get_GetEnabledXStateFeatures()) - { - return _pfnGetEnabledXStateFeatures(); - } - - static DWORD64 s_uXState = 0; - if (s_uXState) - { - return s_uXState; - } + return _pfnGetEnabledXStateFeatures(); + } - DWORD64 _uXState = XSTATE_MASK_LEGACY_FLOATING_POINT; - if (IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE)) - { - _uXState |= XSTATE_MASK_LEGACY_SSE; - } + static DWORD64 s_uXState = 0; + if (s_uXState) + { + return s_uXState; + } - s_uXState = _uXState; - return _uXState; + DWORD64 _uXState = XSTATE_MASK_LEGACY_FLOATING_POINT; + if (IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE)) + { + _uXState |= XSTATE_MASK_LEGACY_SSE; } + + s_uXState = _uXState; + return _uXState; + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN6SP1) - // 最低受支持的客户端 Windows 7 SP1 [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2008 R2 SP1[仅限桌面应用] - __DEFINE_THUNK( - kernel32, - 12, - BOOL, - WINAPI, - SetXStateFeaturesMask, - _Inout_ PCONTEXT Context, - _In_ DWORD64 FeatureMask - ) + // 最低受支持的客户端 Windows 7 SP1 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008 R2 SP1[仅限桌面应用] + __DEFINE_THUNK( + kernel32, + 12, + BOOL, + WINAPI, + SetXStateFeaturesMask, + _Inout_ PCONTEXT Context, + _In_ DWORD64 FeatureMask + ) + { + if (auto const _pfnSetXStateFeaturesMask = try_get_SetXStateFeaturesMask()) { - if (auto const _pfnSetXStateFeaturesMask = try_get_SetXStateFeaturesMask()) - { - return _pfnSetXStateFeaturesMask(Context, FeatureMask); - } - const auto _uSupportFeatures = GetEnabledXStateFeatures(); + return _pfnSetXStateFeaturesMask(Context, FeatureMask); + } + const auto _uSupportFeatures = GetEnabledXStateFeatures(); - if (FeatureMask & (~_uSupportFeatures)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - else - { - return TRUE; - } + if (FeatureMask & (~_uSupportFeatures)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + else + { + return TRUE; } + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN6SP1) - // 最低受支持的客户端 Windows 7 SP1 [桌面应用 |UWP 应用] - // 最低受支持的服务器 Windows Server 2008 R2 SP1[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 12, - PVOID, - WINAPI, - LocateXStateFeature, - _In_ PCONTEXT Context, - _In_ DWORD FeatureId, - _Out_opt_ PDWORD Length - ) + // 最低受支持的客户端 Windows 7 SP1 [桌面应用 |UWP 应用] + // 最低受支持的服务器 Windows Server 2008 R2 SP1[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 12, + PVOID, + WINAPI, + LocateXStateFeature, + _In_ PCONTEXT Context, + _In_ DWORD FeatureId, + _Out_opt_ PDWORD Length + ) + { + if (auto const _pfnLocateXStateFeature = try_get_LocateXStateFeature()) { - if (auto const _pfnLocateXStateFeature = try_get_LocateXStateFeature()) - { - return _pfnLocateXStateFeature(Context, FeatureId, Length); - } + return _pfnLocateXStateFeature(Context, FeatureId, Length); + } #if defined(_X86_) - auto& _XSave = *(XSAVE_FORMAT*)Context->ExtendedRegisters; - constexpr auto kThreadContext = CONTEXT_i386; + auto& _XSave = *(XSAVE_FORMAT*)Context->ExtendedRegisters; + constexpr auto kThreadContext = CONTEXT_i386; #elif defined(_AMD64_) - auto& _XSave = Context->FltSave; - constexpr auto kThreadContext = CONTEXT_AMD64; + auto& _XSave = Context->FltSave; + constexpr auto kThreadContext = CONTEXT_AMD64; #else #error unknow OS. #endif - if (kThreadContext & Context->ContextFlags) + if (kThreadContext & Context->ContextFlags) + { + if (XSTATE_LEGACY_FLOATING_POINT == FeatureId) { - if (XSTATE_LEGACY_FLOATING_POINT == FeatureId) + if (Length) { - if (Length) - { - *Length = UFIELD_OFFSET(XSAVE_FORMAT, XmmRegisters); - } - return &_XSave; + *Length = UFIELD_OFFSET(XSAVE_FORMAT, XmmRegisters); } - else if (XSTATE_LEGACY_SSE == FeatureId) + return &_XSave; + } + else if (XSTATE_LEGACY_SSE == FeatureId) + { + if (IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE)) { - if (IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE)) + if (Length) { - if (Length) - { - *Length = sizeof(_XSave.XmmRegisters); - } - return &_XSave.XmmRegisters; + *Length = sizeof(_XSave.XmmRegisters); } + return &_XSave.XmmRegisters; } } - - if (Length) - *Length = 0; - return nullptr; } + + if (Length) + *Length = 0; + return nullptr; + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN6SP1) - // 最低受支持的客户端 Windows 7 SP1 [桌面应用 |UWP 应用] - // 最低受支持的服务器 Windows Server 2008 R2 SP1[桌面应用 | UWP 应用] - __DEFINE_THUNK( - kernel32, - 16, - BOOL, - WINAPI, - InitializeContext, - _Out_writes_bytes_opt_(*ContextLength) PVOID Buffer, - _In_ DWORD ContextFlags, - _Out_ PCONTEXT* Context, - _Inout_ PDWORD ContextLength - ) + // 最低受支持的客户端 Windows 7 SP1 [桌面应用 |UWP 应用] + // 最低受支持的服务器 Windows Server 2008 R2 SP1[桌面应用 | UWP 应用] + __DEFINE_THUNK( + kernel32, + 16, + BOOL, + WINAPI, + InitializeContext, + _Out_writes_bytes_opt_(*ContextLength) PVOID Buffer, + _In_ DWORD ContextFlags, + _Out_ PCONTEXT* Context, + _Inout_ PDWORD ContextLength + ) + { + if (auto const _pfnInitializeContext = try_get_InitializeContext()) { - if (auto const _pfnInitializeContext = try_get_InitializeContext()) - { - return _pfnInitializeContext(Buffer, ContextFlags, Context, ContextLength); - } - - constexpr auto kSupportContextFlags = CONTEXT_ALL | CONTEXT_EXCEPTION_ACTIVE | CONTEXT_SERVICE_ACTIVE | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING; + return _pfnInitializeContext(Buffer, ContextFlags, Context, ContextLength); + } - if (ContextFlags & (~kSupportContextFlags)) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } + constexpr auto kSupportContextFlags = CONTEXT_ALL | CONTEXT_EXCEPTION_ACTIVE | CONTEXT_SERVICE_ACTIVE | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING; - if (Buffer == nullptr || *ContextLength < sizeof(CONTEXT)) - { - *ContextLength = sizeof(CONTEXT); - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return FALSE; - } + if (ContextFlags & (~kSupportContextFlags)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } - auto _pContext = reinterpret_cast(Buffer); - _pContext->ContextFlags = ContextFlags; + if (Buffer == nullptr || *ContextLength < sizeof(CONTEXT)) + { *ContextLength = sizeof(CONTEXT); - *Context = _pContext; - return TRUE; + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; } + + auto _pContext = reinterpret_cast(Buffer); + _pContext->ContextFlags = ContextFlags; + *ContextLength = sizeof(CONTEXT); + *Context = _pContext; + return TRUE; + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN10_FE) - // 最低受支持的客户端 Windows 10内部版本 20348 - // 最低受支持的服务器 Windows 10内部版本 20348 - __DEFINE_THUNK( - kernel32, - 24, - BOOL, - WINAPI, - InitializeContext2, - _Out_writes_bytes_opt_(*ContextLength) PVOID Buffer, - _In_ DWORD ContextFlags, - _Out_ PCONTEXT* Context, - _Inout_ PDWORD ContextLength, - _In_ ULONG64 XStateCompactionMask - ) + // 最低受支持的客户端 Windows 10内部版本 20348 + // 最低受支持的服务器 Windows 10内部版本 20348 + __DEFINE_THUNK( + kernel32, + 24, + BOOL, + WINAPI, + InitializeContext2, + _Out_writes_bytes_opt_(*ContextLength) PVOID Buffer, + _In_ DWORD ContextFlags, + _Out_ PCONTEXT* Context, + _Inout_ PDWORD ContextLength, + _In_ ULONG64 XStateCompactionMask + ) + { + if (auto const _pfnInitializeContext2 = try_get_InitializeContext2()) { - if (auto const _pfnInitializeContext2 = try_get_InitializeContext2()) - { - return _pfnInitializeContext2(Buffer, ContextFlags, Context, ContextLength, XStateCompactionMask); - } - - return InitializeContext(Buffer, ContextFlags, Context, ContextLength); + return _pfnInitializeContext2(Buffer, ContextFlags, Context, ContextLength, XStateCompactionMask); } + + return InitializeContext(Buffer, ContextFlags, Context, ContextLength); + } #endif #if (YY_Thunks_Support_Version < NTDDI_WIN6SP1) - // 最低受支持的客户端 Windows 7 SP1 [仅限桌面应用] - // 最低受支持的服务器 Windows Server 2008 R2 SP1[仅限桌面应用] - __DEFINE_THUNK( - kernel32, - 12, - BOOL, - WINAPI, - CopyContext, - _Inout_ PCONTEXT _pDestination, - _In_ DWORD _uContextFlags, - _In_ PCONTEXT _pSource - ) + // 最低受支持的客户端 Windows 7 SP1 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008 R2 SP1[仅限桌面应用] + __DEFINE_THUNK( + kernel32, + 12, + BOOL, + WINAPI, + CopyContext, + _Inout_ PCONTEXT _pDestination, + _In_ DWORD _uContextFlags, + _In_ PCONTEXT _pSource + ) + { + if (auto const _pfnCopyContext = try_get_CopyContext()) { - if (auto const _pfnCopyContext = try_get_CopyContext()) - { - return _pfnCopyContext(_pDestination, _uContextFlags, _pSource); - } + return _pfnCopyContext(_pDestination, _uContextFlags, _pSource); + } #if defined(_X86_) - constexpr auto kThreadContext = CONTEXT_i386; + constexpr auto kThreadContext = CONTEXT_i386; #elif defined(_AMD64_) - constexpr auto kThreadContext = CONTEXT_AMD64; + constexpr auto kThreadContext = CONTEXT_AMD64; #else #error unknow OS. #endif - if ((_uContextFlags & kThreadContext) == 0) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } + if ((_uContextFlags & kThreadContext) == 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } - if ((CONTEXT_XSTATE & _uContextFlags) == CONTEXT_XSTATE) - { - // internal::BaseSetLastNTError(0xC00000BB); - SetLastError(ERROR_NOT_SUPPORTED); - return FALSE; - } + if ((CONTEXT_XSTATE & _uContextFlags) == CONTEXT_XSTATE) + { + // internal::BaseSetLastNTError(0xC00000BB); + SetLastError(ERROR_NOT_SUPPORTED); + return FALSE; + } - if ((_pSource->ContextFlags & kThreadContext) == 0 || (_pDestination->ContextFlags & kThreadContext) == 0) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } + if ((_pSource->ContextFlags & kThreadContext) == 0 || (_pDestination->ContextFlags & kThreadContext) == 0) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } - if ((CONTEXT_DEBUG_REGISTERS & _uContextFlags) == CONTEXT_DEBUG_REGISTERS && (CONTEXT_DEBUG_REGISTERS & _pSource->ContextFlags) == CONTEXT_DEBUG_REGISTERS) - { - _pDestination->ContextFlags |= CONTEXT_DEBUG_REGISTERS; - _pDestination->Dr0 = _pSource->Dr0; - _pDestination->Dr1 = _pSource->Dr1; - _pDestination->Dr2 = _pSource->Dr2; - _pDestination->Dr3 = _pSource->Dr3; - _pDestination->Dr6 = _pSource->Dr6; - _pDestination->Dr7 = _pSource->Dr7; + if ((CONTEXT_DEBUG_REGISTERS & _uContextFlags) == CONTEXT_DEBUG_REGISTERS && (CONTEXT_DEBUG_REGISTERS & _pSource->ContextFlags) == CONTEXT_DEBUG_REGISTERS) + { + _pDestination->ContextFlags |= CONTEXT_DEBUG_REGISTERS; + _pDestination->Dr0 = _pSource->Dr0; + _pDestination->Dr1 = _pSource->Dr1; + _pDestination->Dr2 = _pSource->Dr2; + _pDestination->Dr3 = _pSource->Dr3; + _pDestination->Dr6 = _pSource->Dr6; + _pDestination->Dr7 = _pSource->Dr7; #if defined(_AMD64_) - _pDestination->LastBranchToRip = _pSource->LastBranchToRip; - _pDestination->LastBranchFromRip = _pSource->LastBranchFromRip; - _pDestination->LastExceptionToRip = _pSource->LastExceptionToRip; - _pDestination->LastExceptionFromRip = _pSource->LastExceptionFromRip; + _pDestination->LastBranchToRip = _pSource->LastBranchToRip; + _pDestination->LastBranchFromRip = _pSource->LastBranchFromRip; + _pDestination->LastExceptionToRip = _pSource->LastExceptionToRip; + _pDestination->LastExceptionFromRip = _pSource->LastExceptionFromRip; #endif - } + } - if ((CONTEXT_FLOATING_POINT & _uContextFlags) == CONTEXT_FLOATING_POINT && (CONTEXT_FLOATING_POINT & _pSource->ContextFlags) == CONTEXT_FLOATING_POINT) - { - _pDestination->ContextFlags |= CONTEXT_FLOATING_POINT; + if ((CONTEXT_FLOATING_POINT & _uContextFlags) == CONTEXT_FLOATING_POINT && (CONTEXT_FLOATING_POINT & _pSource->ContextFlags) == CONTEXT_FLOATING_POINT) + { + _pDestination->ContextFlags |= CONTEXT_FLOATING_POINT; #if defined(_X86_) - memcpy(&_pDestination->FloatSave, &_pSource->FloatSave, sizeof(_pSource->FloatSave)); + memcpy(&_pDestination->FloatSave, &_pSource->FloatSave, sizeof(_pSource->FloatSave)); #elif defined(_AMD64_) - _pDestination->MxCsr = _pSource->MxCsr; - memcpy(&_pDestination->FltSave, &_pSource->FltSave, sizeof(_pSource->FltSave)); + _pDestination->MxCsr = _pSource->MxCsr; + memcpy(&_pDestination->FltSave, &_pSource->FltSave, sizeof(_pSource->FltSave)); #else #error unknow OS. #endif - } + } - if ((CONTEXT_SEGMENTS & _uContextFlags) == CONTEXT_SEGMENTS && (CONTEXT_SEGMENTS & _pSource->ContextFlags) == CONTEXT_SEGMENTS) - { - _pDestination->ContextFlags |= CONTEXT_SEGMENTS; - _pDestination->SegGs = _pSource->SegGs; - _pDestination->SegFs = _pSource->SegFs; - _pDestination->SegEs = _pSource->SegEs; - _pDestination->SegDs = _pSource->SegDs; - } + if ((CONTEXT_SEGMENTS & _uContextFlags) == CONTEXT_SEGMENTS && (CONTEXT_SEGMENTS & _pSource->ContextFlags) == CONTEXT_SEGMENTS) + { + _pDestination->ContextFlags |= CONTEXT_SEGMENTS; + _pDestination->SegGs = _pSource->SegGs; + _pDestination->SegFs = _pSource->SegFs; + _pDestination->SegEs = _pSource->SegEs; + _pDestination->SegDs = _pSource->SegDs; + } - if ((CONTEXT_INTEGER & _uContextFlags) == CONTEXT_INTEGER && (CONTEXT_INTEGER & _pSource->ContextFlags) == CONTEXT_INTEGER) - { - _pDestination->ContextFlags |= CONTEXT_INTEGER; + if ((CONTEXT_INTEGER & _uContextFlags) == CONTEXT_INTEGER && (CONTEXT_INTEGER & _pSource->ContextFlags) == CONTEXT_INTEGER) + { + _pDestination->ContextFlags |= CONTEXT_INTEGER; #if defined(_X86_) - _pDestination->Edi = _pSource->Edi; - _pDestination->Esi = _pSource->Esi; - _pDestination->Ebx = _pSource->Ebx; - _pDestination->Edx = _pSource->Edx; - _pDestination->Ecx = _pSource->Ecx; - _pDestination->Eax = _pSource->Eax; + _pDestination->Edi = _pSource->Edi; + _pDestination->Esi = _pSource->Esi; + _pDestination->Ebx = _pSource->Ebx; + _pDestination->Edx = _pSource->Edx; + _pDestination->Ecx = _pSource->Ecx; + _pDestination->Eax = _pSource->Eax; #elif defined(_AMD64_) - _pDestination->Rax = _pSource->Rax; - _pDestination->Rcx = _pSource->Rcx; - _pDestination->Rdx = _pSource->Rdx; - _pDestination->Rbx = _pSource->Rbx; - _pDestination->Rbp = _pSource->Rbp; - _pDestination->Rsi = _pSource->Rsi; - _pDestination->Rdi = _pSource->Rdi; - _pDestination->R8 = _pSource->R8; - _pDestination->R9 = _pSource->R9; - _pDestination->R10 = _pSource->R10; - _pDestination->R11 = _pSource->R11; - _pDestination->R12 = _pSource->R12; - _pDestination->R13 = _pSource->R13; - _pDestination->R14 = _pSource->R14; - _pDestination->R15 = _pSource->R15; + _pDestination->Rax = _pSource->Rax; + _pDestination->Rcx = _pSource->Rcx; + _pDestination->Rdx = _pSource->Rdx; + _pDestination->Rbx = _pSource->Rbx; + _pDestination->Rbp = _pSource->Rbp; + _pDestination->Rsi = _pSource->Rsi; + _pDestination->Rdi = _pSource->Rdi; + _pDestination->R8 = _pSource->R8; + _pDestination->R9 = _pSource->R9; + _pDestination->R10 = _pSource->R10; + _pDestination->R11 = _pSource->R11; + _pDestination->R12 = _pSource->R12; + _pDestination->R13 = _pSource->R13; + _pDestination->R14 = _pSource->R14; + _pDestination->R15 = _pSource->R15; #else #error unknow OS. #endif - } + } - if ((CONTEXT_CONTROL & _uContextFlags) == CONTEXT_CONTROL && (CONTEXT_CONTROL & _pSource->ContextFlags) == CONTEXT_CONTROL) - { - _pDestination->ContextFlags |= CONTEXT_CONTROL; + if ((CONTEXT_CONTROL & _uContextFlags) == CONTEXT_CONTROL && (CONTEXT_CONTROL & _pSource->ContextFlags) == CONTEXT_CONTROL) + { + _pDestination->ContextFlags |= CONTEXT_CONTROL; #if defined(_X86_) - _pDestination->Ebp = _pSource->Ebp; - _pDestination->Eip = _pSource->Eip; - _pDestination->SegCs = _pSource->SegCs; - _pDestination->EFlags = _pSource->EFlags; - _pDestination->Esp = _pSource->Esp; - _pDestination->SegSs = _pSource->SegSs; + _pDestination->Ebp = _pSource->Ebp; + _pDestination->Eip = _pSource->Eip; + _pDestination->SegCs = _pSource->SegCs; + _pDestination->EFlags = _pSource->EFlags; + _pDestination->Esp = _pSource->Esp; + _pDestination->SegSs = _pSource->SegSs; #elif defined(_AMD64_) - _pDestination->SegCs = _pSource->SegCs; - _pDestination->SegSs = _pSource->SegSs; - _pDestination->EFlags = _pSource->EFlags; - _pDestination->Rsp = _pSource->Rsp; - _pDestination->Rip = _pSource->Rip; + _pDestination->SegCs = _pSource->SegCs; + _pDestination->SegSs = _pSource->SegSs; + _pDestination->EFlags = _pSource->EFlags; + _pDestination->Rsp = _pSource->Rsp; + _pDestination->Rip = _pSource->Rip; #else #error unknow OS. #endif - } - - return TRUE; + } + +#if defined(CONTEXT_EXTENDED_REGISTERS) + if ((CONTEXT_EXTENDED_REGISTERS & _uContextFlags) == CONTEXT_EXTENDED_REGISTERS && (CONTEXT_EXTENDED_REGISTERS & _pSource->ContextFlags) == CONTEXT_EXTENDED_REGISTERS) + { + memcpy(_pDestination->ExtendedRegisters, _pSource->ExtendedRegisters, sizeof(_pSource->ExtendedRegisters)); } #endif + return TRUE; } +#endif } diff --git a/src/Thunks/api-ms-win-security-base.hpp b/src/Thunks/api-ms-win-security-base.hpp new file mode 100644 index 00000000..a20360a9 --- /dev/null +++ b/src/Thunks/api-ms-win-security-base.hpp @@ -0,0 +1,104 @@ +namespace YY::Thunks +{ +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // 最低受支持的客户端 Windows Vista [桌面应用 | UWP 应用] + // 最低受支持的服务器 Windows Server 2008[桌面应用 | UWP 应用] + __DEFINE_THUNK( + advapi32, + 20, + BOOL, + WINAPI, + AddMandatoryAce, + _Inout_ PACL _pAcl, + _In_ DWORD _uAceRevision, + _In_ DWORD _fAceFlags, + _In_ DWORD _uMandatoryPolicy, + _In_ SID* _pLabelSid + ) + { + if (const auto _pfnAddMandatoryAce = try_get_AddMandatoryAce()) + { + return _pfnAddMandatoryAce(_pAcl, _uAceRevision, _fAceFlags, _uMandatoryPolicy, _pLabelSid); + } + + // 参考 ntdll.RtlAddMandatoryAce 实现 + + if (!_pAcl) + { + // internal::BaseSetLastNTError(0xC0000077); + SetLastError(ERROR_INVALID_ACL); + return FALSE; + } + + const auto _pfnRtlValidSid = try_get_RtlValidSid(); + const auto _pfnRtlValidAcl = try_get_RtlValidAcl(); + const auto _pfnRtlFirstFreeAce = try_get_RtlFirstFreeAce(); + const auto _pfnRtlCopySid = try_get_RtlCopySid(); + if (_pfnRtlValidSid == nullptr || _pfnRtlValidAcl == nullptr || _pfnRtlFirstFreeAce == nullptr || _pfnRtlCopySid == nullptr) + { + SetLastError(ERROR_FUNCTION_FAILED); + return FALSE; + } + + if (!_pfnRtlValidSid(_pLabelSid)) + { + // internal::BaseSetLastNTError(0xC0000078); + SetLastError(ERROR_INVALID_SID); + return FALSE; + } + + static const SID_IDENTIFIER_AUTHORITY s_TargetIdentifierAuthority = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10} }; + static_assert(sizeof(s_TargetIdentifierAuthority) == sizeof(SID::IdentifierAuthority)); + + if (memcmp(_pLabelSid->IdentifierAuthority.Value, s_TargetIdentifierAuthority.Value, sizeof(s_TargetIdentifierAuthority.Value)) != 0) + { + // internal::BaseSetLastNTError(0xC000000D); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (_pAcl->AclRevision > ACL_REVISION_DS || _uAceRevision > ACL_REVISION_DS) + { + // internal::BaseSetLastNTError(0xC0000059); + SetLastError(ERROR_REVISION_MISMATCH); + return FALSE; + } + + _uAceRevision = max(_pAcl->AclRevision, _uAceRevision); + + if ((_fAceFlags & ~VALID_INHERIT_FLAGS) || (_uMandatoryPolicy & ~SYSTEM_MANDATORY_LABEL_VALID_MASK)) + { + // internal::BaseSetLastNTError(0xC000000D); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + _SYSTEM_MANDATORY_LABEL_ACE* _pFirstFree = nullptr; + if (_pfnRtlValidAcl(_pAcl) == FALSE || _pfnRtlFirstFreeAce(_pAcl,(PVOID*)& _pFirstFree) == FALSE) + { + // internal::BaseSetLastNTError(0xC0000077); + SetLastError(ERROR_INVALID_ACL); + return FALSE; + } + + const WORD _cbData = (_pLabelSid->SubAuthorityCount + 4) * sizeof(DWORD); + if (_pFirstFree == nullptr || PBYTE(_pFirstFree) + _cbData > PBYTE(_pAcl) + _pAcl->AclSize) + { + // internal::BaseSetLastNTError(0xC0000099); + SetLastError(ERROR_ALLOTTED_SPACE_EXCEEDED); + return FALSE; + } + + _pFirstFree->Header.AceType = 0x11; + _pFirstFree->Header.AceFlags = (BYTE)_fAceFlags; + _pFirstFree->Header.AceSize = _cbData; + _pFirstFree->Mask = _uMandatoryPolicy; + _pfnRtlCopySid(sizeof(DWORD) * _pLabelSid->SubAuthorityCount + 8, &_pFirstFree->SidStart, _pLabelSid); + _pAcl->AceCount++; + _pAcl->AclRevision = (BYTE)_uAceRevision; + + return TRUE; + } +#endif +} // namespace YY::Thunks diff --git a/src/Thunks/bcrypt.hpp b/src/Thunks/bcrypt.hpp index 5b00cc75..4b19c439 100644 --- a/src/Thunks/bcrypt.hpp +++ b/src/Thunks/bcrypt.hpp @@ -259,7 +259,7 @@ namespace YY::Thunks _In_ ULONG dwFlags ) override { - if (__wcsnicmp_ascii(BCRYPT_ALGORITHM_NAME, pszProperty, -1) == 0) + if (StringCompareIgnoreCaseByAscii(BCRYPT_ALGORITHM_NAME, pszProperty, -1) == 0) { *pcbResult = pMapItem->cbAlgId; if (!pbOutput) @@ -275,7 +275,7 @@ namespace YY::Thunks memcpy(pbOutput, pMapItem->szAlgName, pMapItem->cbAlgId); return STATUS_SUCCESS; } - else if (__wcsnicmp_ascii(BCRYPT_PROVIDER_HANDLE, pszProperty, -1) == 0) + else if (StringCompareIgnoreCaseByAscii(BCRYPT_PROVIDER_HANDLE, pszProperty, -1) == 0) { *pcbResult = sizeof(BCRYPT_ALG_HANDLE); if (!pbOutput) @@ -511,7 +511,7 @@ namespace YY::Thunks _In_ ULONG dwFlags ) override { - if (__wcsnicmp_ascii(BCRYPT_HASH_LENGTH, pszProperty, -1) == 0) + if (StringCompareIgnoreCaseByAscii(BCRYPT_HASH_LENGTH, pszProperty, -1) == 0) { *pcbResult = sizeof(DWORD); if (!pbOutput) @@ -527,7 +527,7 @@ namespace YY::Thunks *reinterpret_cast(pbOutput) = pAlgorithm->GetHashLength(); return STATUS_SUCCESS; } - else if (__wcsnicmp_ascii(BCRYPT_ALGORITHM_NAME, pszProperty, -1) == 0) + else if (StringCompareIgnoreCaseByAscii(BCRYPT_ALGORITHM_NAME, pszProperty, -1) == 0) { *pcbResult = pAlgorithm->pMapItem->cbAlgId; if (!pbOutput) @@ -543,7 +543,7 @@ namespace YY::Thunks memcpy(pbOutput, pAlgorithm->pMapItem->szAlgName, pAlgorithm->pMapItem->cbAlgId); return STATUS_SUCCESS; } - else if (__wcsnicmp_ascii(BCRYPT_PROVIDER_HANDLE, pszProperty, -1) == 0) + else if (StringCompareIgnoreCaseByAscii(BCRYPT_PROVIDER_HANDLE, pszProperty, -1) == 0) { *pcbResult = sizeof(BCRYPT_ALG_HANDLE); if (!pbOutput) @@ -583,7 +583,7 @@ namespace YY::Thunks _In_ ULONG dwFlags ) override { - if (__wcsnicmp_ascii(BCRYPT_OBJECT_LENGTH, pszProperty, -1) == 0) + if (StringCompareIgnoreCaseByAscii(BCRYPT_OBJECT_LENGTH, pszProperty, -1) == 0) { *pcbResult = sizeof(DWORD); if (!pbOutput) @@ -599,7 +599,7 @@ namespace YY::Thunks *reinterpret_cast(pbOutput) = sizeof(BCryptHash); return STATUS_SUCCESS; } - else if (__wcsnicmp_ascii(BCRYPT_HASH_LENGTH, pszProperty, -1) == 0) + else if (StringCompareIgnoreCaseByAscii(BCRYPT_HASH_LENGTH, pszProperty, -1) == 0) { *pcbResult = sizeof(DWORD); if (!pbOutput) @@ -615,7 +615,7 @@ namespace YY::Thunks *reinterpret_cast(pbOutput) = GetHashLength(); return STATUS_SUCCESS; } - else if (__wcsnicmp_ascii(BCRYPT_HASH_BLOCK_LENGTH, pszProperty, -1) == 0) + else if (StringCompareIgnoreCaseByAscii(BCRYPT_HASH_BLOCK_LENGTH, pszProperty, -1) == 0) { *pcbResult = sizeof(DWORD); if (!pbOutput) @@ -890,7 +890,7 @@ namespace YY::Thunks _In_ ULONG dwFlags ) override { - if (__wcsnicmp_ascii(BCRYPT_BLOCK_LENGTH, pszProperty, -1) == 0) + if (StringCompareIgnoreCaseByAscii(BCRYPT_BLOCK_LENGTH, pszProperty, -1) == 0) { *pcbResult = sizeof(DWORD); if (!pbOutput) @@ -911,7 +911,7 @@ namespace YY::Thunks *reinterpret_cast(pbOutput) = _cbBlockLength; return STATUS_SUCCESS; } - else if (__wcsnicmp_ascii(BCRYPT_ALGORITHM_NAME, pszProperty, -1) == 0) + else if (StringCompareIgnoreCaseByAscii(BCRYPT_ALGORITHM_NAME, pszProperty, -1) == 0) { *pcbResult = pAlgorithm->pMapItem->cbAlgId; if (!pbOutput) @@ -927,7 +927,7 @@ namespace YY::Thunks memcpy(pbOutput, pAlgorithm->pMapItem->szAlgName, pAlgorithm->pMapItem->cbAlgId); return STATUS_SUCCESS; } - else if (__wcsnicmp_ascii(BCRYPT_PROVIDER_HANDLE, pszProperty, -1) == 0) + else if (StringCompareIgnoreCaseByAscii(BCRYPT_PROVIDER_HANDLE, pszProperty, -1) == 0) { *pcbResult = sizeof(BCRYPT_ALG_HANDLE); if (!pbOutput) @@ -943,7 +943,7 @@ namespace YY::Thunks *reinterpret_cast(pbOutput) = pAlgorithm; return STATUS_SUCCESS; } - else if (__wcsnicmp_ascii(BCRYPT_CHAINING_MODE, pszProperty, -1) == 0) + else if (StringCompareIgnoreCaseByAscii(BCRYPT_CHAINING_MODE, pszProperty, -1) == 0) { DWORD _uCryptMode = 0; DWORD _cbResult = sizeof(_uCryptMode); @@ -1005,28 +1005,28 @@ namespace YY::Thunks _In_ ULONG _cbInput, _In_ ULONG _fFlags) override { - if (__wcsnicmp_ascii(BCRYPT_CHAINING_MODE, _szProperty, -1) == 0) + if (StringCompareIgnoreCaseByAscii(BCRYPT_CHAINING_MODE, _szProperty, -1) == 0) { DWORD _uCryptMode; - if (_cbInput == sizeof(BCRYPT_CHAIN_MODE_CBC) && __wcsnicmp_ascii((const wchar_t*)_pInput, BCRYPT_CHAIN_MODE_CBC, _countof(BCRYPT_CHAIN_MODE_CBC)) == 0) + if (_cbInput == sizeof(BCRYPT_CHAIN_MODE_CBC) && StringCompareIgnoreCaseByAscii((const wchar_t*)_pInput, BCRYPT_CHAIN_MODE_CBC, _countof(BCRYPT_CHAIN_MODE_CBC)) == 0) { _uCryptMode = CRYPT_MODE_CBC; } - else if (_cbInput == sizeof(BCRYPT_CHAIN_MODE_ECB) && __wcsnicmp_ascii((const wchar_t*)_pInput, BCRYPT_CHAIN_MODE_ECB, _countof(BCRYPT_CHAIN_MODE_ECB)) == 0) + else if (_cbInput == sizeof(BCRYPT_CHAIN_MODE_ECB) && StringCompareIgnoreCaseByAscii((const wchar_t*)_pInput, BCRYPT_CHAIN_MODE_ECB, _countof(BCRYPT_CHAIN_MODE_ECB)) == 0) { _uCryptMode = CRYPT_MODE_ECB; } - else if (_cbInput == sizeof(BCRYPT_CHAIN_MODE_CFB) && __wcsnicmp_ascii((const wchar_t*)_pInput, BCRYPT_CHAIN_MODE_CFB, _countof(BCRYPT_CHAIN_MODE_CFB)) == 0) + else if (_cbInput == sizeof(BCRYPT_CHAIN_MODE_CFB) && StringCompareIgnoreCaseByAscii((const wchar_t*)_pInput, BCRYPT_CHAIN_MODE_CFB, _countof(BCRYPT_CHAIN_MODE_CFB)) == 0) { _uCryptMode = CRYPT_MODE_CFB; } else { - /*if (_cbInput == sizeof(BCRYPT_CHAIN_MODE_CCM) && __wcsnicmp_ascii((const wchar_t*)_pInput, BCRYPT_CHAIN_MODE_CCM, _countof(BCRYPT_CHAIN_MODE_CCM)) == 0) + /*if (_cbInput == sizeof(BCRYPT_CHAIN_MODE_CCM) && StringCompareIgnoreCaseByAscii((const wchar_t*)_pInput, BCRYPT_CHAIN_MODE_CCM, _countof(BCRYPT_CHAIN_MODE_CCM)) == 0) { _uCryptMode = ; } - else if (_cbInput == sizeof(BCRYPT_CHAIN_MODE_GCM) && __wcsnicmp_ascii((const wchar_t*)_pInput, BCRYPT_CHAIN_MODE_GCM, _countof(BCRYPT_CHAIN_MODE_GCM)) == 0) + else if (_cbInput == sizeof(BCRYPT_CHAIN_MODE_GCM) && StringCompareIgnoreCaseByAscii((const wchar_t*)_pInput, BCRYPT_CHAIN_MODE_GCM, _countof(BCRYPT_CHAIN_MODE_GCM)) == 0) { _uCryptMode = ; }*/ @@ -1252,7 +1252,7 @@ namespace YY::Thunks return STATUS_INVALID_PARAMETER; } - if (__wcsnicmp_ascii(_szBlobType, BCRYPT_KEY_DATA_BLOB, -1) == 0 || __wcsnicmp_ascii(_szBlobType, BCRYPT_OPAQUE_KEY_BLOB, -1) == 0) + if (StringCompareIgnoreCaseByAscii(_szBlobType, BCRYPT_KEY_DATA_BLOB, -1) == 0 || StringCompareIgnoreCaseByAscii(_szBlobType, BCRYPT_OPAQUE_KEY_BLOB, -1) == 0) { struct _PLAINTEXTKEYBLOB : public BLOBHEADER { @@ -1310,7 +1310,7 @@ namespace YY::Thunks _In_ ULONG dwFlags ) override { - if (__wcsnicmp_ascii(BCRYPT_OBJECT_LENGTH, pszProperty, -1) == 0) + if (StringCompareIgnoreCaseByAscii(BCRYPT_OBJECT_LENGTH, pszProperty, -1) == 0) { *pcbResult = sizeof(DWORD); if (!pbOutput) @@ -1326,7 +1326,7 @@ namespace YY::Thunks *reinterpret_cast(pbOutput) = sizeof(BCryptKeyType); return STATUS_SUCCESS; } - else if (__wcsnicmp_ascii(BCRYPT_CHAINING_MODE, pszProperty, -1) == 0) + else if (StringCompareIgnoreCaseByAscii(BCRYPT_CHAINING_MODE, pszProperty, -1) == 0) { if (uCryptMode == 0) { @@ -1375,7 +1375,7 @@ namespace YY::Thunks return STATUS_NOT_SUPPORTED; } } - else if(__wcsnicmp_ascii(BCRYPT_BLOCK_SIZE_LIST, pszProperty, -1) == 0) + else if(StringCompareIgnoreCaseByAscii(BCRYPT_BLOCK_SIZE_LIST, pszProperty, -1) == 0) { // 我也觉得有点奇怪,为什么AES这样的没有返回一个列表,仅仅返回一个值。 // 但是实际上微软的BCrypt也是如此。 @@ -1398,7 +1398,7 @@ namespace YY::Thunks *reinterpret_cast(pbOutput) = kDefaultBlockSize; return STATUS_SUCCESS; } - else if (__wcsnicmp_ascii(BCRYPT_EFFECTIVE_KEY_LENGTH, pszProperty, -1) == 0) + else if (StringCompareIgnoreCaseByAscii(BCRYPT_EFFECTIVE_KEY_LENGTH, pszProperty, -1) == 0) { if (uEffectiveKeyBitCount == 0) { @@ -1430,31 +1430,31 @@ namespace YY::Thunks _In_ ULONG _cbInput, _In_ ULONG _fFlags) override { - if (__wcsnicmp_ascii(BCRYPT_CHAINING_MODE, _szProperty, -1) == 0) + if (StringCompareIgnoreCaseByAscii(BCRYPT_CHAINING_MODE, _szProperty, -1) == 0) { if (uCryptMode == 0) { return STATUS_NOT_SUPPORTED; } - else if (_cbInput == sizeof(BCRYPT_CHAIN_MODE_CBC) && __wcsnicmp_ascii((const wchar_t*)_pInput, BCRYPT_CHAIN_MODE_CBC, _countof(BCRYPT_CHAIN_MODE_CBC)) == 0) + else if (_cbInput == sizeof(BCRYPT_CHAIN_MODE_CBC) && StringCompareIgnoreCaseByAscii((const wchar_t*)_pInput, BCRYPT_CHAIN_MODE_CBC, _countof(BCRYPT_CHAIN_MODE_CBC)) == 0) { uCryptMode = CRYPT_MODE_CBC; } - else if (_cbInput == sizeof(BCRYPT_CHAIN_MODE_ECB) && __wcsnicmp_ascii((const wchar_t*)_pInput, BCRYPT_CHAIN_MODE_ECB, _countof(BCRYPT_CHAIN_MODE_ECB)) == 0) + else if (_cbInput == sizeof(BCRYPT_CHAIN_MODE_ECB) && StringCompareIgnoreCaseByAscii((const wchar_t*)_pInput, BCRYPT_CHAIN_MODE_ECB, _countof(BCRYPT_CHAIN_MODE_ECB)) == 0) { uCryptMode = CRYPT_MODE_ECB; } - else if (_cbInput == sizeof(BCRYPT_CHAIN_MODE_CFB) && __wcsnicmp_ascii((const wchar_t*)_pInput, BCRYPT_CHAIN_MODE_CFB, _countof(BCRYPT_CHAIN_MODE_CFB)) == 0) + else if (_cbInput == sizeof(BCRYPT_CHAIN_MODE_CFB) && StringCompareIgnoreCaseByAscii((const wchar_t*)_pInput, BCRYPT_CHAIN_MODE_CFB, _countof(BCRYPT_CHAIN_MODE_CFB)) == 0) { uCryptMode = CRYPT_MODE_CFB; } else { - /*if (_cbInput == sizeof(BCRYPT_CHAIN_MODE_CCM) && __wcsnicmp_ascii((const wchar_t*)_pInput, BCRYPT_CHAIN_MODE_CCM, _countof(BCRYPT_CHAIN_MODE_CCM)) == 0) + /*if (_cbInput == sizeof(BCRYPT_CHAIN_MODE_CCM) && StringCompareIgnoreCaseByAscii((const wchar_t*)_pInput, BCRYPT_CHAIN_MODE_CCM, _countof(BCRYPT_CHAIN_MODE_CCM)) == 0) { uCryptMode = ; } - else if (_cbInput == sizeof(BCRYPT_CHAIN_MODE_GCM) && __wcsnicmp_ascii((const wchar_t*)_pInput, BCRYPT_CHAIN_MODE_GCM, _countof(BCRYPT_CHAIN_MODE_GCM)) == 0) + else if (_cbInput == sizeof(BCRYPT_CHAIN_MODE_GCM) && StringCompareIgnoreCaseByAscii((const wchar_t*)_pInput, BCRYPT_CHAIN_MODE_GCM, _countof(BCRYPT_CHAIN_MODE_GCM)) == 0) { uCryptMode = ; }*/ @@ -1526,7 +1526,7 @@ namespace YY::Thunks return STATUS_INVALID_PARAMETER; } - if (__wcsnicmp_ascii(_szBlobType, BCRYPT_KEY_DATA_BLOB, -1) == 0 || __wcsnicmp_ascii(_szBlobType, BCRYPT_OPAQUE_KEY_BLOB, -1) == 0) + if (StringCompareIgnoreCaseByAscii(_szBlobType, BCRYPT_KEY_DATA_BLOB, -1) == 0 || StringCompareIgnoreCaseByAscii(_szBlobType, BCRYPT_OPAQUE_KEY_BLOB, -1) == 0) { auto _pHerder = (_BCRYPT_KEY_DATA_BLOB_HEADER*)_pInput; if (_pHerder == nullptr || _pHerder->dwMagic != BCRYPT_KEY_DATA_BLOB_MAGIC || _pHerder->dwVersion != BCRYPT_KEY_DATA_BLOB_VERSION1) @@ -1692,7 +1692,7 @@ namespace YY::Thunks for (auto& _Item : g_Map) { - if (__wcsnicmp_ascii(_szAlgId, _Item.szAlgName, (size_t)-1) == 0) + if (StringCompareIgnoreCaseByAscii(_szAlgId, _Item.szAlgName, (size_t)-1) == 0) { return _Item.pfnOpenAlgorithmProviderType(&_Item, _fFlags, reinterpret_cast(_phAlgorithm)); } @@ -2179,7 +2179,7 @@ namespace YY::Thunks wchar_t szAlgorithmNameBuffer[4]; if (hTargetAlg && cbDerivedKey == 16 && _uHashLength < 32 && BCryptGetProperty(hTargetAlg, BCRYPT_ALGORITHM_NAME, (PUCHAR)szAlgorithmNameBuffer, sizeof(szAlgorithmNameBuffer), &_cbResult, 0) >= 0 - && __wcsnicmp_ascii(szAlgorithmNameBuffer, L"AES", -1) == 0) + && StringCompareIgnoreCaseByAscii(szAlgorithmNameBuffer, L"AES", -1) == 0) { v19 = true; } diff --git a/src/Thunks/d3d11.hpp b/src/Thunks/d3d11.hpp index 278c38fa..43351c1c 100644 --- a/src/Thunks/d3d11.hpp +++ b/src/Thunks/d3d11.hpp @@ -1,4 +1,6 @@ -#include +#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#include +#endif namespace YY::Thunks { diff --git a/src/Thunks/d3d12.hpp b/src/Thunks/d3d12.hpp new file mode 100644 index 00000000..04c8c27f --- /dev/null +++ b/src/Thunks/d3d12.hpp @@ -0,0 +1,31 @@ +#if (YY_Thunks_Support_Version < NTDDI_WIN10) +#include +#endif + +namespace YY::Thunks +{ +#if (YY_Thunks_Support_Version < NTDDI_WIN10) + + // Windows 10 + __DEFINE_THUNK( + d3d12, + 16, + HRESULT, + WINAPI, + D3D12CreateDevice, + _In_opt_ IUnknown* pAdapter, + D3D_FEATURE_LEVEL MinimumFeatureLevel, + _In_ REFIID riid, // Expected: ID3D12Device + _COM_Outptr_opt_ void** ppDevice) + { + if (const auto _pfnD3D12CreateDevice = try_get_D3D12CreateDevice()) + { + return _pfnD3D12CreateDevice(pAdapter, MinimumFeatureLevel, riid, ppDevice); + } + + if (ppDevice) + *ppDevice = nullptr; + return E_NOINTERFACE; + } +#endif +} diff --git a/src/Thunks/dwrite.hpp b/src/Thunks/dwrite.hpp index 332d4c73..8bb9e36b 100644 --- a/src/Thunks/dwrite.hpp +++ b/src/Thunks/dwrite.hpp @@ -1,11 +1,1155 @@ -#include +#if (YY_Thunks_Support_Version < NTDDI_WIN10) +#include +#include +#endif + +#if defined(YY_Thunks_Implemented) +namespace YY::Thunks::Fallback +{ +#if (YY_Thunks_Support_Version < NTDDI_WIN10) + class DWriteRenderingParams : public IDWriteRenderingParams3 + { + private: + ULONG uRef = 1; + DWORD uLevel = 0; + union + { + IDWriteRenderingParams* pDWriteRenderingParams = nullptr; + IDWriteRenderingParams1* pDWriteRenderingParams1; + IDWriteRenderingParams2* pDWriteRenderingParams2; + IDWriteRenderingParams3* pDWriteRenderingParams3; + }; + FLOAT enhancedContrastGrayscale = 0.0f; + DWRITE_GRID_FIT_MODE eGridFitMode = DWRITE_GRID_FIT_MODE::DWRITE_GRID_FIT_MODE_DEFAULT; + DWRITE_RENDERING_MODE1 eRenderingMode1 = DWRITE_RENDERING_MODE1::DWRITE_RENDERING_MODE1_DEFAULT; + + public: + DWriteRenderingParams(DWORD uLevel, IDWriteRenderingParams* _pDWriteRenderingParams, + FLOAT _EnhancedContrastGrayscale, + DWRITE_GRID_FIT_MODE _eGridFitMode = DWRITE_GRID_FIT_MODE::DWRITE_GRID_FIT_MODE_DEFAULT, + DWRITE_RENDERING_MODE1 _eRenderingMode1 = DWRITE_RENDERING_MODE1::DWRITE_RENDERING_MODE1_DEFAULT) + : uLevel(uLevel) + , pDWriteRenderingParams(_pDWriteRenderingParams) + , enhancedContrastGrayscale(_EnhancedContrastGrayscale) + , eGridFitMode(_eGridFitMode) + { + pDWriteRenderingParams->AddRef(); + } + + DWriteRenderingParams(IDWriteRenderingParams1* _pDWriteRenderingParams, + DWRITE_GRID_FIT_MODE _eGridFitMode, + DWRITE_RENDERING_MODE1 _eRenderingMode1 = DWRITE_RENDERING_MODE1::DWRITE_RENDERING_MODE1_DEFAULT) + : uLevel(1) + , pDWriteRenderingParams1(_pDWriteRenderingParams) + , eGridFitMode(_eGridFitMode) + { + pDWriteRenderingParams->AddRef(); + } + + DWriteRenderingParams(IDWriteRenderingParams2* _pDWriteRenderingParams, DWRITE_RENDERING_MODE1 _eRenderingMode1) + : uLevel(2) + , pDWriteRenderingParams2(_pDWriteRenderingParams) + , eRenderingMode1(_eRenderingMode1) + { + pDWriteRenderingParams->AddRef(); + } + + DWriteRenderingParams(const DWriteRenderingParams&) = delete; + + ~DWriteRenderingParams() + { + pDWriteRenderingParams->Release(); + } + + //////////////////////////////////////////////////////// + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface( + /* [in] */ REFIID riid, + /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) override + { + if (!ppvObject) + return E_POINTER; + + *ppvObject = nullptr; + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDWriteRenderingParams) + || riid == __uuidof(IDWriteRenderingParams1) + || riid == __uuidof(IDWriteRenderingParams2) + || riid == __uuidof(IDWriteRenderingParams3)) + { + AddRef(); + *ppvObject = this; + return S_OK; + } + else + { + return E_NOINTERFACE; + } + } + + ULONG STDMETHODCALLTYPE AddRef(void) override + { + return InterlockedIncrement(&uRef); + } + + ULONG STDMETHODCALLTYPE Release(void) override + { + const auto _uNewRef = InterlockedDecrement(&uRef); + if (_uNewRef == 0) + { + internal::Delete(this); + } + return _uNewRef; + } + + ///////////////////////////////////////////////////////// + // IDWriteRenderingParams + STDMETHOD_(FLOAT, GetGamma)() override + { + return pDWriteRenderingParams->GetGamma(); + } + + STDMETHOD_(FLOAT, GetEnhancedContrast)() override + { + return pDWriteRenderingParams->GetEnhancedContrast(); + } + + STDMETHOD_(FLOAT, GetClearTypeLevel)() override + { + return pDWriteRenderingParams->GetEnhancedContrast(); + } + + STDMETHOD_(DWRITE_PIXEL_GEOMETRY, GetPixelGeometry)() override + { + return pDWriteRenderingParams->GetPixelGeometry(); + } + + STDMETHOD_(DWRITE_RENDERING_MODE, GetRenderingMode)() override + { + return pDWriteRenderingParams->GetRenderingMode(); + } + + ///////////////////////////////////////////////////////// + // IDWriteRenderingParams1 + STDMETHOD_(FLOAT, GetGrayscaleEnhancedContrast)() override + { + if (uLevel >= 1) + { + return pDWriteRenderingParams1->GetGrayscaleEnhancedContrast(); + } + return enhancedContrastGrayscale; + } + + ///////////////////////////////////////////////////////// + // IDWriteRenderingParams2 + STDMETHOD_(DWRITE_GRID_FIT_MODE, GetGridFitMode)() override + { + if (uLevel >= 2) + { + return pDWriteRenderingParams2->GetGridFitMode(); + } + return eGridFitMode; + } + + ///////////////////////////////////////////////////////// + // IDWriteRenderingParams3 + STDMETHOD_(DWRITE_RENDERING_MODE1, GetRenderingMode1)() override + { + if (uLevel >= 3) + { + return pDWriteRenderingParams3->GetRenderingMode1(); + } + + return eRenderingMode1; + } + }; + + class DWriteFontCollection : public IDWriteFontCollection1 + { + private: + ULONG uRef = 1; + DWORD uLevel = 0; + union + { + IDWriteFontCollection* pFontCollection = nullptr; + IDWriteFontCollection1* pFontCollection1; + }; + + public: + DWriteFontCollection(_In_opt_ IDWriteFontCollection* _pFontCollection = nullptr, DWORD _uLevel = 0) + : uLevel(_uLevel) + , pFontCollection(_pFontCollection) + { + if(pFontCollection) + pFontCollection->AddRef(); + } + + DWriteFontCollection(const DWriteFontCollection&) = delete; + + ~DWriteFontCollection() + { + if(pFontCollection) + pFontCollection->Release(); + } + + //////////////////////////////////////////////////////// + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface( + /* [in] */ REFIID riid, + /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) override + { + if (!ppvObject) + return E_POINTER; + + *ppvObject = nullptr; + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDWriteFontCollection) + || riid == __uuidof(IDWriteFontCollection1)) + { + AddRef(); + *ppvObject = this; + return S_OK; + } + else if (pFontCollection) + { + return pFontCollection->QueryInterface(riid, ppvObject); + } + else + { + return E_NOINTERFACE; + } + } + + ULONG STDMETHODCALLTYPE AddRef(void) override + { + return InterlockedIncrement(&uRef); + } + + ULONG STDMETHODCALLTYPE Release(void) override + { + const auto _uNewRef = InterlockedDecrement(&uRef); + if (_uNewRef == 0) + { + internal::Delete(this); + } + return _uNewRef; + } + + /////////////////////////////////////////////// + // IDWriteFontCollection + STDMETHOD_(UINT32, GetFontFamilyCount)() override + { + return pFontCollection ? pFontCollection->GetFontFamilyCount() : 0u; + } + + STDMETHOD(GetFontFamily)( + UINT32 index, + _COM_Outptr_ IDWriteFontFamily** fontFamily + ) override + { + if (pFontCollection) + { + return pFontCollection->GetFontFamily(index, fontFamily); + } + + if (fontFamily) + *fontFamily = nullptr; + + return E_INVALIDARG; + } + + STDMETHOD(FindFamilyName)( + _In_z_ WCHAR const* familyName, + _Out_ UINT32* index, + _Out_ BOOL* exists + ) override + { + if (pFontCollection) + { + return pFontCollection->FindFamilyName(familyName, index, exists); + } + + if (index == nullptr || exists == nullptr) + return E_INVALIDARG; + + *index = UINT_MAX; + *exists = FALSE; + return S_OK; + } + + STDMETHOD(GetFontFromFontFace)( + _In_ IDWriteFontFace* fontFace, + _COM_Outptr_ IDWriteFont** font + ) override + { + if (pFontCollection) + { + return pFontCollection->GetFontFromFontFace(fontFace, font); + } + + if (!font) + return E_NOINTERFACE; + + *font = nullptr; + return E_NOT_SET; + } + + /////////////////////////////////////////////// + // IDWriteFontCollection1 + STDMETHOD(GetFontSet)( + _COM_Outptr_ IDWriteFontSet** fontSet + ) override + { + if (pFontCollection) + { + if (uLevel >= 1) + { + return pFontCollection1->GetFontSet(fontSet); + } + } + + if (!fontSet) + return E_NOINTERFACE; + + *fontSet = nullptr; + return E_NOTIMPL; + } + + STDMETHOD(GetFontFamily)( + UINT32 index, + _COM_Outptr_ IDWriteFontFamily1** fontFamily + ) override + { + if (pFontCollection) + { + if (uLevel >= 1) + { + return pFontCollection1->GetFontFamily(index, fontFamily); + } + } + + if (!fontFamily) + return E_NOINTERFACE; + + *fontFamily = nullptr; + return E_NOTIMPL; + } + + using IDWriteFontCollection::GetFontFamily; + }; + + class DWriteFontFallback : public IDWriteFontFallback + { + private: + ULONG uRef = 1; + DWORD uLevel = 0; + IDWriteFontFallback* pFontFallback = nullptr; + + public: + DWriteFontFallback() = default; + + DWriteFontFallback(const DWriteFontFallback&) = delete; + + ~DWriteFontFallback() + { + if (pFontFallback) + pFontFallback->Release(); + } + + //////////////////////////////////////////////////////// + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface( + /* [in] */ REFIID riid, + /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) override + { + if (!ppvObject) + return E_POINTER; + + *ppvObject = nullptr; + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDWriteFontFallback)) + { + AddRef(); + *ppvObject = this; + return S_OK; + } + else if (pFontFallback) + { + return pFontFallback->QueryInterface(riid, ppvObject); + } + else + { + return E_NOINTERFACE; + } + } + + ULONG STDMETHODCALLTYPE AddRef(void) override + { + return InterlockedIncrement(&uRef); + } + + ULONG STDMETHODCALLTYPE Release(void) override + { + const auto _uNewRef = InterlockedDecrement(&uRef); + if (_uNewRef == 0) + { + internal::Delete(this); + } + return _uNewRef; + } + + //////////////////////////////////////////////////////// + // IDWriteFontFallback + STDMETHOD(MapCharacters)( + IDWriteTextAnalysisSource* analysisSource, + UINT32 textPosition, + UINT32 textLength, + _In_opt_ IDWriteFontCollection* baseFontCollection, + _In_opt_z_ wchar_t const* baseFamilyName, + DWRITE_FONT_WEIGHT baseWeight, + DWRITE_FONT_STYLE baseStyle, + DWRITE_FONT_STRETCH baseStretch, + _Out_range_(0, textLength) UINT32* mappedLength, + _COM_Outptr_result_maybenull_ IDWriteFont** mappedFont, + _Out_ FLOAT* scale + ) override + { + if (pFontFallback) + { + return pFontFallback->MapCharacters( + analysisSource, + textPosition, + textLength, + baseFontCollection, + baseFamilyName, + baseWeight, + baseStyle, + baseStretch, + mappedLength, + mappedFont, + scale); + } + + if (!mappedFont) + return E_NOINTERFACE; + + if (mappedLength == nullptr || scale == nullptr) + return E_NOINTERFACE; + + // 假装没有字体需要呈现 + *mappedLength = 0; + *scale = 1.0; + *mappedFont = nullptr; + return S_OK; + } + }; + + class DWriteFactory : public IDWriteFactory3 + { + private: + ULONG uRef = 1; + DWORD uLevel = 0; + union + { + IDWriteFactory* pDWriteFactory = nullptr; + IDWriteFactory1* pDWriteFactory1; + IDWriteFactory2* pDWriteFactory2; + IDWriteFactory3* pDWriteFactory3; + }; + + public: + DWriteFactory(IDWriteFactory* _pDWriteFactory, DWORD _uLevel = 0) + : uLevel(_uLevel) + , pDWriteFactory(_pDWriteFactory) + { + pDWriteFactory->AddRef(); + } + + DWriteFactory(const DWriteFactory&) = delete; + + ~DWriteFactory() + { + pDWriteFactory->Release(); + } + + //////////////////////////////////////////////////////// + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface( + /* [in] */ REFIID riid, + /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) override + { + if (riid == __uuidof(IUnknown) + || riid == __uuidof(IDWriteFactory) + || riid == __uuidof(IDWriteFactory1) + || riid == __uuidof(IDWriteFactory2) + || riid == __uuidof(IDWriteFactory3)) + { + if (!ppvObject) + return E_POINTER; + + *ppvObject = nullptr; + + AddRef(); + *ppvObject = this; + return S_OK; + } + else + { + return pDWriteFactory->QueryInterface(riid, ppvObject); + } + } + + ULONG STDMETHODCALLTYPE AddRef(void) override + { + return InterlockedIncrement(&uRef); + } + + ULONG STDMETHODCALLTYPE Release(void) override + { + const auto _uNewRef = InterlockedDecrement(&uRef); + if (_uNewRef == 0) + { + internal::Delete(this); + } + return _uNewRef; + } + + //////////////////////////////////////////////////////// + // IDWriteFactory + + STDMETHOD(GetSystemFontCollection)( + _COM_Outptr_ IDWriteFontCollection** fontCollection, + BOOL checkForUpdates = FALSE + ) override + { + return pDWriteFactory->GetSystemFontCollection(fontCollection, checkForUpdates); + } + + + STDMETHOD(CreateCustomFontCollection)( + _In_ IDWriteFontCollectionLoader* collectionLoader, + _In_reads_bytes_(collectionKeySize) void const* collectionKey, + UINT32 collectionKeySize, + _COM_Outptr_ IDWriteFontCollection** fontCollection + ) override + { + return pDWriteFactory->CreateCustomFontCollection(collectionLoader, collectionKey, collectionKeySize, fontCollection); + } + + STDMETHOD(RegisterFontCollectionLoader)( + _In_ IDWriteFontCollectionLoader* fontCollectionLoader + ) override + { + return pDWriteFactory->RegisterFontCollectionLoader(fontCollectionLoader); + } + + STDMETHOD(UnregisterFontCollectionLoader)( + _In_ IDWriteFontCollectionLoader* fontCollectionLoader + ) override + { + return pDWriteFactory->UnregisterFontCollectionLoader(fontCollectionLoader); + } + + STDMETHOD(CreateFontFileReference)( + _In_z_ WCHAR const* filePath, + _In_opt_ FILETIME const* lastWriteTime, + _COM_Outptr_ IDWriteFontFile** fontFile + ) override + { + return pDWriteFactory->CreateFontFileReference(filePath, lastWriteTime, fontFile); + } + + STDMETHOD(CreateCustomFontFileReference)( + _In_reads_bytes_(fontFileReferenceKeySize) void const* fontFileReferenceKey, + UINT32 fontFileReferenceKeySize, + _In_ IDWriteFontFileLoader* fontFileLoader, + _COM_Outptr_ IDWriteFontFile** fontFile + ) override + { + return pDWriteFactory->CreateCustomFontFileReference(fontFileReferenceKey, fontFileReferenceKeySize, fontFileLoader, fontFile); + } + + STDMETHOD(CreateFontFace)( + DWRITE_FONT_FACE_TYPE fontFaceType, + UINT32 numberOfFiles, + _In_reads_(numberOfFiles) IDWriteFontFile* const* fontFiles, + UINT32 faceIndex, + DWRITE_FONT_SIMULATIONS fontFaceSimulationFlags, + _COM_Outptr_ IDWriteFontFace** fontFace + ) override + { + return pDWriteFactory->CreateFontFace(fontFaceType, numberOfFiles, fontFiles, faceIndex, fontFaceSimulationFlags, fontFace); + } + + STDMETHOD(CreateRenderingParams)( + _COM_Outptr_ IDWriteRenderingParams** renderingParams + ) override + { + return pDWriteFactory->CreateRenderingParams(renderingParams); + } + + STDMETHOD(CreateMonitorRenderingParams)( + HMONITOR monitor, + _COM_Outptr_ IDWriteRenderingParams** renderingParams + ) override + { + return pDWriteFactory->CreateMonitorRenderingParams(monitor, renderingParams); + } + + STDMETHOD(CreateCustomRenderingParams)( + FLOAT gamma, + FLOAT enhancedContrast, + FLOAT clearTypeLevel, + DWRITE_PIXEL_GEOMETRY pixelGeometry, + DWRITE_RENDERING_MODE renderingMode, + _COM_Outptr_ IDWriteRenderingParams** renderingParams + ) override + { + return pDWriteFactory->CreateCustomRenderingParams(gamma, enhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, renderingParams); + } + + STDMETHOD(RegisterFontFileLoader)( + _In_ IDWriteFontFileLoader* fontFileLoader + ) override + { + return pDWriteFactory->RegisterFontFileLoader(fontFileLoader); + } + + STDMETHOD(UnregisterFontFileLoader)( + _In_ IDWriteFontFileLoader* fontFileLoader + ) override + { + return pDWriteFactory->UnregisterFontFileLoader(fontFileLoader); + } + + STDMETHOD(CreateTextFormat)( + _In_z_ WCHAR const* fontFamilyName, + _In_opt_ IDWriteFontCollection* fontCollection, + DWRITE_FONT_WEIGHT fontWeight, + DWRITE_FONT_STYLE fontStyle, + DWRITE_FONT_STRETCH fontStretch, + FLOAT fontSize, + _In_z_ WCHAR const* localeName, + _COM_Outptr_ IDWriteTextFormat** textFormat + ) override + { + return pDWriteFactory->CreateTextFormat(fontFamilyName, fontCollection, fontWeight, fontStyle, fontStretch, fontSize, localeName, textFormat); + } + + STDMETHOD(CreateTypography)( + _COM_Outptr_ IDWriteTypography** typography + ) override + { + return pDWriteFactory->CreateTypography(typography); + } + + STDMETHOD(GetGdiInterop)( + _COM_Outptr_ IDWriteGdiInterop** gdiInterop + ) override + { + return pDWriteFactory->GetGdiInterop(gdiInterop); + } + + STDMETHOD(CreateTextLayout)( + _In_reads_(stringLength) WCHAR const* string, + UINT32 stringLength, + _In_ IDWriteTextFormat* textFormat, + FLOAT maxWidth, + FLOAT maxHeight, + _COM_Outptr_ IDWriteTextLayout** textLayout + ) override + { + return pDWriteFactory->CreateTextLayout(string, stringLength, textFormat, maxWidth, maxHeight, textLayout); + } + + STDMETHOD(CreateGdiCompatibleTextLayout)( + _In_reads_(stringLength) WCHAR const* string, + UINT32 stringLength, + _In_ IDWriteTextFormat* textFormat, + FLOAT layoutWidth, + FLOAT layoutHeight, + FLOAT pixelsPerDip, + _In_opt_ DWRITE_MATRIX const* transform, + BOOL useGdiNatural, + _COM_Outptr_ IDWriteTextLayout** textLayout + ) override + { + return pDWriteFactory->CreateGdiCompatibleTextLayout(string, stringLength, textFormat, layoutWidth, layoutHeight, pixelsPerDip, transform, useGdiNatural, textLayout); + } + + STDMETHOD(CreateEllipsisTrimmingSign)( + _In_ IDWriteTextFormat* textFormat, + _COM_Outptr_ IDWriteInlineObject** trimmingSign + ) override + { + return pDWriteFactory->CreateEllipsisTrimmingSign(textFormat, trimmingSign); + } + + STDMETHOD(CreateTextAnalyzer)( + _COM_Outptr_ IDWriteTextAnalyzer** textAnalyzer + ) override + { + return pDWriteFactory->CreateTextAnalyzer(textAnalyzer); + } + + STDMETHOD(CreateNumberSubstitution)( + _In_ DWRITE_NUMBER_SUBSTITUTION_METHOD substitutionMethod, + _In_z_ WCHAR const* localeName, + _In_ BOOL ignoreUserOverride, + _COM_Outptr_ IDWriteNumberSubstitution** numberSubstitution + ) override + { + return pDWriteFactory->CreateNumberSubstitution(substitutionMethod, localeName, ignoreUserOverride, numberSubstitution); + } + + STDMETHOD(CreateGlyphRunAnalysis)( + _In_ DWRITE_GLYPH_RUN const* glyphRun, + FLOAT pixelsPerDip, + _In_opt_ DWRITE_MATRIX const* transform, + DWRITE_RENDERING_MODE renderingMode, + DWRITE_MEASURING_MODE measuringMode, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + _COM_Outptr_ IDWriteGlyphRunAnalysis** glyphRunAnalysis + ) override + { + return pDWriteFactory->CreateGlyphRunAnalysis(glyphRun, pixelsPerDip, transform, renderingMode, measuringMode, baselineOriginX, baselineOriginY, glyphRunAnalysis); + } + + + //////////////////////////////////////////////////////// + // IDWriteFactory1 + STDMETHOD(GetEudcFontCollection)( + _COM_Outptr_ IDWriteFontCollection** fontCollection, + BOOL checkForUpdates = FALSE + ) override + { + if (uLevel >= 1) + { + return pDWriteFactory1->GetEudcFontCollection(fontCollection, checkForUpdates); + } + + // 假装没有安装 Eudc字体 + + if (!fontCollection) + return E_INVALIDARG; + *fontCollection = nullptr; + + auto _pEmptyCollection = internal::New(); + if (!_pEmptyCollection) + return E_OUTOFMEMORY; + *fontCollection = _pEmptyCollection; + return S_OK; + } + + STDMETHOD(CreateCustomRenderingParams)( + FLOAT gamma, + FLOAT enhancedContrast, + FLOAT enhancedContrastGrayscale, + FLOAT clearTypeLevel, + DWRITE_PIXEL_GEOMETRY pixelGeometry, + DWRITE_RENDERING_MODE renderingMode, + _COM_Outptr_ IDWriteRenderingParams1** renderingParams + ) override + { + if(uLevel >= 1) + { + return pDWriteFactory1->CreateCustomRenderingParams(gamma, enhancedContrast, enhancedContrastGrayscale, clearTypeLevel, pixelGeometry, renderingMode, renderingParams); + } + + if (!renderingParams) + return E_NOINTERFACE; + + *renderingParams = nullptr; + if (enhancedContrastGrayscale < 0.0f) + return E_NOINTERFACE; + + IDWriteRenderingParams* _pRenderingParams = nullptr; + auto _hr = pDWriteFactory->CreateCustomRenderingParams(gamma, enhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, &_pRenderingParams); + if (FAILED(_hr) || _pRenderingParams == nullptr) + return _hr; + + auto _pRenderingParams1 = internal::New(uLevel, _pRenderingParams, enhancedContrastGrayscale); + _pRenderingParams->Release(); + if (!_pRenderingParams1) + return E_OUTOFMEMORY; + + *renderingParams = _pRenderingParams1; + return S_OK; + } + + using IDWriteFactory::CreateCustomRenderingParams; + + //////////////////////////////////////////////////////// + // IDWriteFactory2 + STDMETHOD(GetSystemFontFallback)( + _COM_Outptr_ IDWriteFontFallback** fontFallback + ) override + { + if (uLevel >= 2) + { + return pDWriteFactory2->GetSystemFontFallback(fontFallback); + } + + if (!fontFallback) + return E_INVALIDARG; + + *fontFallback = nullptr; + + auto _pFontFallback = internal::New(); + if (!_pFontFallback) + return E_OUTOFMEMORY; + + *fontFallback = _pFontFallback; + return S_OK; + } + + STDMETHOD(CreateFontFallbackBuilder)( + _COM_Outptr_ IDWriteFontFallbackBuilder** fontFallbackBuilder + ) override + { + if (uLevel >= 2) + { + return pDWriteFactory2->CreateFontFallbackBuilder(fontFallbackBuilder); + } + + if (!fontFallbackBuilder) + return E_INVALIDARG; + + *fontFallbackBuilder = nullptr; + return E_NOTIMPL; + } + + STDMETHOD(TranslateColorGlyphRun)( + FLOAT baselineOriginX, + FLOAT baselineOriginY, + _In_ DWRITE_GLYPH_RUN const* glyphRun, + _In_opt_ DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription, + DWRITE_MEASURING_MODE measuringMode, + _In_opt_ DWRITE_MATRIX const* worldToDeviceTransform, + UINT32 colorPaletteIndex, + _COM_Outptr_ IDWriteColorGlyphRunEnumerator** colorLayers + ) override + { + if (uLevel >= 2) + { + return pDWriteFactory2->TranslateColorGlyphRun(baselineOriginX, baselineOriginY, glyphRun, glyphRunDescription, measuringMode, worldToDeviceTransform, colorPaletteIndex, colorLayers); + } + + if (!colorLayers) + return E_INVALIDARG; + + *colorLayers = nullptr; + return E_NOTIMPL; + } + + STDMETHOD(CreateCustomRenderingParams)( + FLOAT gamma, + FLOAT enhancedContrast, + FLOAT grayscaleEnhancedContrast, + FLOAT clearTypeLevel, + DWRITE_PIXEL_GEOMETRY pixelGeometry, + DWRITE_RENDERING_MODE renderingMode, + DWRITE_GRID_FIT_MODE gridFitMode, + _COM_Outptr_ IDWriteRenderingParams2** renderingParams + ) override + { + if (uLevel >= 2) + { + return pDWriteFactory2->CreateCustomRenderingParams(gamma, enhancedContrast, grayscaleEnhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, gridFitMode, renderingParams); + } + + if (!renderingParams) + return E_INVALIDARG; + + *renderingParams = nullptr; + + IDWriteRenderingParams* _pRenderingParams = nullptr; + HRESULT _hr = S_OK; + if (uLevel >= 1) + { + _hr = pDWriteFactory1->CreateCustomRenderingParams(gamma, enhancedContrast, grayscaleEnhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, (IDWriteRenderingParams1**)&_pRenderingParams); + } + else + { + if (grayscaleEnhancedContrast < 0.0) + return E_INVALIDARG; + + _hr = pDWriteFactory->CreateCustomRenderingParams(gamma, enhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, &_pRenderingParams); + } + + if (FAILED(_hr) || _pRenderingParams == nullptr) + return _hr; + auto _pTemp = internal::New(uLevel, _pRenderingParams, grayscaleEnhancedContrast, gridFitMode); + _pRenderingParams->Release(); + + if (!_pTemp) + return E_OUTOFMEMORY; + + *renderingParams = _pTemp; + return _hr; + } + + using IDWriteFactory::CreateCustomRenderingParams; + using IDWriteFactory1::CreateCustomRenderingParams; + + STDMETHOD(CreateGlyphRunAnalysis)( + _In_ DWRITE_GLYPH_RUN const* glyphRun, + _In_opt_ DWRITE_MATRIX const* transform, + DWRITE_RENDERING_MODE renderingMode, + DWRITE_MEASURING_MODE measuringMode, + DWRITE_GRID_FIT_MODE gridFitMode, + DWRITE_TEXT_ANTIALIAS_MODE antialiasMode, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + _COM_Outptr_ IDWriteGlyphRunAnalysis** glyphRunAnalysis + ) override + { + if (uLevel >= 2) + { + return pDWriteFactory2->CreateGlyphRunAnalysis(glyphRun, transform, renderingMode, measuringMode, gridFitMode, antialiasMode, baselineOriginX, baselineOriginY, glyphRunAnalysis); + } + + return pDWriteFactory->CreateGlyphRunAnalysis(glyphRun, 1.0f, transform, renderingMode, measuringMode, baselineOriginX, baselineOriginY, glyphRunAnalysis); + } + + using IDWriteFactory::CreateGlyphRunAnalysis; + + + // IDWriteFactory3 + STDMETHOD(CreateGlyphRunAnalysis)( + _In_ DWRITE_GLYPH_RUN const* glyphRun, + _In_opt_ DWRITE_MATRIX const* transform, + DWRITE_RENDERING_MODE1 renderingMode, + DWRITE_MEASURING_MODE measuringMode, + DWRITE_GRID_FIT_MODE gridFitMode, + DWRITE_TEXT_ANTIALIAS_MODE antialiasMode, + FLOAT baselineOriginX, + FLOAT baselineOriginY, + _COM_Outptr_ IDWriteGlyphRunAnalysis** glyphRunAnalysis + ) override + { + if (uLevel >= 3) + { + return pDWriteFactory3->CreateGlyphRunAnalysis(glyphRun, transform, renderingMode, measuringMode, gridFitMode, antialiasMode, baselineOriginX, baselineOriginY, glyphRunAnalysis); + } + + DWRITE_RENDERING_MODE _eRenderingMode = renderingMode == DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED ? DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC : DWRITE_RENDERING_MODE(renderingMode); + return CreateGlyphRunAnalysis(glyphRun, transform, _eRenderingMode, measuringMode, gridFitMode, antialiasMode, baselineOriginX, baselineOriginY, glyphRunAnalysis); + } + + using IDWriteFactory::CreateGlyphRunAnalysis; + using IDWriteFactory2::CreateGlyphRunAnalysis; + + STDMETHOD(CreateCustomRenderingParams)( + FLOAT gamma, + FLOAT enhancedContrast, + FLOAT grayscaleEnhancedContrast, + FLOAT clearTypeLevel, + DWRITE_PIXEL_GEOMETRY pixelGeometry, + DWRITE_RENDERING_MODE1 renderingMode, + DWRITE_GRID_FIT_MODE gridFitMode, + _COM_Outptr_ IDWriteRenderingParams3** renderingParams + ) override + { + if (uLevel >= 3) + { + return pDWriteFactory3->CreateCustomRenderingParams(gamma, enhancedContrast, grayscaleEnhancedContrast, clearTypeLevel, pixelGeometry, renderingMode, gridFitMode, renderingParams); + } + + if (!renderingParams) + return E_INVALIDARG; + + *renderingParams = nullptr; + DWRITE_RENDERING_MODE _eRenderingMode = renderingMode == DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED ? DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC : DWRITE_RENDERING_MODE(renderingMode); + IDWriteRenderingParams* _pRenderingParams = nullptr; + HRESULT _hr = S_OK; + if (uLevel >= 2) + { + _hr = pDWriteFactory2->CreateCustomRenderingParams(gamma, enhancedContrast, grayscaleEnhancedContrast, clearTypeLevel, pixelGeometry, _eRenderingMode, gridFitMode, (IDWriteRenderingParams2**)&_pRenderingParams); + } + else if (uLevel >= 1) + { + DWRITE_RENDERING_MODE _eRenderingMode = renderingMode == DWRITE_RENDERING_MODE1_NATURAL_SYMMETRIC_DOWNSAMPLED ? DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC : DWRITE_RENDERING_MODE(renderingMode); + _hr = pDWriteFactory1->CreateCustomRenderingParams(gamma, enhancedContrast, grayscaleEnhancedContrast, clearTypeLevel, pixelGeometry, _eRenderingMode, (IDWriteRenderingParams1**)&_pRenderingParams); + } + else + { + if (grayscaleEnhancedContrast < 0.0) + return E_INVALIDARG; + + _hr = pDWriteFactory->CreateCustomRenderingParams(gamma, enhancedContrast, clearTypeLevel, pixelGeometry, _eRenderingMode, &_pRenderingParams); + } + + if (FAILED(_hr) || _pRenderingParams == nullptr) + return _hr; + + auto _pTemp = internal::New(uLevel, _pRenderingParams, grayscaleEnhancedContrast, gridFitMode, renderingMode); + _pRenderingParams->Release(); + + if (!_pTemp) + return E_OUTOFMEMORY; + + *renderingParams = _pTemp; + return _hr; + } + + using IDWriteFactory::CreateCustomRenderingParams; + using IDWriteFactory1::CreateCustomRenderingParams; + using IDWriteFactory2::CreateCustomRenderingParams; + + STDMETHOD(CreateFontFaceReference)( + _In_z_ WCHAR const* filePath, + _In_opt_ FILETIME const* lastWriteTime, + UINT32 faceIndex, + DWRITE_FONT_SIMULATIONS fontSimulations, + _COM_Outptr_ IDWriteFontFaceReference** fontFaceReference + ) override + { + if (uLevel >= 3) + { + return pDWriteFactory3->CreateFontFaceReference(filePath, lastWriteTime, faceIndex, fontSimulations, fontFaceReference); + } + + if (!fontFaceReference) + return E_NOINTERFACE; + + *fontFaceReference = nullptr; + return E_NOTIMPL; + } + + STDMETHOD(CreateFontFaceReference)( + _In_ IDWriteFontFile* fontFile, + UINT32 faceIndex, + DWRITE_FONT_SIMULATIONS fontSimulations, + _COM_Outptr_ IDWriteFontFaceReference** fontFaceReference + ) override + { + if (uLevel >= 3) + { + return pDWriteFactory3->CreateFontFaceReference(fontFile, faceIndex, fontSimulations, fontFaceReference); + } + + if (!fontFaceReference) + return E_NOINTERFACE; + + *fontFaceReference = nullptr; + return E_NOTIMPL; + } + + STDMETHOD(GetSystemFontSet)( + _COM_Outptr_ IDWriteFontSet** fontSet + ) override + { + if (uLevel >= 3) + { + return pDWriteFactory3->GetSystemFontSet(fontSet); + } + + // E:\Chromium\src\content\browser\renderer_host\dwrite_font_proxy_impl_win.cc + __WarningMessage__("CHrome用到了这个接口 GetSystemFontSet"); + + if (!fontSet) + return E_NOINTERFACE; + + *fontSet = nullptr; + return E_NOTIMPL; + } + + STDMETHOD(CreateFontSetBuilder)( + _COM_Outptr_ IDWriteFontSetBuilder** fontSetBuilder + ) override + { + if (uLevel >= 3) + { + return pDWriteFactory3->CreateFontSetBuilder(fontSetBuilder); + } + + __WarningMessage__("CHrome用到了这个接口 CreateFontSetBuilder"); + + if (!fontSetBuilder) + return E_NOINTERFACE; + + *fontSetBuilder = nullptr; + return E_NOTIMPL; + } + + STDMETHOD(CreateFontCollectionFromFontSet)( + IDWriteFontSet* fontSet, + _COM_Outptr_ IDWriteFontCollection1** fontCollection + ) override + { + if (uLevel >= 3) + { + return pDWriteFactory3->CreateFontCollectionFromFontSet(fontSet, fontCollection); + } + + if (!fontCollection) + return E_NOINTERFACE; + + *fontCollection = nullptr; + return E_NOTIMPL; + } + + STDMETHOD(GetSystemFontCollection)( + BOOL includeDownloadableFonts, + _COM_Outptr_ IDWriteFontCollection1** fontCollection, + BOOL checkForUpdates = FALSE + ) override + { + if (uLevel >= 3) + { + return pDWriteFactory3->GetSystemFontCollection(includeDownloadableFonts, fontCollection, checkForUpdates); + } + + if (!fontCollection) + return E_NOINTERFACE; + + *fontCollection = nullptr; + + IDWriteFontCollection* _pFontCollection = nullptr; + auto _hr = pDWriteFactory->GetSystemFontCollection(&_pFontCollection, checkForUpdates); + if (FAILED(_hr) || _pFontCollection == nullptr) + return _hr; + + auto _pResult = internal::New(_pFontCollection, 0); + _pFontCollection->Release(); + if (!_pResult) + return E_OUTOFMEMORY; + + *fontCollection = _pResult; + return S_OK; + } + + using IDWriteFactory::GetSystemFontCollection; + + STDMETHOD(GetFontDownloadQueue)( + _COM_Outptr_ IDWriteFontDownloadQueue** fontDownloadQueue + ) override + { + if (uLevel >= 3) + { + return pDWriteFactory3->GetFontDownloadQueue(fontDownloadQueue); + } + + if (!fontDownloadQueue) + return E_NOINTERFACE; + + *fontDownloadQueue = nullptr; + return E_NOTIMPL; + } + }; +#endif // (YY_Thunks_Support_Version < NTDDI_WIN10) +} +#endif namespace YY::Thunks { -#if (YY_Thunks_Support_Version < NTDDI_WIN6SP2) +#if (YY_Thunks_Support_Version < NTDDI_WIN10) // 最低受支持的客户端 Windows 7、带 SP2 的 Windows Vista 和适用于 Windows Vista 的平台更新 [桌面应用 |UWP 应用] // 最低受支持的服务器 Windows Server 2008 R2、Windows Server 2008 SP2 和适用于 Windows Server 2008 的平台更新[桌面应用 | UWP 应用] + // Windows 10引入IDWriteFactory3,所以额外进行Thunks __DEFINE_THUNK( dwrite, 12, @@ -17,13 +1161,67 @@ namespace YY::Thunks _COM_Outptr_ IUnknown **factory ) { - if (const auto _pfnDWriteCreateFactory = try_get_DWriteCreateFactory()) + const auto _pfnDWriteCreateFactory = try_get_DWriteCreateFactory(); + if (!_pfnDWriteCreateFactory) { - return _pfnDWriteCreateFactory(factoryType, iid, factory); + if (!factory) + return E_POINTER; + *factory = nullptr; + return E_NOINTERFACE; } - if (factory) + + if (iid == __uuidof(IDWriteFactory) || iid == __uuidof(IDWriteFactory1) + || iid == __uuidof(IDWriteFactory2) || iid == __uuidof(IDWriteFactory3)) + { + auto _hr = _pfnDWriteCreateFactory(factoryType, __uuidof(IDWriteFactory3), factory); + if (_hr != E_NOINTERFACE) + { + return _hr; + } + + if (!factory) + return E_POINTER; *factory = nullptr; - return E_NOINTERFACE; + + // 不支持IDWriteFactory3,开始伪装IDWriteFactory3支持 + static const GUID kIdLevel[] = + { + __uuidof(IDWriteFactory), + __uuidof(IDWriteFactory1), + __uuidof(IDWriteFactory2), + }; + + for (DWORD _uLevel = _countof(kIdLevel); _uLevel;) + { + --_uLevel; + IDWriteFactory* _pDWriteFactory = nullptr; + _hr = _pfnDWriteCreateFactory(factoryType, kIdLevel[_uLevel], (IUnknown**)&_pDWriteFactory); + if (_hr == E_NOINTERFACE) + continue; + + if (SUCCEEDED(_hr) && _pDWriteFactory) + { + auto _pForward = internal::New(_pDWriteFactory, _uLevel); + if (_pForward) + { + _pDWriteFactory->Release(); + *factory = _pForward; + } + else + { + *factory = _pDWriteFactory; + } + } + + break; + } + + return _hr; + } + else + { + return _pfnDWriteCreateFactory(factoryType, iid, factory); + } } #endif } diff --git a/src/Thunks/esent.hpp b/src/Thunks/esent.hpp index 0f847324..84c7c0aa 100644 --- a/src/Thunks/esent.hpp +++ b/src/Thunks/esent.hpp @@ -332,7 +332,7 @@ namespace YY::Thunks return JET_errInstanceUnavailable; } - szParam[min(_iResult, _cchMax - 1)] = L'\0'; + szParam[min(size_t(_iResult), _cchMax - 1)] = L'\0'; return JET_wrnBufferTruncated; } return JET_errBufferTooSmall; @@ -347,7 +347,7 @@ namespace YY::Thunks return JET_errInstanceUnavailable; } - if (_iResult < _cchMax) + if (size_t(_iResult) < _cchMax) { szParam[_iResult] = L'\0'; return JET_errSuccess; @@ -371,7 +371,7 @@ namespace YY::Thunks return JET_errInstanceUnavailable; } - szParam[min(_iResult, _cchMax - 1)] = L'\0'; + szParam[min(size_t(_iResult), _cchMax - 1)] = L'\0'; return JET_wrnBufferTruncated; } return JET_errBufferTooSmall; diff --git a/src/Thunks/ext-ms-win-rtcore-ntuser-wmpointer.hpp b/src/Thunks/ext-ms-win-rtcore-ntuser-wmpointer.hpp new file mode 100644 index 00000000..f91a68b6 --- /dev/null +++ b/src/Thunks/ext-ms-win-rtcore-ntuser-wmpointer.hpp @@ -0,0 +1,125 @@ +namespace YY::Thunks +{ +#if (YY_Thunks_Support_Version < NTDDI_WIN8) + + // 最低受支持的客户端 Windows 8 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] + __DEFINE_THUNK( + user32, + 8, + BOOL, + WINAPI, + RegisterPointerDeviceNotifications, + _In_ HWND _hWindow, + _In_ BOOL _bNotifyRange + ) + { + if (const auto _pfnRegisterPointerDeviceNotifications = try_get_RegisterPointerDeviceNotifications()) + { + return _pfnRegisterPointerDeviceNotifications(_hWindow, _bNotifyRange); + } + + return TRUE; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN8) + + // 最低受支持的客户端 Windows 8 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] + __DEFINE_THUNK( + user32, + 8, + BOOL, + WINAPI, + GetPointerDevices, + _Inout_ UINT32* _uDeviceCount, + _Out_writes_opt_(*_uDeviceCount) POINTER_DEVICE_INFO* _pPointerDevices + ) + { + if (const auto _pfnRGetPointerDevices = try_get_GetPointerDevices()) + { + return _pfnRGetPointerDevices(_uDeviceCount, _pPointerDevices); + } + + SetLastError(ERROR_SYSTEM_DEVICE_NOT_FOUND); + return FALSE; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN8) + + // 最低受支持的客户端 Windows 8 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] + __DEFINE_THUNK( + user32, + 8, + BOOL, + WINAPI, + GetPointerDevice, + _In_ HANDLE _hDevice, + _Out_writes_(1) POINTER_DEVICE_INFO* _pPointerDevice + ) + { + if (const auto _pfnGetPointerDevice = try_get_GetPointerDevice()) + { + return _pfnGetPointerDevice(_hDevice, _pPointerDevice); + } + + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN8) + + // 最低受支持的客户端 Windows 8 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] + __DEFINE_THUNK( + user32, + 8, + BOOL, + WINAPI, + GetPointerPenInfo, + _In_ UINT32 _uPointerId, + _Out_writes_(1) POINTER_PEN_INFO* _pPenInfo + ) + { + if (const auto _pfnGetPointerPenInfo = try_get_GetPointerPenInfo()) + { + return _pfnGetPointerPenInfo(_uPointerId, _pPenInfo); + } + + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN8) + + // 最低受支持的客户端 Windows 8 [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2012[仅限桌面应用] + __DEFINE_THUNK( + user32, + 8, + BOOL, + WINAPI, + GetPointerType, + _In_ UINT32 _uPointerId, + _Out_ POINTER_INPUT_TYPE* _pPointerType + ) + { + if (const auto _pfnGetPointerType = try_get_GetPointerType()) + { + return _pfnGetPointerType(_uPointerId, _pPointerType); + } + + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } +#endif +} diff --git a/src/Thunks/mf.hpp b/src/Thunks/mf.hpp new file mode 100644 index 00000000..e2c2ec1e --- /dev/null +++ b/src/Thunks/mf.hpp @@ -0,0 +1,65 @@ +#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#include +#endif + +namespace YY::Thunks +{ +#if (YY_Thunks_Support_Version < NTDDI_WIN7) + + // Minimum supported client Windows 7 [desktop apps only] + // Minimum supported server Windows Server 2008 R2[desktop apps only] + __DEFINE_THUNK( + mf, + 8, + HRESULT, + STDAPICALLTYPE, + MFCreateDeviceSource, + _In_ IMFAttributes* pAttributes, + _Outptr_ IMFMediaSource** ppSource + ) + { + if (const auto _pfnMFCreateDeviceSource = try_get_MFCreateDeviceSource()) + { + return _pfnMFCreateDeviceSource(pAttributes, ppSource); + } + + if (!ppSource) + return E_POINTER; + + *ppSource = nullptr; + return E_NOTIMPL; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN7) + + // Minimum supported client Windows 7 [desktop apps only] + // Minimum supported server Windows Server 2008 R2[desktop apps only] + __DEFINE_THUNK( + mf, + 12, + HRESULT, + STDAPICALLTYPE, + MFEnumDeviceSources, + _In_ IMFAttributes* pAttributes, + _Outptr_result_buffer_(*pcSourceActivate) IMFActivate*** pppSourceActivate, + _Out_ UINT32* pcSourceActivate + ) + { + if (const auto _pfnMFEnumDeviceSources = try_get_MFEnumDeviceSources()) + { + return _pfnMFEnumDeviceSources(pAttributes, pppSourceActivate, pcSourceActivate); + } + + if (!pcSourceActivate) + return E_POINTER; + *pcSourceActivate = 0; + + if (!pppSourceActivate) + return E_POINTER; + *pppSourceActivate = nullptr; + return E_NOTIMPL; + } +#endif +} diff --git a/src/Thunks/mfplat.hpp b/src/Thunks/mfplat.hpp index c981bd81..96422891 100644 --- a/src/Thunks/mfplat.hpp +++ b/src/Thunks/mfplat.hpp @@ -2,6 +2,10 @@ #include #endif +#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#include +#endif + namespace YY::Thunks { #if (YY_Thunks_Support_Version < NTDDI_WIN8) @@ -112,5 +116,519 @@ namespace YY::Thunks return E_NOTIMPL; } #endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported server Windows Server 2008[desktop apps | UWP apps] + // Windows XP SP2需要安装补丁 + __DEFINE_THUNK( + mfplat, + 12, + HRESULT, + STDAPICALLTYPE, + MFCreateAlignedMemoryBuffer, + _In_ DWORD cbMaxLength, + _In_ DWORD cbAligment, + _Out_ IMFMediaBuffer** ppBuffer + ) + { + if (const auto _pfnMFCreateAlignedMemoryBuffer = try_get_MFCreateAlignedMemoryBuffer()) + { + return _pfnMFCreateAlignedMemoryBuffer(cbMaxLength, cbAligment, ppBuffer); + } + + if (!ppBuffer) + return E_POINTER; + *ppBuffer = nullptr; + return E_NOTIMPL; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported server Windows Server 2008[desktop apps | UWP apps] + // Windows XP SP2需要安装补丁 + __DEFINE_THUNK( + mfplat, + 16, + HRESULT, + STDAPICALLTYPE, + MFCreateAsyncResult, + IUnknown* punkObject, + IMFAsyncCallback* pCallback, + IUnknown* punkState, + _Out_ IMFAsyncResult** ppAsyncResult + ) + { + if (const auto _pfnMFCreateAsyncResult = try_get_MFCreateAsyncResult()) + { + return _pfnMFCreateAsyncResult(punkObject, pCallback, punkState, ppAsyncResult); + } + + if (!ppAsyncResult) + return E_POINTER; + *ppAsyncResult = nullptr; + return E_NOTIMPL; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported server Windows Server 2008[desktop apps | UWP apps] + // Windows XP SP2需要安装补丁 + __DEFINE_THUNK( + mfplat, + 8, + HRESULT, + STDAPICALLTYPE, + MFCreateAttributes, + _Out_ IMFAttributes** ppMFAttributes, + _In_ UINT32 cInitialSize + ) + { + if (const auto _pfnMFCreateAttributes = try_get_MFCreateAttributes()) + { + return _pfnMFCreateAttributes(ppMFAttributes, cInitialSize); + } + + if (!ppMFAttributes) + return E_POINTER; + *ppMFAttributes = nullptr; + return E_NOTIMPL; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported server Windows Server 2008[desktop apps | UWP apps] + // Windows XP SP2需要安装补丁 + __DEFINE_THUNK( + mfplat, + 4, + HRESULT, + STDAPICALLTYPE, + MFCreateEventQueue, + _Out_ IMFMediaEventQueue** ppMediaEventQueue + ) + { + if (const auto _pfnMFCreateEventQueue = try_get_MFCreateEventQueue()) + { + return _pfnMFCreateEventQueue(ppMediaEventQueue); + } + + if (!ppMediaEventQueue) + return E_POINTER; + *ppMediaEventQueue = nullptr; + return E_NOTIMPL; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported server Windows Server 2008[desktop apps | UWP apps] + // Windows XP SP2需要安装补丁 + __DEFINE_THUNK( + mfplat, + 16, + HRESULT, + STDAPICALLTYPE, + MFCreateMediaBufferWrapper, + _In_ IMFMediaBuffer* pBuffer, + _In_ DWORD cbOffset, + _In_ DWORD dwLength, + _Out_ IMFMediaBuffer** ppBuffer + ) + { + if (const auto _pfnMFCreateMediaBufferWrapper = try_get_MFCreateMediaBufferWrapper()) + { + return _pfnMFCreateMediaBufferWrapper(pBuffer, cbOffset, dwLength, ppBuffer); + } + + if (!ppBuffer) + return E_POINTER; + *ppBuffer = nullptr; + return E_NOTIMPL; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported server Windows Server 2008[desktop apps | UWP apps] + // Windows XP SP2需要安装补丁 + __DEFINE_THUNK( + mfplat, + 20, + HRESULT, + STDAPICALLTYPE, + MFCreateMediaEvent, + _In_ MediaEventType met, + _In_ REFGUID guidExtendedType, + _In_ HRESULT hrStatus, + _In_opt_ const PROPVARIANT* pvValue, + _Out_ IMFMediaEvent** ppEvent + ) + { + if (const auto _pfnMFCreateMediaEvent = try_get_MFCreateMediaEvent()) + { + return _pfnMFCreateMediaEvent(met, guidExtendedType, hrStatus, pvValue, ppEvent); + } + + if (!ppEvent) + return E_POINTER; + *ppEvent = nullptr; + return E_NOTIMPL; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported server Windows Server 2008[desktop apps | UWP apps] + // Windows XP SP2需要安装补丁 + __DEFINE_THUNK( + mfplat, + 4, + HRESULT, + STDAPICALLTYPE, + MFCreateMediaType, + _Outptr_ IMFMediaType** ppMFType + ) + { + if (const auto _pfnMFCreateMediaType = try_get_MFCreateMediaType()) + { + return _pfnMFCreateMediaType(ppMFType); + } + + if (!ppMFType) + return E_POINTER; + *ppMFType = nullptr; + return E_NOTIMPL; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported server Windows Server 2008[desktop apps | UWP apps] + // Windows XP SP2需要安装补丁 + __DEFINE_THUNK( + mfplat, + 8, + HRESULT, + STDAPICALLTYPE, + MFCreateMemoryBuffer, + _In_ DWORD cbMaxLength, + _Out_ IMFMediaBuffer** ppBuffer + ) + { + if (const auto _pfnMFCreateMemoryBuffer = try_get_MFCreateMemoryBuffer()) + { + return _pfnMFCreateMemoryBuffer(cbMaxLength, ppBuffer); + } + + if (!ppBuffer) + return E_POINTER; + *ppBuffer = nullptr; + return E_NOTIMPL; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported server Windows Server 2008[desktop apps | UWP apps] + // Windows XP SP2需要安装补丁 + __DEFINE_THUNK( + mfplat, + 12, + HRESULT, + STDAPICALLTYPE, + MFCreatePresentationDescriptor, + DWORD cStreamDescriptors, + _In_reads_opt_(cStreamDescriptors) IMFStreamDescriptor** apStreamDescriptors, + _Outptr_ IMFPresentationDescriptor** ppPresentationDescriptor + ) + { + if (const auto _pfnMFCreatePresentationDescriptor = try_get_MFCreatePresentationDescriptor()) + { + return _pfnMFCreatePresentationDescriptor(cStreamDescriptors, apStreamDescriptors, ppPresentationDescriptor); + } + + if (!ppPresentationDescriptor) + return E_POINTER; + *ppPresentationDescriptor = nullptr; + return E_NOTIMPL; + } +#endif + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported server Windows Server 2008[desktop apps | UWP apps] + // Windows XP SP2需要安装补丁 + __DEFINE_THUNK( + mfplat, + 12, + HRESULT, + STDAPICALLTYPE, + MFCreateSample, + _Out_ IMFSample** ppIMFSample + ) + { + if (const auto _pfnMFCreateSample = try_get_MFCreateSample()) + { + return _pfnMFCreateSample(ppIMFSample); + } + + if (!ppIMFSample) + return E_POINTER; + *ppIMFSample = nullptr; + return E_NOTIMPL; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported server Windows Server 2008[desktop apps | UWP apps] + // Windows XP SP2需要安装补丁 + __DEFINE_THUNK( + mfplat, + 16, + HRESULT, + STDAPICALLTYPE, + MFCreateStreamDescriptor, + DWORD dwStreamIdentifier, + DWORD cMediaTypes, + _In_reads_(cMediaTypes) IMFMediaType** apMediaTypes, + _Outptr_ IMFStreamDescriptor** ppDescriptor + ) + { + if (const auto _pfnMFCreateStreamDescriptor = try_get_MFCreateStreamDescriptor()) + { + return _pfnMFCreateStreamDescriptor(dwStreamIdentifier, cMediaTypes, apMediaTypes, ppDescriptor); + } + + if (!ppDescriptor) + return E_POINTER; + *ppDescriptor = nullptr; + return E_NOTIMPL; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported server Windows Server 2008[desktop apps | UWP apps] + // Windows XP SP2需要安装补丁 + __DEFINE_THUNK( + mfplat, + 16, + HRESULT, + STDAPICALLTYPE, + MFCreateWaveFormatExFromMFMediaType, + _In_ IMFMediaType* pMFType, + _Out_ WAVEFORMATEX** ppWF, + _Out_opt_ UINT32* pcbSize, + _In_ UINT32 Flags + ) + { + if (const auto _pfnMFCreateWaveFormatExFromMFMediaType = try_get_MFCreateWaveFormatExFromMFMediaType()) + { + return _pfnMFCreateWaveFormatExFromMFMediaType(pMFType, ppWF, pcbSize, Flags); + } + + if (pcbSize) + *pcbSize = 0; + + if (!ppWF) + return E_POINTER; + *ppWF = nullptr; + return E_NOTIMPL; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported server Windows Server 2008[desktop apps | UWP apps] + // Windows XP SP2需要安装补丁 + __DEFINE_THUNK( + mfplat, + 12, + HRESULT, + STDAPICALLTYPE, + MFFrameRateToAverageTimePerFrame, + _In_ UINT32 unNumerator, + _In_ UINT32 unDenominator, + _Out_ UINT64* punAverageTimePerFrame + ) + { + if (const auto _pfnMFFrameRateToAverageTimePerFrame = try_get_MFFrameRateToAverageTimePerFrame()) + { + return _pfnMFFrameRateToAverageTimePerFrame(unNumerator, unDenominator, punAverageTimePerFrame); + } + + if (punAverageTimePerFrame) + return E_POINTER; + + return E_NOTIMPL; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported server Windows Server 2008[desktop apps | UWP apps] + // Windows XP SP2需要安装补丁 + __DEFINE_THUNK( + mfplat, + 0, + MFTIME, + STDAPICALLTYPE, + MFGetSystemTime, + void + ) + { + if (const auto _pfnMFGetSystemTime = try_get_MFGetSystemTime()) + { + return _pfnMFGetSystemTime(); + } + + FILETIME _ftTime; + GetSystemTimeAsFileTime(&_ftTime); + return *(LONG64*)(&_ftTime); + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported server Windows Server 2008[desktop apps | UWP apps] + // Windows XP SP2需要安装补丁 + __DEFINE_THUNK( + mfplat, + 12, + HRESULT, + STDAPICALLTYPE, + MFInitMediaTypeFromWaveFormatEx, + _In_ IMFMediaType* pMFType, + _In_reads_bytes_(cbBufSize) const WAVEFORMATEX* pWaveFormat, + _In_ UINT32 cbBufSize + ) + { + if (const auto _pfnMFInitMediaTypeFromWaveFormatEx = try_get_MFInitMediaTypeFromWaveFormatEx()) + { + return _pfnMFInitMediaTypeFromWaveFormatEx(pMFType, pWaveFormat, cbBufSize); + } + + return E_NOTIMPL; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported server Windows Server 2008[desktop apps | UWP apps] + // Windows XP SP2需要安装补丁 + __DEFINE_THUNK( + mfplat, + 0, + HRESULT, + STDAPICALLTYPE, + MFShutdown + ) + { + if (const auto _pfnMFShutdown = try_get_MFShutdown()) + { + return _pfnMFShutdown(); + } + + return E_NOTIMPL; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // Minimum supported client Windows Vista [desktop apps | UWP apps] + // Minimum supported server Windows Server 2008[desktop apps | UWP apps] + // Windows XP SP2需要安装补丁 + __DEFINE_THUNK( + mfplat, + 8, + HRESULT, + STDAPICALLTYPE, + MFStartup, + ULONG Version, + DWORD dwFlags + ) + { + if (const auto _pfnMFStartup = try_get_MFStartup()) + { + return _pfnMFStartup(Version, dwFlags); + } + + return E_NOTIMPL; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN7) + + // Minimum supported client Windows 7 [desktop apps | UWP apps] + // Minimum supported server Windows Server 2008 R2[desktop apps | UWP apps] + __DEFINE_THUNK( + mfplat, + 24, + HRESULT, + STDAPICALLTYPE, + MFTEnumEx, + _In_ GUID guidCategory, + _In_ UINT32 Flags, + _In_opt_ const MFT_REGISTER_TYPE_INFO* pInputType, + _In_opt_ const MFT_REGISTER_TYPE_INFO* pOutputType, + _Outptr_result_buffer_(*pnumMFTActivate) IMFActivate*** pppMFTActivate, + _Out_ UINT32* pnumMFTActivate + ) + { + if (const auto _pfnMFTEnumEx = try_get_MFTEnumEx()) + { + return _pfnMFTEnumEx(guidCategory, Flags, pInputType, pOutputType, pppMFTActivate, pnumMFTActivate); + } + + if (!pppMFTActivate) + return E_POINTER; + + *pppMFTActivate = nullptr; + + if (!pnumMFTActivate) + return E_POINTER; + + *pnumMFTActivate = 0; + return E_NOTIMPL; + } +#endif } // namespace YY::Thunks diff --git a/src/Thunks/mfreadwrite.hpp b/src/Thunks/mfreadwrite.hpp new file mode 100644 index 00000000..543f393d --- /dev/null +++ b/src/Thunks/mfreadwrite.hpp @@ -0,0 +1,34 @@ +#if (YY_Thunks_Support_Version < NTDDI_WIN7) +#include +#endif + +namespace YY::Thunks +{ +#if (YY_Thunks_Support_Version < NTDDI_WIN7) + + // 最低受支持的客户端 适用于 Windows Vista 的 Windows 7、Windows Vista 和平台更新补充 [桌面应用 |UWP 应用] + // 最低受支持的服务器 Windows Server 2008 R2[桌面应用 | UWP 应用] + __DEFINE_THUNK( + mfreadwrite, + 12, + HRESULT, + STDAPICALLTYPE, + MFCreateSourceReaderFromMediaSource, + _In_ IMFMediaSource* pMediaSource, + _In_opt_ IMFAttributes* pAttributes, + _Out_ IMFSourceReader** ppSourceReader + ) + { + if (const auto _pfnMFCreateSourceReaderFromMediaSource = try_get_MFCreateSourceReaderFromMediaSource()) + { + return _pfnMFCreateSourceReaderFromMediaSource(pMediaSource, pAttributes, ppSourceReader); + } + + if (!ppSourceReader) + return E_POINTER; + + *ppSourceReader = nullptr; + return E_NOTIMPL; + } +#endif +} diff --git a/src/Thunks/ndfapi.hpp b/src/Thunks/ndfapi.hpp new file mode 100644 index 00000000..c6d98b90 --- /dev/null +++ b/src/Thunks/ndfapi.hpp @@ -0,0 +1,88 @@ +#if (YY_Thunks_Support_Version < NTDDI_WIN6) +#include +#endif + +namespace YY::Thunks +{ +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // 最低受支持的客户端 Windows Vista [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] + __DEFINE_THUNK( + ndfapi, + 8, + HRESULT, + WINAPI, + NdfCreateWebIncident, + _In_ LPCWSTR _szUrl, + _Outptr_ NDFHANDLE* _phHandle + ) + { + if (const auto _pfnNdfCreateWebIncident = try_get_NdfCreateWebIncident()) + { + return _pfnNdfCreateWebIncident(_szUrl, _phHandle); + } + + if (_szUrl == nullptr || _phHandle == nullptr) + return NDF_E_BAD_PARAM; + + *_phHandle = INVALID_HANDLE_VALUE; + return S_OK; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // 最低受支持的客户端 Windows Vista [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] + __DEFINE_THUNK( + ndfapi, + 4, + HRESULT, + WINAPI, + NdfCloseIncident, + NDFHANDLE _hHandle + ) + { + if (const auto _pfnNdfCloseIncident = try_get_NdfCloseIncident()) + { + return _pfnNdfCloseIncident(_hHandle); + } + + if (_hHandle != INVALID_HANDLE_VALUE) + return E_HANDLE; + + return S_OK; + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN6) + + // 最低受支持的客户端 Windows Vista [仅限桌面应用] + // 最低受支持的服务器 Windows Server 2008[仅限桌面应用] + __DEFINE_THUNK( + ndfapi, + 8, + HRESULT, + WINAPI, + NdfExecuteDiagnosis, + _In_ NDFHANDLE _hHandle, + _In_opt_ HWND _hWnd + ) + { + if (const auto _pfnNdfExecuteDiagnosis = try_get_NdfExecuteDiagnosis()) + { + return _pfnNdfExecuteDiagnosis(_hHandle, _hWnd); + } + + if (_hHandle != INVALID_HANDLE_VALUE) + { + return E_HANDLE; + } + + return S_OK; + } +#endif +} diff --git a/src/Thunks/ntdll.hpp b/src/Thunks/ntdll.hpp index 53bceb97..df68bc95 100644 --- a/src/Thunks/ntdll.hpp +++ b/src/Thunks/ntdll.hpp @@ -20,14 +20,108 @@ return _pfnNtCancelIoFileEx(handle, io, io_status); } +#ifndef __USING_NTDLL_LIB + const auto NtCancelIoFile = try_get_NtCancelIoFile(); + if(!NtCancelIoFile) + { + // 正常来说不应该走到这里 + return STATUS_NOT_SUPPORTED; + } +#endif // 最坏打算,清除所有的调用 - if (const auto _pfnNtCancelIoFile = try_get_NtCancelIoFile()) + return NtCancelIoFile(handle, io_status); + } +#endif + + +#if (YY_Thunks_Support_Version < NTDDI_WIN7) + + // 最低受支持的客户端 在 Windows 7 和更高版本的 Windows 中可用。 + __DEFINE_THUNK( + ntdll, + 16, + NTSTATUS, + NTAPI, + NtOpenKeyEx, + __out PHANDLE _phKeyHandle, + __in ACCESS_MASK _fDesiredAccess, + __in POBJECT_ATTRIBUTES _pObjectAttributes, + __in ULONG _fOpenOptions + ) + { + if (const auto _pfnNtOpenKeyEx = try_get_NtOpenKeyEx()) + { + return _pfnNtOpenKeyEx(_phKeyHandle, _fDesiredAccess, _pObjectAttributes, _fOpenOptions); + } + +#ifndef __USING_NTDLL_LIB + const auto NtOpenKey = try_get_NtOpenKey(); + if (!NtOpenKey) + { + // 正常来说不应该走到这里,XP存在此函数 + return STATUS_NOT_SUPPORTED; + } +#endif + + if (_fOpenOptions & (~(REG_OPTION_OPEN_LINK | REG_OPTION_BACKUP_RESTORE))) + return STATUS_INVALID_PARAMETER_4; + + OBJECT_ATTRIBUTES _ObjectAttributes; + if (_fOpenOptions & REG_OPTION_OPEN_LINK) { - return _pfnNtCancelIoFile(handle, io_status); + __try + { + // 避免 ObjectAttributes 指针非法 + // 我们抓异常为了模拟原版函数行为,内存无效时可以返回错误代码。 + _ObjectAttributes = *_pObjectAttributes; + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + return GetExceptionCode(); + } + + _ObjectAttributes.Attributes |= OBJ_OPENLINK; + _pObjectAttributes = &_ObjectAttributes; } - // 正常来说不应该走到这里 - return STATUS_NOT_SUPPORTED; + if ((_fOpenOptions & REG_OPTION_BACKUP_RESTORE) == 0) + return NtOpenKey(_phKeyHandle, _fDesiredAccess, _pObjectAttributes); + +#ifndef __USING_NTDLL_LIB + const auto NtCreateKey = try_get_NtCreateKey(); + const auto NtDeleteKey = try_get_NtDeleteKey(); + const auto NtClose = try_get_NtClose(); + if (NtCreateKey == nullptr || NtDeleteKey == nullptr || NtClose == nullptr) + return STATUS_NOT_SUPPORTED; +#endif + + // 先测试一下 Key在不在,如果确定不在就没有必要继续了。 + HANDLE _hKey = NULL; + LONG _Status = NtOpenKey(&_hKey, STANDARD_RIGHTS_READ, _pObjectAttributes); + if (_Status < 0 && _Status != STATUS_ACCESS_DENIED) + return _Status; + + do + { + ULONG Disposition; + _Status = NtCreateKey(_phKeyHandle, _fDesiredAccess, _pObjectAttributes, 0, nullptr, REG_OPTION_BACKUP_RESTORE, &Disposition); + if (_Status < 0) + break; + + if (Disposition == REG_CREATED_NEW_KEY) + { + // 新建的话就重新删除,毕竟NtOpenKeyEx是没有创建功能的。 + NtDeleteKey(*_phKeyHandle); + NtClose(*_phKeyHandle); + *_phKeyHandle = NULL; + _Status = STATUS_OBJECT_NAME_NOT_FOUND; + } + } while (false); + + if(_hKey) + NtClose(_hKey); + + return _Status; } #endif } // namespace YY::Thunks diff --git a/src/Thunks/shell32.hpp b/src/Thunks/shell32.hpp index f43c2800..2b8a0b1c 100644 --- a/src/Thunks/shell32.hpp +++ b/src/Thunks/shell32.hpp @@ -3,6 +3,14 @@ #include #endif +#if (YY_Thunks_Support_Version < NTDDI_WIN6) +// FOLDERID_Windows +#include + +// BHID_SFObject +#include +#endif + #if (YY_Thunks_Support_Version < NTDDI_WIN6) && !defined(__Comment_Lib_shell32) #define __Comment_Lib_shell32 #pragma comment(lib, "Shell32.lib") diff --git a/src/Thunks/uxtheme.hpp b/src/Thunks/uxtheme.hpp index 329878ef..be4b5a37 100644 --- a/src/Thunks/uxtheme.hpp +++ b/src/Thunks/uxtheme.hpp @@ -7,35 +7,33 @@ #pragma comment(lib, "UxTheme.lib") #endif -#if defined(YY_Thunks_Implemented) && defined(_X86_) && (YY_Thunks_Support_Version < NTDDI_WIN6) +#if defined(YY_Thunks_Implemented) && (YY_Thunks_Support_Version < NTDDI_WIN6) namespace YY::Thunks::Fallback { - static void* __fastcall try_get_DrawThemeTextEx() noexcept + static void* __fastcall try_get_DrawThemeTextEx(const ProcInfo& _ProcInfo) noexcept { - auto _pUxThemeBase = (const char*)try_get_module_uxtheme(); - if (!_pUxThemeBase) - return nullptr; + auto _pProc = try_get_proc_address_from_dll(_ProcInfo); + if (_pProc) + return _pProc; - MEMORY_BASIC_INFORMATION _BaseInfo; - - // Windows XP SP3 其实已经实现了DrawThemeTextEx,只是没有导出。 - static const BYTE kAttributeCode_6_0_2900_5512[] = + static constexpr const ProcOffsetInfo kProcInfo[] = { - 0x8B, 0xFF, 0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x0C, - 0x83, 0x4D, 0xF8, 0xFF, 0x83, 0x65, 0xF4, 0x00, - 0x83, 0x7D, 0x0C, 0x00, 0x56, +#if defined(_X86_) + { 0x3B901769ul, 0x5ADC5C2Ful - 0x5ADC0000ul }, // 6.0.2600.0 (Windows XP RTM) + { 0x3D7D2609ul, 0x5ADC5AEDul - 0x5ADC0000ul }, // 6.0.2800.1106 (Windows XP SP1) + { 0x4121457Aul, 0x5ADC645Cul - 0x5ADC0000ul }, // 6.0.2900.2180 (Windows XP SP2) + { 0x4802BDC0ul, 0x5ADC2FF8ul - 0x5ADC0000ul }, // 6.0.2900.5512 (Windows XP SP3) + { 0x3E8024BEul, 0x71B8ACA0ul - 0x71B70000ul }, // 6.0.3790.0 (Windows 2003) + { 0x42437794ul, 0x7DF64466ul - 0x7DF50000ul }, // 6.0.3790.1830 (Windows 2003 SP1) + { 0x45D70ACBul, 0x71B91D41ul - 0x71B70000ul }, // 6.0.3790.3959 (Windows 2003 SP2) +#elif defined(_AMD64_) + { 0x42438B57ul, 0x7FF77069A60ull - 0x7FF77060000ull }, // 6.0.3790.1830 (Windows 2003 SP1) + { 0x45D6CCAEul, 0x000007FF77239A70ull - 0x7FF77230000ull }, // 6.0.3790.3959 (Windows 2003 SP2) +#endif }; - constexpr auto kAttributeCode_6_0_2900_5512_Offset = 0x5ADC2FF8 - 0x5ADC0000; - auto _pTarget = _pUxThemeBase + kAttributeCode_6_0_2900_5512_Offset; - if (VirtualQuery(_pTarget, &_BaseInfo, sizeof(_BaseInfo)) && _BaseInfo.AllocationBase == _pUxThemeBase) - { - if (memcmp(_pTarget, kAttributeCode_6_0_2900_5512, sizeof(kAttributeCode_6_0_2900_5512)) == 0) - { - return (void*)_pTarget; - } - } - return nullptr; + __WarningMessage__("try_get_DrawThemeTextEx 可能遗漏某些XP/2003补丁中的uxtheme.dll,如果你知道详细可以提交PR。"); + return try_get_proc_address_from_offset(try_get_module_uxtheme(), kProcInfo); } } #endif diff --git a/src/YY-Thunks.UnitTest/PropSys.UnitTest.cpp b/src/YY-Thunks.UnitTest/PropSys.UnitTest.cpp new file mode 100644 index 00000000..1d048067 --- /dev/null +++ b/src/YY-Thunks.UnitTest/PropSys.UnitTest.cpp @@ -0,0 +1,71 @@ +#include "pch.h" +#include "Thunks/PropSys.hpp" + +namespace PropSys +{ + TEST_CLASS(VariantCompare) + { + AwaysNullGuard Guard; + + public: + VariantCompare() + { + Guard |= YY::Thunks::aways_null_try_get_VariantCompare; + } + + TEST_METHOD(一般) + { + { + VARIANT _Left = {}; + VARIANT _Rigth = {}; + + _Left.vt = VT_I1; + _Left.bVal = 8; + + _Rigth.vt = VT_I1; + _Rigth.bVal = 9; + + Assert::IsTrue(::VariantCompare(_Left, _Rigth) < 0); + } + + { + VARIANT _Left = {}; + VARIANT _Rigth = {}; + + _Left.vt = VT_R4; + _Left.fltVal = 8; + + _Rigth.vt = VT_R4; + _Rigth.fltVal = 8; + + Assert::IsTrue(::VariantCompare(_Left, _Rigth) == 0); + } + + { + VARIANT _Left = {}; + VARIANT _Rigth = {}; + + _Left.vt = VT_R4; + _Left.fltVal = 9; + + _Rigth.vt = VT_R4; + _Rigth.fltVal = 8; + + Assert::IsTrue(::VariantCompare(_Left, _Rigth) > 0); + } + + { + VARIANT _Left = {}; + VARIANT _Rigth = {}; + + _Left.vt = VT_R4; + _Left.fltVal = 8.1f; + + _Rigth.vt = VT_R4; + _Rigth.fltVal = 8; + + Assert::IsTrue(::VariantCompare(_Left, _Rigth) > 0); + } + } + }; +} diff --git a/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj b/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj index ad4a6fbc..2bd4c24d 100644 --- a/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj +++ b/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj @@ -96,7 +96,7 @@ true true $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) - SymbolBuildTestPath=LR"($(ProjectDir)TestProject\)";YY_ThunksRootPath=LR"($(ProjectDir)..\..\)";MSBuildBinPath=LR"($(MSBuildBinPath)\)";__YY_Thunks_Unit_Test;WIN32;NDEBUG;YY_Thunks_Support_Version=NTDDI_WIN2K;%(PreprocessorDefinitions) + SymbolBuildTestPath=LR"($(ProjectDir)TestProject\)";YY_ThunksRootPath=LR"($(ProjectDir)..\..\)";MSBuildBinPath=LR"($(MSBuildBinPath)\)";__YY_Thunks_Unit_Test;WIN32;NDEBUG;YY_Thunks_Support_Version=NTDDI_WIN2K;__ENABLE_WORKAROUND_ALL;__USING_NTDLL_LIB;%(PreprocessorDefinitions) true pch.h Use @@ -104,6 +104,7 @@ false 4715;%(TreatSpecificWarningsAsErrors) stdcpp17 + /execution-charset:utf-8 %(AdditionalOptions) Windows @@ -117,7 +118,7 @@ Level3 $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) - SymbolBuildTestPath=LR"($(ProjectDir)TestProject\)";YY_ThunksRootPath=LR"($(ProjectDir)..\..\)";MSBuildBinPath=LR"($(MSBuildBinPath)\)";__YY_Thunks_Unit_Test;WIN32;_DEBUG;YY_Thunks_Support_Version=NTDDI_WIN2K;%(PreprocessorDefinitions) + SymbolBuildTestPath=LR"($(ProjectDir)TestProject\)";YY_ThunksRootPath=LR"($(ProjectDir)..\..\)";MSBuildBinPath=LR"($(MSBuildBinPath)\)";__YY_Thunks_Unit_Test;WIN32;_DEBUG;YY_Thunks_Support_Version=NTDDI_WIN2K;__ENABLE_WORKAROUND_ALL;__USING_NTDLL_LIB;%(PreprocessorDefinitions) true pch.h Use @@ -125,6 +126,7 @@ false 4715;%(TreatSpecificWarningsAsErrors) stdcpp17 + /execution-charset:utf-8 %(AdditionalOptions) Windows @@ -144,6 +146,7 @@ false 4715;%(TreatSpecificWarningsAsErrors) stdcpp17 + /execution-charset:utf-8 %(AdditionalOptions) Windows @@ -165,6 +168,7 @@ false 4715;%(TreatSpecificWarningsAsErrors) stdcpp17 + /execution-charset:utf-8 %(AdditionalOptions) Windows @@ -175,6 +179,7 @@ + @@ -190,6 +195,7 @@ + NotUsing @@ -213,6 +219,7 @@ + @@ -220,11 +227,14 @@ + + + @@ -238,19 +248,25 @@ + + + + + + diff --git a/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj.filters b/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj.filters index 3a0d727d..a1dc22a5 100644 --- a/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj.filters +++ b/src/YY-Thunks.UnitTest/YY-Thunks.UnitTest.vcxproj.filters @@ -81,6 +81,12 @@ 源文件\UnitTest + + 源文件\UnitTest + + + 源文件\UnitTest + @@ -317,19 +323,40 @@ Thunks - + Thunks - + Thunks - + Thunks - + Thunks - + + Thunks + + + Thunks + + + Thunks + + + Thunks + + + Thunks + + + Thunks + + + Thunks + + Thunks diff --git a/src/YY-Thunks.UnitTest/api-ms-win-core-handle.UnitTest.cpp b/src/YY-Thunks.UnitTest/api-ms-win-core-handle.UnitTest.cpp new file mode 100644 index 00000000..e6d88049 --- /dev/null +++ b/src/YY-Thunks.UnitTest/api-ms-win-core-handle.UnitTest.cpp @@ -0,0 +1,361 @@ +#include "pch.h" +#include "Thunks/api-ms-win-core-handle.hpp" + +#pragma comment(lib, "KtmW32.lib") + +namespace api_ms_win_core_handle +{ + TEST_CLASS(CompareObjectHandles) + { + AwaysNullGuard Guard; + + public: + CompareObjectHandles() + { + Guard |= YY::Thunks::aways_null_try_get_CompareObjectHandles; + } + + TEST_METHOD(常规比较) + { + { + HANDLE _hHandle1 = CreateTransaction(nullptr, 0, 0, 0, 0, 0, nullptr); + Assert::IsNotNull(_hHandle1); + + HANDLE _hHandle2 = CreateTransaction(nullptr, 0, 0, 0, 0, 0, nullptr); + Assert::IsNotNull(_hHandle2); + + Assert::IsFalse(::CompareObjectHandles(_hHandle1, _hHandle2)); + + CloseHandle(_hHandle1); + CloseHandle(_hHandle2); + } + + if(ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL::SecurityImpersonation)) + { + HANDLE _hHandle1; + Assert::IsTrue(OpenThreadToken(NtCurrentThread(), TOKEN_QUERY_SOURCE, FALSE, &_hHandle1)); + + HANDLE _hHandle2; + Assert::IsTrue(OpenThreadToken(NtCurrentThread(), TOKEN_QUERY_SOURCE, FALSE, &_hHandle2)); + + bool _bRet = false; + auto _hThread = CreateThread(nullptr, 0, + [](void* _pUserData) -> DWORD + { + if (ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL::SecurityImpersonation)) + { + for (;;) + { + if (*(volatile bool*)_pUserData) + break; + + Sleep(10); + } + RevertToSelf(); + } + + return 0; + }, & _bRet, 0, nullptr); + + Assert::IsNotNull(_hThread); + + Assert::IsTrue(::CompareObjectHandles(_hHandle1, _hHandle2)); + + Sleep(500); + HANDLE _hHandle3; + Assert::IsTrue(OpenThreadToken(_hThread, TOKEN_QUERY_SOURCE, FALSE, &_hHandle3)); + + HANDLE _hHandle4; + Assert::IsTrue(OpenThreadToken(_hThread, TOKEN_QUERY, FALSE, &_hHandle4)); + + Assert::IsTrue(::CompareObjectHandles(_hHandle3, _hHandle4)); + Assert::IsFalse(::CompareObjectHandles(_hHandle1, _hHandle4)); + + _bRet = true; + CloseHandle(_hHandle1); + CloseHandle(_hHandle2); + CloseHandle(_hHandle3); + CloseHandle(_hHandle4); + + WaitForSingleObject(_hThread, INFINITE); + CloseHandle(_hThread); + + RevertToSelf(); + } + + + { + HANDLE _hHandle1; + Assert::IsTrue(OpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, &_hHandle1)); + + HANDLE _hHandle2; + Assert::IsTrue(OpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, &_hHandle2)); + + Assert::IsTrue(::CompareObjectHandles(_hHandle1, _hHandle2)); + + CloseHandle(_hHandle1); + CloseHandle(_hHandle2); + } + + { + constexpr const wchar_t Name[] = L"\\KernelObjects\\CritSecOutOfMemoryEvent"; + auto pNtOpenKeyedEvent = (decltype(NtOpenKeyedEvent)*) GetProcAddress(GetModuleHandleW(L"ntdll"), "NtOpenKeyedEvent"); + + UNICODE_STRING ObjectName = { sizeof(Name) - sizeof(wchar_t),sizeof(Name) - sizeof(wchar_t) ,(PWSTR)Name }; + OBJECT_ATTRIBUTES attr = { sizeof(attr),nullptr,&ObjectName }; + + HANDLE _hHandle1; + pNtOpenKeyedEvent(&_hHandle1, MAXIMUM_ALLOWED, &attr); + + HANDLE _hHandle2; + pNtOpenKeyedEvent(&_hHandle2, MAXIMUM_ALLOWED, &attr); + + Assert::IsTrue(::CompareObjectHandles(_hHandle1, _hHandle2)); + + CloseHandle(_hHandle1); + CloseHandle(_hHandle2); + } + + { + HANDLE _hHandle1 = CreateWaitableTimerW(nullptr, FALSE, L"Local\\TestWaitableTimer"); + Assert::IsNotNull(_hHandle1); + + HANDLE _hHandle2 = OpenWaitableTimerW(SYNCHRONIZE, FALSE, L"Local\\TestWaitableTimer"); + Assert::IsNotNull(_hHandle2); + + Assert::IsTrue(::CompareObjectHandles(_hHandle1, _hHandle2)); + + CloseHandle(_hHandle1); + CloseHandle(_hHandle2); + } + + { + auto _hHandle1 = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 4); + HANDLE _hHandle2; + Assert::IsTrue(DuplicateHandle(NtGetCurrentProcess(), _hHandle1, NtGetCurrentProcess(), &_hHandle2, 0, FALSE, DUPLICATE_SAME_ACCESS)); + auto _hFile1 = CreateFileW(LR"(C:\Windows\System32\ntdll.dll)", GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + + Assert::IsTrue(::CompareObjectHandles(_hHandle1, _hHandle2)); + auto _hHandle3 = CreateIoCompletionPort(_hFile1, _hHandle1, 0, 0); + Assert::IsTrue(::CompareObjectHandles(_hHandle1, _hHandle2)); + + CloseHandle(_hHandle1); + CloseHandle(_hHandle2); + CloseHandle(_hFile1); + } + + { + auto _hHandle1 = OpenDesktopW(L"Default", 0, FALSE, STANDARD_RIGHTS_READ); + auto _hHandle2 = OpenDesktopW(L"Default", 0, FALSE, STANDARD_RIGHTS_READ); + + // CI可能没有桌面 + if (_hHandle1 || _hHandle2) + { + Assert::IsTrue(::CompareObjectHandles(_hHandle1, _hHandle2)); + } + + if(_hHandle1) + CloseHandle(_hHandle1); + if(_hHandle2) + CloseHandle(_hHandle2); + } + + { + auto _hHandle1 = OpenWindowStationW(nullptr, FALSE, STANDARD_RIGHTS_READ); + auto _hHandle2 = OpenWindowStationW(nullptr, FALSE, STANDARD_RIGHTS_READ); + + // CI可能没有桌面 + if (_hHandle1 || _hHandle2) + { + Assert::IsTrue(::CompareObjectHandles(_hHandle1, _hHandle2)); + } + + if(_hHandle1) + CloseHandle(_hHandle1); + + if(_hHandle2) + CloseHandle(_hHandle2); + } + + { + auto _hHandle1 = CreateFileW(L"C:\\Windows", 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + Assert::AreNotEqual(_hHandle1, INVALID_HANDLE_VALUE); + + auto _hHandle2 = CreateFileW(L"C:\\Windows", 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + Assert::AreNotEqual(_hHandle2, INVALID_HANDLE_VALUE); + + HANDLE _hHandle3; + Assert::IsTrue(DuplicateHandle(NtGetCurrentProcess(), _hHandle1, NtGetCurrentProcess(), &_hHandle3, 0, FALSE, DUPLICATE_SAME_ACCESS)); + + Assert::IsFalse(::CompareObjectHandles(_hHandle1, _hHandle2)); + Assert::IsTrue(::CompareObjectHandles(_hHandle1, _hHandle3)); + + CloseHandle(_hHandle1); + CloseHandle(_hHandle2); + CloseHandle(_hHandle3); + } + + { + auto _hHandle1 = CreateSemaphoreW(nullptr, 0, 2, L"Local\\TestSemaphore"); + auto _hHandle2 = OpenSemaphoreW(SYNCHRONIZE, FALSE, L"Local\\TestSemaphore"); + + Assert::IsNotNull(_hHandle1); + Assert::IsNotNull(_hHandle2); + + Assert::IsTrue(::CompareObjectHandles(_hHandle1, _hHandle2)); + CloseHandle(_hHandle1); + CloseHandle(_hHandle2); + } + + { + auto _hHandle1 = CreateMutexW(nullptr, FALSE, L"Local\\TestMutex"); + auto _hHandle2 = OpenMutexW(SYNCHRONIZE, FALSE, L"Local\\TestMutex"); + + Assert::IsNotNull(_hHandle1); + Assert::IsNotNull(_hHandle2); + + Assert::IsTrue(::CompareObjectHandles(_hHandle1, _hHandle2)); + CloseHandle(_hHandle1); + CloseHandle(_hHandle2); + } + + { + auto _hHandle1 = CreateNamedPipeW( + L"\\\\.\\pipe\\TestNamedPipe", + PIPE_ACCESS_DUPLEX, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, + PIPE_UNLIMITED_INSTANCES, + 512, + 512, + 0, + NULL); + + auto _hHandle2 = CreateFileW(L"\\\\.\\pipe\\TestNamedPipe",GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, NULL); + HANDLE _hHandle3; + Assert::IsTrue(DuplicateHandle(NtGetCurrentProcess(), _hHandle1, NtGetCurrentProcess(), &_hHandle3, 0, FALSE, DUPLICATE_SAME_ACCESS)); + + //auto _hHandle1 = CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, PAGE_READONLY, 0, 4096, L"Local\\TestFileMap"); + //auto _hHandle2 = OpenFileMappingW(FILE_MAP_READ, FALSE, L"Local\\TestFileMap"); + + Assert::IsNotNull(_hHandle1); + Assert::IsNotNull(_hHandle2); + + Assert::IsFalse(::CompareObjectHandles(_hHandle1, _hHandle2)); + Assert::IsTrue(::CompareObjectHandles(_hHandle1, _hHandle3)); + CloseHandle(_hHandle1); + CloseHandle(_hHandle2); + } + + { + auto _hHandle1 = CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, PAGE_READONLY, 0, 4096, L"Local\\TestFileMap"); + auto _hHandle2 = OpenFileMappingW(FILE_MAP_READ, FALSE, L"Local\\TestFileMap"); + + Assert::IsNotNull(_hHandle1); + Assert::IsNotNull(_hHandle2); + + Assert::IsTrue(::CompareObjectHandles(_hHandle1, _hHandle2)); + CloseHandle(_hHandle1); + CloseHandle(_hHandle2); + } + + { + HKEY _hHandle1; + auto _lStatus = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"SOFTWARE", &_hHandle1); + Assert::AreEqual(_lStatus, ERROR_SUCCESS); + + HKEY _hHandle2; + _lStatus = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"SOFTWARE", &_hHandle2); + Assert::AreEqual(_lStatus, ERROR_SUCCESS); + + Assert::IsFalse(::CompareObjectHandles(_hHandle1, _hHandle2)); + + HKEY _hHandle3; + Assert::IsTrue(DuplicateHandle(NtGetCurrentProcess(), _hHandle1, NtGetCurrentProcess(), (HANDLE*)&_hHandle3, 0, FALSE, DUPLICATE_SAME_ACCESS)); + Assert::IsTrue(::CompareObjectHandles(_hHandle1, _hHandle3)); + + RegCloseKey(_hHandle1); + RegCloseKey(_hHandle2); + RegCloseKey(_hHandle3); + } + + { + auto _hHandle1 = OpenThread(SYNCHRONIZE, FALSE, GetCurrentThreadId()); + auto _hHandle2 = OpenThread(SYNCHRONIZE, FALSE, GetCurrentThreadId()); + + Assert::IsNotNull(_hHandle1); + Assert::IsNotNull(_hHandle2); + + Assert::IsTrue(::CompareObjectHandles(_hHandle1, _hHandle2)); + CloseHandle(_hHandle1); + CloseHandle(_hHandle2); + } + + { + auto _hHandle1 = OpenProcess(SYNCHRONIZE, FALSE, GetCurrentProcessId()); + auto _hHandle2 = OpenProcess(SYNCHRONIZE, FALSE, GetCurrentProcessId()); + + Assert::IsNotNull(_hHandle1); + Assert::IsNotNull(_hHandle2); + + Assert::IsTrue(::CompareObjectHandles(_hHandle1, _hHandle2)); + CloseHandle(_hHandle1); + CloseHandle(_hHandle2); + } + + { + auto _hHandle1 = CreateEventW(nullptr, FALSE, FALSE, L"Local\\TestEvent"); + auto _hHandle2 = OpenEventW(SYNCHRONIZE, FALSE, L"Local\\TestEvent"); + auto _hHandle3 = CreateEventW(nullptr, FALSE, FALSE, L"Local\\TestEvend"); + + Assert::IsNotNull(_hHandle1); + Assert::IsNotNull(_hHandle2); + Assert::IsNotNull(_hHandle3); + + Assert::IsTrue(::CompareObjectHandles(_hHandle1, _hHandle2)); + Assert::IsFalse(::CompareObjectHandles(_hHandle1, _hHandle3)); + CloseHandle(_hHandle1); + CloseHandle(_hHandle2); + CloseHandle(_hHandle3); + } + + { + auto _hFile1 = CreateFileW(LR"(C:\Windows\System32\ntdll.dll)", 0, FILE_SHARE_DELETE | FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, NULL); + auto _hFile2 = CreateFileW(LR"(C:\Windows\System32\ntdll.dll)", 0, FILE_SHARE_DELETE | FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, NULL); + HANDLE _hFile3; + Assert::IsTrue(DuplicateHandle(NtGetCurrentProcess(), _hFile1, NtGetCurrentProcess(), &_hFile3, 0, FALSE, DUPLICATE_SAME_ACCESS)); + + Assert::IsNotNull(_hFile1); + Assert::IsNotNull(_hFile2); + Assert::IsNotNull(_hFile3); + + Assert::IsFalse(::CompareObjectHandles(_hFile1, _hFile2)); + Assert::IsTrue(::CompareObjectHandles(_hFile1, _hFile3)); + CloseHandle(_hFile1); + CloseHandle(_hFile2); + CloseHandle(_hFile3); + } + } + + TEST_METHOD(匿名对象) + { + { + auto _hHandle1 = CreateEventW(nullptr, FALSE, FALSE, nullptr); + Assert::IsNotNull(_hHandle1); + auto _hHandle2 = CreateEventW(nullptr, FALSE, FALSE, nullptr); + Assert::IsNotNull(_hHandle2); + HANDLE _hHandle3; + HANDLE _hHandle4; + Assert::IsTrue(DuplicateHandle(NtGetCurrentProcess(), _hHandle1, NtGetCurrentProcess(), &_hHandle3, 0, FALSE, DUPLICATE_SAME_ACCESS)); + Assert::IsTrue(DuplicateHandle(NtGetCurrentProcess(), _hHandle2, NtGetCurrentProcess(), &_hHandle4, 0, FALSE, DUPLICATE_SAME_ACCESS)); + + Assert::IsFalse(::CompareObjectHandles(_hHandle1, _hHandle2)); + Assert::IsTrue(::CompareObjectHandles(_hHandle1, _hHandle3)); + + CloseHandle(_hHandle1); + CloseHandle(_hHandle2); + CloseHandle(_hHandle3); + CloseHandle(_hHandle4); + } + } + }; +} diff --git a/src/YY-Thunks.UnitTest/pch.h b/src/YY-Thunks.UnitTest/pch.h index 6dfa4604..faf79d10 100644 --- a/src/YY-Thunks.UnitTest/pch.h +++ b/src/YY-Thunks.UnitTest/pch.h @@ -32,6 +32,23 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework; EXTERN_C _RETURN_ _CONVENTION_ _FUNCTION(__VA_ARGS__); \ __if_not_exists(_FUNCTION) +//#undef TEST_METHOD +// +//#define TEST_METHOD(methodName)\ +// static const EXPORT_METHOD ::Microsoft::VisualStudio::CppUnitTestFramework::MemberMethodInfo* CALLING_CONVENTION CATNAME(__GetTestMethodInfo_, __COUNTER__)()\ +// {\ +// __GetTestClassInfo();\ +// __GetTestVersion();\ +// ALLOCATE_TESTDATA_SECTION_METHOD\ +// static const ::Microsoft::VisualStudio::CppUnitTestFramework::MethodMetadata s_Metadata = {L"TestMethodInfo", L## #methodName, reinterpret_cast(__FUNCTION__), reinterpret_cast(__FUNCDNAME__), __WFILE__, __LINE__};\ +//\ +// static ::Microsoft::VisualStudio::CppUnitTestFramework::MemberMethodInfo s_Info = {::Microsoft::VisualStudio::CppUnitTestFramework::MemberMethodInfo::TestMethod, {NULL}, &s_Metadata};\ +// s_Info.method.pVoidMethod = static_cast<::Microsoft::VisualStudio::CppUnitTestFramework::TestClassImpl::__voidFunc>(&ThisClass::methodName);\ +// return &s_Info;\ +// }\ +// void methodName() + + class AwaysNullGuard { private: diff --git a/src/YY.Depends.Analyzer/YY.Depends.Analyzer.vcxproj b/src/YY.Depends.Analyzer/YY.Depends.Analyzer.vcxproj index d3212a4e..e28c9b82 100644 --- a/src/YY.Depends.Analyzer/YY.Depends.Analyzer.vcxproj +++ b/src/YY.Depends.Analyzer/YY.Depends.Analyzer.vcxproj @@ -139,6 +139,20 @@ 5.1.1-Beta1 + + + + + + + + + + + + + + diff --git a/src/YY.Depends.Analyzer/YY.Depends.Analyzer.vcxproj.filters b/src/YY.Depends.Analyzer/YY.Depends.Analyzer.vcxproj.filters index f1a8083d..849b1ae0 100644 --- a/src/YY.Depends.Analyzer/YY.Depends.Analyzer.vcxproj.filters +++ b/src/YY.Depends.Analyzer/YY.Depends.Analyzer.vcxproj.filters @@ -13,10 +13,57 @@ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + {1b2150a9-3ecd-466c-8ed6-4c05d2b5feb9} + + + {bd9cc60a-cd73-4766-a69b-50fdfa675fc6} + + + {367324e4-0b88-4554-b1e1-cb4204867029} + - + 源文件 + + + 资源文件\Config\x64 + + + 资源文件\Config\x64 + + + 资源文件\Config\x64 + + + 资源文件\Config\x64 + + + 资源文件\Config\x64 + + + 资源文件\Config\x64 + + + 资源文件\Config\x86 + + + 资源文件\Config\x86 + + + 资源文件\Config\x86 + + + 资源文件\Config\x86 + + + 资源文件\Config\x86 + + + 资源文件\Config\x86 + + \ No newline at end of file