@@ -457,30 +457,94 @@ PHP_METHOD(variant, __construct)
457
457
/* If already an array and VT_ARRAY is passed then:
458
458
- if only VT_ARRAY passed then do not perform a conversion
459
459
- if VT_ARRAY plus other type passed then perform conversion
460
- but will probably fail (original behavior)
461
460
*/
462
- if ((vt & VT_ARRAY ) && (V_VT (& obj -> v ) & VT_ARRAY )) {
463
- zend_long orig_vt = vt ;
464
461
465
- vt &= ~VT_ARRAY ;
466
- if (vt ) {
467
- vt = orig_vt ;
462
+ res = S_OK ;
463
+ SAFEARRAYBOUND Bound ;
464
+
465
+ if (!(V_VT (& obj -> v ) & VT_BYREF ) && //not supported
466
+ (vt & ~VT_ARRAY ) && //new variant have some type except VT_ARRAY
467
+ (V_VT (& obj -> v ) & VT_ARRAY ) && //old variant is array
468
+ SafeArrayGetDim (V_ARRAY (& obj -> v )) == 1 && //old array have one dimension
469
+ SUCCEEDED (res = SafeArrayGetLBound (V_ARRAY (& obj -> v ), 1 , & Bound .lLbound )) &&
470
+ SUCCEEDED (res = SafeArrayGetUBound (V_ARRAY (& obj -> v ), 1 , & Bound .cElements )))
471
+ {
472
+
473
+ zend_long need_vt = vt & ~VT_ARRAY ;
474
+ zend_long old_vt = V_VT (& obj -> v ) & ~VT_ARRAY ;
475
+
476
+ Bound .cElements -= Bound .lLbound - 1 ;
477
+ SAFEARRAY * newArray = SafeArrayCreate (need_vt , 1 , & Bound );
478
+
479
+ if (newArray ) {
480
+
481
+ for (LONG i = Bound .lLbound ; i < Bound .lLbound + Bound .cElements ; i ++ ) {
482
+ VARIANT temp ;
483
+ VariantInit (& temp );
484
+ if (old_vt != VT_VARIANT )
485
+ V_VT (& temp ) = old_vt ;
486
+
487
+ switch (old_vt ) {
488
+ case VT_VARIANT :
489
+ res = SafeArrayGetElement (V_ARRAY (& obj -> v ), & i , & temp ); break ;
490
+ default :
491
+ res = SafeArrayGetElement (V_ARRAY (& obj -> v ), & i , & V_I8 (& temp )); break ;
492
+ }
493
+
494
+ if (FAILED (res ))
495
+ break ;
496
+
497
+ if (FAILED (res = VariantChangeType (& temp , & temp , 0 , (VARTYPE )need_vt ))) {
498
+ VariantClear (& temp );
499
+ break ;
500
+ }
501
+
502
+ switch (need_vt ) {
503
+ case VT_VARIANT :
504
+ res = SafeArrayPutElement (newArray , & i , & temp ); break ;
505
+ case VT_DISPATCH :
506
+ case VT_UNKNOWN :
507
+ case VT_BSTR :
508
+ res = SafeArrayPutElement (newArray , & i , V_DISPATCH (& temp )); break ;
509
+ default :
510
+ res = SafeArrayPutElement (newArray , & i , & V_I8 (& temp ));
511
+ break ;
512
+ }
513
+
514
+ VariantClear (& temp );
515
+ if (FAILED (res ))
516
+ break ;
517
+ }
518
+
519
+ if (SUCCEEDED (res )) {
520
+ SafeArrayDestroy (V_ARRAY (& obj -> v ));
521
+ V_ARRAY (& obj -> v ) = newArray ;
522
+ V_VT (& obj -> v ) = vt | VT_ARRAY ; //Set VT_ARRAY automatically
523
+ vt = VT_EMPTY ;//No need change type any more
524
+ }
525
+ else
526
+ SafeArrayDestroy (newArray );
468
527
}
469
528
}
470
529
471
- if (vt ) {
530
+ /** Try to system conversion function if our array conversion
531
+ * function don't do conversion before (vt is not VT_EMPTY)
532
+ * and wasn't tried it (SUCCEEDED(res))
533
+ */
534
+
535
+ if (SUCCEEDED (res ) && vt ) {
472
536
res = VariantChangeType (& obj -> v , & obj -> v , 0 , (VARTYPE )vt );
537
+ }
473
538
474
- if (FAILED (res )) {
475
- char * werr , * msg ;
539
+ if (FAILED (res )) {
540
+ char * werr , * msg ;
476
541
477
542
werr = php_win32_error_to_msg (res );
478
543
spprintf (& msg , 0 , "Variant type conversion failed: %s" , werr );
479
544
php_win32_error_msg_free (werr );
480
545
481
- php_com_throw_exception (res , msg );
482
- efree (msg );
483
- }
546
+ php_com_throw_exception (res , msg );
547
+ efree (msg );
484
548
}
485
549
}
486
550
0 commit comments