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