php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #71879 Variant type changed with PHP7 x64 with lange values (VT_R8 -> VT_I8)
Submitted: 2016-03-22 10:06 UTC Modified: 2018-02-07 11:00 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:-1 (-100.0%)
From: markus dot demml at bmlvs dot gv dot at Assigned:
Status: Duplicate Package: COM related
PHP Version: 7.x x64 OS: Windows 7 x64
Private report: No CVE-ID: None
 [2016-03-22 10:06 UTC] markus dot demml at bmlvs dot gv dot at
Description:
------------
With PHP 7.0.4 (x64) i get an com_exception "Type mismatch" from the WMI-Functions EnumValues, EnumKey but this works with 5.6.19 5.5.33 5.5.29 5.5.12.

I used php.ini-development with these changes:
extension_dir = "ext"
extension=php_com_dotnet.dll

Test script:
---------------
define('HKEY_LOCAL_MACHINE', 0x80000002);
$StdRegProv = new COM("WinMgmts:{impersonationLevel=impersonate}//localhost/root/default:StdRegProv");
$valueNames = new Variant(array(), VT_ARRAY); // also new Variant(array())
$valueTypes = new Variant(array(), VT_ARRAY); // also new Variant(array())
try {
	$StdRegProv->EnumValues(HKEY_LOCAL_MACHINE, "SOFTWARE\PhpTestRegEnum", $valueNames, $valueTypes);
	foreach($valueNames as $name) {

		echo "[" . __LINE__ . "] " . "name: $name \n";

	}
	foreach($valueTypes as $type) {
		echo "[" . __LINE__ . "] " . "type: $type \n";
	}	
} catch (Exception $e) {
	echo "[" . __LINE__ . "] " . "Exception $e\n";
	echo "[" . __LINE__ . "] " . "var_dump:\n"; var_dump($e);
	echo "[" . __LINE__ . "] " . "print_r:\n"; print_r($e);
}

Expected result:
----------------
C:\php-5.6.19-Win32-VC11-x64>php ..\test-registry-access-shortversion.php
[9]name: test-reg_sz
[9]name: test-reg_bin
[9]name: test-reg_dword_32
[9]name: test-reg_qword_64
[9]name: test-reg_multi_sz
[12]type: 1
[12]type: 3
[12]type: 4
[12]type: 11
[12]type: 7

Actual result:
--------------
C:\php-7.0.4-Win32-VC14-x64>php ..\test-registry-access-shortversion.php
[15]Exception com_exception: Source: SWbemObjectEx
Description: Type mismatch  in C:\test-registry-access-shortversion.php:7
Stack trace:
#0 C:\test-registry-access-shortversion.php(7): com->EnumValues(2147483650, 'SOFTWARE\\PhpTes...', Object(variant), Object(variant))
#1 {main}
[16]var_dump:
...

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-01-26 10:44 UTC] markus dot demml at bmlvs dot gv dot at
-Summary: Variant type VT_ARRAY as output parameter invalid +Summary: Variant type changed with PHP7 x64 with lange values (VT_R8 -> VT_I8) -PHP Version: 7.0.4 +PHP Version: 7.x x64
 [2018-01-26 10:44 UTC] markus dot demml at bmlvs dot gv dot at
I've tested this problem again with all current released versions, resulting thats only a problem with PHP 7 x64

ok with:

* php-5.6.33-Win32-VC11-x64
* php-5.6.33-Win32-VC11-x86
* php-7.0.27-Win32-VC14-x86
* php-7.1.13-Win32-VC14-x86
* php-7.2.1-Win32-VC15-x86

error with:

* php-7.0.27-Win32-VC14-x64
* php-7.1.13-Win32-VC14-x64
* php-7.2.1-Win32-VC15-x64

I found that RegRead works properly and GetStringValue doesn't.

$WSH        = new COM("WScript.Shell");
$value1     = $WSH->RegRead('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion');

$StdRegProv = new COM("WinMgmts://localhost/root/default:StdRegProv");
$value2     = new VARIANT("", VT_BSTR); // 8
$retval     = $StdRegProv->GetStringValue(0x80000002, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion','CurrentVersion' , $sValue);

With some other checks and PHP Source reading I found that the Value 0x80000002 makes the difference with the function php_com_variant_from_zval

with PHP x86 and PHP 5.6 x64  -> case IS_DOUBLE:

variant_get_type( new VARIANT(0x80000002 /* 2147483650 */));  // 5 = VT_R8

with PHP 7 x64 -> case IS_LONG:

variant_get_type( new VARIANT(0x80000002 /* 2147483650 */)); // 20 = VT_UI8 / VT_I8 ?

-> changed with https://github.com/php/php-src/commit/26e7e54e782d8ba80a7f964f0bfcc3a7920349c2

--

If you pin the types, every version is working properly

// uint32 = GetStringValue(uint32 hDefKey, string sSubKeyName, string sValueName, string &sValue) // Gets the string data value of a named value.

$sSubKeyName = new VARIANT('SOFTWARE\Microsoft\Windows NT\CurrentVersion', VT_BSTR); // 8
$sValueName  = new VARIANT('CurrentVersion', VT_BSTR); // 8
$sValue      = new VARIANT("", VT_BSTR); // 8
$hDefKey     = new VARIANT(0x80000002 /* 2147483650 */, VT_R8 ); // 5

$StdRegProv = new COM("WinMgmts://localhost/root/default:StdRegProv");
$retval = $StdRegProv->GetStringValue($hDefKey, $sSubKeyName,$sValueName , $sValue);
// $sValue = "6.1" on Win7

---

The posted test scripts works correctly on PHP 7.x x64 if you fix the type to VT_R8

define('HKEY_LOCAL_MACHINE', 0x80000002);
$StdRegProv = new COM("WinMgmts:{impersonationLevel=impersonate}//localhost/root/default:StdRegProv");
$valueNames = new Variant(array(), VT_ARRAY);
$valueTypes = new Variant(array(), VT_ARRAY);

$hDefKey = new Variant(HKEY_LOCAL_MACHINE, VT_R8); // patch
try {
    $StdRegProv->EnumValues($hDefKey, "SOFTWARE\Microsoft\Windows NT\CurrentVersion", $valueNames, $valueTypes);
    foreach($valueNames as $name) {
        echo "[" . __LINE__ . "] " . "name: $name \n";
    }
    foreach($valueTypes as $type) {
        echo "[" . __LINE__ . "] " . "type: $type \n";
    }
} catch (Exception $e) {
    echo "[" . __LINE__ . "] " . "Exception $e\n";
    echo "[" . __LINE__ . "] " . "var_dump:\n"; var_dump($e);
    echo "[" . __LINE__ . "] " . "print_r:\n"; print_r($e);
}

----

* I don't understand why i can't use VT_UI4 for hDefKey but thats an API and no PHP problem, isn't?

* VT_UI8 and VT_I8 are not documented http://php.net/manual/en/com.constants.php

* was this change VT_R8 to VT_I8 intended or a side effect ?
 [2018-02-07 10:58 UTC] ab@php.net
-Status: Open +Status: Duplicate
 [2018-02-07 10:58 UTC] ab@php.net
Thanks for the report. This is a dup of bug #73605.

You need to use the exact datatype as API requires

define('HKEY_LOCAL_MACHINE', new VARIANT(0x80000002, VT_UI8));

See also https://msdn.microsoft.com/de-de/library/aa390388(v=vs.85).aspx

Thanks.
 [2018-02-07 11:00 UTC] ab@php.net
Typo there, 

define('HKEY_LOCAL_MACHINE', new VARIANT(0x80000002, VT_UI4));

Thanks.
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Fri Mar 05 05:01:23 2021 UTC