xref: /PHP-7.3/ext/com_dotnet/com_olechar.c (revision a385cfa7)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2018 The PHP Group                                |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Author: Wez Furlong <wez@thebrainroom.com>                           |
16    |         Harald Radi <h.radi@nme.at>                                  |
17    +----------------------------------------------------------------------+
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include "php.h"
25 #include "php_ini.h"
26 #include "ext/standard/info.h"
27 #include "php_com_dotnet.h"
28 #include "php_com_dotnet_internal.h"
29 
30 
php_com_string_to_olestring(char * string,size_t string_len,int codepage)31 PHP_COM_DOTNET_API OLECHAR *php_com_string_to_olestring(char *string, size_t string_len, int codepage)
32 {
33 	OLECHAR *olestring = NULL;
34 	DWORD flags = codepage == CP_UTF8 ? 0 : MB_PRECOMPOSED | MB_ERR_INVALID_CHARS;
35 	BOOL ok;
36 
37 	if (string_len == -1) {
38 		/* determine required length for the buffer (includes NUL terminator) */
39 		string_len = MultiByteToWideChar(codepage, flags, string, -1, NULL, 0);
40 	} else {
41 		/* allow room for NUL terminator */
42 		string_len++;
43 	}
44 
45 	if (string_len > 0) {
46 		olestring = (OLECHAR*)safe_emalloc(string_len, sizeof(OLECHAR), 0);
47 		/* XXX if that's a real multibyte string, olestring is obviously allocated excessively.
48 		This should be fixed by reallocating the olestring, but as emalloc is used, that doesn't
49 		matter much. */
50 		ok = MultiByteToWideChar(codepage, flags, string, (int)string_len, olestring, (int)string_len);
51 		if (ok > 0 && (size_t)ok < string_len) {
52 			olestring[ok] = '\0';
53 		}
54 	} else {
55 		ok = FALSE;
56 		olestring = (OLECHAR*)emalloc(sizeof(OLECHAR));
57 		*olestring = 0;
58 	}
59 
60 	if (!ok) {
61 		char *msg = php_win32_error_to_msg(GetLastError());
62 
63 		php_error_docref(NULL, E_WARNING,
64 			"Could not convert string to unicode: `%s'", msg);
65 
66 		LocalFree(msg);
67 	}
68 
69 	return olestring;
70 }
71 
php_com_olestring_to_string(OLECHAR * olestring,size_t * string_len,int codepage)72 PHP_COM_DOTNET_API char *php_com_olestring_to_string(OLECHAR *olestring, size_t *string_len, int codepage)
73 {
74 	char *string;
75 	uint32_t length = 0;
76 	BOOL ok;
77 
78 	length = WideCharToMultiByte(codepage, 0, olestring, -1, NULL, 0, NULL, NULL);
79 
80 	if (length) {
81 		string = (char*)safe_emalloc(length, sizeof(char), 0);
82 		length = WideCharToMultiByte(codepage, 0, olestring, -1, string, length, NULL, NULL);
83 		ok = length > 0;
84 	} else {
85 		string = (char*)emalloc(sizeof(char));
86 		*string = '\0';
87 		ok = FALSE;
88 		length = 0;
89 	}
90 
91 	if (!ok) {
92 		char *msg = php_win32_error_to_msg(GetLastError());
93 
94 		php_error_docref(NULL, E_WARNING,
95 			"Could not convert string from unicode: `%s'", msg);
96 
97 		LocalFree(msg);
98 	}
99 
100 	if (string_len) {
101 		*string_len = length-1;
102 	}
103 
104 	return string;
105 }
106 
php_com_string_to_bstr(zend_string * string,int codepage)107 BSTR php_com_string_to_bstr(zend_string *string, int codepage)
108 {
109 	BSTR bstr = NULL;
110 	DWORD flags = codepage == CP_UTF8 ? 0 : MB_PRECOMPOSED | MB_ERR_INVALID_CHARS;
111 	size_t mb_len = ZSTR_LEN(string);
112 	int wc_len;
113 
114 	if ((wc_len = MultiByteToWideChar(codepage, flags, ZSTR_VAL(string), (int)mb_len + 1, NULL, 0)) <= 0) {
115 		goto fail;
116 	}
117 	if ((bstr = SysAllocStringLen(NULL, (UINT)(wc_len - 1))) == NULL) {
118 		goto fail;
119 	}
120 	if ((wc_len = MultiByteToWideChar(codepage, flags, ZSTR_VAL(string), (int)mb_len + 1, bstr, wc_len)) <= 0) {
121 		goto fail;
122 	}
123 	return bstr;
124 
125 fail:
126 	char *msg = php_win32_error_to_msg(GetLastError());
127 	php_error_docref(NULL, E_WARNING,
128 		"Could not convert string to unicode: `%s'", msg);
129 	LocalFree(msg);
130 	SysFreeString(bstr);
131 	return SysAllocString(L"");
132 }
133 
php_com_bstr_to_string(BSTR bstr,int codepage)134 zend_string *php_com_bstr_to_string(BSTR bstr, int codepage)
135 {
136 	zend_string *string = NULL;
137 	UINT wc_len = SysStringLen(bstr);
138 	int mb_len;
139 
140 	mb_len = WideCharToMultiByte(codepage, 0, bstr, wc_len + 1, NULL, 0, NULL, NULL);
141 	if (mb_len > 0) {
142 		string = zend_string_alloc(mb_len - 1, 0);
143 		mb_len = WideCharToMultiByte(codepage, 0, bstr, wc_len + 1, ZSTR_VAL(string), mb_len, NULL, NULL);
144 	}
145 
146 	if (mb_len <= 0) {
147 		char *msg = php_win32_error_to_msg(GetLastError());
148 
149 		php_error_docref(NULL, E_WARNING,
150 			"Could not convert string from unicode: `%s'", msg);
151 		LocalFree(msg);
152 
153 		if (string != NULL) {
154 			zend_string_release(string);
155 		}
156 		string = ZSTR_EMPTY_ALLOC();
157 	}
158 
159 	return string;
160 }
161