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