From 3bf9df6b2785fa6d951086978a3e66f49427166a Mon Sep 17 00:00:00 2001 From: FluorescentCIAAfricanAmerican <0934gj3049fk@protonmail.com> Date: Wed, 22 Apr 2020 12:56:21 -0400 Subject: 1 --- devtools/WiseInstallerHelpers/LicenseViewed.cpp | 217 ++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 devtools/WiseInstallerHelpers/LicenseViewed.cpp (limited to 'devtools/WiseInstallerHelpers/LicenseViewed.cpp') diff --git a/devtools/WiseInstallerHelpers/LicenseViewed.cpp b/devtools/WiseInstallerHelpers/LicenseViewed.cpp new file mode 100644 index 0000000..037c26d --- /dev/null +++ b/devtools/WiseInstallerHelpers/LicenseViewed.cpp @@ -0,0 +1,217 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Checks to see if the user has completely viewed the EULA before activing the accept/decline radio buttons +// +//=============================================================================// +#include < windows.h > +#include < msi.h > +#include < msiquery.h > +#include +#include +#include +#include + +#define CHILD_WINDOW_OF_LICENSE "vHackLicenseWindowSibling092304" +#define WINDOW_CLASS_OF_EULA_WINDOW "RichEdit20W" +#define ALLOWABLE_POS_FROM_BOTTOM 5 + +//----------------------------------------------------------------------------- +// Purpose: Call back function for EnumChildWindows +// Input : hwnd - +// lParam - +// Output : BOOL CALLBACK +//----------------------------------------------------------------------------- +BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam) +{ + TCHAR buf[100]; + + GetClassName( hwnd, (LPTSTR)&buf, 100 ); + if ( _tcscmp( buf, _T( WINDOW_CLASS_OF_EULA_WINDOW ) ) == 0 ) + { + *(HWND*)lParam = hwnd; + return FALSE; + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// Purpose: Context for searching sub windows... +//----------------------------------------------------------------------------- +struct FindParams_t +{ + HWND wnd; + char searchtext[ 512 ]; +}; + +//----------------------------------------------------------------------------- +// Purpose: +// Input : hwnd - +// lParam - +// Output : BOOL CALLBACK +//----------------------------------------------------------------------------- +BOOL CALLBACK EnumChildrenLookingForSpecialControl(HWND hwnd,LPARAM lParam) +{ + FindParams_t *p = ( FindParams_t *)lParam; + + char buf[ 512 ]; + GetWindowText( hwnd, buf, sizeof( buf ) ); + + if ( !stricmp( buf, p->searchtext ) ) + { + p->wnd = hwnd; + return FALSE; + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : hwnd - +// lParam - +// Output : BOOL CALLBACK +//----------------------------------------------------------------------------- +BOOL CALLBACK EnumChildWindowsProc(HWND hwnd, LPARAM lParam) +{ + // Now search for the special hidden text control inside a top level window + + FindParams_t *p = ( FindParams_t *)lParam; + + FindParams_t special; + memset( &special, 0, sizeof( special ) ); + strcpy( special.searchtext, p->searchtext ); + + EnumChildWindows( hwnd, EnumChildrenLookingForSpecialControl, (LPARAM)&special ); + if ( special.wnd != NULL ) + { + p->wnd = hwnd; + return FALSE; + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// Purpose: Finds given a root window, finds a child window which itself has a special child window with the specified text string as the window title. +// e.g.: +// if root == NULL (desktop), then you can search the top level dialogs (Half-Life 2 Setup,e.g.) for a subwindow with "vHackxxx" as the text, this would +// return the appropriate top level dialog. +// Input : root - +// *text - +// Output : HWND +//----------------------------------------------------------------------------- +HWND FindWindowHavingChildWithSpecifiedText( HWND root, char const *text ) +{ + FindParams_t params; + memset( ¶ms, 0, sizeof( params ) ); + + strncpy( params.searchtext, text, sizeof( params.searchtext ) - 1 ); + + EnumChildWindows( root, EnumChildWindowsProc, (LPARAM)¶ms ); + + return params.wnd; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *text - +// Output : HWND +//----------------------------------------------------------------------------- +HWND FindTopLevelWindowHavingChildWithSpecifiedText( char const *text ) +{ + return FindWindowHavingChildWithSpecifiedText( GetDesktopWindow(), text ); +} + + +//*********************************************************** +//** Custom action to check if the license is completly +//** viewed. +//**--------------------------------------------------------- +//** Return values: +//** (1) Always returns success +//** (2) Sets the private property LicenseViewed when +//** the text is scrolled to near end. +//**--------------------------------------------------------- +//** Usage: +//** (1) Find installer window by looking for child with specified text. Can't +//** just use window title because it's translated into foreign languages +//** (2) In the license agreement dialog, on the scrollable +//** text control event, call the custom action +//** CheckLicenseViewed using a DoAction +//** (3) For the Next button, modify the Enable +//** ControlCondition to include the property +//** LicenseViewed +//**--------------------------------------------------------- +//*********************************************************** + +// Needs to be exported as non-__stdcall with C name mangling (no mangling) +extern "C" __declspec( dllexport ) UINT CheckLicenseViewed(MSIHANDLE hMSI) +{ + HWND hWnd; + HWND hWndChild=NULL; + + if (MsiEvaluateCondition(hMSI,"LicenseViewed")==MSICONDITION_FALSE) + { + hWnd = FindTopLevelWindowHavingChildWithSpecifiedText(CHILD_WINDOW_OF_LICENSE ); + if (hWnd) + { + EnumChildWindows( hWnd, EnumChildProc, (LPARAM)&hWndChild ); + if ( hWndChild ) + { + SCROLLINFO sinfo; + memset( &sinfo, 0, sizeof( sinfo ) ); + sinfo.cbSize=sizeof(sinfo); + sinfo.fMask=SIF_TRACKPOS | SIF_RANGE | SIF_POS | SIF_PAGE; + GetScrollInfo(hWndChild, SB_VERT, &sinfo); + //max range depends on page size + UINT MaxScrollPos = sinfo.nMax - ( sinfo.nPage - 1 ); + //max less, say ALLOWABLE_POS_FROM_BOTTOM - an allowable max. + MaxScrollPos = MaxScrollPos - ALLOWABLE_POS_FROM_BOTTOM; + + // THIS IS A HACK, but the RichEdit20W control has a bug where while the thumb is being dragged, the position doesn't + // get updated. In fact, it doesn't get updated until the next time + UINT nScrollPos = ::SendMessage(hWndChild, EM_GETTHUMB, 0, 0); + + bool trackedPastEnd = false; // (UINT)sinfo.nTrackPos >= MaxScrollPos ? true : false; + bool positionedPastEnd = nScrollPos >= MaxScrollPos ? true : false; + // Note above, this method doesn't always work... but maybe it will work in win98 and the other won't, etc. etc. + bool positionedPastEnd2 = (UINT)sinfo.nPos >= MaxScrollPos ? true : false; + + /* + + HDC dc = GetDC( GetDesktopWindow() ); + COLORREF oldColor = SetTextColor( dc, RGB( 255, 0, 0 ) ); + + char sz[ 256 ]; + _snprintf( sz, sizeof( sz ), "max %i page %i msp %i track %u pos %u pos2 %u", + sinfo.nMax, + sinfo.nPage, + MaxScrollPos, + sinfo.nTrackPos, + sinfo.nPos, + nScrollPos ); + + RECT rc; + rc.left = 0; + rc.right = 1000; + rc.top = 20; + rc.bottom = 50; + + DrawText( dc, sz, -1, &rc, DT_NOPREFIX ); + + SetTextColor( dc, oldColor ); + ReleaseDC( GetDesktopWindow(), dc ); + */ + + if ( trackedPastEnd || positionedPastEnd || positionedPastEnd2 ) + { + MsiSetProperty(hMSI, TEXT("LicenseViewed"), TEXT("1")); + } + else + { + MsiSetProperty(hMSI, TEXT("LicenseViewed"), NULL); + } + } + } + } + return ERROR_SUCCESS; +} \ No newline at end of file -- cgit v1.2.3