Sandboxie/Sandboxie/core/dll/guiprop.c

1272 lines
36 KiB
C

/*
* Copyright 2004-2020 Sandboxie Holdings, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
// GUI Services
//---------------------------------------------------------------------------
#include "dll.h"
#include "gui_p.h"
#include "core/svc/GuiWire.h"
#include "common/my_version.h"
#include <stdio.h>
#pragma auto_inline(off)
//---------------------------------------------------------------------------
// Functions
//---------------------------------------------------------------------------
static void Gui_InitPropAtoms(void);
static const void *Gui_ReplaceAtom(const void *lpString);
HANDLE Gui_GetPropCommon(
HWND hWnd, const void *lpString, BOOLEAN unicode, ULONG LastError);
static HANDLE Gui_GetPropW(HWND hWnd, const WCHAR *lpString);
static HANDLE Gui_GetPropA(HWND hWnd, const UCHAR *lpString);
static BOOL Gui_SetPropW(HWND hWnd, const WCHAR *lpString, HANDLE hData);
static BOOL Gui_SetPropA(HWND hWnd, const UCHAR *lpString, HANDLE hData);
static HANDLE Gui_RemovePropW(HWND hWnd, const WCHAR *lpString);
static HANDLE Gui_RemovePropA(HWND hWnd, const UCHAR *lpString);
static ULONG_PTR Gui_GetLongCommon(HWND hWnd, int nIndex, ULONG which);
static ULONG_PTR Gui_GetWindowLong_DragDrop(
HWND hWnd, int nIndex, ULONG_PTR value);
static ULONG_PTR Gui_SetWindowLong_DragDrop(
HWND hWnd, int nIndex, ULONG_PTR dwNew, ULONG_PTR value);
static ULONG Gui_GetWindowLongW(HWND hWnd, int nIndex);
static ULONG Gui_GetWindowLongA(HWND hWnd, int nIndex);
static ULONG Gui_SetWindowLongW(HWND hWnd, int nIndex, ULONG dwNew);
static ULONG Gui_SetWindowLongA(HWND hWnd, int nIndex, ULONG dwNew);
static ULONG_PTR Gui_SetWindowLong8(
HWND hWnd, int nIndex, ULONG_PTR dwNew, ULONG IsAscii);
#ifndef _M_ARM64
static BOOLEAN Gui_Hook_SetWindowLong8(HMODULE module);
#endif
static ULONG Gui_GetClassLongW(HWND hWnd, int nIndex);
static ULONG Gui_GetClassLongA(HWND hWnd, int nIndex);
#ifdef _WIN64
static ULONG_PTR Gui_GetWindowLongPtrW(HWND hWnd, int nIndex);
static ULONG_PTR Gui_GetWindowLongPtrA(HWND hWnd, int nIndex);
static ULONG_PTR Gui_SetWindowLongPtrW(
HWND hWnd, int nIndex, ULONG_PTR dwNew);
static ULONG_PTR Gui_SetWindowLongPtrA(
HWND hWnd, int nIndex, ULONG_PTR dwNew);
static ULONG_PTR Gui_SetWindowLongPtr8(
HWND hWnd, int nIndex, ULONG_PTR dwNew, ULONG IsAscii);
#ifndef _M_ARM64
static BOOLEAN Gui_Hook_SetWindowLongPtr8(HMODULE module);
#endif
static ULONG_PTR Gui_GetClassLongPtrW(HWND hWnd, int nIndex);
static ULONG_PTR Gui_GetClassLongPtrA(HWND hWnd, int nIndex);
#endif _WIN64
//---------------------------------------------------------------------------
// Variables
//---------------------------------------------------------------------------
ATOM Gui_DropTargetProp_Atom = 0;
ATOM Gui_WindowProcOldW_Atom = 0;
ATOM Gui_WindowProcOldA_Atom = 0;
static ATOM Gui_WindowProcNewW_Atom = 0;
static ATOM Gui_WindowProcNewA_Atom = 0;
static ATOM Gui_OleDropTargetInterface_Atom = 0;
static ATOM Gui_OleDropTargetMarshalHwnd_Atom = 0;
static ATOM Gui_OleEndPointID_Atom = 0;
static ATOM Gui_Sandbox_OleDropTargetInterface_Atom = 0;
static ATOM Gui_Sandbox_OleDropTargetMarshalHwnd_Atom = 0;
static ATOM Gui_Sandbox_OleEndPointID_Atom = 0;
#ifdef _WIN64
static P_SetWindowLong8 __sys_SetWindowLong8 = 0;
static P_SetWindowLongPtr8 __sys_SetWindowLongPtr8 = 0;
#endif _WIN64
//---------------------------------------------------------------------------
// Gui_InitProp
//---------------------------------------------------------------------------
_FX BOOLEAN Gui_InitProp(HMODULE module)
{
//
// initialize our Drag-n-Drop atoms
//
Gui_InitPropAtoms();
//
// hook functions
//
// DisableComProxy BEGIN
if (!SbieApi_QueryConfBool(NULL, L"DisableComProxy", FALSE))
// DisableComProxy END
if (! SbieDll_IsOpenCOM()) {
//
// if there is access to the real COM epmapper, then don't
// hook Prop functions that are used to hide drag/drop props
//
SBIEDLL_HOOK_GUI(GetPropA);
SBIEDLL_HOOK_GUI(GetPropW);
SBIEDLL_HOOK_GUI(SetPropA);
SBIEDLL_HOOK_GUI(SetPropW);
SBIEDLL_HOOK_GUI(RemovePropA);
SBIEDLL_HOOK_GUI(RemovePropW);
}
if (! Gui_OpenAllWinClasses) {
//
// if not hooking window classes, don't install custom wndproc
//
SBIEDLL_HOOK_GUI(GetWindowLongA);
SBIEDLL_HOOK_GUI(GetWindowLongW);
#ifdef _WIN64
if (Dll_OsBuild >= 14942) { // Windows 10 1703 preview #7
HMODULE hWin32u = GetModuleHandleA("win32u.dll");
__sys_SetWindowLong8 = (P_SetWindowLong8) GetProcAddress(hWin32u, "NtUserSetWindowLong");
SBIEDLL_HOOK_GUI(SetWindowLong8);
}
else if (Dll_OsBuild < 9600) {
SBIEDLL_HOOK_GUI(SetWindowLongA);
SBIEDLL_HOOK_GUI(SetWindowLongW);
}
else
#ifndef _M_ARM64
// new style hook on SetWindowLong on 64-bit Windows 8.1 and later
if (! Gui_Hook_SetWindowLong8(module))
#endif
{
SbieApi_Log(2205, L"SetWindowLong8");
return FALSE;
}
#else ! _WIN64
// otherwise old style hooks on SetWindowLongA and SetWindowLongW
SBIEDLL_HOOK_GUI(SetWindowLongA);
SBIEDLL_HOOK_GUI(SetWindowLongW);
#endif _WIN64
SBIEDLL_HOOK_GUI(GetClassLongA);
SBIEDLL_HOOK_GUI(GetClassLongW);
#ifdef _WIN64
SBIEDLL_HOOK_GUI(GetWindowLongPtrA);
SBIEDLL_HOOK_GUI(GetWindowLongPtrW);
if (Dll_OsBuild >= 14942) { // Windows 10 1703 preview #7
HMODULE hWin32u = GetModuleHandleA("win32u.dll");
__sys_SetWindowLongPtr8 = (P_SetWindowLongPtr8) GetProcAddress(hWin32u,"NtUserSetWindowLongPtr");
SBIEDLL_HOOK_GUI(SetWindowLongPtr8);
}
else if (Dll_OsBuild < 8400) {
SBIEDLL_HOOK_GUI(SetWindowLongPtrA);
SBIEDLL_HOOK_GUI(SetWindowLongPtrW);
}
else
#ifndef _M_ARM64
// special hook on SetWindowLongPtr on 64-bit Windows 8 and later
if (! Gui_Hook_SetWindowLongPtr8(module))
#endif
{
SbieApi_Log(2205, L"SetWindowLongPtr8");
return FALSE;
}
SBIEDLL_HOOK_GUI(GetClassLongPtrA);
SBIEDLL_HOOK_GUI(GetClassLongPtrW);
#endif _WIN64
}
return TRUE;
}
//---------------------------------------------------------------------------
// Gui_InitPropAtoms
//---------------------------------------------------------------------------
_FX void Gui_InitPropAtoms(void)
{
//
// drag drop props
//
static const WCHAR *_OleDropTargetInterface = L"OleDropTargetInterface";
static const WCHAR *_OleDropTargetMarshalHwnd =
L"OleDropTargetMarshalHwnd";
static const WCHAR *_OleEndPointID =
L"OleEndPointID";
static const WCHAR *_format = L"Sandbox:%s:%s";
WCHAR name[128];
if (! Gui_OleDropTargetInterface_Atom) {
Gui_OleDropTargetInterface_Atom =
GlobalAddAtomW(_OleDropTargetInterface);
if (Gui_OleDropTargetInterface_Atom) {
Sbie_snwprintf(name, 128, _format, Dll_BoxName, _OleDropTargetInterface);
Gui_Sandbox_OleDropTargetInterface_Atom = GlobalAddAtomW(name);
}
}
if (! Gui_OleDropTargetMarshalHwnd_Atom) {
Gui_OleDropTargetMarshalHwnd_Atom =
GlobalAddAtomW(_OleDropTargetMarshalHwnd);
if (Gui_OleDropTargetMarshalHwnd_Atom) {
Sbie_snwprintf(name, 128, _format, Dll_BoxName, _OleDropTargetMarshalHwnd);
Gui_Sandbox_OleDropTargetMarshalHwnd_Atom = GlobalAddAtomW(name);
}
}
if (! Gui_OleEndPointID_Atom) {
Gui_OleEndPointID_Atom =
GlobalAddAtomW(_OleEndPointID);
if (Gui_OleEndPointID_Atom) {
Sbie_snwprintf(name, 128, _format, Dll_BoxName, _OleEndPointID);
Gui_Sandbox_OleEndPointID_Atom = GlobalAddAtomW(name);
}
}
//
// window/dialog procedure props
//
if (! Gui_DropTargetProp_Atom)
Gui_DropTargetProp_Atom = GlobalAddAtomW(SBIE L"_DropTarget");
if (! Gui_WindowProcOldW_Atom)
Gui_WindowProcOldW_Atom = GlobalAddAtomW(SBIE L"_WindowProcOldW");
if (! Gui_WindowProcOldA_Atom)
Gui_WindowProcOldA_Atom = GlobalAddAtomW(SBIE L"_WindowProcOldA");
if (! Gui_WindowProcNewW_Atom)
Gui_WindowProcNewW_Atom = GlobalAddAtomW(SBIE L"_WindowProcNewW");
if (! Gui_WindowProcNewA_Atom)
Gui_WindowProcNewA_Atom = GlobalAddAtomW(SBIE L"_WindowProcNewA");
}
//---------------------------------------------------------------------------
// Gui_ReplaceAtom
//---------------------------------------------------------------------------
_FX const void *Gui_ReplaceAtom(const void *lpString)
{
Gui_InitPropAtoms();
if (((LONG_PTR)lpString & ~0xFFFF) == 0) {
LONG_PTR atom = (LONG_PTR)lpString & 0xFFFF;
if (atom == Gui_OleDropTargetInterface_Atom)
(ATOM)lpString = Gui_Sandbox_OleDropTargetInterface_Atom;
if (atom == Gui_OleDropTargetMarshalHwnd_Atom)
(ATOM)lpString = Gui_Sandbox_OleDropTargetMarshalHwnd_Atom;
if (atom == Gui_OleEndPointID_Atom)
(ATOM)lpString = Gui_Sandbox_OleEndPointID_Atom;
}
return lpString;
}
//---------------------------------------------------------------------------
// Gui_GetPropCommon
//---------------------------------------------------------------------------
_FX HANDLE Gui_GetPropCommon(
HWND hWnd, const void *lpString, BOOLEAN unicode, ULONG LastError)
{
GUI_GET_WINDOW_PROP_REQ req;
GUI_GET_WINDOW_PROP_RPL *rpl;
HANDLE handle;
ULONG error;
ULONG len;
memzero(&req, sizeof(req));
req.msgid = GUI_GET_WINDOW_PROP;
req.error = LastError;
req.hwnd = (ULONG)(ULONG_PTR)hWnd;
req.unicode = unicode;
if (((ULONG_PTR)lpString & 0xFFFF0000) == 0) {
req.prop_atom = ((ULONG)(ULONG_PTR)lpString) & 0xFFFF;
} else if (unicode) {
len = wcslen((WCHAR *)lpString);
if (len >= RTL_NUMBER_OF_V1(req.prop_text) - 1)
return NULL;
wmemcpy(req.prop_text, lpString, len);
req.prop_is_text = TRUE;
} else {
len = strlen((char *)lpString);
if (len >= RTL_NUMBER_OF_V1(req.prop_text) - 1)
return NULL;
memcpy(req.prop_text, lpString, len);
req.prop_is_text = TRUE;
}
rpl = Gui_CallProxy(&req, sizeof(req), sizeof(GUI_GET_WINDOW_PROP_RPL));
if (! rpl)
return FALSE;
handle = (HANDLE)(ULONG_PTR)rpl->result;
error = rpl->error;
Dll_Free(rpl);
SetLastError(error);
return handle;
}
//---------------------------------------------------------------------------
// Gui_GetPropW
//---------------------------------------------------------------------------
_FX HANDLE Gui_GetPropW(HWND hWnd, const WCHAR *lpString)
{
if (! Gui_OpenAllWinClasses) {
//
// normal mode
//
ULONG LastError = GetLastError();
BOOLEAN IsDesktop = (hWnd == __sys_GetDesktopWindow());
if (! Gui_IsWindowAccessible(hWnd) && !IsDesktop) {
SetLastError(ERROR_INVALID_WINDOW_HANDLE);
return NULL;
}
lpString = Gui_ReplaceAtom(lpString);
if (!Gui_UseProxyService || Gui_IsSameBox(hWnd, NULL, NULL) || IsDesktop)
return __sys_GetPropW(hWnd, lpString);
else
return Gui_GetPropCommon(hWnd, lpString, TRUE, LastError);
} else {
//
// OpenWinClass=* mode
//
lpString = Gui_ReplaceAtom(lpString);
return __sys_GetPropW(hWnd, lpString);
}
}
//---------------------------------------------------------------------------
// Gui_GetPropA
//---------------------------------------------------------------------------
_FX HANDLE Gui_GetPropA(HWND hWnd, const UCHAR *lpString)
{
if (! Gui_OpenAllWinClasses) {
//
// normal mode
//
ULONG LastError = GetLastError();
BOOLEAN IsDesktop = (hWnd == __sys_GetDesktopWindow());
if (! Gui_IsWindowAccessible(hWnd) && !IsDesktop) {
SetLastError(ERROR_INVALID_WINDOW_HANDLE);
return NULL;
}
lpString = Gui_ReplaceAtom(lpString);
if (!Gui_UseProxyService || Gui_IsSameBox(hWnd, NULL, NULL) || IsDesktop)
return __sys_GetPropA(hWnd, lpString);
else
return Gui_GetPropCommon(hWnd, lpString, TRUE, LastError);
} else {
//
// OpenWinClass=* mode
//
lpString = Gui_ReplaceAtom(lpString);
return __sys_GetPropA(hWnd, lpString);
}
}
//---------------------------------------------------------------------------
// Gui_SetPropW
//---------------------------------------------------------------------------
_FX BOOL Gui_SetPropW(HWND hWnd, const WCHAR *lpString, HANDLE hData)
{
if (! Gui_OpenAllWinClasses) {
if (! Gui_IsWindowAccessible(hWnd)) {
SetLastError(ERROR_INVALID_WINDOW_HANDLE);
return FALSE;
}
}
lpString = Gui_ReplaceAtom(lpString);
return __sys_SetPropW(hWnd, lpString, hData);
}
//---------------------------------------------------------------------------
// Gui_SetPropA
//---------------------------------------------------------------------------
_FX BOOL Gui_SetPropA(HWND hWnd, const UCHAR *lpString, HANDLE hData)
{
if (! Gui_OpenAllWinClasses) {
if (! Gui_IsWindowAccessible(hWnd)) {
SetLastError(ERROR_INVALID_WINDOW_HANDLE);
return FALSE;
}
}
lpString = Gui_ReplaceAtom(lpString);
return __sys_SetPropA(hWnd, lpString, hData);
}
//---------------------------------------------------------------------------
// Gui_RemovePropW
//---------------------------------------------------------------------------
_FX HANDLE Gui_RemovePropW(HWND hWnd, const WCHAR *lpString)
{
if (! Gui_OpenAllWinClasses) {
if (! Gui_IsWindowAccessible(hWnd)) {
SetLastError(ERROR_INVALID_WINDOW_HANDLE);
return NULL;
}
}
lpString = Gui_ReplaceAtom(lpString);
return __sys_RemovePropW(hWnd, lpString);
}
//---------------------------------------------------------------------------
// Gui_RemovePropA
//---------------------------------------------------------------------------
_FX HANDLE Gui_RemovePropA(HWND hWnd, const UCHAR *lpString)
{
if (! Gui_OpenAllWinClasses) {
if (! Gui_IsWindowAccessible(hWnd)) {
SetLastError(ERROR_INVALID_WINDOW_HANDLE);
return NULL;
}
}
lpString = Gui_ReplaceAtom(lpString);
return __sys_RemovePropA(hWnd, lpString);
}
//---------------------------------------------------------------------------
// Gui_GetLongCommon
//---------------------------------------------------------------------------
_FX ULONG_PTR Gui_GetLongCommon(HWND hWnd, int nIndex, ULONG which)
{
ULONG_PTR result;
ULONG LastError = GetLastError();
if (!Gui_UseProxyService || Gui_IsSameBox(hWnd, NULL, NULL)) {
//
// if target window is in the same sandbox (i.e. within the
// boundary of the job object) then issue a direct call
//
if (which == 'cl w')
result = __sys_GetClassLongW(hWnd, nIndex);
else if (which == 'cl a')
result = __sys_GetClassLongA(hWnd, nIndex);
else if (which == 'wl w')
result = __sys_GetWindowLongW(hWnd, nIndex);
else if (which == 'wl a')
result = __sys_GetWindowLongA(hWnd, nIndex);
#ifdef _WIN64
else if (which == 'clpw')
result = __sys_GetClassLongPtrW(hWnd, nIndex);
else if (which == 'clpa')
result = __sys_GetClassLongPtrA(hWnd, nIndex);
else if (which == 'wlpw')
result = __sys_GetWindowLongPtrW(hWnd, nIndex);
else if (which == 'wlpa')
result = __sys_GetWindowLongPtrA(hWnd, nIndex);
#endif _WIN64
else {
result = 0;
SetLastError(ERROR_INVALID_PARAMETER);
}
} else {
//
// if target window is outside the job, issue an indirect request
//
GUI_GET_WINDOW_LONG_REQ req;
GUI_GET_WINDOW_LONG_RPL *rpl;
ULONG error;
req.msgid = GUI_GET_WINDOW_LONG;
req.error = LastError;
req.hwnd = (ULONG)(ULONG_PTR)hWnd;
req.index = nIndex;
req.which = which;
rpl = Gui_CallProxy(
&req, sizeof(req), sizeof(GUI_GET_WINDOW_LONG_RPL));
if (! rpl)
return FALSE;
result = (ULONG_PTR)rpl->result;
error = rpl->error;
Dll_Free(rpl);
SetLastError(error);
}
return result;
}
//---------------------------------------------------------------------------
// Gui_GetWindowLong_DragDrop
//---------------------------------------------------------------------------
_FX ULONG_PTR Gui_GetWindowLong_DragDrop(
HWND hWnd, int nIndex, ULONG_PTR value)
{
if (nIndex == GWL_EXSTYLE && (value & WS_EX_ACCEPTFILES)) {
//
// if the style WS_EX_ACCEPTFILES is there because we put it
// there (see Ole_RegisterDragDrop) to make it possible for
// unsandboxed windows to drop files in sandboxed windows,
// then hide it from sandboxed processes (because they can
// find and use the sandboxed IDropTarget)
//
void *pDropTarget =
__sys_GetPropW(hWnd, (LPCWSTR)Gui_DropTargetProp_Atom);
if (pDropTarget)
value &= ~WS_EX_ACCEPTFILES;
}
return value;
}
//---------------------------------------------------------------------------
// Gui_SetWindowLong_DragDrop
//---------------------------------------------------------------------------
_FX ULONG_PTR Gui_SetWindowLong_DragDrop(
HWND hWnd, int nIndex, ULONG_PTR dwNew, ULONG_PTR value)
{
if (nIndex == GWL_EXSTYLE) {
if (dwNew & WS_EX_ACCEPTFILES) {
//
// if the app is explicitly setting the WS_EX_ACCEPTFILES flag
// then make sure we are not trying to handle WM_DROPFILES on
// its behalf
//
// Note: Updated to not remove our property. With Win10 Creator's
// update and Win8.1, drag-n-drop was not working because
// we were removing it below and thus the IDropTarget was
// not found in Ole_DoDragDrop().
//
if (Gui_DropTargetProp_Atom)
{
// __sys_RemovePropW(hWnd, (LPCWSTR)Gui_DropTargetProp_Atom);
}
} else {
//
// if the app does a SetWindowLong(GetWindowLong(), ...)
// sequence on the window, it will clear our WS_EX_ACCEPTFILES
// flag (per Gui_GetWindowLong_DragDrop) so apply it again
//
void *pDropTarget =
__sys_GetPropW(hWnd, (LPCWSTR)Gui_DropTargetProp_Atom);
if (pDropTarget) {
dwNew |= WS_EX_ACCEPTFILES;
__sys_SetWindowLongW(hWnd, nIndex, (ULONG)dwNew);
}
}
}
return value;
}
//---------------------------------------------------------------------------
// Gui_GetWindowLongW
//---------------------------------------------------------------------------
_FX ULONG Gui_GetWindowLongW(HWND hWnd, int nIndex)
{
ULONG value;
Gui_InitPropAtoms();
//value = __sys_GetWindowLongW(hWnd, nIndex);
value = (ULONG)Gui_GetLongCommon(hWnd, nIndex, 'wl w');
#ifndef _WIN64
if (Gui_RenameClasses && (nIndex == GWLP_WNDPROC)) {
//
// prevent caller from seeing our window procedure
//
WNDPROC w = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewW_Atom);
WNDPROC a = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewA_Atom);
if ((w && value == (ULONG_PTR)w) || (a && value == (ULONG_PTR)a)) {
value = (ULONG_PTR)__sys_GetPropW(
hWnd, (LPCWSTR)Gui_WindowProcOldW_Atom);
}
}
#endif ! _WIN64
return (ULONG)Gui_GetWindowLong_DragDrop(hWnd, nIndex, value);
}
//---------------------------------------------------------------------------
// Gui_GetWindowLongA
//---------------------------------------------------------------------------
_FX ULONG Gui_GetWindowLongA(HWND hWnd, int nIndex)
{
ULONG value;
Gui_InitPropAtoms();
//value = __sys_GetWindowLongA(hWnd, nIndex);
value = (ULONG)Gui_GetLongCommon(hWnd, nIndex, 'wl a');
#ifndef _WIN64
if (Gui_RenameClasses && (nIndex == GWLP_WNDPROC)) {
//
// prevent caller from seeing our window procedure
//
WNDPROC w = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewW_Atom);
WNDPROC a = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewA_Atom);
if ((w && value == (ULONG_PTR)w) || (a && value == (ULONG_PTR)a)) {
value = (ULONG_PTR)__sys_GetPropW(
hWnd, (LPCWSTR)Gui_WindowProcOldA_Atom);
}
}
#endif ! _WIN64
return (ULONG)Gui_GetWindowLong_DragDrop(hWnd, nIndex, value);
}
//---------------------------------------------------------------------------
// Gui_SetWindowLongW
//---------------------------------------------------------------------------
_FX ULONG Gui_SetWindowLongW(HWND hWnd, int nIndex, ULONG dwNew)
{
ULONG value;
Gui_InitPropAtoms();
value = __sys_SetWindowLongW(hWnd, nIndex, dwNew);
#ifndef _WIN64
if (Gui_RenameClasses && (nIndex == GWLP_WNDPROC)) {
//
// replace window procedure, then override the new procedure
//
WNDPROC w = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewW_Atom);
WNDPROC a = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewA_Atom);
if ((w && value == (ULONG_PTR)w) || (a && value == (ULONG_PTR)a)) {
value = (ULONG_PTR)__sys_GetPropW(
hWnd, (LPCWSTR)Gui_WindowProcOldW_Atom);
Gui_SetWindowProc(hWnd, TRUE);
}
}
#endif ! _WIN64
return (ULONG)Gui_SetWindowLong_DragDrop(hWnd, nIndex, dwNew, value);
}
//---------------------------------------------------------------------------
// Gui_SetWindowLongA
//---------------------------------------------------------------------------
_FX ULONG Gui_SetWindowLongA(HWND hWnd, int nIndex, ULONG dwNew)
{
ULONG value;
Gui_InitPropAtoms();
value = __sys_SetWindowLongA(hWnd, nIndex, dwNew);
#ifndef _WIN64
if (Gui_RenameClasses && (nIndex == GWLP_WNDPROC)) {
//
// replace window procedure, then override the new procedure
//
WNDPROC w = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewW_Atom);
WNDPROC a = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewA_Atom);
if ((w && value == (ULONG_PTR)w) || (a && value == (ULONG_PTR)a)) {
value = (ULONG_PTR)__sys_GetPropW(
hWnd, (LPCWSTR)Gui_WindowProcOldA_Atom);
Gui_SetWindowProc(hWnd, TRUE);
}
}
#endif ! _WIN64
return (ULONG)Gui_SetWindowLong_DragDrop(hWnd, nIndex, dwNew, value);
}
//---------------------------------------------------------------------------
// Gui_GetClassLongW
//---------------------------------------------------------------------------
_FX ULONG Gui_GetClassLongW(HWND hWnd, int nIndex)
{
return (ULONG)Gui_GetLongCommon(hWnd, nIndex, 'cl w');
}
//---------------------------------------------------------------------------
// Gui_GetClassLongA
//---------------------------------------------------------------------------
_FX ULONG Gui_GetClassLongA(HWND hWnd, int nIndex)
{
return (ULONG)Gui_GetLongCommon(hWnd, nIndex, 'cl a');
}
//---------------------------------------------------------------------------
// Begin 64-bit Get/SetWindowLongPtr functions
//---------------------------------------------------------------------------
#ifdef _WIN64
//---------------------------------------------------------------------------
// Gui_GetWindowLongPtrW
//---------------------------------------------------------------------------
_FX ULONG_PTR Gui_GetWindowLongPtrW(HWND hWnd, int nIndex)
{
ULONG_PTR value;
Gui_InitPropAtoms();
//value = (ULONG_PTR)__sys_GetWindowLongPtrW(hWnd, nIndex);
value = (ULONG_PTR)Gui_GetLongCommon(hWnd, nIndex, 'wlpw');
if (Gui_RenameClasses && (nIndex == GWLP_WNDPROC)) {
//
// prevent caller from seeing our window procedure
//
WNDPROC w = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewW_Atom);
WNDPROC a = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewA_Atom);
if ((w && value == (ULONG_PTR)w) || (a && value == (ULONG_PTR)a)) {
value = (ULONG_PTR)__sys_GetPropW(
hWnd, (LPCWSTR)Gui_WindowProcOldW_Atom);
}
}
return Gui_GetWindowLong_DragDrop(hWnd, nIndex, value);
}
//---------------------------------------------------------------------------
// Gui_GetWindowLongPtrA
//---------------------------------------------------------------------------
_FX ULONG_PTR Gui_GetWindowLongPtrA(HWND hWnd, int nIndex)
{
ULONG_PTR value;
Gui_InitPropAtoms();
//value = (ULONG_PTR)__sys_GetWindowLongPtrA(hWnd, nIndex);
value = (ULONG_PTR)Gui_GetLongCommon(hWnd, nIndex, 'wlpa');
if (Gui_RenameClasses && (nIndex == GWLP_WNDPROC)) {
//
// prevent caller from seeing our window procedure
//
WNDPROC w = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewW_Atom);
WNDPROC a = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewA_Atom);
if ((w && value == (ULONG_PTR)w) || (a && value == (ULONG_PTR)a)) {
value = (ULONG_PTR)__sys_GetPropW(
hWnd, (LPCWSTR)Gui_WindowProcOldA_Atom);
}
}
return Gui_GetWindowLong_DragDrop(hWnd, nIndex, value);
}
//---------------------------------------------------------------------------
// Gui_SetWindowLongPtrW
//---------------------------------------------------------------------------
_FX ULONG_PTR Gui_SetWindowLongPtrW(HWND hWnd, int nIndex, ULONG_PTR dwNew)
{
ULONG_PTR value;
Gui_InitPropAtoms();
value = __sys_SetWindowLongPtrW(hWnd, nIndex, dwNew);
if (Gui_RenameClasses && (nIndex == GWLP_WNDPROC)) {
//
// replace window procedure, then override the new procedure
//
WNDPROC w = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewW_Atom);
WNDPROC a = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewA_Atom);
if ((w && value == (ULONG_PTR)w) || (a && value == (ULONG_PTR)a)) {
value = (ULONG_PTR)__sys_GetPropW(
hWnd, (LPCWSTR)Gui_WindowProcOldW_Atom);
Gui_SetWindowProc(hWnd, TRUE);
}
}
return Gui_SetWindowLong_DragDrop(hWnd, nIndex, dwNew, value);
}
//---------------------------------------------------------------------------
// Gui_SetWindowLongPtrA
//---------------------------------------------------------------------------
_FX ULONG_PTR Gui_SetWindowLongPtrA(HWND hWnd, int nIndex, ULONG_PTR dwNew)
{
ULONG_PTR value;
Gui_InitPropAtoms();
value = __sys_SetWindowLongPtrA(hWnd, nIndex, dwNew);
if (Gui_RenameClasses && (nIndex == GWLP_WNDPROC)) {
//
// replace window procedure, then override the new procedure
//
WNDPROC w = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewW_Atom);
WNDPROC a = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewA_Atom);
if ((w && value == (ULONG_PTR)w) || (a && value == (ULONG_PTR)a)) {
value = (ULONG_PTR)__sys_GetPropW(
hWnd, (LPCWSTR)Gui_WindowProcOldA_Atom);
Gui_SetWindowProc(hWnd, TRUE);
}
}
return Gui_SetWindowLong_DragDrop(hWnd, nIndex, dwNew, value);
}
//---------------------------------------------------------------------------
// Gui_GetClassLongPtrW
//---------------------------------------------------------------------------
_FX ULONG_PTR Gui_GetClassLongPtrW(HWND hWnd, int nIndex)
{
return Gui_GetLongCommon(hWnd, nIndex, 'clpw');
}
//---------------------------------------------------------------------------
// Gui_GetClassLongPtrA
//---------------------------------------------------------------------------
_FX ULONG_PTR Gui_GetClassLongPtrA(HWND hWnd, int nIndex)
{
return Gui_GetLongCommon(hWnd, nIndex, 'clpa');
}
//---------------------------------------------------------------------------
// Gui_SetWindowLong8
//---------------------------------------------------------------------------
_FX ULONG_PTR Gui_SetWindowLong8(
HWND hWnd, int nIndex, ULONG_PTR dwNew, ULONG IsAscii)
{
ULONG_PTR value;
Gui_InitPropAtoms();
value = __sys_SetWindowLong8(hWnd, nIndex, dwNew, IsAscii);
if (Gui_RenameClasses && (nIndex == GWLP_WNDPROC)) {
//
// replace window procedure, then override the new procedure
//
WNDPROC w = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewW_Atom);
WNDPROC a = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewA_Atom);
if ((w && value == (ULONG_PTR)w) || (a && value == (ULONG_PTR)a)) {
ATOM atom = IsAscii ? Gui_WindowProcOldA_Atom
: Gui_WindowProcOldW_Atom;
value = (ULONG_PTR)__sys_GetPropW(hWnd, (LPCWSTR)atom);
Gui_SetWindowProc(hWnd, TRUE);
}
}
return Gui_SetWindowLong_DragDrop(hWnd, nIndex, dwNew, value);
}
//---------------------------------------------------------------------------
// Gui_Hook_SetWindowLong8
//---------------------------------------------------------------------------
#ifndef _M_ARM64
// $HookHack$ - Custom, not automated, Hook
_FX BOOLEAN Gui_Hook_SetWindowLong8(HMODULE module)
{
//
// on Windows 8.1, the SetWindowLongA and SetWindowLongW functions
// are very short stubs that invoke user32!SetWindowLong.
// the hook trampoline may override past the end of the short function,
// and corrupt surrounding code. to work around this, we analyze the
// short functions in order to hook user32!SetWindowLong instead
//
// SetWindowLongA mov r9d,1 41 B9 01 00 00 00
// (11 bytes) jmp xxx E9 xx xx xx xx
// SetWindowLongW xor r9d,r9d 45 33 C9
// (8 bytes) jmp xxx E9 xx xx xx xx
//
UCHAR *a = (UCHAR *)__sys_SetWindowLongA;
UCHAR *w = (UCHAR *)__sys_SetWindowLongW;
if (*(ULONG *)a == 0x0001B941 && *(ULONG *)w == 0xE9C93345) {
LONG a_offset = *(LONG *)(a + 7);
LONG w_offset = *(LONG *)(w + 4);
if ((a + 11 + a_offset) == (w + 8 + w_offset)) {
__sys_SetWindowLong8 = (P_SetWindowLong8)(w + 8 + w_offset);
SBIEDLL_HOOK_GUI(SetWindowLong8);
return TRUE;
}
}
//windows 10 build 10147 no longer has the wrapper for SetWindowLongW.
//SetWindowLongA remains the same as the previous version but points to a
//separate function
else if (*(ULONG *)a == 0x0001B941) {
LONG a_offset = *(LONG *)(a + 7);
__sys_SetWindowLong8 = (P_SetWindowLong8)w;
if ((a + 11 + a_offset) != w) {
__sys_SetWindowLongA = (P_SetWindowLong)(a + 11 + a_offset);
}
return TRUE;
}
return FALSE;
}
#endif
//---------------------------------------------------------------------------
// Gui_SetWindowLongPtr8
//---------------------------------------------------------------------------
_FX ULONG_PTR Gui_SetWindowLongPtr8(
HWND hWnd, int nIndex, ULONG_PTR dwNew, ULONG IsAscii)
{
ULONG_PTR value;
Gui_InitPropAtoms();
value = __sys_SetWindowLongPtr8(hWnd, nIndex, dwNew, IsAscii);
if (Gui_RenameClasses && (nIndex == GWLP_WNDPROC)) {
//
// replace window procedure, then override the new procedure
//
WNDPROC w = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewW_Atom);
WNDPROC a = __sys_GetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewA_Atom);
if ((w && value == (ULONG_PTR)w) || (a && value == (ULONG_PTR)a)) {
ATOM atom = IsAscii ? Gui_WindowProcOldA_Atom
: Gui_WindowProcOldW_Atom;
value = (ULONG_PTR)__sys_GetPropW(hWnd, (LPCWSTR)atom);
Gui_SetWindowProc(hWnd, TRUE);
}
}
return Gui_SetWindowLong_DragDrop(hWnd, nIndex, dwNew, value);
}
//---------------------------------------------------------------------------
// Gui_Hook_SetWindowLongPtr8
//---------------------------------------------------------------------------
#ifndef _M_ARM64
// $HookHack$ - Custom, not automated, Hook
_FX BOOLEAN Gui_Hook_SetWindowLongPtr8(HMODULE module)
{
//
// on Windows 8, the SetWindowLongPtrA and SetWindowLongPtrW functions
// are very short stubs that invoke user32!SetWindowLongPtr.
// the hook trampoline may override past the end of the short function,
// and corrupt surrounding code. to work around this, we analyze the
// short functions in order to hook user32!SetWindowLongPtr instead
//
// SetWindowLongPtrA mov r9d,1 41 B9 01 00 00 00
// (11 bytes) jmp xxx E9 xx xx xx xx
// SetWindowLongPtrW xor r9d,r9d 45 33 C9
// (8 bytes) jmp xxx E9 xx xx xx xx
//
UCHAR *a = (UCHAR *)__sys_SetWindowLongPtrA;
UCHAR *w = (UCHAR *)__sys_SetWindowLongPtrW;
if (*(ULONG *)a == 0x0001B941 && *(ULONG *)w == 0xE9C93345) {
LONG a_offset = *(LONG *)(a + 7);
LONG w_offset = *(LONG *)(w + 4);
if ((a + 11 + a_offset) == (w + 8 + w_offset)) {
__sys_SetWindowLongPtr8 =
(P_SetWindowLongPtr8)(w + 8 + w_offset);
SBIEDLL_HOOK_GUI(SetWindowLongPtr8);
return TRUE;
}
}
return FALSE;
}
#endif
//---------------------------------------------------------------------------
// End 64-bit Get/SetWindowLongPtr functions
//---------------------------------------------------------------------------
#endif _WIN64
//---------------------------------------------------------------------------
// Gui_SetWindowProc
//---------------------------------------------------------------------------
_FX void Gui_SetWindowProc(HWND hWnd, BOOLEAN force)
{
void *pWindowProcW;
void *pWindowProcA;
//
// ignore windows that are not top level windows, unless forced
//
// note that SetWindowLongXxx functions specify the force parameter
// when they re-apply our wndproc after the caller program requested
// to replace our wndproc
//
if ((! force) && __sys_GetParent(hWnd))
return;
Gui_InitPropAtoms();
//
// replace window procedure while recording the results of
// GetWindowLong A+W before and after the replace
//
pWindowProcW = (void *)__sys_GetWindowLongPtrW(hWnd, GWLP_WNDPROC);
pWindowProcA = (void *)__sys_GetWindowLongPtrA(hWnd, GWLP_WNDPROC);
if (pWindowProcW == Gui_WindowProcW || pWindowProcA == Gui_WindowProcA)
return;
__sys_SetPropW(hWnd, (LPCWSTR)Gui_WindowProcOldW_Atom, pWindowProcW);
__sys_SetPropW(hWnd, (LPCWSTR)Gui_WindowProcOldA_Atom, pWindowProcA);
if (__sys_IsWindowUnicode(hWnd)) {
__sys_SetWindowLongPtrW(
hWnd, GWLP_WNDPROC, (ULONG_PTR)Gui_WindowProcW);
} else {
__sys_SetWindowLongPtrA(
hWnd, GWLP_WNDPROC, (ULONG_PTR)Gui_WindowProcA);
}
pWindowProcW = (void *)__sys_GetWindowLongPtrW(hWnd, GWLP_WNDPROC);
pWindowProcA = (void *)__sys_GetWindowLongPtrA(hWnd, GWLP_WNDPROC);
__sys_SetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewW_Atom, pWindowProcW);
__sys_SetPropW(hWnd, (LPCWSTR)Gui_WindowProcNewA_Atom, pWindowProcA);
}