php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
com_variant.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Wez Furlong <wez@thebrainroom.com> |
14 +----------------------------------------------------------------------+
15 */
16
17#ifdef HAVE_CONFIG_H
18#include <config.h>
19#endif
20
21#include "php.h"
22#include "php_ini.h"
23#include "ext/standard/info.h"
24#include "php_com_dotnet.h"
26
27/* create an automation SafeArray from a PHP array.
28 * Only creates a single-dimensional array of variants.
29 * The keys of the PHP hash MUST be numeric. */
30static void safe_array_from_zval(VARIANT *v, zval *z, int codepage)
31{
32 SAFEARRAY *sa = NULL;
33 SAFEARRAYBOUND bound;
35 int keytype;
36 zend_string *strindex;
37 zend_ulong intindex = 0;
38 VARIANT *va;
39 zval *item;
40
41 /* find the largest array index, and assert that all keys are integers */
44
45 keytype = zend_hash_get_current_key_ex(Z_ARRVAL_P(z), &strindex, &intindex, &pos);
46
47 if (HASH_KEY_IS_STRING == keytype) {
48 goto bogus;
49 } else if (HASH_KEY_NON_EXISTENT == keytype) {
50 break;
51 } else if (intindex > UINT_MAX) {
52 php_error_docref(NULL, E_WARNING, "COM: max number %u of elements in safe array exceeded", UINT_MAX);
53 break;
54 }
55 }
56
57 /* allocate the structure */
58 bound.lLbound = 0;
59 bound.cElements = zend_hash_num_elements(Z_ARRVAL_P(z));
60 sa = SafeArrayCreate(VT_VARIANT, 1, &bound);
61
62 /* get a lock on the array itself */
63 SafeArrayAccessData(sa, &va);
64 va = (VARIANT*)sa->pvData;
65
66 /* now fill it in */
69 if (NULL == (item = zend_hash_get_current_data_ex(Z_ARRVAL_P(z), &pos))) {
70 break;
71 }
72 zend_hash_get_current_key_ex(Z_ARRVAL_P(z), &strindex, &intindex, &pos);
73 if (intindex < bound.cElements) {
74 php_com_variant_from_zval(&va[intindex], item, codepage);
75 }
76 }
77
78 /* Unlock it and stuff it into our variant */
79 SafeArrayUnaccessData(sa);
80 V_VT(v) = VT_ARRAY|VT_VARIANT;
81 V_ARRAY(v) = sa;
82
83 return;
84
85bogus:
86 php_error_docref(NULL, E_WARNING, "COM: converting from PHP array to VARIANT array; only arrays with numeric keys are allowed");
87
88 V_VT(v) = VT_NULL;
89
90 if (sa) {
91 SafeArrayUnlock(sa);
92 SafeArrayDestroy(sa);
93 }
94}
95
96static void php_com_variant_from_zval_ex(VARIANT *v, zval *z, int codepage, VARTYPE vt)
97{
99 uint8_t ztype = IS_NULL;
100
101 if (z) {
102 ZVAL_DEREF(z);
103 ztype = Z_TYPE_P(z);
104 }
105
106 switch (ztype) {
107 case IS_NULL:
108 V_VT(v) = VT_NULL;
109 break;
110
111 case IS_FALSE:
112 V_VT(v) = VT_BOOL;
113 V_BOOL(v) = VARIANT_FALSE;
114 break;
115
116 case IS_TRUE:
117 V_VT(v) = VT_BOOL;
118 V_BOOL(v) = VARIANT_TRUE;
119 break;
120
121 case IS_OBJECT:
122 if (php_com_is_valid_object(z)) {
123 obj = CDNO_FETCH(z);
124 if (V_VT(&obj->v) == VT_DISPATCH) {
125 /* pass the underlying object */
126 V_VT(v) = VT_DISPATCH;
127 if (V_DISPATCH(&obj->v)) {
128 IDispatch_AddRef(V_DISPATCH(&obj->v));
129 }
130 V_DISPATCH(v) = V_DISPATCH(&obj->v);
131 } else {
132 /* pass the variant by reference */
133 V_VT(v) = VT_VARIANT | VT_BYREF;
134 V_VARIANTREF(v) = &obj->v;
135 }
136 } else {
137 /* export the PHP object using our COM wrapper */
138 V_VT(v) = VT_DISPATCH;
139 V_DISPATCH(v) = php_com_wrapper_export(z);
140 }
141 break;
142
143 case IS_ARRAY:
144 /* map as safe array */
145 safe_array_from_zval(v, z, codepage);
146 break;
147
148 case IS_LONG:
149 if (vt == VT_ERROR) {
150 V_VT(v) = VT_ERROR;
151 V_ERROR(v) = Z_LVAL_P(z);
152 break;
153 }
154#if SIZEOF_ZEND_LONG == 4
155 V_VT(v) = VT_I4;
156 V_I4(v) = Z_LVAL_P(z);
157#else
158 V_VT(v) = VT_I8;
159 V_I8(v) = Z_LVAL_P(z);
160#endif
161 break;
162
163 case IS_DOUBLE:
164 V_VT(v) = VT_R8;
165 V_R8(v) = Z_DVAL_P(z);
166 break;
167
168 case IS_STRING:
169 V_VT(v) = VT_BSTR;
170 V_BSTR(v) = php_com_string_to_bstr(Z_STR_P(z), codepage);
171 break;
172
173 case IS_RESOURCE:
174 case IS_CONSTANT_AST:
175 default:
176 V_VT(v) = VT_NULL;
177 break;
178 }
179}
180
181PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage)
182{
183 php_com_variant_from_zval_ex(v, z, codepage, VT_EMPTY);
184}
185
187{
188 OLECHAR *olestring = NULL;
190
191 switch (V_VT(v)) {
192 case VT_EMPTY:
193 case VT_NULL:
194 case VT_VOID:
195 ZVAL_NULL(z);
196 break;
197 case VT_UI1:
198 ZVAL_LONG(z, (zend_long)V_UI1(v));
199 break;
200 case VT_I1:
201 ZVAL_LONG(z, (zend_long)V_I1(v));
202 break;
203 case VT_UI2:
204 ZVAL_LONG(z, (zend_long)V_UI2(v));
205 break;
206 case VT_I2:
207 ZVAL_LONG(z, (zend_long)V_I2(v));
208 break;
209 case VT_UI4: /* TODO: promote to double if large? */
210 ZVAL_LONG(z, (long)V_UI4(v));
211 break;
212 case VT_I4:
213 ZVAL_LONG(z, (long)V_I4(v));
214 break;
215#if SIZEOF_ZEND_LONG == 8
216 case VT_UI8:
217 ZVAL_LONG(z, (zend_long)V_UI8(v));
218 break;
219 case VT_I8:
220 ZVAL_LONG(z, (zend_long)V_I8(v));
221 break;
222#endif
223 case VT_INT:
224 ZVAL_LONG(z, V_INT(v));
225 break;
226 case VT_UINT: /* TODO: promote to double if large? */
227 ZVAL_LONG(z, (zend_long)V_UINT(v));
228 break;
229 case VT_R4:
230 ZVAL_DOUBLE(z, (double)V_R4(v));
231 break;
232 case VT_R8:
233 ZVAL_DOUBLE(z, V_R8(v));
234 break;
235 case VT_BOOL:
236 ZVAL_BOOL(z, V_BOOL(v) ? 1 : 0);
237 break;
238 case VT_BSTR:
239 olestring = V_BSTR(v);
240 if (olestring) {
241 zend_string *str = php_com_bstr_to_string(olestring, codepage);
242 ZVAL_STR(z, str);
243 olestring = NULL;
244 }
245 break;
246 case VT_UNKNOWN:
247 if (V_UNKNOWN(v) != NULL) {
248 IDispatch *disp;
249
250 if (SUCCEEDED(IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IDispatch, &disp))) {
251 php_com_wrap_dispatch(z, disp, codepage);
252 IDispatch_Release(disp);
253 } else {
254 ret = FAILURE;
255 }
256 }
257 break;
258
259 case VT_DISPATCH:
260 if (V_DISPATCH(v) != NULL) {
261 php_com_wrap_dispatch(z, V_DISPATCH(v), codepage);
262 }
263 break;
264
265 case VT_VARIANT:
266 /* points to another variant */
267 return php_com_zval_from_variant(z, V_VARIANTREF(v), codepage);
268
269 default:
270 php_com_wrap_variant(z, v, codepage);
271 }
272
273 if (olestring) {
274 efree(olestring);
275 }
276
277 if (ret == FAILURE) {
278 php_error_docref(NULL, E_WARNING, "variant->zval: conversion from 0x%x ret=%d", V_VT(v), ret);
279 }
280
281 return ret;
282}
283
284
285PHP_COM_DOTNET_API zend_result php_com_copy_variant(VARIANT *dstvar, VARIANT *srcvar)
286{
288
289 switch (V_VT(dstvar) & ~VT_BYREF) {
290 case VT_EMPTY:
291 case VT_NULL:
292 case VT_VOID:
293 /* should not be possible */
294 break;
295
296 case VT_UI1:
297 if (V_VT(dstvar) & VT_BYREF) {
298 *V_UI1REF(dstvar) = V_UI1(srcvar);
299 } else {
300 V_UI1(dstvar) = V_UI1(srcvar);
301 }
302 break;
303
304 case VT_I1:
305 if (V_VT(dstvar) & VT_BYREF) {
306 *V_I1REF(dstvar) = V_I1(srcvar);
307 } else {
308 V_I1(dstvar) = V_I1(srcvar);
309 }
310 break;
311
312 case VT_UI2:
313 if (V_VT(dstvar) & VT_BYREF) {
314 *V_UI2REF(dstvar) = V_UI2(srcvar);
315 } else {
316 V_UI2(dstvar) = V_UI2(srcvar);
317 }
318 break;
319
320 case VT_I2:
321 if (V_VT(dstvar) & VT_BYREF) {
322 *V_I2REF(dstvar) = V_I2(srcvar);
323 } else {
324 V_I2(dstvar) = V_I2(srcvar);
325 }
326 break;
327
328 case VT_UI4:
329 if (V_VT(dstvar) & VT_BYREF) {
330 *V_UI4REF(dstvar) = V_UI4(srcvar);
331 } else {
332 V_UI4(dstvar) = V_UI4(srcvar);
333 }
334 break;
335
336 case VT_I4:
337 if (V_VT(dstvar) & VT_BYREF) {
338 *V_I4REF(dstvar) = V_I4(srcvar);
339 } else {
340 V_I4(dstvar) = V_I4(srcvar);
341 }
342 break;
343#if SIZEOF_ZEND_LONG == 8
344 case VT_UI8:
345 if (V_VT(dstvar) & VT_BYREF) {
346 *V_UI8REF(dstvar) = V_UI8(srcvar);
347 } else {
348 V_UI8(dstvar) = V_UI8(srcvar);
349 }
350 break;
351
352 case VT_I8:
353 if (V_VT(dstvar) & VT_BYREF) {
354 *V_I8REF(dstvar) = V_I8(srcvar);
355 } else {
356 V_I8(dstvar) = V_I8(srcvar);
357 }
358 break;
359#endif
360 case VT_INT:
361 if (V_VT(dstvar) & VT_BYREF) {
362 *V_INTREF(dstvar) = V_INT(srcvar);
363 } else {
364 V_INT(dstvar) = V_INT(srcvar);
365 }
366 break;
367
368 case VT_UINT:
369 if (V_VT(dstvar) & VT_BYREF) {
370 *V_UINTREF(dstvar) = V_UINT(srcvar);
371 } else {
372 V_UINT(dstvar) = V_UINT(srcvar);
373 }
374 break;
375
376 case VT_R4:
377 if (V_VT(dstvar) & VT_BYREF) {
378 *V_R4REF(dstvar) = V_R4(srcvar);
379 } else {
380 V_R4(dstvar) = V_R4(srcvar);
381 }
382 break;
383
384 case VT_R8:
385 if (V_VT(dstvar) & VT_BYREF) {
386 *V_R8REF(dstvar) = V_R8(srcvar);
387 } else {
388 V_R8(dstvar) = V_R8(srcvar);
389 }
390 break;
391
392 case VT_BOOL:
393 if (V_VT(dstvar) & VT_BYREF) {
394 *V_BOOLREF(dstvar) = V_BOOL(srcvar);
395 } else {
396 V_BOOL(dstvar) = V_BOOL(srcvar);
397 }
398 break;
399
400 case VT_BSTR:
401 if (V_VT(dstvar) & VT_BYREF) {
402 *V_BSTRREF(dstvar) = V_BSTR(srcvar);
403 } else {
404 V_BSTR(dstvar) = V_BSTR(srcvar);
405 }
406 break;
407
408 case VT_UNKNOWN:
409 if (V_VT(dstvar) & VT_BYREF) {
410 *V_UNKNOWNREF(dstvar) = V_UNKNOWN(srcvar);
411 } else {
412 V_UNKNOWN(dstvar) = V_UNKNOWN(srcvar);
413 }
414 break;
415
416 case VT_DISPATCH:
417 if (V_VT(dstvar) & VT_BYREF) {
418 *V_DISPATCHREF(dstvar) = V_DISPATCH(srcvar);
419 } else {
420 V_DISPATCH(dstvar) = V_DISPATCH(srcvar);
421 }
422 break;
423
424 case VT_VARIANT:
425 return php_com_copy_variant(V_VARIANTREF(dstvar), srcvar);
426
427 default:
428 php_error_docref(NULL, E_WARNING, "variant->__construct: failed to copy from 0x%x to 0x%x", V_VT(dstvar), V_VT(srcvar));
429 ret = FAILURE;
430 }
431 return ret;
432}
433
434/* {{{ com_variant_create_instance - ctor for new VARIANT() */
435PHP_METHOD(variant, __construct)
436{
437 /* VARTYPE == unsigned short */ zend_long vt = VT_EMPTY;
438 zend_long codepage = CP_ACP;
439 zval *object = ZEND_THIS;
441 zval *zvalue = NULL;
442 HRESULT res;
443
444 if (ZEND_NUM_ARGS() == 0) {
445 /* just leave things as-is - an empty variant */
446 return;
447 }
448
450 "z!|ll", &zvalue, &vt, &codepage)) {
452 }
453
455 obj = CDNO_FETCH(object);
456
457 if (ZEND_NUM_ARGS() == 3) {
458 obj->code_page = (int)codepage;
459 }
460
461 if (zvalue) {
462 php_com_variant_from_zval_ex(&obj->v, zvalue, obj->code_page, vt);
463 }
464
465 /* Only perform conversion if variant not already of type passed */
466 if ((ZEND_NUM_ARGS() >= 2) && (vt != V_VT(&obj->v))) {
467
468 /* If already an array and VT_ARRAY is passed then:
469 - if only VT_ARRAY passed then do not perform a conversion
470 - if VT_ARRAY plus other type passed then perform conversion
471 but will probably fail (original behavior)
472 */
473 if ((vt & VT_ARRAY) && (V_VT(&obj->v) & VT_ARRAY)) {
474 zend_long orig_vt = vt;
475
476 vt &= ~VT_ARRAY;
477 if (vt) {
478 vt = orig_vt;
479 }
480 }
481
482 if (vt) {
483 res = VariantChangeType(&obj->v, &obj->v, 0, (VARTYPE)vt);
484
485 if (FAILED(res)) {
486 char *werr, *msg;
487
489 spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
491
493 efree(msg);
494 }
495 }
496 }
497
498 if (V_VT(&obj->v) != VT_DISPATCH && obj->typeinfo) {
499 ITypeInfo_Release(obj->typeinfo);
500 obj->typeinfo = NULL;
501 }
502}
503/* }}} */
504
505/* {{{ Assigns a new value for a variant object */
507{
508 zval *zobj, *zvalue = NULL;
510
512 "Oz!", &zobj, php_com_variant_class_entry, &zvalue)) {
514 }
515
516 obj = CDNO_FETCH(zobj);
517
518 /* dtor the old value */
519 if (obj->typeinfo) {
520 ITypeInfo_Release(obj->typeinfo);
521 obj->typeinfo = NULL;
522 }
523 if (obj->sink_dispatch) {
524 php_com_object_enable_event_sink(obj, /* enable */ false);
525 IDispatch_Release(obj->sink_dispatch);
526 obj->sink_dispatch = NULL;
527 }
528
529 VariantClear(&obj->v);
530
531 php_com_variant_from_zval(&obj->v, zvalue, obj->code_page);
532 /* remember we modified this variant */
533 obj->modified = 1;
534}
535/* }}} */
536
542
546
547static void variant_binary_operation(enum variant_binary_opcode op, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
548{
549 VARIANT vres;
550 VARIANT left_val, right_val;
551 VARIANT *vleft = NULL, *vright = NULL;
552 zval *zleft = NULL, *zright = NULL;
554 HRESULT result;
555 int codepage = CP_ACP;
556
557 VariantInit(&left_val);
558 VariantInit(&right_val);
559 VariantInit(&vres);
560
563 &zright, php_com_variant_class_entry)) {
564 obj = CDNO_FETCH(zleft);
565 vleft = &obj->v;
566 obj = CDNO_FETCH(zright);
567 vright = &obj->v;
570 &zright)) {
571 obj = CDNO_FETCH(zleft);
572 vleft = &obj->v;
573 vright = &right_val;
574 php_com_variant_from_zval(vright, zright, codepage);
576 ZEND_NUM_ARGS(), "z!O", &zleft, &zright, php_com_variant_class_entry)) {
577 obj = CDNO_FETCH(zright);
578 vright = &obj->v;
579 vleft = &left_val;
580 php_com_variant_from_zval(vleft, zleft, codepage);
582 "z!z!", &zleft, &zright)) {
583
584 vleft = &left_val;
585 php_com_variant_from_zval(vleft, zleft, codepage);
586
587 vright = &right_val;
588 php_com_variant_from_zval(vright, zright, codepage);
589
590 } else {
592 }
593
594 switch (op) {
595 case VOP_ADD:
596 result = VarAdd(vleft, vright, &vres);
597 break;
598 case VOP_CAT:
599 result = VarCat(vleft, vright, &vres);
600 break;
601 case VOP_SUB:
602 result = VarSub(vleft, vright, &vres);
603 break;
604 case VOP_MUL:
605 result = VarMul(vleft, vright, &vres);
606 break;
607 case VOP_AND:
608 result = VarAnd(vleft, vright, &vres);
609 break;
610 case VOP_DIV:
611 result = VarDiv(vleft, vright, &vres);
612 break;
613 case VOP_EQV:
614 result = VarEqv(vleft, vright, &vres);
615 break;
616 case VOP_IDIV:
617 result = VarIdiv(vleft, vright, &vres);
618 break;
619 case VOP_IMP:
620 result = VarImp(vleft, vright, &vres);
621 break;
622 case VOP_MOD:
623 result = VarMod(vleft, vright, &vres);
624 break;
625 case VOP_OR:
626 result = VarOr(vleft, vright, &vres);
627 break;
628 case VOP_POW:
629 result = VarPow(vleft, vright, &vres);
630 break;
631 case VOP_XOR:
632 result = VarXor(vleft, vright, &vres);
633 break;
634 /*Let say it fails as no valid op has been given */
635 default:
636 result = E_INVALIDARG;
637 }
638
639 if (SUCCEEDED(result)) {
640 php_com_wrap_variant(return_value, &vres, codepage);
641 } else {
643 }
644
645 VariantClear(&vres);
646 VariantClear(&left_val);
647 VariantClear(&right_val);
648}
649/* }}} */
650
651/* {{{ "Adds" two variant values together and returns the result */
653{
654 variant_binary_operation(VOP_ADD, INTERNAL_FUNCTION_PARAM_PASSTHRU);
655}
656/* }}} */
657
658/* {{{ concatenates two variant values together and returns the result */
660{
661 variant_binary_operation(VOP_CAT, INTERNAL_FUNCTION_PARAM_PASSTHRU);
662}
663/* }}} */
664
665/* {{{ subtracts the value of the right variant from the left variant value and returns the result */
667{
668 variant_binary_operation(VOP_SUB, INTERNAL_FUNCTION_PARAM_PASSTHRU);
669}
670/* }}} */
671
672/* {{{ multiplies the values of the two variants and returns the result */
674{
675 variant_binary_operation(VOP_MUL, INTERNAL_FUNCTION_PARAM_PASSTHRU);
676}
677/* }}} */
678
679/* {{{ performs a bitwise AND operation between two variants and returns the result */
681{
682 variant_binary_operation(VOP_AND, INTERNAL_FUNCTION_PARAM_PASSTHRU);
683}
684/* }}} */
685
686/* {{{ Returns the result from dividing two variants */
688{
689 variant_binary_operation(VOP_DIV, INTERNAL_FUNCTION_PARAM_PASSTHRU);
690}
691/* }}} */
692
693/* {{{ Performs a bitwise equivalence on two variants */
695{
696 variant_binary_operation(VOP_EQV, INTERNAL_FUNCTION_PARAM_PASSTHRU);
697}
698/* }}} */
699
700/* {{{ Converts variants to integers and then returns the result from dividing them */
702{
703 variant_binary_operation(VOP_IDIV, INTERNAL_FUNCTION_PARAM_PASSTHRU);
704}
705/* }}} */
706
707/* {{{ Performs a bitwise implication on two variants */
709{
710 variant_binary_operation(VOP_IMP, INTERNAL_FUNCTION_PARAM_PASSTHRU);
711}
712/* }}} */
713
714/* {{{ Divides two variants and returns only the remainder */
716{
717 variant_binary_operation(VOP_MOD, INTERNAL_FUNCTION_PARAM_PASSTHRU);
718}
719/* }}} */
720
721/* {{{ Performs a logical disjunction on two variants */
723{
724 variant_binary_operation(VOP_OR, INTERNAL_FUNCTION_PARAM_PASSTHRU);
725}
726/* }}} */
727
728/* {{{ Returns the result of performing the power function with two variants */
730{
731 variant_binary_operation(VOP_POW, INTERNAL_FUNCTION_PARAM_PASSTHRU);
732}
733/* }}} */
734
735/* {{{ Performs a logical exclusion on two variants */
737{
738 variant_binary_operation(VOP_XOR, INTERNAL_FUNCTION_PARAM_PASSTHRU);
739}
740/* }}} */
741
742static void variant_unary_operation(enum variant_unary_opcode op, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */
743{
744 VARIANT vres;
745 VARIANT left_val;
746 VARIANT *vleft = NULL;
747 zval *zleft = NULL;
749 HRESULT result;
750 int codepage = CP_ACP;
751
752 VariantInit(&left_val);
753 VariantInit(&vres);
754
757 obj = CDNO_FETCH(zleft);
758 vleft = &obj->v;
760 "z!", &zleft)) {
761 vleft = &left_val;
762 php_com_variant_from_zval(vleft, zleft, codepage);
763 } else {
765 }
766
767 switch (op) {
768 case VOP_ABS:
769 result = VarAbs(vleft, &vres);
770 break;
771 case VOP_FIX:
772 result = VarFix(vleft, &vres);
773 break;
774 case VOP_INT:
775 result = VarInt(vleft, &vres);
776 break;
777 case VOP_NEG:
778 result = VarNeg(vleft, &vres);
779 break;
780 case VOP_NOT:
781 result = VarNot(vleft, &vres);
782 break;
783 default:
784 result = E_INVALIDARG;
785 }
786
787 if (SUCCEEDED(result)) {
788 php_com_wrap_variant(return_value, &vres, codepage);
789 } else {
791 }
792
793 VariantClear(&vres);
794 VariantClear(&left_val);
795}
796/* }}} */
797
798/* {{{ Returns the absolute value of a variant */
800{
801 variant_unary_operation(VOP_ABS, INTERNAL_FUNCTION_PARAM_PASSTHRU);
802}
803/* }}} */
804
805/* {{{ Returns the integer part ? of a variant */
807{
808 variant_unary_operation(VOP_FIX, INTERNAL_FUNCTION_PARAM_PASSTHRU);
809}
810/* }}} */
811
812/* {{{ Returns the integer portion of a variant */
814{
815 variant_unary_operation(VOP_INT, INTERNAL_FUNCTION_PARAM_PASSTHRU);
816}
817/* }}} */
818
819/* {{{ Performs logical negation on a variant */
821{
822 variant_unary_operation(VOP_NEG, INTERNAL_FUNCTION_PARAM_PASSTHRU);
823}
824/* }}} */
825
826/* {{{ Performs bitwise not negation on a variant */
828{
829 variant_unary_operation(VOP_NOT, INTERNAL_FUNCTION_PARAM_PASSTHRU);
830}
831/* }}} */
832
833/* {{{ Rounds a variant to the specified number of decimal places */
835{
836 VARIANT vres;
837 VARIANT left_val;
838 VARIANT *vleft = NULL;
839 zval *zleft = NULL;
841 int codepage = CP_ACP;
842 zend_long decimals = 0;
843
844 VariantInit(&left_val);
845 VariantInit(&vres);
846
848 ZEND_NUM_ARGS(), "Ol", &zleft, php_com_variant_class_entry, &decimals)) {
849 obj = CDNO_FETCH(zleft);
850 vleft = &obj->v;
852 "z!l", &zleft, &decimals)) {
853 vleft = &left_val;
854 php_com_variant_from_zval(vleft, zleft, codepage);
855 } else {
857 }
858
859 if (SUCCEEDED(VarRound(vleft, (int)decimals, &vres))) {
860 php_com_wrap_variant(return_value, &vres, codepage);
861 }
862
863 VariantClear(&vres);
864 VariantClear(&left_val);
865}
866/* }}} */
867
868/* {{{ Compares two variants */
870{
871 VARIANT left_val, right_val;
872 VARIANT *vleft = NULL, *vright = NULL;
873 zval *zleft = NULL, *zright = NULL;
875 int codepage = CP_ACP;
877 zend_long flags = 0;
878 /* it is safe to ignore the warning for this line; see the comments in com_handlers.c */
879 STDAPI VarCmp(LPVARIANT pvarLeft, LPVARIANT pvarRight, LCID lcid, DWORD flags);
880
881 VariantInit(&left_val);
882 VariantInit(&right_val);
883
885 ZEND_NUM_ARGS(), "OO|ll", &zleft, php_com_variant_class_entry,
886 &zright, php_com_variant_class_entry, &lcid, &flags)) {
887 obj = CDNO_FETCH(zleft);
888 vleft = &obj->v;
889 obj = CDNO_FETCH(zright);
890 vright = &obj->v;
892 ZEND_NUM_ARGS(), "Oz!|ll", &zleft, php_com_variant_class_entry,
893 &zright, &lcid, &flags)) {
894 obj = CDNO_FETCH(zleft);
895 vleft = &obj->v;
896 vright = &right_val;
897 php_com_variant_from_zval(vright, zright, codepage);
899 ZEND_NUM_ARGS(), "z!O|ll", &zleft, &zright, php_com_variant_class_entry,
900 &lcid, &flags)) {
901 obj = CDNO_FETCH(zright);
902 vright = &obj->v;
903 vleft = &left_val;
904 php_com_variant_from_zval(vleft, zleft, codepage);
906 "z!z!|ll", &zleft, &zright, &lcid, &flags)) {
907
908 vleft = &left_val;
909 php_com_variant_from_zval(vleft, zleft, codepage);
910
911 vright = &right_val;
912 php_com_variant_from_zval(vright, zright, codepage);
913
914 } else {
916 }
917
918 ZVAL_LONG(return_value, VarCmp(vleft, vright, (LCID)lcid, (ULONG)flags));
919
920 VariantClear(&left_val);
921 VariantClear(&right_val);
922}
923/* }}} */
924
925/* {{{ Converts a variant date/time value to unix timestamp */
927{
928 VARIANT vres;
929 zval *zleft = NULL;
931
932 VariantInit(&vres);
933
935 "O", &zleft, php_com_variant_class_entry)) {
937 }
938 obj = CDNO_FETCH(zleft);
939
940 if (SUCCEEDED(VariantChangeType(&vres, &obj->v, 0, VT_DATE))) {
941 SYSTEMTIME systime;
942 struct tm tmv;
943
944 VariantTimeToSystemTime(V_DATE(&vres), &systime);
945
946 memset(&tmv, 0, sizeof(tmv));
947 tmv.tm_year = systime.wYear - 1900;
948 tmv.tm_mon = systime.wMonth - 1;
949 tmv.tm_mday = systime.wDay;
950 tmv.tm_hour = systime.wHour;
951 tmv.tm_min = systime.wMinute;
952 tmv.tm_sec = systime.wSecond;
953 tmv.tm_isdst = -1;
954
955 tzset();
956 RETVAL_LONG(mktime(&tmv));
957 }
958
959 VariantClear(&vres);
960}
961/* }}} */
962
963/* {{{ Returns a variant date representation of a unix timestamp */
965{
966 zend_long timestamp;
967 time_t ttstamp;
968 SYSTEMTIME systime;
969 struct tm *tmv;
970 VARIANT res;
971
973 &timestamp)) {
975 }
976
977 if (timestamp < 0) {
978 zend_argument_value_error(1, "must be greater than or equal to 0");
980 }
981
982 VariantInit(&res);
983 tzset();
984 ttstamp = timestamp;
985 tmv = localtime(&ttstamp);
986
987 /* Invalid after 23:59:59, December 31, 3000, UTC */
988 if (!tmv) {
989 zend_argument_value_error(1, "must not go past 23:59:59, December 31, 3000, UTC");
991 }
992
993 memset(&systime, 0, sizeof(systime));
994
995 systime.wDay = tmv->tm_mday;
996 systime.wHour = tmv->tm_hour;
997 systime.wMinute = tmv->tm_min;
998 systime.wMonth = tmv->tm_mon + 1;
999 systime.wSecond = tmv->tm_sec;
1000 systime.wYear = tmv->tm_year + 1900;
1001
1002 V_VT(&res) = VT_DATE;
1003 SystemTimeToVariantTime(&systime, &V_DATE(&res));
1004
1006
1007 VariantClear(&res);
1008}
1009/* }}} */
1010
1011/* {{{ Returns the VT_XXX type code for a variant */
1013{
1014 zval *zobj;
1016
1019 RETURN_THROWS();
1020 }
1021 obj = CDNO_FETCH(zobj);
1022
1023 RETURN_LONG(V_VT(&obj->v));
1024}
1025/* }}} */
1026
1027/* {{{ Convert a variant into another type. Variant is modified "in-place" */
1029{
1030 zval *zobj;
1032 /* VARTYPE == unsigned short */ zend_long vt;
1033 VARIANT vtmp;
1034 HRESULT res;
1035
1037 "Ol", &zobj, php_com_variant_class_entry, &vt)) {
1038 RETURN_THROWS();
1039 }
1040 obj = CDNO_FETCH(zobj);
1041
1042 if (V_VT(&obj->v) == VT_ERROR) {
1043 VariantInit(&vtmp);
1044 V_VT(&vtmp) = VT_I4;
1045 V_I4(&vtmp) = V_ERROR(&obj->v);
1046 }
1047 res = VariantChangeType(&obj->v, V_VT(&obj->v) != VT_ERROR ? &obj->v : &vtmp, 0, (VARTYPE)vt);
1048
1049 if (SUCCEEDED(res)) {
1050 if (vt != VT_DISPATCH && obj->typeinfo) {
1051 ITypeInfo_Release(obj->typeinfo);
1052 obj->typeinfo = NULL;
1053 }
1054 } else {
1055 char *werr, *msg;
1056
1058 spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
1060
1062 efree(msg);
1063 }
1064}
1065/* }}} */
1066
1067/* {{{ Convert a variant into a new variant object of another type */
1069{
1070 zval *zobj;
1072 /* VARTYPE == unsigned short */ zend_long vt;
1073 VARIANT vres;
1074 HRESULT res;
1075
1077 "Ol", &zobj, php_com_variant_class_entry, &vt)) {
1078 RETURN_THROWS();
1079 }
1080 obj = CDNO_FETCH(zobj);
1081
1082 VariantInit(&vres);
1083 if (V_VT(&obj->v) == VT_ERROR) {
1084 V_VT(&vres) = VT_I4;
1085 V_I4(&vres) = V_ERROR(&obj->v);
1086 }
1087 res = VariantChangeType(&vres, V_VT(&vres) == VT_EMPTY ? &obj->v : &vres, 0, (VARTYPE)vt);
1088
1089 if (SUCCEEDED(res)) {
1091 } else {
1092 char *werr, *msg;
1093
1095 spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
1097
1099 efree(msg);
1100 }
1101
1102 VariantClear(&vres);
1103}
1104/* }}} */
uint32_t v
Definition cdf.c:1237
zend_class_entry * php_com_variant_class_entry
const VT_BYREF
variant_imp(mixed $left, mixed $right)
const VT_UI2
variant_and(mixed $left, mixed $right)
const VT_ERROR
variant_or(mixed $left, mixed $right)
variant_neg(mixed $value)
variant_eqv(mixed $left, mixed $right)
const VT_BSTR
variant_abs(mixed $value)
variant_get_type(variant $variant)
const VT_UI4
variant_cmp(mixed $left, mixed $right, int $locale_id=LOCALE_SYSTEM_DEFAULT, int $flags=0)
variant_idiv(mixed $left, mixed $right)
const VT_DISPATCH
variant_mul(mixed $left, mixed $right)
variant_set(variant $variant, mixed $value)
variant_date_from_timestamp(int $timestamp)
variant_mod(mixed $left, mixed $right)
const VT_I2
variant_set_type(variant $variant, int $type)
variant_xor(mixed $left, mixed $right)
const CP_ACP
const VT_I1
variant_int(mixed $value)
variant_fix(mixed $value)
const VT_UI1
const LOCALE_SYSTEM_DEFAULT
variant_sub(mixed $left, mixed $right)
const VT_R4
const VT_I4
variant_pow(mixed $left, mixed $right)
variant_round(mixed $value, int $decimals)
const VT_UINT
const VT_INT
const VT_DATE
const VT_R8
const VT_NULL
const VT_VARIANT
variant_cat(mixed $left, mixed $right)
variant_add(mixed $left, mixed $right)
const VT_UNKNOWN
const VT_EMPTY
const VT_ARRAY
const VT_I8
const VT_UI8
const VT_BOOL
variant_date_to_timestamp(variant $variant)
variant_div(mixed $left, mixed $right)
variant_not(mixed $value)
variant_cast(variant $variant, int $type)
void php_com_object_enable_event_sink(php_com_dotnet_object *obj, bool enable)
PHP_COM_DOTNET_API void php_com_wrap_variant(zval *z, VARIANT *v, int codepage)
Definition com_misc.c:67
void php_com_throw_exception(HRESULT code, char *message)
Definition com_misc.c:28
PHP_COM_DOTNET_API void php_com_wrap_dispatch(zval *z, IDispatch *disp, int codepage)
Definition com_misc.c:45
zend_string * php_com_bstr_to_string(BSTR bstr, int codepage)
BSTR php_com_string_to_bstr(zend_string *string, int codepage)
VARTYPE vt
PHP_COM_DOTNET_API zend_result php_com_zval_from_variant(zval *z, VARIANT *v, int codepage)
variant_unary_opcode
@ VOP_ABS
@ VOP_NOT
@ VOP_NEG
@ VOP_FIX
@ VOP_INT
PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage)
PHP_COM_DOTNET_API zend_result php_com_copy_variant(VARIANT *dstvar, VARIANT *srcvar)
variant_binary_opcode
@ VOP_XOR
@ VOP_OR
@ VOP_CAT
@ VOP_ADD
@ VOP_MOD
@ VOP_IMP
@ VOP_AND
@ VOP_MUL
@ VOP_SUB
@ VOP_DIV
@ VOP_POW
@ VOP_EQV
@ VOP_IDIV
PHP_COM_DOTNET_API IDispatch * php_com_wrapper_export(zval *val)
#define DWORD
Definition exif.c:1762
zend_string * res
Definition ffi.c:4692
memset(ptr, 0, type->size)
zend_object * ztype
Definition ffi.c:3970
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
Definition main.c:1173
PHPAPI void php_com_initialize(void)
Definition main.c:2005
#define PHP_FUNCTION
Definition php.h:364
#define PHP_METHOD
Definition php.h:365
#define PHP_COM_DOTNET_API
#define CDNO_FETCH(zv)
struct _php_com_dotnet_object php_com_dotnet_object
mktime(int $hour, ?int $minute=null, ?int $second=null, ?int $month=null, ?int $day=null, ?int $year=null)
localtime(?int $timestamp=null, bool $associative=false)
unsigned const char * pos
Definition php_ffi.h:52
char * msg
Definition phpdbg.h:289
#define spprintf
Definition spprintf.h:29
PHP_WINUTIL_API char * php_win32_error_to_msg(HRESULT error)
Definition winutil.c:25
PHP_WINUTIL_API void php_win32_error_msg_free(char *msg)
Definition winutil.c:50
#define INTERNAL_FUNCTION_PARAMETERS
Definition zend.h:49
#define INTERNAL_FUNCTION_PARAM_PASSTHRU
Definition zend.h:50
ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1300
ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:433
ZEND_API zend_result zend_parse_parameters_ex(int flags, uint32_t num_args, const char *type_spec,...)
Definition zend_API.c:1287
#define ZEND_NUM_ARGS()
Definition zend_API.h:530
#define ZEND_PARSE_PARAMS_QUIET
Definition zend_API.h:361
#define RETURN_LONG(l)
Definition zend_API.h:1037
#define RETURN_THROWS()
Definition zend_API.h:1060
#define ZEND_THIS
Definition zend_API.h:523
#define RETVAL_LONG(l)
Definition zend_API.h:1011
#define efree(ptr)
Definition zend_alloc.h:155
struct _zval_struct zval
#define E_WARNING
Definition zend_errors.h:24
ZEND_API zend_result ZEND_FASTCALL zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos)
Definition zend_hash.c:2773
ZEND_API int ZEND_FASTCALL zend_hash_get_current_key_ex(const HashTable *ht, zend_string **str_index, zend_ulong *num_index, const HashPosition *pos)
Definition zend_hash.c:2846
ZEND_API void ZEND_FASTCALL zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos)
Definition zend_hash.c:2733
ZEND_API zval *ZEND_FASTCALL zend_hash_get_current_data_ex(HashTable *ht, HashPosition *pos)
Definition zend_hash.c:2915
#define HASH_KEY_NON_EXISTENT
Definition zend_hash.h:31
#define HASH_KEY_IS_STRING
Definition zend_hash.h:29
int32_t zend_long
Definition zend_long.h:42
uint32_t zend_ulong
Definition zend_long.h:43
struct _zend_string zend_string
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define IS_TRUE
Definition zend_types.h:603
#define ZVAL_STR(z, s)
#define IS_FALSE
Definition zend_types.h:602
#define Z_ARRVAL_P(zval_p)
Definition zend_types.h:987
#define ZVAL_NULL(z)
#define ZVAL_DEREF(z)
#define ZVAL_LONG(z, l)
#define IS_STRING
Definition zend_types.h:606
#define IS_RESOURCE
Definition zend_types.h:609
#define IS_ARRAY
Definition zend_types.h:607
#define IS_DOUBLE
Definition zend_types.h:605
#define Z_STR_P(zval_p)
Definition zend_types.h:972
#define IS_NULL
Definition zend_types.h:601
@ FAILURE
Definition zend_types.h:61
#define IS_OBJECT
Definition zend_types.h:608
#define IS_LONG
Definition zend_types.h:604
uint32_t HashPosition
Definition zend_types.h:548
#define ZVAL_DOUBLE(z, d)
ZEND_RESULT_CODE zend_result
Definition zend_types.h:64
#define IS_CONSTANT_AST
Definition zend_types.h:611
#define Z_DVAL_P(zval_p)
Definition zend_types.h:969
#define Z_LVAL_P(zval_p)
Definition zend_types.h:966
#define ZVAL_BOOL(z, b)
zval * return_value
bool result
zval * ret
zend_object * zobj