xref: /PHP-7.2/win32/winutil.c (revision 902d39a3)
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: Zeev Suraski <zeev@zend.com>                                 |
16    *         Pierre Joye <pierre@php.net>                                 |
17    +----------------------------------------------------------------------+
18  */
19 
20 /* $Id$ */
21 
22 #include "php.h"
23 #include "winutil.h"
24 #include <bcrypt.h>
25 #include <lmcons.h>
26 
php_win32_error_to_msg(HRESULT error)27 PHP_WINUTIL_API char *php_win32_error_to_msg(HRESULT error)
28 {/*{{{*/
29 	char *buf = NULL;
30 
31 	FormatMessage(
32 		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |	FORMAT_MESSAGE_IGNORE_INSERTS,
33 		NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),	(LPTSTR)&buf, 0, NULL
34 	);
35 
36 	return (buf ? (char *) buf : "");
37 }/*}}}*/
38 
php_win32_check_trailing_space(const char * path,const size_t path_len)39 int php_win32_check_trailing_space(const char * path, const size_t path_len)
40 {/*{{{*/
41 	if (path_len > MAXPATHLEN - 1) {
42 		return 1;
43 	}
44 	if (path) {
45 		if (path[0] == ' ' || path[path_len - 1] == ' ') {
46 			return 0;
47 		} else {
48 			return 1;
49 		}
50 	} else {
51 		return 0;
52 	}
53 }/*}}}*/
54 
55 static BCRYPT_ALG_HANDLE bcrypt_algo;
56 static BOOL has_bcrypt_algo = 0;
57 
58 #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
59 
60 #ifdef PHP_EXPORTS
php_win32_shutdown_random_bytes(void)61 BOOL php_win32_shutdown_random_bytes(void)
62 {/*{{{*/
63 	BOOL ret = TRUE;
64 
65 	if (has_bcrypt_algo) {
66 		ret = NT_SUCCESS(BCryptCloseAlgorithmProvider(bcrypt_algo, 0));
67 		has_bcrypt_algo = 0;
68 	}
69 
70 	return ret;
71 }/*}}}*/
72 
php_win32_init_random_bytes(void)73 BOOL php_win32_init_random_bytes(void)
74 {/*{{{*/
75 	if (has_bcrypt_algo) {
76 		return TRUE;
77 	}
78 
79 	has_bcrypt_algo = NT_SUCCESS(BCryptOpenAlgorithmProvider(&bcrypt_algo, BCRYPT_RNG_ALGORITHM, NULL, 0));
80 
81 	return has_bcrypt_algo;
82 }/*}}}*/
83 #endif
84 
php_win32_get_random_bytes(unsigned char * buf,size_t size)85 PHP_WINUTIL_API int php_win32_get_random_bytes(unsigned char *buf, size_t size)
86 {  /* {{{ */
87 
88 	BOOL ret;
89 
90 #if 0
91 	/* Currently we fail on startup, with CNG API it shows no regressions so far and is secure.
92 		Should switch on and try to reinit, if it fails too often on startup. This means also
93 		bringing locks back. */
94 	if (has_bcrypt_algo == 0) {
95 		return FAILURE;
96 	}
97 #endif
98 
99 	/* No sense to loop here, the limit is huge enough. */
100 	ret = NT_SUCCESS(BCryptGenRandom(bcrypt_algo, buf, (ULONG)size, 0));
101 
102 	return ret ? SUCCESS : FAILURE;
103 }
104 /* }}} */
105 
106 
107 /*
108 * This functions based on the code from the UNIXem project under
109 * the BSD like license. Modified for PHP by ab@php.net
110 *
111 * Home:    http://synesis.com.au/software/
112 *
113 * Copyright (c) 2005-2010, Matthew Wilson and Synesis Software
114 */
115 
php_win32_code_to_errno(unsigned long w32Err)116 PHP_WINUTIL_API int php_win32_code_to_errno(unsigned long w32Err)
117 {/*{{{*/
118     size_t  i;
119 
120     struct code_to_errno_map
121     {
122         unsigned long   w32Err;
123         int             eerrno;
124     };
125 
126     static const struct code_to_errno_map errmap[] =
127     {
128         /*   1 */       {   ERROR_INVALID_FUNCTION          ,   EINVAL          }
129         /*   2 */   ,   {   ERROR_FILE_NOT_FOUND            ,   ENOENT          }
130         /*   3 */   ,   {   ERROR_PATH_NOT_FOUND            ,   ENOENT          }
131         /*   4 */   ,   {   ERROR_TOO_MANY_OPEN_FILES       ,   EMFILE          }
132         /*   5 */   ,   {   ERROR_ACCESS_DENIED             ,   EACCES          }
133         /*   6 */   ,   {   ERROR_INVALID_HANDLE            ,   EBADF           }
134         /*   7 */   ,   {   ERROR_ARENA_TRASHED             ,   ENOMEM          }
135         /*   8 */   ,   {   ERROR_NOT_ENOUGH_MEMORY         ,   ENOMEM          }
136         /*   9 */   ,   {   ERROR_INVALID_BLOCK             ,   ENOMEM          }
137         /*  10 */   ,   {   ERROR_BAD_ENVIRONMENT           ,   E2BIG           }
138         /*  11 */   ,   {   ERROR_BAD_FORMAT                ,   ENOEXEC         }
139         /*  12 */   ,   {   ERROR_INVALID_ACCESS            ,   EINVAL          }
140         /*  13 */   ,   {   ERROR_INVALID_DATA              ,   EINVAL          }
141         /*  14 */   ,   {   ERROR_OUTOFMEMORY               ,   ENOMEM          }
142         /*  15 */   ,   {   ERROR_INVALID_DRIVE             ,   ENOENT          }
143         /*  16 */   ,   {   ERROR_CURRENT_DIRECTORY         ,   ECURDIR         }
144         /*  17 */   ,   {   ERROR_NOT_SAME_DEVICE           ,   EXDEV           }
145         /*  18 */   ,   {   ERROR_NO_MORE_FILES             ,   ENOENT          }
146         /*  19 */   ,   {   ERROR_WRITE_PROTECT             ,   EROFS           }
147         /*  20 */   ,   {   ERROR_BAD_UNIT                  ,   ENXIO           }
148         /*  21 */   ,   {   ERROR_NOT_READY                 ,   EBUSY           }
149         /*  22 */   ,   {   ERROR_BAD_COMMAND               ,   EIO             }
150         /*  23 */   ,   {   ERROR_CRC                       ,   EIO             }
151         /*  24 */   ,   {   ERROR_BAD_LENGTH                ,   EIO             }
152         /*  25 */   ,   {   ERROR_SEEK                      ,   EIO             }
153         /*  26 */   ,   {   ERROR_NOT_DOS_DISK              ,   EIO             }
154         /*  27 */   ,   {   ERROR_SECTOR_NOT_FOUND          ,   ENXIO           }
155         /*  28 */   ,   {   ERROR_OUT_OF_PAPER              ,   EBUSY           }
156         /*  29 */   ,   {   ERROR_WRITE_FAULT               ,   EIO             }
157         /*  30 */   ,   {   ERROR_READ_FAULT                ,   EIO             }
158         /*  31 */   ,   {   ERROR_GEN_FAILURE               ,   EIO             }
159         /*  32 */   ,   {   ERROR_SHARING_VIOLATION         ,   EAGAIN          }
160         /*  33 */   ,   {   ERROR_LOCK_VIOLATION            ,   EACCES          }
161         /*  34 */   ,   {   ERROR_WRONG_DISK                ,   ENXIO           }
162         /*  35 */   ,   {   35                              ,   ENFILE          }
163         /*  36 */   ,   {   ERROR_SHARING_BUFFER_EXCEEDED   ,   ENFILE          }
164         /*  37 */   ,   {   ERROR_HANDLE_EOF                ,   EINVAL          }
165         /*  38 */   ,   {   ERROR_HANDLE_DISK_FULL          ,   ENOSPC          }
166 #if 0
167         /*  39 */   ,   {   0                               ,   0               }
168         /*  40 */   ,   {   0                               ,   0               }
169         /*  41 */   ,   {   0                               ,   0               }
170         /*  42 */   ,   {   0                               ,   0               }
171         /*  43 */   ,   {   0                               ,   0               }
172         /*  44 */   ,   {   0                               ,   0               }
173         /*  45 */   ,   {   0                               ,   0               }
174         /*  46 */   ,   {   0                               ,   0               }
175         /*  47 */   ,   {   0                               ,   0               }
176         /*  48 */   ,   {   0                               ,   0               }
177         /*  49 */   ,   {   0                               ,   0               }
178 #endif
179         /*  50 */   ,   {   ERROR_NOT_SUPPORTED             ,   ENOSYS          }
180 #if 0
181         /*  51 */   ,   {   0                               ,   0               }
182         /*  52 */   ,   {   0                               ,   0               }
183 #endif
184         /*  53 */   ,   {   ERROR_BAD_NETPATH               ,   ENOENT          }
185 #if 0
186         /*  54 */   ,   {   0                               ,   0               }
187         /*  55 */   ,   {   0                               ,   0               }
188         /*  56 */   ,   {   0                               ,   0               }
189         /*  57 */   ,   {   0                               ,   0               }
190         /*  58 */   ,   {   0                               ,   0               }
191         /*  59 */   ,   {   0                               ,   0               }
192         /*  60 */   ,   {   0                               ,   0               }
193         /*  61 */   ,   {   0                               ,   0               }
194         /*  62 */   ,   {   0                               ,   0               }
195         /*  63 */   ,   {   0                               ,   0               }
196         /*  64 */   ,   {   0                               ,   0               }
197 #endif
198         /*  65 */   ,   {   ERROR_NETWORK_ACCESS_DENIED     ,   EACCES          }
199 #if 0
200         /*  66 */   ,   {   0                               ,   0               }
201 #endif
202         /*  67 */   ,   {   ERROR_BAD_NET_NAME              ,   ENOENT          }
203 #if 0
204         /*  68 */   ,   {   0                               ,   0               }
205         /*  69 */   ,   {   0                               ,   0               }
206         /*  70 */   ,   {   0                               ,   0               }
207         /*  71 */   ,   {   0                               ,   0               }
208         /*  72 */   ,   {   0                               ,   0               }
209         /*  73 */   ,   {   0                               ,   0               }
210         /*  74 */   ,   {   0                               ,   0               }
211         /*  75 */   ,   {   0                               ,   0               }
212         /*  76 */   ,   {   0                               ,   0               }
213         /*  77 */   ,   {   0                               ,   0               }
214         /*  78 */   ,   {   0                               ,   0               }
215         /*  79 */   ,   {   0                               ,   0               }
216 #endif
217         /*  80 */   ,   {   ERROR_FILE_EXISTS               ,   EEXIST          }
218 #if 0
219         /*  81 */   ,   {   0                               ,   0               }
220 #endif
221         /*  82 */   ,   {   ERROR_CANNOT_MAKE               ,   EACCES          }
222         /*  83 */   ,   {   ERROR_FAIL_I24                  ,   EACCES          }
223 #if 0
224         /*  84 */   ,   {   0                               ,   0               }
225         /*  85 */   ,   {   0                               ,   0               }
226         /*  86 */   ,   {   0                               ,   0               }
227 #endif
228         /*  87 */   ,   {   ERROR_INVALID_PARAMETER         ,   EINVAL          }
229 #if 0
230         /*  88 */   ,   {   0                               ,   0               }
231 #endif
232         /*  89 */   ,   {   ERROR_NO_PROC_SLOTS             ,   EAGAIN          }
233 #if 0
234         /*  90 */   ,   {   0                               ,   0               }
235         /*  91 */   ,   {   0                               ,   0               }
236         /*  92 */   ,   {   0                               ,   0               }
237         /*  93 */   ,   {   0                               ,   0               }
238         /*  94 */   ,   {   0                               ,   0               }
239         /*  95 */   ,   {   0                               ,   0               }
240         /*  96 */   ,   {   0                               ,   0               }
241         /*  97 */   ,   {   0                               ,   0               }
242         /*  98 */   ,   {   0                               ,   0               }
243         /*  99 */   ,   {   0                               ,   0               }
244         /* 100 */   ,   {   0                               ,   0               }
245         /* 101 */   ,   {   0                               ,   0               }
246         /* 102 */   ,   {   0                               ,   0               }
247         /* 103 */   ,   {   0                               ,   0               }
248         /* 104 */   ,   {   0                               ,   0               }
249         /* 105 */   ,   {   0                               ,   0               }
250         /* 106 */   ,   {   0                               ,   0               }
251         /* 107 */   ,   {   0                               ,   0               }
252 #endif
253         /* 108 */   ,   {   ERROR_DRIVE_LOCKED              ,   EACCES          }
254         /* 109 */   ,   {   ERROR_BROKEN_PIPE               ,   EPIPE           }
255 #if 0
256         /* 110 */   ,   {   0                               ,   0               }
257 #endif
258         /* 111 */   ,   {   ERROR_BUFFER_OVERFLOW           ,   ENAMETOOLONG    }
259         /* 112 */   ,   {   ERROR_DISK_FULL                 ,   ENOSPC          }
260 #if 0
261         /* 113 */   ,   {   0                               ,   0               }
262 #endif
263         /* 114 */   ,   {   ERROR_INVALID_TARGET_HANDLE     ,   EBADF           }
264 #if 0
265         /* 115 */   ,   {   0                               ,   0               }
266         /* 116 */   ,   {   0                               ,   0               }
267         /* 117 */   ,   {   0                               ,   0               }
268         /* 118 */   ,   {   0                               ,   0               }
269         /* 119 */   ,   {   0                               ,   0               }
270         /* 120 */   ,   {   0                               ,   0               }
271         /* 121 */   ,   {   0                               ,   0               }
272 #endif
273         /* 122 */   ,   {   ERROR_INSUFFICIENT_BUFFER       ,   ERANGE          }
274         /* 123 */   ,   {   ERROR_INVALID_NAME              ,   ENOENT          }
275         /* 124 */   ,   {   ERROR_INVALID_HANDLE            ,   EINVAL          }
276 #if 0
277         /* 125 */   ,   {   0                               ,   0               }
278 #endif
279         /* 126 */   ,   {   ERROR_MOD_NOT_FOUND             ,   ENOENT          }
280         /* 127 */   ,   {   ERROR_PROC_NOT_FOUND            ,   ENOENT          }
281         /* 128 */   ,   {   ERROR_WAIT_NO_CHILDREN          ,   ECHILD          }
282         /* 129 */   ,   {   ERROR_CHILD_NOT_COMPLETE        ,   ECHILD          }
283         /* 130 */   ,   {   ERROR_DIRECT_ACCESS_HANDLE      ,   EBADF           }
284         /* 131 */   ,   {   ERROR_NEGATIVE_SEEK             ,   EINVAL          }
285         /* 132 */   ,   {   ERROR_SEEK_ON_DEVICE            ,   EACCES          }
286 #if 0
287         /* 133 */   ,   {   0                               ,   0               }
288         /* 134 */   ,   {   0                               ,   0               }
289         /* 135 */   ,   {   0                               ,   0               }
290         /* 136 */   ,   {   0                               ,   0               }
291         /* 137 */   ,   {   0                               ,   0               }
292         /* 138 */   ,   {   0                               ,   0               }
293         /* 139 */   ,   {   0                               ,   0               }
294         /* 140 */   ,   {   0                               ,   0               }
295         /* 141 */   ,   {   0                               ,   0               }
296         /* 142 */   ,   {   0                               ,   0               }
297         /* 143 */   ,   {   0                               ,   0               }
298         /* 144 */   ,   {   0                               ,   0               }
299 #endif
300         /* 145 */   ,   {   ERROR_DIR_NOT_EMPTY             ,   ENOTEMPTY       }
301 #if 0
302         /* 146 */   ,   {   0                               ,   0               }
303         /* 147 */   ,   {   0                               ,   0               }
304         /* 148 */   ,   {   0                               ,   0               }
305         /* 149 */   ,   {   0                               ,   0               }
306         /* 150 */   ,   {   0                               ,   0               }
307         /* 151 */   ,   {   0                               ,   0               }
308         /* 152 */   ,   {   0                               ,   0               }
309         /* 153 */   ,   {   0                               ,   0               }
310         /* 154 */   ,   {   0                               ,   0               }
311         /* 155 */   ,   {   0                               ,   0               }
312         /* 156 */   ,   {   0                               ,   0               }
313         /* 157 */   ,   {   0                               ,   0               }
314 #endif
315         /* 158 */   ,   {   ERROR_NOT_LOCKED                ,   EACCES          }
316 #if 0
317         /* 159 */   ,   {   0                               ,   0               }
318         /* 160 */   ,   {   0                               ,   0               }
319 #endif
320         /* 161 */   ,   {   ERROR_BAD_PATHNAME              ,   ENOENT          }
321 #if 0
322         /* 162 */   ,   {   0                               ,   0               }
323         /* 163 */   ,   {   0                               ,   0               }
324 #endif
325         /* 164 */   ,   {   ERROR_MAX_THRDS_REACHED         ,   EAGAIN          }
326 #if 0
327         /* 165 */   ,   {   0                               ,   0               }
328         /* 166 */   ,   {   0                               ,   0               }
329 #endif
330         /* 167 */   ,   {   ERROR_LOCK_FAILED               ,   EACCES          }
331 #if 0
332         /* 168 */   ,   {   0                               ,   0               }
333         /* 169 */   ,   {   0                               ,   0               }
334         /* 170 */   ,   {   0                               ,   0               }
335         /* 171 */   ,   {   0                               ,   0               }
336         /* 172 */   ,   {   0                               ,   0               }
337         /* 173 */   ,   {   0                               ,   0               }
338         /* 174 */   ,   {   0                               ,   0               }
339         /* 175 */   ,   {   0                               ,   0               }
340         /* 176 */   ,   {   0                               ,   0               }
341         /* 177 */   ,   {   0                               ,   0               }
342         /* 178 */   ,   {   0                               ,   0               }
343         /* 179 */   ,   {   0                               ,   0               }
344         /* 180 */   ,   {   0                               ,   0               }
345         /* 181 */   ,   {   0                               ,   0               }
346         /* 182 */   ,   {   0                               ,   0               }
347 #endif
348         /* 183 */   ,   {   ERROR_ALREADY_EXISTS            ,   EEXIST          }
349 #if 0
350         /* 184 */   ,   {   0                               ,   0               }
351         /* 185 */   ,   {   0                               ,   0               }
352         /* 186 */   ,   {   0                               ,   0               }
353         /* 187 */   ,   {   0                               ,   0               }
354         /* 188 */   ,   {   0                               ,   0               }
355         /* 189 */   ,   {   0                               ,   0               }
356         /* 190 */   ,   {   0                               ,   0               }
357         /* 191 */   ,   {   0                               ,   0               }
358         /* 192 */   ,   {   0                               ,   0               }
359         /* 193 */   ,   {   0                               ,   0               }
360         /* 194 */   ,   {   0                               ,   0               }
361         /* 195 */   ,   {   0                               ,   0               }
362         /* 196 */   ,   {   0                               ,   0               }
363         /* 197 */   ,   {   0                               ,   0               }
364         /* 198 */   ,   {   0                               ,   0               }
365         /* 199 */   ,   {   0                               ,   0               }
366 #endif
367 
368         /* 206 */   ,   {   ERROR_FILENAME_EXCED_RANGE      ,   ENAMETOOLONG    }
369 
370         /* 215 */   ,   {   ERROR_NESTING_NOT_ALLOWED       ,   EAGAIN          }
371 		/* 258 */   ,   { WAIT_TIMEOUT, ETIME}
372 
373         /* 267 */   ,   {   ERROR_DIRECTORY                 ,   ENOTDIR         }
374 
375         /* 996 */   ,   {   ERROR_IO_INCOMPLETE             ,   EAGAIN          }
376         /* 997 */   ,   {   ERROR_IO_PENDING                ,   EAGAIN          }
377 
378         /* 1004 */   ,  {   ERROR_INVALID_FLAGS             ,   EINVAL          }
379         /* 1113 */   ,  {   ERROR_NO_UNICODE_TRANSLATION    ,   EINVAL          }
380         /* 1168 */   ,  {   ERROR_NOT_FOUND                 ,   ENOENT          }
381         /* 1224 */   ,  {   ERROR_USER_MAPPED_FILE          ,   EACCES          }
382         /* 1816 */  ,   {   ERROR_NOT_ENOUGH_QUOTA          ,   ENOMEM          }
383 					,   {   ERROR_ABANDONED_WAIT_0          ,   EIO }
384     };
385 
386     for(i = 0; i < sizeof(errmap)/sizeof(struct code_to_errno_map); ++i)
387     {
388         if(w32Err == errmap[i].w32Err)
389         {
390             return errmap[i].eerrno;
391         }
392     }
393 
394     assert(!"Unrecognised value");
395 
396     return EINVAL;
397 }/*}}}*/
398 
php_win32_get_username(void)399 PHP_WINUTIL_API char *php_win32_get_username(void)
400 {/*{{{*/
401 	wchar_t unamew[UNLEN + 1];
402 	size_t uname_len;
403 	char *uname;
404 	DWORD unsize = UNLEN;
405 
406 	GetUserNameW(unamew, &unsize);
407 	uname = php_win32_cp_conv_w_to_any(unamew, unsize - 1, &uname_len);
408 	if (!uname) {
409 		return NULL;
410 	}
411 
412 	/* Ensure the length doesn't overflow. */
413 	if (uname_len > UNLEN) {
414 		uname[uname_len] = '\0';
415 	}
416 
417 	return uname;
418 }/*}}}*/
419 
420 /*
421  * Local variables:
422  * tab-width: 4
423  * c-basic-offset: 4
424  * End:
425  * vim600: sw=4 ts=4 fdm=marker
426  * vim<600: sw=4 ts=4
427  */
428