The ICoreWebView2EnvironmentOptions interface must be created before any webview gadget is created and passed to it during creation. This cannot be done through usual methods and can only be passed via a hook.
.
Please check if it works properly.
Move the call to the put_AdditionalBrowserArguments method inside the functions.
Code: Select all
; https://github.com/webview/webview
;// The minimum WebView2 API version we need regardless of the SDK release
;// actually used. The number comes from the SDK release version,
;// e.g. 1.0.1150.38. To be safe the SDK should have a number that is greater
;// than or equal to this number. The Edge browser webview client must
;// have a number greater than or equal to this number.
EnableExplicit
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
#Lib_x86x64 = "86"
CompilerElse
#Lib_x86x64 = "64"
CompilerEndIf
;Import "z:\Detours_x" + #Lib_x86x64 + ".lib"
Import "Detours.lib"
DetourTransactionBegin.l()
DetourTransactionCommit.l()
DetourUpdateThread.l(hThread)
DetourAttach.l(*ppPointer, pDetour)
DetourDetach.l(*ppPointer, pDetour)
EndImport
DataSection
IID_IUnknown:
Data.l $00000000
Data.w $0000, $0000
Data.b $C0, $00, $00, $00, $00, $00, $00, $46
IID_ICoreWebView2EnvironmentOptions:
Data.l $2fde08a8
Data.w $1e9a, $4766
Data.b $8c, $05, $95, $a9, $ce, $b9, $d1, $c5
IID_ICoreWebView2EnvironmentOptions2:
Data.l $FF85C98A
Data.w $1BA7, $4A6B
Data.b $90, $C8, $2B, $75, $2C, $89, $E9, $E2
IID_ICoreWebView2EnvironmentOptions3:
Data.l $4A5C436E
Data.w $A9E3, $4A2E
Data.b $89, $C3, $91, $0D, $35, $13, $F5, $CC
IID_ICoreWebView2EnvironmentOptions4:
Data.l $ac52d13f
Data.w $0d38, $475a
Data.b $9d, $ca, $87, $65, $80, $d6, $79, $3e
IID_ICoreWebView2EnvironmentOptions5:
Data.l $0AE35D64
Data.w $C47F, $4464
Data.b $81, $4E, $25, $9C, $34, $5D, $15, $01
IID_ICoreWebView2EnvironmentOptions6:
Data.l $57D29CC3
Data.w $C84F, $42A0
Data.b $B0, $E2, $EF, $FB, $D5, $E1, $79, $DE
EndDataSection
#CORE_WEBVIEW_TARGET_PRODUCT_VERSION = "123.0.2415.0"
Structure STRUC_IUnknownBase Align #PB_Structure_AlignC
*pVtbl
lRefCount.l
*pQueryInterface
*pAddRef
*pRelease
EndStructure
Structure STRUC_ICoreWebView2EnvironmentOptions Extends STRUC_IUnknownBase
*get_AdditionalBrowserArguments
*put_AdditionalBrowserArguments
*get_Language
*put_Language
*get_TargetCompatibleBrowserVersion
*put_TargetCompatibleBrowserVersion
*get_AllowSingleSignOnUsingOSPrimaryAccount
*put_AllowSingleSignOnUsingOSPrimaryAccount
sAdditionalBrowserArguments.s
sLanguage.s
sTargetCompatibleBrowserVersion.s
lAllowSingleSignOnUsingOSPrimaryAccount.l
EndStructure
Structure STRUC_ICoreWebView2EnvironmentOptions2 Extends STRUC_IUnknownBase
*get_ExclusiveUserDataFolderAccess
*put_ExclusiveUserDataFolderAccess
EndStructure
Structure STRUC_ICoreWebView2EnvironmentOptions3 Extends STRUC_IUnknownBase
*get_IsCustomCrashReportingEnabled
*put_IsCustomCrashReportingEnabled
EndStructure
Structure STRUC_ICoreWebView2EnvironmentOptions4 Extends STRUC_IUnknownBase
*GetCustomSchemeRegistrations
*SetCustomSchemeRegistrations
EndStructure
Structure STRUC_ICoreWebView2EnvironmentOptions5 Extends STRUC_IUnknownBase
*get_EnableTrackingPrevention
*put_EnableTrackingPrevention
EndStructure
Structure STRUC_ICoreWebView2EnvironmentOptions6 Extends STRUC_IUnknownBase
*get_AreBrowserExtensionsEnabled
*put_AreBrowserExtensionsEnabled
EndStructure
Procedure MakeCoMemString(String.s, *Result.Long)
Protected iResult, *Buffer, lStrBytes = StringByteLength(String)
If *Result = 0 : ProcedureReturn 0 : EndIf
*Result\l = #S_FALSE
If lStrBytes > 0
*Buffer = CoTaskMemAlloc_(lStrBytes + 2)
If *Buffer
If PokeS(*Buffer, String) > 0
iResult = *Buffer
*Result\l = #S_OK
EndIf
If *Result\l <> #S_OK
CoTaskMemFree_(*Buffer)
EndIf
Else
*Result\l = #E_OUTOFMEMORY
EndIf
EndIf
ProcedureReturn iResult
EndProcedure
Procedure.l ICoreWebView2EnvironmentOptions_QueryInterface(*this.STRUC_IUnknownBase, *riid.IID, *ppvObject.Integer)
If *ppvObject And *riid
If CompareMemory(*riid, ?IID_IUnknown, SizeOf(IID)) Or CompareMemory(*riid, ?IID_ICoreWebView2EnvironmentOptions, SizeOf(IID))
*this\lRefCount + 1
*ppvObject\i = *this
ElseIf CompareMemory(*riid, ?IID_ICoreWebView2EnvironmentOptions2, SizeOf(IID))
Debug "Req: Options2"
*ppvObject\i = 0
ProcedureReturn #E_NOINTERFACE
ElseIf CompareMemory(*riid, ?IID_ICoreWebView2EnvironmentOptions3, SizeOf(IID))
Debug "Req: Options3"
*ppvObject\i = 0
ProcedureReturn #E_NOINTERFACE
ElseIf CompareMemory(*riid, ?IID_ICoreWebView2EnvironmentOptions4, SizeOf(IID))
Debug "Req: Options4"
*ppvObject\i = 0
ProcedureReturn #E_NOINTERFACE
ElseIf CompareMemory(*riid, ?IID_ICoreWebView2EnvironmentOptions5, SizeOf(IID))
Debug "Req: Options5"
*ppvObject\i = 0
ProcedureReturn #E_NOINTERFACE
ElseIf CompareMemory(*riid, ?IID_ICoreWebView2EnvironmentOptions6, SizeOf(IID))
Debug "Req: Options6"
*ppvObject\i = 0
ProcedureReturn #E_NOINTERFACE
Else
*ppvObject\i = 0
ProcedureReturn #E_NOINTERFACE
EndIf
Else
ProcedureReturn #E_POINTER
EndIf
ProcedureReturn #S_OK
EndProcedure
Procedure.l ICoreWebView2EnvironmentOptions_AddRef(*this.STRUC_IUnknownBase)
*this\lRefCount + 1
ProcedureReturn *this\lRefCount
EndProcedure
Procedure.l ICoreWebView2EnvironmentOptions_Release(*this.STRUC_IUnknownBase)
*this\lRefCount - 1
If *this\lRefCount <= 0
FreeStructure(*this)
Debug "EnvironmentOptions Freed"
ProcedureReturn 0
EndIf
ProcedureReturn *this\lRefCount
EndProcedure
Procedure.l ICoreWebView2EnvironmentOptions_get_AdditionalBrowserArguments(*this.STRUC_ICoreWebView2EnvironmentOptions, *value.Integer)
Protected lResult.l = #S_FALSE
Protected *Buffer
Debug #PB_Compiler_Procedure
If *value = 0 : ProcedureReturn #E_POINTER : EndIf
*value\i = 0
*Buffer = MakeCoMemString(*this\sAdditionalBrowserArguments, @lResult)
If *Buffer : *value\i = *Buffer : EndIf
ProcedureReturn lResult
EndProcedure
Procedure.l ICoreWebView2EnvironmentOptions_put_AdditionalBrowserArguments(*this.STRUC_ICoreWebView2EnvironmentOptions, *value)
Debug #PB_Compiler_Procedure
If *value = 0 : ProcedureReturn #E_POINTER : EndIf
*this\sAdditionalBrowserArguments = PeekS(*value)
ProcedureReturn #S_OK
EndProcedure
Procedure.l ICoreWebView2EnvironmentOptions_get_Language(*this.STRUC_ICoreWebView2EnvironmentOptions, *value.Integer)
Protected lResult.l = #S_FALSE
Protected *Buffer
Debug #PB_Compiler_Procedure
If *value = 0 : ProcedureReturn #E_POINTER : EndIf
*value\i = 0
*Buffer = MakeCoMemString(*this\sLanguage, @lResult)
If *Buffer : *value\i = *Buffer : EndIf
ProcedureReturn lResult
EndProcedure
Procedure.l ICoreWebView2EnvironmentOptions_put_Language(*this.STRUC_ICoreWebView2EnvironmentOptions, *value)
Debug #PB_Compiler_Procedure
If *value = 0 : ProcedureReturn #E_POINTER : EndIf
*this\sLanguage = PeekS(*value)
ProcedureReturn #S_OK
EndProcedure
Procedure.l ICoreWebView2EnvironmentOptions_get_TargetCompatibleBrowserVersion(*this.STRUC_ICoreWebView2EnvironmentOptions, *value.Integer)
Protected lResult.l = #S_FALSE
Protected *Buffer
Debug #PB_Compiler_Procedure
If *value = 0 : ProcedureReturn #E_POINTER : EndIf
*value\i = 0
*Buffer = MakeCoMemString(*this\sTargetCompatibleBrowserVersion, @lResult)
If *Buffer : *value\i = *Buffer : EndIf
ProcedureReturn lResult
EndProcedure
Procedure.l ICoreWebView2EnvironmentOptions_put_TargetCompatibleBrowserVersion(*this.STRUC_ICoreWebView2EnvironmentOptions, *value)
Debug #PB_Compiler_Procedure
If *value = 0 : ProcedureReturn #E_POINTER : EndIf
*this\sTargetCompatibleBrowserVersion = PeekS(*value)
ProcedureReturn #S_OK
EndProcedure
Procedure.l ICoreWebView2EnvironmentOptions_get_AllowSingleSignOnUsingOSPrimaryAccount(*this.STRUC_ICoreWebView2EnvironmentOptions, *allow.Long)
Debug #PB_Compiler_Procedure
If *allow = 0 : ProcedureReturn #E_POINTER : EndIf
*allow\l = *this\lAllowSingleSignOnUsingOSPrimaryAccount
ProcedureReturn #S_OK
EndProcedure
Procedure.l ICoreWebView2EnvironmentOptions_put_AllowSingleSignOnUsingOSPrimaryAccount(*this.STRUC_ICoreWebView2EnvironmentOptions, allow)
Debug #PB_Compiler_Procedure
*this\lAllowSingleSignOnUsingOSPrimaryAccount = allow
ProcedureReturn #S_OK
EndProcedure
Procedure New_ICoreWebView2EnvironmentOptions()
Protected *Buffer.STRUC_ICoreWebView2EnvironmentOptions = AllocateStructure(STRUC_ICoreWebView2EnvironmentOptions)
If *Buffer
With *Buffer
\pVtbl = *Buffer + OffsetOf(STRUC_IUnknownBase\pQueryInterface)
\lRefCount + 1
\pQueryInterface = @ICoreWebView2EnvironmentOptions_QueryInterface()
\pAddRef = @ICoreWebView2EnvironmentOptions_AddRef()
\pRelease = @ICoreWebView2EnvironmentOptions_Release()
\get_AdditionalBrowserArguments = @ICoreWebView2EnvironmentOptions_get_AdditionalBrowserArguments()
\put_AdditionalBrowserArguments = @ICoreWebView2EnvironmentOptions_put_AdditionalBrowserArguments()
\get_Language = @ICoreWebView2EnvironmentOptions_get_Language()
\put_Language = @ICoreWebView2EnvironmentOptions_put_Language()
\get_TargetCompatibleBrowserVersion = @ICoreWebView2EnvironmentOptions_get_TargetCompatibleBrowserVersion()
\put_TargetCompatibleBrowserVersion = @ICoreWebView2EnvironmentOptions_put_TargetCompatibleBrowserVersion()
\get_AllowSingleSignOnUsingOSPrimaryAccount = @ICoreWebView2EnvironmentOptions_get_AllowSingleSignOnUsingOSPrimaryAccount()
\put_AllowSingleSignOnUsingOSPrimaryAccount = @ICoreWebView2EnvironmentOptions_put_AllowSingleSignOnUsingOSPrimaryAccount()
\sTargetCompatibleBrowserVersion = #CORE_WEBVIEW_TARGET_PRODUCT_VERSION
;\lAllowSingleSignOnUsingOSPrimaryAccount = 0
EndWith
EndIf
ProcedureReturn *Buffer
EndProcedure
Global g_Temp_ICoreWebView2EnvironmentOptions.ICoreWebView2EnvironmentOptions
; https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2365.46
; STDAPI CreateCoreWebView2EnvironmentWithOptions(PCWSTR browserExecutableFolder, PCWSTR userDataFolder, ICoreWebView2EnvironmentOptions* environmentOptions, ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler* environmentCreatedHandler);
; STDAPI GetAvailableCoreWebView2BrowserVersionString(PCWSTR browserExecutableFolder, LPWSTR* versionInfo);
; STDAPI CompareBrowserVersions(PCWSTR version1, PCWSTR version2, int* result);
; https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2365.46#createcorewebview2environmentwithoptions
; CreateCoreWebView2EnvironmentWithOptions(PCWSTR browserExecutableFolder, PCWSTR userDataFolder, ICoreWebView2EnvironmentOptions * environmentOptions, ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler * environmentCreatedHandler)
Prototype.l CreateCoreWebView2EnvironmentWithOptions(*browserExecutableFolder, *userDataFolder, *environmentOptions, *createdEnvironmentCallback)
Global CreateCoreWebView2EnvironmentWithOptions__.CreateCoreWebView2EnvironmentWithOptions
; https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.2365.46#createwebviewenvironmentwithoptionsinternal
; CreateWebViewEnvironmentWithOptionsInternal(bool checkRunningInstance, int runtimeType, PCWSTR userDataFolder, IUnknown * environmentOptions, ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler * webViewEnvironmentCreatedHandler)
Prototype.l CreateWebViewEnvironmentWithOptionsInternal(checkRunningInstance.l, runtimeType.l, *userDataFolder, *environmentOptions, *webViewEnvironmentCreatedHandler)
Global CreateWebViewEnvironmentWithOptionsInternal__.CreateWebViewEnvironmentWithOptionsInternal
Procedure.l My_CreateWebViewEnvironmentWithOptionsInternal(checkRunningInstance.l, runtimeType.l, *userDataFolder, *environmentOptions.ICoreWebView2EnvironmentOptions, *webViewEnvironmentCreatedHandler)
Protected lResult.l
; ; Read the value you set in the environment variable below.
; Protected sUserDataFolder.s = GetEnvironmentVariable("WEBVIEW2_USER_DATA_FOLDER")
Debug "----------------------------------------"
Debug #PB_Compiler_Procedure
; If sUserDataFolder
;
; ; In this example, it is only used to show the "UserDataFolder", which is already specified.
; If *userDataFolder
; Debug "Previous UserDataFolder: " + PeekS(*userDataFolder)
; EndIf
;
; ; Specify the new "UserDataFolder" that you obtained above.
; *userDataFolder = @sUserDataFolder
; Debug "Set new UserDataFolder: " + sUserDataFolder
; EndIf
If *environmentOptions = 0 And g_Temp_ICoreWebView2EnvironmentOptions
*environmentOptions = g_Temp_ICoreWebView2EnvironmentOptions
g_Temp_ICoreWebView2EnvironmentOptions = 0
If *environmentOptions\put_AdditionalBrowserArguments(GetEnvironmentVariable("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS")) = #S_OK
Debug "Set AdditionalBrowserArguments"
EndIf
Debug "Set ICoreWebView2EnvironmentOptions"
EndIf
Debug "----------------------------------------"
; Call the original unhooked function.
lResult = CreateWebViewEnvironmentWithOptionsInternal__(checkRunningInstance, runtimeType, *userDataFolder, *environmentOptions, *webViewEnvironmentCreatedHandler)
ProcedureReturn lResult
EndProcedure
Procedure.l My_CreateCoreWebView2EnvironmentWithOptions(*browserExecutableFolder, *userDataFolder, *environmentOptions.ICoreWebView2EnvironmentOptions, *createdEnvironmentCallback)
Protected lResult.l
; Protected sUserDataFolder.s = GetEnvironmentVariable("WEBVIEW2_USER_DATA_FOLDER")
Debug "----------------------------------------"
Debug #PB_Compiler_Procedure
; If sUserDataFolder
; If *userDataFolder
; Debug "Previous UserDataFolder: " + PeekS(*userDataFolder)
; EndIf
; *userDataFolder = @sUserDataFolder
; Debug "Set new UserDataFolder: " + sUserDataFolder
; EndIf
If *environmentOptions = 0 And g_Temp_ICoreWebView2EnvironmentOptions
*environmentOptions = g_Temp_ICoreWebView2EnvironmentOptions
g_Temp_ICoreWebView2EnvironmentOptions = 0
If *environmentOptions\put_AdditionalBrowserArguments(GetEnvironmentVariable("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS")) = #S_OK
Debug "Set AdditionalBrowserArguments"
EndIf
Debug "Set ICoreWebView2EnvironmentOptions"
EndIf
Debug "----------------------------------------"
lResult = CreateCoreWebView2EnvironmentWithOptions__(*browserExecutableFolder, *userDataFolder, *environmentOptions, *createdEnvironmentCallback)
ProcedureReturn lResult
EndProcedure
Procedure.s GetWebView2Path()
Protected sResult.s
Protected sSubkey.s = "SOFTWARE\Microsoft\EdgeUpdate\ClientState\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}"
Protected hkey, *m, lDataBytes.l
If RegOpenKeyEx_(#HKEY_LOCAL_MACHINE, sSubkey, 0, #KEY_READ | #KEY_WOW64_32KEY, @hkey) = #ERROR_SUCCESS
If RegQueryValueEx_(hkey, "EBWebView", 0, 0, *m, @lDataBytes) = #ERROR_SUCCESS
If lDataBytes > 0
*m = AllocateMemory(lDataBytes)
If *m
If RegQueryValueEx_(hkey, "EBWebView", 0, 0, *m, @lDataBytes) = #ERROR_SUCCESS
sResult = PeekS(*m)
EndIf
FreeMemory(*m)
EndIf
EndIf
EndIf
RegCloseKey_(hkey)
EndIf
ProcedureReturn sResult
EndProcedure
Define Lib_WV2, sPath.s
; First, we look in the registry to see if WebView2 is installed on the system.
sPath = GetWebView2Path()
If sPath
; If the "WebView2Loader.dll" file exists in the application folder,
; the WebGadget is created using the CreateCoreWebView2EnvironmentWithOptions function inside the "WebView2Loader.dll" file,
; otherwise, the WebGadget is created using the CreateWebViewEnvironmentWithOptionsInternal function inside the "EmbeddedBrowserWebView.dll" file at the path obtained above.
; We'll intercept the call to one of the two functions used to create the WebGadget.
Lib_WV2 = OpenLibrary(#PB_Any, "WebView2Loader.dll")
If Lib_WV2
Debug "WebView2Loader.dll open."
CreateCoreWebView2EnvironmentWithOptions__ = GetFunction(Lib_WV2, "CreateCoreWebView2EnvironmentWithOptions")
Else
Lib_WV2 = OpenLibrary(#PB_Any, sPath + "\EBWebView\x" + #Lib_x86x64 + "\EmbeddedBrowserWebView.dll")
If Lib_WV2
Debug "EmbeddedBrowserWebView.dll open."
CreateWebViewEnvironmentWithOptionsInternal__ = GetFunction(Lib_WV2, "CreateWebViewEnvironmentWithOptionsInternal")
EndIf
EndIf
; Once you have the address of one of the two functions, try the hook.
If CreateCoreWebView2EnvironmentWithOptions__ Or CreateWebViewEnvironmentWithOptionsInternal__
; https://github.com/microsoft/Detours/wiki/DetourTransactionBegin
If DetourTransactionBegin() = #NO_ERROR
; https://github.com/microsoft/Detours/wiki/DetourUpdateThread
If DetourUpdateThread(GetCurrentThread_()) = #NO_ERROR
If CreateCoreWebView2EnvironmentWithOptions__
; https://github.com/microsoft/Detours/wiki/DetourAttach
; As a result of the function execution, the former variable stores the original function address before it was hooked.
If DetourAttach(@CreateCoreWebView2EnvironmentWithOptions__, @My_CreateCoreWebView2EnvironmentWithOptions()) <> #NO_ERROR
Debug "Error 0"
EndIf
EndIf
If CreateWebViewEnvironmentWithOptionsInternal__
If DetourAttach(@CreateWebViewEnvironmentWithOptionsInternal__, @My_CreateWebViewEnvironmentWithOptionsInternal()) <> #NO_ERROR
Debug "Error 1"
EndIf
EndIf
; https://github.com/microsoft/Detours/wiki/DetourTransactionCommit
DetourTransactionCommit()
EndIf
EndIf
Else
Debug "WebView2 function not found."
EndIf
Else
Debug "No WebView2 installed."
EndIf
OpenWindow(0, 0, 0, 1000, 900, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
; Strings returned by methods such as get_xxx in the ICoreWebView2EnvironmentOptions interface should be released by the caller using the CoTaskMemFree function.
Define OptionsWVG_1.ICoreWebView2EnvironmentOptions = New_ICoreWebView2EnvironmentOptions()
If OptionsWVG_1
Debug "ICoreWebView2EnvironmentOptions for Webview gadget #1: " + OptionsWVG_1
If OptionsWVG_1\put_AllowSingleSignOnUsingOSPrimaryAccount(#True) = #S_OK
Debug "OK : put_AllowSingleSignOnUsingOSPrimaryAccount"
EndIf
; You must specify the interface in the global variable "g_Temp_ICoreWebView2EnvironmentOptions" immediately before creating any webview gadget.
g_Temp_ICoreWebView2EnvironmentOptions = OptionsWVG_1
EndIf
WebViewGadget(1, 0, 35, 1000, 900)
SetGadgetText(1, "file://" + #PB_Compiler_Home + "examples/sources/Data/WebView/webview.html")
Define e
Repeat
e = WaitWindowEvent()
Until e = #PB_Event_CloseWindow
If OptionsWVG_1
OptionsWVG_1\Release()
EndIf
CloseLibrary(#PB_All)