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