1 /* win32_util.c
2 *
3 * This file is part of vchanger by Josh Fisher.
4 *
5 * vchanger copyright (C) 2008-2012 Josh Fisher
6 *
7 * vchanger is free software.
8 * You may redistribute it and/or modify it under the terms of the
9 * GNU General Public License version 2, as published by the Free
10 * Software Foundation.
11 *
12 * vchanger is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 * See the GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with vchanger. See the file "COPYING". If not,
19 * write to: The Free Software Foundation, Inc.,
20 * 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
22 */
23
24 #include "config.h"
25
26 #ifdef HAVE_WINDOWS_H
27
28 #include "targetver.h"
29 #include <windows.h>
30 #include <winerror.h>
31 #ifdef HAVE_STDLIB_H
32 #include <stdlib.h>
33 #endif
34 #ifdef HAVE_STDINT_H
35 #include <stdint.h>
36 #endif
37 #ifdef HAVE_ERRNO_H
38 #include <errno.h>
39 #endif
40
41 #include "win32_util.h"
42
43 #ifndef ENODATA
44 #define ENODATA EIO
45 #endif
46 #ifndef ENOMEDIUM
47 #define ENOMEDIUM ENOSPC
48 #endif
49
50 /*-------------------------------------------------
51 * Convert 100 ns intervals since 1601-01-01 00:00:00 UTC in 'ftime' to
52 * seconds since 1970-01-01 00:00:00 UTC and return as type time_t.
53 *-------------------------------------------------*/
ftime2utime(const FILETIME * ftime)54 time_t ftime2utime(const FILETIME *ftime)
55 {
56 uint64_t ut = ftime->dwHighDateTime;
57 ut <<= 32;
58 ut |= ftime->dwLowDateTime; /* 100 ns intervals since FILETIME epoch */
59 ut -= EPOCH_FILETIME; /* convert to 100 ns intervals since Unix epoch */
60 ut /= 10000000; /* convert to seconds since Unix epoch */
61 return (time_t)ut;
62 }
63
64
65 /*-------------------------------------------------
66 * Utility function to convert an ANSI string 'str' to a UTF-16 string.
67 * 'u16str' is pointer to a pointer to a caller supplied buffer where the
68 * UTF-16 string will be created. 'u16size' is a pointer to a size_t variable
69 * that contains the size of the supplied buffer. On entry, if the pointer that
70 * 'u16str' points to is NULL, then a buffer for the result UTF-16 string will
71 * be allocated using malloc. A pointer to the allocated buffer will be
72 * returned in *u16str and the size of the allocated buffer (in bytes) will be
73 * returned in *u16size. It is the caller's responsibility to free the
74 * allocated buffer. If the caller supplies a buffer then no memory will be
75 * allocated, and if the buffer is too small then NULL will be returned.
76 * On success, a pointer to the UTF-16 string is returned.
77 * On error, NULL is returned.
78 *-------------------------------------------------*/
AnsiToUTF16(const char * str,wchar_t ** u16str,size_t * u16size)79 wchar_t* AnsiToUTF16(const char *str, wchar_t **u16str, size_t *u16size)
80 {
81 size_t needed;
82 UINT acp = GetACP(); /* Use current active code page for conversion */
83
84 if (!str) {
85 return NULL; /* NULL input string is an error */
86 }
87 /* Determine size of buffer needed for the UTF-16 string */
88 needed = MultiByteToWideChar(acp, 0, str, -1, NULL, 0);
89 if (*u16str) {
90 /* If caller supplied a buffer, check that it's large enough */
91 if (*u16size < needed) {
92 return NULL; /* caller's buffer is too small */
93 }
94 } else {
95 /* If caller did not supply buffer, then allocate one */
96 *u16size = needed * sizeof(wchar_t);
97 *u16str = (wchar_t*)malloc(*u16size);
98 }
99 /* Do the ANSI to UTF-16 conversion */
100 MultiByteToWideChar(acp, 0, str, -1, *u16str, *u16size);
101 return *u16str;
102 }
103
104
105 /*-------------------------------------------------
106 * Utility function to convert UTF-16 string 'u16str' to an ANSI string.
107 * 'str' is a pointer to a pointer to a caller supplied buffer where the UTF-8
108 * string will be created. 'str_size' is a pointer to a size_t variable that
109 * contains the size of the supplied buffer. On entry, if the pointer that
110 * 'str' points to is NULL, then a buffer for the result ANSI string will
111 * be allocated using malloc. A pointer to the allocated buffer will be
112 * returned in *str and the size of the allocated buffer (in bytes) will
113 * be returned in *str_size. It is the caller's responsibility to free the
114 * allocated buffer.If the caller supplies a buffer then no memory will be
115 * allocated, and if the buffer is too small then NULL will be returned.
116 * On success, a pointer to the ANSI string is returned.
117 * On error, NULL is returned.
118 *-------------------------------------------------*/
UTF16ToAnsi(const wchar_t * u16str,char ** str,size_t * str_size)119 char *UTF16ToAnsi(const wchar_t *u16str, char **str, size_t *str_size)
120 {
121 size_t needed;
122 UINT acp = GetACP(); /* Use current code page for conversion */
123
124 if (!u16str) {
125 return NULL; /* NULL input string is an error */
126 }
127 /* Determine size of buffer needed for UTF-8 string */
128 needed = WideCharToMultiByte(acp, 0, u16str, -1, NULL, 0, NULL, NULL);
129 if (*str) {
130 /* If caller supplied a buffer, check that it's large enough */
131 if (*str_size < needed) {
132 return NULL; // caller's buffer is too small */
133 }
134 } else {
135 /* If caller did not supply buffer, then allocate one */
136 *str_size = needed;
137 *str = (char*)malloc(*str_size);
138 }
139 /* Do the UTF-16 to ANSI conversion */
140 WideCharToMultiByte(acp, 0, u16str, -1, *str, *str_size, NULL, NULL);
141 return *str;
142 }
143
144
145 /*-------------------------------------------------
146 * Translate win32 error codes to errno
147 *-------------------------------------------------*/
w32errno(DWORD werr)148 int w32errno(DWORD werr)
149 {
150 switch (werr) {
151 case ERROR_SUCCESS:
152 return 0;
153 case ERROR_ACCESS_DENIED:
154 case ERROR_SHARING_VIOLATION:
155 case ERROR_LOCK_VIOLATION:
156 return EACCES;
157 case ERROR_NO_PROC_SLOTS:
158 case ERROR_MORE_DATA:
159 case ERROR_MAX_THRDS_REACHED:
160 case ERROR_ACTIVE_CONNECTIONS:
161 case ERROR_DEVICE_IN_USE:
162 return EAGAIN;
163 case ERROR_INVALID_HANDLE:
164 return EBADF;
165 case ERROR_BUSY:
166 case ERROR_PIPE_BUSY:
167 case ERROR_PIPE_CONNECTED:
168 case ERROR_SIGNAL_PENDING:
169 case ERROR_CHILD_NOT_COMPLETE:
170 return EBUSY;
171 case ERROR_WAIT_NO_CHILDREN:
172 return ECHILD;
173 case ERROR_POSSIBLE_DEADLOCK:
174 return EDEADLOCK;
175 case ERROR_FILE_EXISTS:
176 case ERROR_ALREADY_EXISTS:
177 return EEXIST;
178 case ERROR_PROCESS_ABORTED:
179 case ERROR_NOACCESS:
180 return EFAULT;
181 case ERROR_INVALID_AT_INTERRUPT_TIME:
182 return EINTR;
183 case ERROR_INVALID_DATA:
184 case ERROR_INVALID_PARAMETER:
185 case ERROR_FILENAME_EXCED_RANGE:
186 case ERROR_META_EXPANSION_TOO_LONG:
187 case ERROR_INVALID_SIGNAL_NUMBER:
188 case ERROR_THREAD_1_INACTIVE:
189 case ERROR_BAD_PIPE:
190 case ERROR_NO_TOKEN:
191 case ERROR_NEGATIVE_SEEK:
192 case ERROR_BAD_USERNAME:
193 return EINVAL;
194 case ERROR_OPEN_FAILED:
195 case ERROR_SIGNAL_REFUSED:
196 case ERROR_NO_SIGNAL_SENT:
197 case ERROR_IO_DEVICE:
198 case ERROR_CRC:
199 return EIO;
200 case ERROR_TOO_MANY_OPEN_FILES:
201 return EMFILE;
202 case ERROR_NO_MORE_SEARCH_HANDLES:
203 case ERROR_NO_MORE_FILES:
204 return ENFILE;
205 case ERROR_HANDLE_EOF:
206 return ENODATA;
207 case ERROR_BAD_DEVICE:
208 case ERROR_BAD_UNIT:
209 case ERROR_INVALID_DRIVE:
210 return ENODEV;
211 case ERROR_FILE_NOT_FOUND:
212 case ERROR_PATH_NOT_FOUND:
213 case ERROR_INVALID_NAME:
214 case ERROR_BAD_PATHNAME:
215 case ERROR_BAD_NETPATH:
216 case ERROR_BAD_NET_NAME:
217 return ENOENT;
218 case ERROR_SHARING_BUFFER_EXCEEDED:
219 return ENOLCK;
220 case ERROR_NOT_CONNECTED:
221 case ERROR_NOT_READY:
222 return ENOMEDIUM;
223 case ERROR_NOT_ENOUGH_MEMORY:
224 case ERROR_OUTOFMEMORY:
225 return ENOMEM;
226 case ERROR_DISK_FULL:
227 case ERROR_END_OF_MEDIA:
228 case ERROR_EOM_OVERFLOW:
229 case ERROR_NO_DATA_DETECTED:
230 case ERROR_HANDLE_DISK_FULL:
231 return ENOSPC;
232 case ERROR_CALL_NOT_IMPLEMENTED:
233 case ERROR_NOT_SUPPORTED:
234 return ENOSYS;
235 case ERROR_DIRECTORY:
236 return ENOTDIR;
237 case ERROR_DIR_NOT_EMPTY:
238 return ENOTEMPTY;
239 case ERROR_FILE_INVALID:
240 return ENXIO;
241 case ERROR_NOT_OWNER:
242 case ERROR_CANNOT_MAKE:
243 return EPERM;
244 case ERROR_BROKEN_PIPE:
245 case ERROR_NO_DATA:
246 return EPIPE;
247 case ERROR_WRITE_PROTECT:
248 return EROFS;
249 case ERROR_SETMARK_DETECTED:
250 case ERROR_BEGINNING_OF_MEDIA:
251 return ESPIPE;
252 case ERROR_NOT_SAME_DEVICE:
253 return EXDEV;
254 }
255 return ENOSYS;
256 }
257
258 #endif
259
260