xref: /PHP-8.1/ext/com_dotnet/com_olechar.c (revision 01b3fc03)
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    |         Harald Radi <h.radi@nme.at>                                  |
15    +----------------------------------------------------------------------+
16  */
17 
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21 
22 #include "php.h"
23 #include "php_ini.h"
24 #include "ext/standard/info.h"
25 #include "php_com_dotnet.h"
26 #include "php_com_dotnet_internal.h"
27 
28 
php_com_string_to_olestring(const char * string,size_t string_len,int codepage)29 PHP_COM_DOTNET_API OLECHAR *php_com_string_to_olestring(const char *string, size_t string_len, int codepage)
30 {
31 	OLECHAR *olestring = NULL;
32 	DWORD flags = codepage == CP_UTF8 ? 0 : MB_PRECOMPOSED | MB_ERR_INVALID_CHARS;
33 	BOOL ok;
34 
35 	if (string_len == -1) {
36 		/* determine required length for the buffer (includes NUL terminator) */
37 		string_len = MultiByteToWideChar(codepage, flags, string, -1, NULL, 0);
38 	} else {
39 		/* allow room for NUL terminator */
40 		string_len++;
41 	}
42 
43 	if (string_len > 0) {
44 		olestring = (OLECHAR*)safe_emalloc(string_len, sizeof(OLECHAR), 0);
45 		/* XXX if that's a real multibyte string, olestring is obviously allocated excessively.
46 		This should be fixed by reallocating the olestring, but as emalloc is used, that doesn't
47 		matter much. */
48 		ok = MultiByteToWideChar(codepage, flags, string, (int)string_len, olestring, (int)string_len);
49 		if (ok > 0 && (size_t)ok < string_len) {
50 			olestring[ok] = '\0';
51 		}
52 	} else {
53 		ok = FALSE;
54 		olestring = (OLECHAR*)emalloc(sizeof(OLECHAR));
55 		*olestring = 0;
56 	}
57 
58 	if (!ok) {
59 		char *msg = php_win32_error_to_msg(GetLastError());
60 
61 		php_error_docref(NULL, E_WARNING,
62 			"Could not convert string to unicode: `%s'", msg);
63 
64 		php_win32_error_msg_free(msg);
65 	}
66 
67 	return olestring;
68 }
69 
php_com_olestring_to_string(OLECHAR * olestring,size_t * string_len,int codepage)70 PHP_COM_DOTNET_API char *php_com_olestring_to_string(OLECHAR *olestring, size_t *string_len, int codepage)
71 {
72 	char *string;
73 	uint32_t length = 0;
74 	BOOL ok;
75 
76 	length = WideCharToMultiByte(codepage, 0, olestring, -1, NULL, 0, NULL, NULL);
77 
78 	if (length) {
79 		string = (char*)safe_emalloc(length, sizeof(char), 0);
80 		length = WideCharToMultiByte(codepage, 0, olestring, -1, string, length, NULL, NULL);
81 		ok = length > 0;
82 	} else {
83 		string = (char*)emalloc(sizeof(char));
84 		*string = '\0';
85 		ok = FALSE;
86 		length = 0;
87 	}
88 
89 	if (!ok) {
90 		char *msg = php_win32_error_to_msg(GetLastError());
91 
92 		php_error_docref(NULL, E_WARNING,
93 			"Could not convert string from unicode: `%s'", msg);
94 
95 		php_win32_error_msg_free(msg);
96 	}
97 
98 	if (string_len) {
99 		*string_len = length-1;
100 	}
101 
102 	return string;
103 }
104 
php_com_string_to_bstr(zend_string * string,int codepage)105 BSTR php_com_string_to_bstr(zend_string *string, int codepage)
106 {
107 	BSTR bstr = NULL;
108 	DWORD flags = codepage == CP_UTF8 ? 0 : MB_PRECOMPOSED | MB_ERR_INVALID_CHARS;
109 	size_t mb_len = ZSTR_LEN(string);
110 	int wc_len;
111 
112 	if ((wc_len = MultiByteToWideChar(codepage, flags, ZSTR_VAL(string), (int)mb_len + 1, NULL, 0)) <= 0) {
113 		goto fail;
114 	}
115 	if ((bstr = SysAllocStringLen(NULL, (UINT)(wc_len - 1))) == NULL) {
116 		goto fail;
117 	}
118 	if ((wc_len = MultiByteToWideChar(codepage, flags, ZSTR_VAL(string), (int)mb_len + 1, bstr, wc_len)) <= 0) {
119 		goto fail;
120 	}
121 	return bstr;
122 
123 fail:
124 	char *msg = php_win32_error_to_msg(GetLastError());
125 	php_error_docref(NULL, E_WARNING,
126 		"Could not convert string to unicode: `%s'", msg);
127 	LocalFree(msg);
128 	SysFreeString(bstr);
129 	return SysAllocString(L"");
130 }
131 
php_com_bstr_to_string(BSTR bstr,int codepage)132 zend_string *php_com_bstr_to_string(BSTR bstr, int codepage)
133 {
134 	zend_string *string = NULL;
135 	UINT wc_len = SysStringLen(bstr);
136 	int mb_len;
137 
138 	mb_len = WideCharToMultiByte(codepage, 0, bstr, wc_len + 1, NULL, 0, NULL, NULL);
139 	if (mb_len > 0) {
140 		string = zend_string_alloc(mb_len - 1, 0);
141 		mb_len = WideCharToMultiByte(codepage, 0, bstr, wc_len + 1, ZSTR_VAL(string), mb_len, NULL, NULL);
142 	}
143 
144 	if (mb_len <= 0) {
145 		char *msg = php_win32_error_to_msg(GetLastError());
146 
147 		php_error_docref(NULL, E_WARNING,
148 			"Could not convert string from unicode: `%s'", msg);
149 		LocalFree(msg);
150 
151 		if (string != NULL) {
152 			zend_string_release(string);
153 		}
154 		string = ZSTR_EMPTY_ALLOC();
155 	}
156 
157 	return string;
158 }
159