Warning Fixes - const correctness in unicode encoding, unused variables in blenlib...
[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         if (dp->direntry.d_name) {
221                 MEM_freeN(dp->direntry.d_name);
222                 dp->direntry.d_name= NULL;
223         }
224                 
225         if (dp->handle==INVALID_HANDLE_VALUE) {
226                 wchar_t * path_16 = alloc_utf16_from_8(dp->path, 0);
227                 dp->handle= FindFirstFileW(path_16, &(dp->data));
228                 free(path_16);
229                 if (dp->handle==INVALID_HANDLE_VALUE)
230                         return NULL;
231                         
232                 dp->direntry.d_name= BLI_alloc_utf_8_from_16(dp->data.cFileName, 0);
233                 
234                 return &dp->direntry;
235         }
236         else if (FindNextFileW (dp->handle, &(dp->data))) {
237                 dp->direntry.d_name= BLI_alloc_utf_8_from_16(dp->data.cFileName,0);
238
239                 return &dp->direntry;
240         }
241         else {
242                 return NULL;
243         }
244 }
245
246 int closedir (DIR *dp)
247 {
248         if (dp->direntry.d_name) MEM_freeN(dp->direntry.d_name);
249         if (dp->handle!=INVALID_HANDLE_VALUE) FindClose(dp->handle);
250
251         MEM_freeN(dp);
252         
253         return 0;
254 }
255
256 void get_default_root(char* root)
257 {
258         char str[MAX_PATH+1];
259         
260         /* the default drive to resolve a directory without a specified drive 
261          * should be the Windows installation drive, since this was what the OS
262          * assumes. */
263         if (GetWindowsDirectory(str,MAX_PATH+1)) {
264                 root[0] = str[0];
265                 root[1] = ':';
266                 root[2] = '\\';
267                 root[3] = '\0';
268         }
269         else {
270                 /* if GetWindowsDirectory fails, something has probably gone wrong, 
271                  * we are trying the blender install dir though */
272                 if (GetModuleFileName(NULL,str,MAX_PATH+1)) {
273                         printf("Error! Could not get the Windows Directory - Defaulting to Blender installation Dir!");
274                         root[0] = str[0];
275                         root[1] = ':';
276                         root[2] = '\\';
277                         root[3] = '\0';
278                 }
279                 else {
280                         DWORD tmp;
281                         int i;
282                         int rc = 0;
283                         /* now something has gone really wrong - still trying our best guess */
284                         printf("Error! Could not get the Windows Directory - Defaulting to first valid drive! Path might be invalid!");
285                         tmp= GetLogicalDrives();
286                         for (i=2; i < 26; i++) {
287                                 if ((tmp>>i) & 1) {
288                                         root[0] = 'a'+i;
289                                         root[1] = ':';
290                                         root[2] = '\\';
291                                         root[3] = '\0';
292                                         if (GetFileAttributes(root) != 0xFFFFFFFF) {
293                                                 rc = i;
294                                                 break;                  
295                                         }
296                                 }
297                         }
298                         if (0 == rc) {
299                                 printf("ERROR in 'get_default_root': can't find a valid drive!");
300                                 root[0] = 'C';
301                                 root[1] = ':';
302                                 root[2] = '\\';
303                                 root[3] = '\0';
304                         }
305                 }               
306         }
307 }
308
309 int check_file_chars(char *filename)
310 {
311         char *p = filename;
312         while (*p) {
313                 switch (*p) {
314                         case ':':
315                         case '?':
316                         case '*':
317                         case '|':
318                         case '\\':
319                         case '/':
320                         case '\"':
321                                 return 0;
322                                 break;
323                 }
324
325                 p++;
326         }
327         return 1;
328 }
329
330 /* Copied from http://sourceware.org/ml/newlib/2005/msg00248.html */
331 /* Copyright 2005 Shaun Jackman
332  * Permission to use, copy, modify, and distribute this software
333  * is freely granted, provided that this notice is preserved.
334  */
335 #include <string.h>
336 char* dirname(char *path)
337 {
338         char *p;
339         if ( path == NULL || *path == '\0' )
340                 return ".";
341         p = path + strlen(path) - 1;
342         while ( *p == '/' ) {
343                 if ( p == path )
344                         return path;
345                 *p-- = '\0';
346         }
347         while ( p >= path && *p != '/' )
348                 p--;
349         return
350                 p < path ? "." :
351                 p == path ? "/" :
352                 (*p = '\0', path);
353 }
354 /* End of copied part */
355
356 #else
357
358 /* intentionally empty for UNIX */
359
360 #endif