3b06b7df09a4ac161dbb5588426765eb33b88e76
[blender-staging.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
42 #define WIN32_SKIP_HKEY_PROTECTION      // need to use HKEY
43 #include "BLI_winstuff.h"
44 #include "BLI_utildefines.h"
45 #include "BLI_path_util.h"
46 #include "BLI_string.h"
47
48 #include "../blenkernel/BKE_global.h"  /* G.background, bad level include (no function calls) */
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 static 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         char *blender_app;
96 #ifndef _WIN64
97         BOOL IsWOW64;
98 #endif
99
100         printf("Registering file extension...");
101         GetModuleFileName(0, BlPath, MAX_PATH);
102
103         /* Replace the actual app name with the wrapper. */
104         blender_app = strstr(BlPath, "blender-app.exe");
105         if (blender_app != NULL) {
106                 strcpy(blender_app, "blender.exe");
107         }
108
109         /* root is HKLM by default */
110         lresult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Classes", 0, KEY_ALL_ACCESS, &root);
111         if (lresult != ERROR_SUCCESS) {
112                 /* try HKCU on failure */
113                 usr_mode = true;
114                 lresult = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Classes", 0, KEY_ALL_ACCESS, &root);
115                 if (lresult != ERROR_SUCCESS)
116                         RegisterBlendExtension_Fail(0);
117         }
118
119         lresult = RegCreateKeyEx(root, "blendfile", 0,
120                                  NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd);
121         if (lresult == ERROR_SUCCESS) {
122                 strcpy(buffer, "Blender File");
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\\shell\\open\\command", 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, "blendfile\\DefaultIcon", 0,
140                                  NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd);
141         if (lresult == ERROR_SUCCESS) {
142                 sprintf(buffer, "\"%s\", 1", BlPath);
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         lresult = RegCreateKeyEx(root, ".blend", 0,
150                                  NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd);
151         if (lresult == ERROR_SUCCESS) {
152                 strcpy(buffer, "blendfile");
153                 lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1);
154                 RegCloseKey(hkey);
155         }
156         if (lresult != ERROR_SUCCESS)
157                 RegisterBlendExtension_Fail(root);
158         
159         BLI_getInstallationDir(InstallDir);
160         GetSystemDirectory(SysDir, FILE_MAXDIR);
161 #ifdef _WIN64
162         ThumbHandlerDLL = "BlendThumb64.dll";
163 #elif defined(__MINGW32__)
164         ThumbHandlerDLL = "BlendThumb.dll";
165 #else
166         IsWow64Process(GetCurrentProcess(), &IsWOW64);
167         if (IsWOW64 == true)
168                 ThumbHandlerDLL = "BlendThumb64.dll";
169         else
170                 ThumbHandlerDLL = "BlendThumb.dll";
171 #endif
172         snprintf(RegCmd, MAX_PATH * 2, "%s\\regsvr32 /s \"%s\\%s\"", SysDir, InstallDir, ThumbHandlerDLL);
173         system(RegCmd);
174
175         RegCloseKey(root);
176         printf("success (%s)\n", usr_mode ? "user" : "system");
177         if (!G.background) {
178                 sprintf(MBox, "File extension registered for %s.", usr_mode ? "the current user. To register for all users, run as an administrator" : "all users");
179                 MessageBox(0, MBox, "Blender", MB_OK | MB_ICONINFORMATION);
180         }
181         TerminateProcess(GetCurrentProcess(), 0);
182 }
183
184 void get_default_root(char *root)
185 {
186         char str[MAX_PATH + 1];
187         
188         /* the default drive to resolve a directory without a specified drive 
189          * should be the Windows installation drive, since this was what the OS
190          * assumes. */
191         if (GetWindowsDirectory(str, MAX_PATH + 1)) {
192                 root[0] = str[0];
193                 root[1] = ':';
194                 root[2] = '\\';
195                 root[3] = '\0';
196         }
197         else {
198                 /* if GetWindowsDirectory fails, something has probably gone wrong, 
199                  * we are trying the blender install dir though */
200                 if (GetModuleFileName(NULL, str, MAX_PATH + 1)) {
201                         printf("Error! Could not get the Windows Directory - "
202                                "Defaulting to Blender installation Dir!\n");
203                         root[0] = str[0];
204                         root[1] = ':';
205                         root[2] = '\\';
206                         root[3] = '\0';
207                 }
208                 else {
209                         DWORD tmp;
210                         int i;
211                         int rc = 0;
212                         /* now something has gone really wrong - still trying our best guess */
213                         printf("Error! Could not get the Windows Directory - "
214                                "Defaulting to first valid drive! Path might be invalid!\n");
215                         tmp = GetLogicalDrives();
216                         for (i = 2; i < 26; i++) {
217                                 if ((tmp >> i) & 1) {
218                                         root[0] = 'a' + i;
219                                         root[1] = ':';
220                                         root[2] = '\\';
221                                         root[3] = '\0';
222                                         if (GetFileAttributes(root) != 0xFFFFFFFF) {
223                                                 rc = i;
224                                                 break;
225                                         }
226                                 }
227                         }
228                         if (0 == rc) {
229                                 printf("ERROR in 'get_default_root': can't find a valid drive!\n");
230                                 root[0] = 'C';
231                                 root[1] = ':';
232                                 root[2] = '\\';
233                                 root[3] = '\0';
234                         }
235                 }
236         }
237 }
238
239 /* UNUSED */
240 #if 0
241 int check_file_chars(char *filename)
242 {
243         char *p = filename;
244         while (*p) {
245                 switch (*p) {
246                         case ':':
247                         case '?':
248                         case '*':
249                         case '|':
250                         case '\\':
251                         case '/':
252                         case '\"':
253                                 return 0;
254                                 break;
255                 }
256
257                 p++;
258         }
259         return 1;
260 }
261 #endif
262
263 #else
264
265 /* intentionally empty for UNIX */
266
267 #endif