This source file includes following definitions.
- safe_array_from_zval
- php_com_variant_from_zval
- php_com_zval_from_variant
- php_com_copy_variant
- PHP_FUNCTION
- PHP_FUNCTION
- variant_binary_operation
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- variant_unary_operation
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "php.h"
26 #include "php_ini.h"
27 #include "ext/standard/info.h"
28 #include "php_com_dotnet.h"
29 #include "php_com_dotnet_internal.h"
30
31
32
33
34
35 static void safe_array_from_zval(VARIANT *v, zval *z, int codepage)
36 {
37 SAFEARRAY *sa = NULL;
38 SAFEARRAYBOUND bound;
39 HashPosition pos;
40 int keytype;
41 zend_string *strindex;
42 zend_ulong intindex = 0;
43 VARIANT *va;
44 zval *item;
45
46
47 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(z), &pos);
48 for (;; zend_hash_move_forward_ex(Z_ARRVAL_P(z), &pos)) {
49
50 keytype = zend_hash_get_current_key_ex(Z_ARRVAL_P(z), &strindex, &intindex, &pos);
51
52 if (HASH_KEY_IS_STRING == keytype) {
53 goto bogus;
54 } else if (HASH_KEY_NON_EXISTENT == keytype) {
55 break;
56 } else if (intindex > UINT_MAX) {
57 php_error_docref(NULL, E_WARNING, "COM: max number %u of elements in safe array exceeded", UINT_MAX);
58 break;
59 }
60 }
61
62
63 bound.lLbound = 0;
64 bound.cElements = zend_hash_num_elements(Z_ARRVAL_P(z));
65 sa = SafeArrayCreate(VT_VARIANT, 1, &bound);
66
67
68 SafeArrayAccessData(sa, &va);
69 va = (VARIANT*)sa->pvData;
70
71
72 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(z), &pos);
73 for (;; zend_hash_move_forward_ex(Z_ARRVAL_P(z), &pos)) {
74 if (NULL == (item = zend_hash_get_current_data_ex(Z_ARRVAL_P(z), &pos))) {
75 break;
76 }
77 zend_hash_get_current_key_ex(Z_ARRVAL_P(z), &strindex, &intindex, &pos);
78 php_com_variant_from_zval(&va[intindex], item, codepage);
79 }
80
81
82 SafeArrayUnaccessData(sa);
83 V_VT(v) = VT_ARRAY|VT_VARIANT;
84 V_ARRAY(v) = sa;
85
86 return;
87
88 bogus:
89 php_error_docref(NULL, E_WARNING, "COM: converting from PHP array to VARIANT array; only arrays with numeric keys are allowed");
90
91 V_VT(v) = VT_NULL;
92
93 if (sa) {
94 SafeArrayUnlock(sa);
95 SafeArrayDestroy(sa);
96 }
97 }
98
99 PHP_COM_DOTNET_API void php_com_variant_from_zval(VARIANT *v, zval *z, int codepage)
100 {
101 OLECHAR *olestring;
102 php_com_dotnet_object *obj;
103 zend_uchar ztype = (z == NULL ? IS_NULL : Z_TYPE_P(z));
104
105 switch (ztype) {
106 case IS_NULL:
107 V_VT(v) = VT_NULL;
108 break;
109
110 case IS_FALSE:
111 V_VT(v) = VT_BOOL;
112 V_BOOL(v) = VARIANT_FALSE;
113 break;
114
115 case IS_TRUE:
116 V_VT(v) = VT_BOOL;
117 V_BOOL(v) = VARIANT_TRUE;
118 break;
119
120 case IS_OBJECT:
121 if (php_com_is_valid_object(z)) {
122 obj = CDNO_FETCH(z);
123 if (V_VT(&obj->v) == VT_DISPATCH) {
124
125 V_VT(v) = VT_DISPATCH;
126 if (V_DISPATCH(&obj->v)) {
127 IDispatch_AddRef(V_DISPATCH(&obj->v));
128 }
129 V_DISPATCH(v) = V_DISPATCH(&obj->v);
130 } else {
131
132 V_VT(v) = VT_VARIANT | VT_BYREF;
133 V_VARIANTREF(v) = &obj->v;
134 }
135 } else {
136
137 V_VT(v) = VT_DISPATCH;
138 V_DISPATCH(v) = php_com_wrapper_export(z);
139 }
140 break;
141
142 case IS_ARRAY:
143
144 safe_array_from_zval(v, z, codepage);
145 break;
146
147 case IS_LONG:
148 #if SIZEOF_ZEND_LONG == 4
149 V_VT(v) = VT_I4;
150 V_I4(v) = Z_LVAL_P(z);
151 #else
152 V_VT(v) = VT_I8;
153 V_I8(v) = Z_LVAL_P(z);
154 #endif
155 break;
156
157 case IS_DOUBLE:
158 V_VT(v) = VT_R8;
159 V_R8(v) = Z_DVAL_P(z);
160 break;
161
162 case IS_STRING:
163 V_VT(v) = VT_BSTR;
164 olestring = php_com_string_to_olestring(Z_STRVAL_P(z), Z_STRLEN_P(z), codepage);
165 if (CP_UTF8 == codepage) {
166 V_BSTR(v) = SysAllocStringByteLen((char*)olestring, (UINT)(wcslen(olestring) * sizeof(OLECHAR)));
167 } else {
168 V_BSTR(v) = SysAllocStringByteLen((char*)olestring, (UINT)(Z_STRLEN_P(z) * sizeof(OLECHAR)));
169 }
170 efree(olestring);
171 break;
172
173 case IS_RESOURCE:
174 case IS_CONSTANT:
175 case IS_CONSTANT_AST:
176 default:
177 V_VT(v) = VT_NULL;
178 break;
179 }
180 }
181
182 PHP_COM_DOTNET_API int php_com_zval_from_variant(zval *z, VARIANT *v, int codepage)
183 {
184 OLECHAR *olestring = NULL;
185 int ret = SUCCESS;
186
187 switch (V_VT(v)) {
188 case VT_EMPTY:
189 case VT_NULL:
190 case VT_VOID:
191 ZVAL_NULL(z);
192 break;
193 case VT_UI1:
194 ZVAL_LONG(z, (zend_long)V_UI1(v));
195 break;
196 case VT_I1:
197 ZVAL_LONG(z, (zend_long)V_I1(v));
198 break;
199 case VT_UI2:
200 ZVAL_LONG(z, (zend_long)V_UI2(v));
201 break;
202 case VT_I2:
203 ZVAL_LONG(z, (zend_long)V_I2(v));
204 break;
205 case VT_UI4:
206 ZVAL_LONG(z, (long)V_UI4(v));
207 break;
208 case VT_I4:
209 ZVAL_LONG(z, (long)V_I4(v));
210 break;
211 #if SIZEOF_ZEND_LONG == 8
212 case VT_UI8:
213 ZVAL_LONG(z, (zend_long)V_UI8(v));
214 break;
215 case VT_I8:
216 ZVAL_LONG(z, (zend_long)V_I8(v));
217 break;
218 #endif
219 case VT_INT:
220 ZVAL_LONG(z, V_INT(v));
221 break;
222 case VT_UINT:
223 ZVAL_LONG(z, (zend_long)V_UINT(v));
224 break;
225 case VT_R4:
226 ZVAL_DOUBLE(z, (double)V_R4(v));
227 break;
228 case VT_R8:
229 ZVAL_DOUBLE(z, V_R8(v));
230 break;
231 case VT_BOOL:
232 ZVAL_BOOL(z, V_BOOL(v) ? 1 : 0);
233 break;
234 case VT_BSTR:
235 olestring = V_BSTR(v);
236 if (olestring) {
237 size_t len;
238 char *str = php_com_olestring_to_string(olestring,
239 &len, codepage);
240 ZVAL_STRINGL(z, str, len);
241
242 efree(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
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
285 PHP_COM_DOTNET_API int php_com_copy_variant(VARIANT *dstvar, VARIANT *srcvar)
286 {
287 int ret = SUCCESS;
288
289 switch (V_VT(dstvar) & ~VT_BYREF) {
290 case VT_EMPTY:
291 case VT_NULL:
292 case VT_VOID:
293
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->variant: 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
435 PHP_FUNCTION(com_variant_create_instance)
436 {
437 zend_long vt = VT_EMPTY;
438 zend_long codepage = CP_ACP;
439 zval *object = getThis();
440 php_com_dotnet_object *obj;
441 zval *zvalue = NULL;
442 HRESULT res;
443
444 if (ZEND_NUM_ARGS() == 0) {
445
446 return;
447 }
448
449 obj = CDNO_FETCH(object);
450
451 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(),
452 "z!|ll", &zvalue, &vt, &codepage)) {
453 php_com_throw_exception(E_INVALIDARG, "Invalid arguments");
454 return;
455 }
456
457 php_com_initialize();
458 if (ZEND_NUM_ARGS() == 3) {
459 obj->code_page = (int)codepage;
460 }
461
462 if (zvalue) {
463 php_com_variant_from_zval(&obj->v, zvalue, obj->code_page);
464 }
465
466
467 if ((ZEND_NUM_ARGS() >= 2) && (vt != V_VT(&obj->v))) {
468
469
470
471
472
473
474 if ((vt & VT_ARRAY) && (V_VT(&obj->v) & VT_ARRAY)) {
475 zend_long orig_vt = vt;
476
477 vt &= ~VT_ARRAY;
478 if (vt) {
479 vt = orig_vt;
480 }
481 }
482
483 if (vt) {
484 res = VariantChangeType(&obj->v, &obj->v, 0, (VARTYPE)vt);
485
486 if (FAILED(res)) {
487 char *werr, *msg;
488
489 werr = php_win32_error_to_msg(res);
490 spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
491 LocalFree(werr);
492
493 php_com_throw_exception(res, msg);
494 efree(msg);
495 }
496 }
497 }
498
499 if (V_VT(&obj->v) != VT_DISPATCH && obj->typeinfo) {
500 ITypeInfo_Release(obj->typeinfo);
501 obj->typeinfo = NULL;
502 }
503 }
504
505
506
507
508 PHP_FUNCTION(variant_set)
509 {
510 zval *zobj, *zvalue = NULL;
511 php_com_dotnet_object *obj;
512
513 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(),
514 "Oz!", &zobj, php_com_variant_class_entry, &zvalue)) {
515 return;
516 }
517
518 obj = CDNO_FETCH(zobj);
519
520
521 if (obj->typeinfo) {
522 ITypeInfo_Release(obj->typeinfo);
523 obj->typeinfo = NULL;
524 }
525 if (obj->sink_dispatch) {
526 php_com_object_enable_event_sink(obj, FALSE);
527 IDispatch_Release(obj->sink_dispatch);
528 obj->sink_dispatch = NULL;
529 }
530
531 VariantClear(&obj->v);
532
533 php_com_variant_from_zval(&obj->v, zvalue, obj->code_page);
534
535 obj->modified = 1;
536 }
537
538
539 enum variant_binary_opcode {
540 VOP_ADD, VOP_CAT, VOP_SUB, VOP_MUL, VOP_AND, VOP_DIV,
541 VOP_EQV, VOP_IDIV, VOP_IMP, VOP_MOD, VOP_OR, VOP_POW,
542 VOP_XOR
543 };
544
545 enum variant_unary_opcode {
546 VOP_ABS, VOP_FIX, VOP_INT, VOP_NEG, VOP_NOT
547 };
548
549 static void variant_binary_operation(enum variant_binary_opcode op, INTERNAL_FUNCTION_PARAMETERS)
550 {
551 VARIANT vres;
552 VARIANT left_val, right_val;
553 VARIANT *vleft = NULL, *vright = NULL;
554 zval *zleft = NULL, *zright = NULL;
555 php_com_dotnet_object *obj;
556 HRESULT result;
557 int codepage = CP_ACP;
558
559 VariantInit(&left_val);
560 VariantInit(&right_val);
561 VariantInit(&vres);
562
563 if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
564 ZEND_NUM_ARGS(), "OO", &zleft, php_com_variant_class_entry,
565 &zright, php_com_variant_class_entry)) {
566 obj = CDNO_FETCH(zleft);
567 vleft = &obj->v;
568 obj = CDNO_FETCH(zright);
569 vright = &obj->v;
570 } else if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
571 ZEND_NUM_ARGS(), "Oz!", &zleft, php_com_variant_class_entry,
572 &zright)) {
573 obj = CDNO_FETCH(zleft);
574 vleft = &obj->v;
575 vright = &right_val;
576 php_com_variant_from_zval(vright, zright, codepage);
577 } else if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
578 ZEND_NUM_ARGS(), "z!O", &zleft, &zright, php_com_variant_class_entry)) {
579 obj = CDNO_FETCH(zright);
580 vright = &obj->v;
581 vleft = &left_val;
582 php_com_variant_from_zval(vleft, zleft, codepage);
583 } else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(),
584 "z!z!", &zleft, &zright)) {
585
586 vleft = &left_val;
587 php_com_variant_from_zval(vleft, zleft, codepage);
588
589 vright = &right_val;
590 php_com_variant_from_zval(vright, zright, codepage);
591
592 } else {
593 return;
594 }
595
596 switch (op) {
597 case VOP_ADD:
598 result = VarAdd(vleft, vright, &vres);
599 break;
600 case VOP_CAT:
601 result = VarCat(vleft, vright, &vres);
602 break;
603 case VOP_SUB:
604 result = VarSub(vleft, vright, &vres);
605 break;
606 case VOP_MUL:
607 result = VarMul(vleft, vright, &vres);
608 break;
609 case VOP_AND:
610 result = VarAnd(vleft, vright, &vres);
611 break;
612 case VOP_DIV:
613 result = VarDiv(vleft, vright, &vres);
614 break;
615 case VOP_EQV:
616 result = VarEqv(vleft, vright, &vres);
617 break;
618 case VOP_IDIV:
619 result = VarIdiv(vleft, vright, &vres);
620 break;
621 case VOP_IMP:
622 result = VarImp(vleft, vright, &vres);
623 break;
624 case VOP_MOD:
625 result = VarMod(vleft, vright, &vres);
626 break;
627 case VOP_OR:
628 result = VarOr(vleft, vright, &vres);
629 break;
630 case VOP_POW:
631 result = VarPow(vleft, vright, &vres);
632 break;
633 case VOP_XOR:
634 result = VarXor(vleft, vright, &vres);
635 break;
636
637 default:
638 result = E_INVALIDARG;
639 }
640
641 if (SUCCEEDED(result)) {
642 php_com_wrap_variant(return_value, &vres, codepage);
643 } else {
644 php_com_throw_exception(result, NULL);
645 }
646
647 VariantClear(&vres);
648 VariantClear(&left_val);
649 VariantClear(&right_val);
650 }
651
652
653
654
655 PHP_FUNCTION(variant_add)
656 {
657 variant_binary_operation(VOP_ADD, INTERNAL_FUNCTION_PARAM_PASSTHRU);
658 }
659
660
661
662
663 PHP_FUNCTION(variant_cat)
664 {
665 variant_binary_operation(VOP_CAT, INTERNAL_FUNCTION_PARAM_PASSTHRU);
666 }
667
668
669
670
671 PHP_FUNCTION(variant_sub)
672 {
673 variant_binary_operation(VOP_SUB, INTERNAL_FUNCTION_PARAM_PASSTHRU);
674 }
675
676
677
678
679 PHP_FUNCTION(variant_mul)
680 {
681 variant_binary_operation(VOP_MUL, INTERNAL_FUNCTION_PARAM_PASSTHRU);
682 }
683
684
685
686
687 PHP_FUNCTION(variant_and)
688 {
689 variant_binary_operation(VOP_AND, INTERNAL_FUNCTION_PARAM_PASSTHRU);
690 }
691
692
693
694
695 PHP_FUNCTION(variant_div)
696 {
697 variant_binary_operation(VOP_DIV, INTERNAL_FUNCTION_PARAM_PASSTHRU);
698 }
699
700
701
702
703 PHP_FUNCTION(variant_eqv)
704 {
705 variant_binary_operation(VOP_EQV, INTERNAL_FUNCTION_PARAM_PASSTHRU);
706 }
707
708
709
710
711 PHP_FUNCTION(variant_idiv)
712 {
713 variant_binary_operation(VOP_IDIV, INTERNAL_FUNCTION_PARAM_PASSTHRU);
714 }
715
716
717
718
719 PHP_FUNCTION(variant_imp)
720 {
721 variant_binary_operation(VOP_IMP, INTERNAL_FUNCTION_PARAM_PASSTHRU);
722 }
723
724
725
726
727 PHP_FUNCTION(variant_mod)
728 {
729 variant_binary_operation(VOP_MOD, INTERNAL_FUNCTION_PARAM_PASSTHRU);
730 }
731
732
733
734
735 PHP_FUNCTION(variant_or)
736 {
737 variant_binary_operation(VOP_OR, INTERNAL_FUNCTION_PARAM_PASSTHRU);
738 }
739
740
741
742
743 PHP_FUNCTION(variant_pow)
744 {
745 variant_binary_operation(VOP_POW, INTERNAL_FUNCTION_PARAM_PASSTHRU);
746 }
747
748
749
750
751 PHP_FUNCTION(variant_xor)
752 {
753 variant_binary_operation(VOP_XOR, INTERNAL_FUNCTION_PARAM_PASSTHRU);
754 }
755
756
757 static void variant_unary_operation(enum variant_unary_opcode op, INTERNAL_FUNCTION_PARAMETERS)
758 {
759 VARIANT vres;
760 VARIANT left_val;
761 VARIANT *vleft = NULL;
762 zval *zleft = NULL;
763 php_com_dotnet_object *obj;
764 HRESULT result;
765 int codepage = CP_ACP;
766
767 VariantInit(&left_val);
768 VariantInit(&vres);
769
770 if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
771 ZEND_NUM_ARGS(), "O", &zleft, php_com_variant_class_entry)) {
772 obj = CDNO_FETCH(zleft);
773 vleft = &obj->v;
774 } else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(),
775 "z!", &zleft)) {
776 vleft = &left_val;
777 php_com_variant_from_zval(vleft, zleft, codepage);
778 } else {
779 return;
780 }
781
782 switch (op) {
783 case VOP_ABS:
784 result = VarAbs(vleft, &vres);
785 break;
786 case VOP_FIX:
787 result = VarFix(vleft, &vres);
788 break;
789 case VOP_INT:
790 result = VarInt(vleft, &vres);
791 break;
792 case VOP_NEG:
793 result = VarNeg(vleft, &vres);
794 break;
795 case VOP_NOT:
796 result = VarNot(vleft, &vres);
797 break;
798 default:
799 result = E_INVALIDARG;
800 }
801
802 if (SUCCEEDED(result)) {
803 php_com_wrap_variant(return_value, &vres, codepage);
804 } else {
805 php_com_throw_exception(result, NULL);
806 }
807
808 VariantClear(&vres);
809 VariantClear(&left_val);
810 }
811
812
813
814
815 PHP_FUNCTION(variant_abs)
816 {
817 variant_unary_operation(VOP_ABS, INTERNAL_FUNCTION_PARAM_PASSTHRU);
818 }
819
820
821
822
823 PHP_FUNCTION(variant_fix)
824 {
825 variant_unary_operation(VOP_FIX, INTERNAL_FUNCTION_PARAM_PASSTHRU);
826 }
827
828
829
830
831 PHP_FUNCTION(variant_int)
832 {
833 variant_unary_operation(VOP_INT, INTERNAL_FUNCTION_PARAM_PASSTHRU);
834 }
835
836
837
838
839 PHP_FUNCTION(variant_neg)
840 {
841 variant_unary_operation(VOP_NEG, INTERNAL_FUNCTION_PARAM_PASSTHRU);
842 }
843
844
845
846
847 PHP_FUNCTION(variant_not)
848 {
849 variant_unary_operation(VOP_NOT, INTERNAL_FUNCTION_PARAM_PASSTHRU);
850 }
851
852
853
854
855 PHP_FUNCTION(variant_round)
856 {
857 VARIANT vres;
858 VARIANT left_val;
859 VARIANT *vleft = NULL;
860 zval *zleft = NULL;
861 php_com_dotnet_object *obj;
862 int codepage = CP_ACP;
863 zend_long decimals = 0;
864
865 VariantInit(&left_val);
866 VariantInit(&vres);
867
868 if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
869 ZEND_NUM_ARGS(), "Ol", &zleft, php_com_variant_class_entry, &decimals)) {
870 obj = CDNO_FETCH(zleft);
871 vleft = &obj->v;
872 } else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(),
873 "z!l", &zleft, &decimals)) {
874 vleft = &left_val;
875 php_com_variant_from_zval(vleft, zleft, codepage);
876 } else {
877 return;
878 }
879
880 if (SUCCEEDED(VarRound(vleft, (int)decimals, &vres))) {
881 php_com_wrap_variant(return_value, &vres, codepage);
882 }
883
884 VariantClear(&vres);
885 VariantClear(&left_val);
886 }
887
888
889
890
891 PHP_FUNCTION(variant_cmp)
892 {
893 VARIANT left_val, right_val;
894 VARIANT *vleft = NULL, *vright = NULL;
895 zval *zleft = NULL, *zright = NULL;
896 php_com_dotnet_object *obj;
897 int codepage = CP_ACP;
898 zend_long lcid = LOCALE_SYSTEM_DEFAULT;
899 zend_long flags = 0;
900
901 STDAPI VarCmp(LPVARIANT pvarLeft, LPVARIANT pvarRight, LCID lcid, DWORD flags);
902
903 VariantInit(&left_val);
904 VariantInit(&right_val);
905
906 if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
907 ZEND_NUM_ARGS(), "OO|ll", &zleft, php_com_variant_class_entry,
908 &zright, php_com_variant_class_entry, &lcid, &flags)) {
909 obj = CDNO_FETCH(zleft);
910 vleft = &obj->v;
911 obj = CDNO_FETCH(zright);
912 vright = &obj->v;
913 } else if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
914 ZEND_NUM_ARGS(), "Oz!|ll", &zleft, php_com_variant_class_entry,
915 &zright, &lcid, &flags)) {
916 obj = CDNO_FETCH(zleft);
917 vleft = &obj->v;
918 vright = &right_val;
919 php_com_variant_from_zval(vright, zright, codepage);
920 } else if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
921 ZEND_NUM_ARGS(), "z!O|ll", &zleft, &zright, php_com_variant_class_entry,
922 &lcid, &flags)) {
923 obj = CDNO_FETCH(zright);
924 vright = &obj->v;
925 vleft = &left_val;
926 php_com_variant_from_zval(vleft, zleft, codepage);
927 } else if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(),
928 "z!z!|ll", &zleft, &zright, &lcid, &flags)) {
929
930 vleft = &left_val;
931 php_com_variant_from_zval(vleft, zleft, codepage);
932
933 vright = &right_val;
934 php_com_variant_from_zval(vright, zright, codepage);
935
936 } else {
937 return;
938 }
939
940 ZVAL_LONG(return_value, VarCmp(vleft, vright, (LCID)lcid, (ULONG)flags));
941
942 VariantClear(&left_val);
943 VariantClear(&right_val);
944 }
945
946
947
948
949 PHP_FUNCTION(variant_date_to_timestamp)
950 {
951 VARIANT vres;
952 zval *zleft = NULL;
953 php_com_dotnet_object *obj;
954
955 VariantInit(&vres);
956
957 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(),
958 "O", &zleft, php_com_variant_class_entry)) {
959 return;
960 }
961 obj = CDNO_FETCH(zleft);
962
963 if (SUCCEEDED(VariantChangeType(&vres, &obj->v, 0, VT_DATE))) {
964 SYSTEMTIME systime;
965 struct tm tmv;
966
967 VariantTimeToSystemTime(V_DATE(&vres), &systime);
968
969 memset(&tmv, 0, sizeof(tmv));
970 tmv.tm_year = systime.wYear - 1900;
971 tmv.tm_mon = systime.wMonth - 1;
972 tmv.tm_mday = systime.wDay;
973 tmv.tm_hour = systime.wHour;
974 tmv.tm_min = systime.wMinute;
975 tmv.tm_sec = systime.wSecond;
976 tmv.tm_isdst = -1;
977
978 tzset();
979 RETVAL_LONG(mktime(&tmv));
980 }
981
982 VariantClear(&vres);
983 }
984
985
986
987
988 PHP_FUNCTION(variant_date_from_timestamp)
989 {
990 zend_long timestamp;
991 time_t ttstamp;
992 SYSTEMTIME systime;
993 struct tm *tmv;
994 VARIANT res;
995
996 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "l",
997 ×tamp)) {
998 return;
999 }
1000
1001 if (timestamp < 0) {
1002 php_error_docref(NULL, E_WARNING, "Timestamp value must be a positive value.");
1003 RETURN_FALSE;
1004 }
1005
1006 VariantInit(&res);
1007 tzset();
1008 ttstamp = timestamp;
1009 tmv = localtime(&ttstamp);
1010 memset(&systime, 0, sizeof(systime));
1011
1012 systime.wDay = tmv->tm_mday;
1013 systime.wHour = tmv->tm_hour;
1014 systime.wMinute = tmv->tm_min;
1015 systime.wMonth = tmv->tm_mon + 1;
1016 systime.wSecond = tmv->tm_sec;
1017 systime.wYear = tmv->tm_year + 1900;
1018
1019 V_VT(&res) = VT_DATE;
1020 SystemTimeToVariantTime(&systime, &V_DATE(&res));
1021
1022 php_com_wrap_variant(return_value, &res, CP_ACP);
1023
1024 VariantClear(&res);
1025 }
1026
1027
1028
1029
1030 PHP_FUNCTION(variant_get_type)
1031 {
1032 zval *zobj;
1033 php_com_dotnet_object *obj;
1034
1035 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(),
1036 "O", &zobj, php_com_variant_class_entry)) {
1037 return;
1038 }
1039 obj = CDNO_FETCH(zobj);
1040
1041 RETURN_LONG(V_VT(&obj->v));
1042 }
1043
1044
1045
1046
1047 PHP_FUNCTION(variant_set_type)
1048 {
1049 zval *zobj;
1050 php_com_dotnet_object *obj;
1051 zend_long vt;
1052 HRESULT res;
1053
1054 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(),
1055 "Ol", &zobj, php_com_variant_class_entry, &vt)) {
1056 return;
1057 }
1058 obj = CDNO_FETCH(zobj);
1059
1060 res = VariantChangeType(&obj->v, &obj->v, 0, (VARTYPE)vt);
1061
1062 if (SUCCEEDED(res)) {
1063 if (vt != VT_DISPATCH && obj->typeinfo) {
1064 ITypeInfo_Release(obj->typeinfo);
1065 obj->typeinfo = NULL;
1066 }
1067 } else {
1068 char *werr, *msg;
1069
1070 werr = php_win32_error_to_msg(res);
1071 spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
1072 LocalFree(werr);
1073
1074 php_com_throw_exception(res, msg);
1075 efree(msg);
1076 }
1077 }
1078
1079
1080
1081
1082 PHP_FUNCTION(variant_cast)
1083 {
1084 zval *zobj;
1085 php_com_dotnet_object *obj;
1086 zend_long vt;
1087 VARIANT vres;
1088 HRESULT res;
1089
1090 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(),
1091 "Ol", &zobj, php_com_variant_class_entry, &vt)) {
1092 return;
1093 }
1094 obj = CDNO_FETCH(zobj);
1095
1096 VariantInit(&vres);
1097 res = VariantChangeType(&vres, &obj->v, 0, (VARTYPE)vt);
1098
1099 if (SUCCEEDED(res)) {
1100 php_com_wrap_variant(return_value, &vres, obj->code_page);
1101 } else {
1102 char *werr, *msg;
1103
1104 werr = php_win32_error_to_msg(res);
1105 spprintf(&msg, 0, "Variant type conversion failed: %s", werr);
1106 LocalFree(werr);
1107
1108 php_com_throw_exception(res, msg);
1109 efree(msg);
1110 }
1111
1112 VariantClear(&vres);
1113 }
1114
1115