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