1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  * Windows-posix compatibility layer, windows-specific functions.
19  */
20 
21 /** \file
22  * \ingroup bli
23  */
24 
25 #ifdef WIN32
26 
27 #  include <conio.h>
28 #  include <stdio.h>
29 #  include <stdlib.h>
30 
31 #  include "MEM_guardedalloc.h"
32 
33 #  define WIN32_SKIP_HKEY_PROTECTION  // need to use HKEY
34 #  include "BLI_path_util.h"
35 #  include "BLI_string.h"
36 #  include "BLI_utildefines.h"
37 #  include "BLI_winstuff.h"
38 
39 #  include "utf_winfunc.h"
40 #  include "utfconv.h"
41 
42 /* FILE_MAXDIR + FILE_MAXFILE */
43 
BLI_windows_get_executable_dir(char * str)44 int BLI_windows_get_executable_dir(char *str)
45 {
46   char dir[FILE_MAXDIR];
47   int a;
48   /*change to utf support*/
49   GetModuleFileName(NULL, str, FILE_MAX);
50   BLI_split_dir_part(str, dir, sizeof(dir)); /* shouldn't be relative */
51   a = strlen(dir);
52   if (dir[a - 1] == '\\') {
53     dir[a - 1] = 0;
54   }
55 
56   strcpy(str, dir);
57 
58   return 1;
59 }
60 
register_blend_extension_failed(HKEY root,const bool background)61 static void register_blend_extension_failed(HKEY root, const bool background)
62 {
63   printf("failed\n");
64   if (root) {
65     RegCloseKey(root);
66   }
67   if (!background) {
68     MessageBox(0, "Could not register file extension.", "Blender error", MB_OK | MB_ICONERROR);
69   }
70   TerminateProcess(GetCurrentProcess(), 1);
71 }
72 
BLI_windows_register_blend_extension(const bool background)73 void BLI_windows_register_blend_extension(const bool background)
74 {
75   LONG lresult;
76   HKEY hkey = 0;
77   HKEY root = 0;
78   BOOL usr_mode = false;
79   DWORD dwd = 0;
80   char buffer[256];
81 
82   char BlPath[MAX_PATH];
83   char InstallDir[FILE_MAXDIR];
84   char SysDir[FILE_MAXDIR];
85   const char *ThumbHandlerDLL;
86   char RegCmd[MAX_PATH * 2];
87   char MBox[256];
88   char *blender_app;
89 #  ifndef _WIN64
90   BOOL IsWOW64;
91 #  endif
92 
93   printf("Registering file extension...");
94   GetModuleFileName(0, BlPath, MAX_PATH);
95 
96   /* Replace the actual app name with the wrapper. */
97   blender_app = strstr(BlPath, "blender-app.exe");
98   if (blender_app != NULL) {
99     strcpy(blender_app, "blender.exe");
100   }
101 
102   /* root is HKLM by default */
103   lresult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Classes", 0, KEY_ALL_ACCESS, &root);
104   if (lresult != ERROR_SUCCESS) {
105     /* try HKCU on failure */
106     usr_mode = true;
107     lresult = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Classes", 0, KEY_ALL_ACCESS, &root);
108     if (lresult != ERROR_SUCCESS) {
109       register_blend_extension_failed(0, background);
110     }
111   }
112 
113   lresult = RegCreateKeyEx(
114       root, "blendfile", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd);
115   if (lresult == ERROR_SUCCESS) {
116     strcpy(buffer, "Blender File");
117     lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1);
118     RegCloseKey(hkey);
119   }
120   if (lresult != ERROR_SUCCESS) {
121     register_blend_extension_failed(root, background);
122   }
123 
124   lresult = RegCreateKeyEx(root,
125                            "blendfile\\shell\\open\\command",
126                            0,
127                            NULL,
128                            REG_OPTION_NON_VOLATILE,
129                            KEY_ALL_ACCESS,
130                            NULL,
131                            &hkey,
132                            &dwd);
133   if (lresult == ERROR_SUCCESS) {
134     sprintf(buffer, "\"%s\" \"%%1\"", BlPath);
135     lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1);
136     RegCloseKey(hkey);
137   }
138   if (lresult != ERROR_SUCCESS) {
139     register_blend_extension_failed(root, background);
140   }
141 
142   lresult = RegCreateKeyEx(root,
143                            "blendfile\\DefaultIcon",
144                            0,
145                            NULL,
146                            REG_OPTION_NON_VOLATILE,
147                            KEY_ALL_ACCESS,
148                            NULL,
149                            &hkey,
150                            &dwd);
151   if (lresult == ERROR_SUCCESS) {
152     sprintf(buffer, "\"%s\", 1", BlPath);
153     lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1);
154     RegCloseKey(hkey);
155   }
156   if (lresult != ERROR_SUCCESS) {
157     register_blend_extension_failed(root, background);
158   }
159 
160   lresult = RegCreateKeyEx(
161       root, ".blend", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd);
162   if (lresult == ERROR_SUCCESS) {
163     strcpy(buffer, "blendfile");
164     lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1);
165     RegCloseKey(hkey);
166   }
167   if (lresult != ERROR_SUCCESS) {
168     register_blend_extension_failed(root, background);
169   }
170 
171   BLI_windows_get_executable_dir(InstallDir);
172   GetSystemDirectory(SysDir, FILE_MAXDIR);
173   ThumbHandlerDLL = "BlendThumb.dll";
174   snprintf(
175       RegCmd, MAX_PATH * 2, "%s\\regsvr32 /s \"%s\\%s\"", SysDir, InstallDir, ThumbHandlerDLL);
176   system(RegCmd);
177 
178   RegCloseKey(root);
179   printf("success (%s)\n", usr_mode ? "user" : "system");
180   if (!background) {
181     sprintf(MBox,
182             "File extension registered for %s.",
183             usr_mode ? "the current user. To register for all users, run as an administrator" :
184                        "all users");
185     MessageBox(0, MBox, "Blender", MB_OK | MB_ICONINFORMATION);
186   }
187   TerminateProcess(GetCurrentProcess(), 0);
188 }
189 
BLI_windows_get_default_root_dir(char * root)190 void BLI_windows_get_default_root_dir(char *root)
191 {
192   char str[MAX_PATH + 1];
193 
194   /* the default drive to resolve a directory without a specified drive
195    * should be the Windows installation drive, since this was what the OS
196    * assumes. */
197   if (GetWindowsDirectory(str, MAX_PATH + 1)) {
198     root[0] = str[0];
199     root[1] = ':';
200     root[2] = '\\';
201     root[3] = '\0';
202   }
203   else {
204     /* if GetWindowsDirectory fails, something has probably gone wrong,
205      * we are trying the blender install dir though */
206     if (GetModuleFileName(NULL, str, MAX_PATH + 1)) {
207       printf(
208           "Error! Could not get the Windows Directory - "
209           "Defaulting to Blender installation Dir!\n");
210       root[0] = str[0];
211       root[1] = ':';
212       root[2] = '\\';
213       root[3] = '\0';
214     }
215     else {
216       DWORD tmp;
217       int i;
218       int rc = 0;
219       /* now something has gone really wrong - still trying our best guess */
220       printf(
221           "Error! Could not get the Windows Directory - "
222           "Defaulting to first valid drive! Path might be invalid!\n");
223       tmp = GetLogicalDrives();
224       for (i = 2; i < 26; i++) {
225         if ((tmp >> i) & 1) {
226           root[0] = 'a' + i;
227           root[1] = ':';
228           root[2] = '\\';
229           root[3] = '\0';
230           if (GetFileAttributes(root) != 0xFFFFFFFF) {
231             rc = i;
232             break;
233           }
234         }
235       }
236       if (0 == rc) {
237         printf("ERROR in 'BLI_windows_get_default_root_dir': can't find a valid drive!\n");
238         root[0] = 'C';
239         root[1] = ':';
240         root[2] = '\\';
241         root[3] = '\0';
242       }
243     }
244   }
245 }
246 
247 #else
248 
249 /* intentionally empty for UNIX */
250 
251 #endif
252