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