fix for building with mingw in since recent changes.
[blender.git] / source / blender / blenlib / intern / winstuff.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  * Windows-posix compatibility layer, windows-specific functions.
27  */
28
29 /** \file blender/blenlib/intern/winstuff.c
30  *  \ingroup bli
31  */
32
33
34 #ifdef WIN32
35
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <conio.h>
39
40 #include "MEM_guardedalloc.h"
41
42 #include "../blenkernel/BKE_global.h"  /* G.background, bad level include (no function calls) */
43
44 #define WIN32_SKIP_HKEY_PROTECTION      // need to use HKEY
45 #include "BLI_winstuff.h"
46 #include "BLI_utildefines.h"
47 #include "BLI_path_util.h"
48 #include "BLI_string.h"
49
50 #include "utf_winfunc.h"
51 #include "utfconv.h"
52
53 /* FILE_MAXDIR + FILE_MAXFILE */
54
55 int BLI_getInstallationDir(char *str)
56 {
57         char dir[FILE_MAXDIR];
58         int a;
59         /*change to utf support*/
60         GetModuleFileName(NULL, str, FILE_MAX);
61         BLI_split_dir_part(str, dir, sizeof(dir)); /* shouldn't be relative */
62         a = strlen(dir);
63         if (dir[a - 1] == '\\') dir[a - 1] = 0;
64         
65         strcpy(str, dir);
66         
67         return 1;
68 }
69
70 static void RegisterBlendExtension_Fail(HKEY root)
71 {
72         printf("failed\n");
73         if (root)
74                 RegCloseKey(root);
75         if (!G.background)
76                 MessageBox(0, "Could not register file extension.", "Blender error", MB_OK | MB_ICONERROR);
77         TerminateProcess(GetCurrentProcess(), 1);
78 }
79
80 void RegisterBlendExtension(void)
81 {
82         LONG lresult;
83         HKEY hkey = 0;
84         HKEY root = 0;
85         BOOL usr_mode = FALSE;
86         DWORD dwd = 0;
87         char buffer[256];
88
89         char BlPath[MAX_PATH];
90         char InstallDir[FILE_MAXDIR];
91         char SysDir[FILE_MAXDIR];
92         const char *ThumbHandlerDLL;
93         char RegCmd[MAX_PATH * 2];
94         char MBox[256];
95         BOOL IsWOW64;
96
97         printf("Registering file extension...");
98         GetModuleFileName(0, BlPath, MAX_PATH);
99
100         /* root is HKLM by default */
101         lresult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Classes", 0, KEY_ALL_ACCESS, &root);
102         if (lresult != ERROR_SUCCESS) {
103                 /* try HKCU on failure */
104                 usr_mode = TRUE;
105                 lresult = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Classes", 0, KEY_ALL_ACCESS, &root);
106                 if (lresult != ERROR_SUCCESS)
107                         RegisterBlendExtension_Fail(0);
108         }
109
110         lresult = RegCreateKeyEx(root, "blendfile", 0,
111                                  NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd);
112         if (lresult == ERROR_SUCCESS) {
113                 strcpy(buffer, "Blender File");
114                 lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1);
115                 RegCloseKey(hkey);
116         }
117         if (lresult != ERROR_SUCCESS)
118                 RegisterBlendExtension_Fail(root);
119
120         lresult = RegCreateKeyEx(root, "blendfile\\shell\\open\\command", 0,
121                                  NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd);
122         if (lresult == ERROR_SUCCESS) {
123                 sprintf(buffer, "\"%s\" \"%%1\"", BlPath);
124                 lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1);
125                 RegCloseKey(hkey);
126         }
127         if (lresult != ERROR_SUCCESS)
128                 RegisterBlendExtension_Fail(root);
129
130         lresult = RegCreateKeyEx(root, "blendfile\\DefaultIcon", 0,
131                                  NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd);
132         if (lresult == ERROR_SUCCESS) {
133                 sprintf(buffer, "\"%s\", 1", BlPath);
134                 lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1);
135                 RegCloseKey(hkey);
136         }
137         if (lresult != ERROR_SUCCESS)
138                 RegisterBlendExtension_Fail(root);
139
140         lresult = RegCreateKeyEx(root, ".blend", 0,
141                                  NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd);
142         if (lresult == ERROR_SUCCESS) {
143                 sprintf(buffer, "%s", "blendfile");
144                 lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1);
145                 RegCloseKey(hkey);
146         }
147         if (lresult != ERROR_SUCCESS)
148                 RegisterBlendExtension_Fail(root);
149         
150         BLI_getInstallationDir(InstallDir);
151         GetSystemDirectory(SysDir, FILE_MAXDIR);
152 #ifdef WIN64
153         ThumbHandlerDLL = "BlendThumb64.dll";
154 #else
155         IsWow64Process(GetCurrentProcess(), &IsWOW64);
156         if (IsWOW64 == TRUE)
157                 ThumbHandlerDLL = "BlendThumb64.dll";
158         else
159                 ThumbHandlerDLL = "BlendThumb.dll";
160 #endif
161         snprintf(RegCmd, MAX_PATH * 2, "%s\\regsvr32 /s \"%s\\%s\"", SysDir, InstallDir, ThumbHandlerDLL);
162         system(RegCmd);
163
164         RegCloseKey(root);
165         printf("success (%s)\n", usr_mode ? "user" : "system");
166         if (!G.background) {
167                 sprintf(MBox, "File extension registered for %s.", usr_mode ? "the current user. To register for all users, run as an administrator" : "all users");
168                 MessageBox(0, MBox, "Blender", MB_OK | MB_ICONINFORMATION);
169         }
170         TerminateProcess(GetCurrentProcess(), 0);
171 }
172
173 DIR *opendir(const char *path)
174 {
175         wchar_t *path_16 = alloc_utf16_from_8(path, 0);
176
177         if (GetFileAttributesW(path_16) & FILE_ATTRIBUTE_DIRECTORY) {
178                 DIR *newd = MEM_mallocN(sizeof(DIR), "opendir");
179
180                 newd->handle = INVALID_HANDLE_VALUE;
181                 sprintf(newd->path, "%s\\*", path);
182                 
183                 newd->direntry.d_ino = 0;
184                 newd->direntry.d_off = 0;
185                 newd->direntry.d_reclen = 0;
186                 newd->direntry.d_name = NULL;
187                 
188                 free(path_16);
189                 return newd;
190         }
191         else {
192                 free(path_16);
193                 return NULL;
194         }
195 }
196
197 static char *BLI_alloc_utf_8_from_16(wchar_t *in16, size_t add)
198 {
199         size_t bsize = count_utf_8_from_16(in16);
200         char *out8 = NULL;
201         if (!bsize) return NULL;
202         out8 = (char *)MEM_mallocN(sizeof(char) * (bsize + add), "UTF-8 String");
203         conv_utf_16_to_8(in16, out8, bsize);
204         return out8;
205 }
206
207 static wchar_t *UNUSED_FUNCTION(BLI_alloc_utf16_from_8) (char *in8, size_t add)
208 {
209         size_t bsize = count_utf_16_from_8(in8);
210         wchar_t *out16 = NULL;
211         if (!bsize) return NULL;
212         out16 = (wchar_t *) MEM_mallocN(sizeof(wchar_t) * (bsize + add), "UTF-16 String");
213         conv_utf_8_to_16(in8, out16, bsize);
214         return out16;
215 }
216
217
218
219 struct dirent *readdir(DIR *dp)
220 {
221         if (dp->direntry.d_name) {
222                 MEM_freeN(dp->direntry.d_name);
223                 dp->direntry.d_name = NULL;
224         }
225                 
226         if (dp->handle == INVALID_HANDLE_VALUE) {
227                 wchar_t *path_16 = alloc_utf16_from_8(dp->path, 0);
228                 dp->handle = FindFirstFileW(path_16, &(dp->data));
229                 free(path_16);
230                 if (dp->handle == INVALID_HANDLE_VALUE)
231                         return NULL;
232                         
233                 dp->direntry.d_name = BLI_alloc_utf_8_from_16(dp->data.cFileName, 0);
234                 
235                 return &dp->direntry;
236         }
237         else if (FindNextFileW(dp->handle, &(dp->data))) {
238                 dp->direntry.d_name = BLI_alloc_utf_8_from_16(dp->data.cFileName, 0);
239
240                 return &dp->direntry;
241         }
242         else {
243                 return NULL;
244         }
245 }
246
247 int closedir(DIR *dp)
248 {
249         if (dp->direntry.d_name) MEM_freeN(dp->direntry.d_name);
250         if (dp->handle != INVALID_HANDLE_VALUE) FindClose(dp->handle);
251
252         MEM_freeN(dp);
253         
254         return 0;
255 }
256
257 void get_default_root(char *root)
258 {
259         char str[MAX_PATH + 1];
260         
261         /* the default drive to resolve a directory without a specified drive 
262          * should be the Windows installation drive, since this was what the OS
263          * assumes. */
264         if (GetWindowsDirectory(str, MAX_PATH + 1)) {
265                 root[0] = str[0];
266                 root[1] = ':';
267                 root[2] = '\\';
268                 root[3] = '\0';
269         }
270         else {
271                 /* if GetWindowsDirectory fails, something has probably gone wrong, 
272                  * we are trying the blender install dir though */
273                 if (GetModuleFileName(NULL, str, MAX_PATH + 1)) {
274                         printf("Error! Could not get the Windows Directory - Defaulting to Blender installation Dir!");
275                         root[0] = str[0];
276                         root[1] = ':';
277                         root[2] = '\\';
278                         root[3] = '\0';
279                 }
280                 else {
281                         DWORD tmp;
282                         int i;
283                         int rc = 0;
284                         /* now something has gone really wrong - still trying our best guess */
285                         printf("Error! Could not get the Windows Directory - Defaulting to first valid drive! Path might be invalid!");
286                         tmp = GetLogicalDrives();
287                         for (i = 2; i < 26; i++) {
288                                 if ((tmp >> i) & 1) {
289                                         root[0] = 'a' + i;
290                                         root[1] = ':';
291                                         root[2] = '\\';
292                                         root[3] = '\0';
293                                         if (GetFileAttributes(root) != 0xFFFFFFFF) {
294                                                 rc = i;
295                                                 break;
296                                         }
297                                 }
298                         }
299                         if (0 == rc) {
300                                 printf("ERROR in 'get_default_root': can't find a valid drive!");
301                                 root[0] = 'C';
302                                 root[1] = ':';
303                                 root[2] = '\\';
304                                 root[3] = '\0';
305                         }
306                 }
307         }
308 }
309
310 int check_file_chars(char *filename)
311 {
312         char *p = filename;
313         while (*p) {
314                 switch (*p) {
315                         case ':':
316                         case '?':
317                         case '*':
318                         case '|':
319                         case '\\':
320                         case '/':
321                         case '\"':
322                                 return 0;
323                                 break;
324                 }
325
326                 p++;
327         }
328         return 1;
329 }
330
331 /* Copied from http://sourceware.org/ml/newlib/2005/msg00248.html */
332 /* Copyright 2005 Shaun Jackman
333  * Permission to use, copy, modify, and distribute this software
334  * is freely granted, provided that this notice is preserved.
335  */
336 #include <string.h>
337 const char *dirname(char *path)
338 {
339         char *p;
340         if (path == NULL || *path == '\0')
341                 return ".";
342         p = path + strlen(path) - 1;
343         while (*p == '/') {
344                 if (p == path)
345                         return path;
346                 *p-- = '\0';
347         }
348         while (p >= path && *p != '/')
349                 p--;
350         return
351             p < path ? "." :
352             p == path ? "/" :
353             (*p = '\0', path);
354 }
355 /* End of copied part */
356
357 #else
358
359 /* intentionally empty for UNIX */
360
361 #endif