d2c98b7aaf31cafd4412e79d04ce3c55da6a71d7
[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_utildefines.h"
45 #include "BKE_global.h"
46
47 #define WIN32_SKIP_HKEY_PROTECTION              // need to use HKEY
48 #include "BLI_winstuff.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 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 * 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         char * FileName;
221         size_t size;
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 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