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