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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: markus dot demml at bmlvs dot gv dot at
New email:
PHP Version: OS:

 

 [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

Pull Requests

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-2024 The PHP Group
All rights reserved.
Last updated: Fri Nov 22 00:01:30 2024 UTC