Hi Internals
Attached is a suggested patch for COM defect 35464
(http://bugs.php.net/bug.php?id=34564) Any comments; good or bad welcome.
Regards
Andy
Andy Wharmby
IBM United Kingdom Limited
Winchester, England SO21 2JN
E-mail: andy_wharmby@uk.ibm.com
COM defect 35464
The following details 2 reasons why in/out parameters don't work; one
caused by a problem with tetscase another a defect in COM extension code.
The testcase supplied by the raiser implements the DWebBrowserEvents2
interface to register an handler for the BeforeNaviagte2 event. This
handler is passed just one in/out parameter; a VARIANT_BOOL which can
be set to TRUE
by the handler to cancel the navigation operation.
Doing so in PHP currently has no affect, for the 2 reasons I will
describe below, so the navigation completes and the specified page is
displayed by IE.
Issue 1
The users code is attempting to modify the variant directly in PHP code
as follows:
$cancel = true;
rather than using the COM method variant_set as follows:
variant_set($cancel, true);
With this correction to the PHP script in place the variant for $cancel
is correctly changed to TRUE
but IE still navigates to the requested page
so the modification is having no effect. The reason for this is the
subject of issue 2 below.
Issue 2
When an event notification is received by the COM extension
disp_invokeex() processes the incoming parameters (variants) by taking
each one
and wrapping it in a php_com_dotnet_object object. At this time a COPY
of the incoming variant is embedded into the php_com_dotnet_object so we
immediately have 2 copies of the variant and it is this copy in the
php_com_dotnet_object which is processed (get and set) by the PHP code.
I see no code that checks for modification to our copy in the
php_com_dotnet_object before returning to the caller (in this case IE)
so modification
to in/out parameters by the PHP code has no affect.
Given that the code copies an incoming variant in php_com_wrap_variant()
I would have expected to see some code prior to return in disp_invokeex()
which checks for modifications to in/out parameters and copies any
modified values back to the callers copy of the variant.
I have hacked some code as follows:
com_wrapper.c: http://www.pastebin.ca/328026
com_variant.c: http://www.pastebin.ca/328022
com_misc.c: http://www.pastebin.ca/328025
php_com_dotnet_internal.h: http://www.pastebin.ca/328027
The new code works as follows:
(1) When a variant is modified by a call to variant_set() in
com_variant.c a new flag (obj->modified) is set in the
php_com_dotnet_object.
(2) After a successful call to a event handler new code in
com_wrapper.c function disp_invokeex() checks each of the event
handlers arguments
(php_com_dotnet_object's ) to see if any of their embedded variants
have been modified. If so and the argument passed into the event handler was
passed by reference then the value in the embedded variant is copied to
the callers copy by a call to a new function php_com_copy_variant()
defined in com_variant.c.
With this patch applied when the supplied testcase is run the navigation
is now cancelled as expected.