21# define WIN32_SKIP_HKEY_PROTECTION
39 GetModuleFileName(
NULL, filepath,
sizeof(filepath));
42 if (dir[a - 1] ==
'\\') {
58static void registry_error(HKEY root,
const char *message)
63 fprintf(stderr,
"%s\n", message);
66static bool open_registry_hive(
bool all_users, HKEY *r_root)
68 if (RegOpenKeyEx(all_users ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
72 r_root) != ERROR_SUCCESS)
74 registry_error(*r_root,
"Unable to open the registry with the required permissions");
80static bool register_blender_prog_id(
const char *prog_id,
81 const char *executable,
82 const char *friendly_name,
91 if (!open_registry_hive(all_users, &root)) {
95 lresult = RegCreateKeyEx(
96 root, prog_id, 0,
NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
NULL, &hkey_progid, &dwd);
98 if (lresult == ERROR_SUCCESS) {
99 lresult = RegSetValueEx(
100 hkey_progid,
NULL, 0, REG_SZ, (BYTE *)friendly_name, strlen(friendly_name) + 1);
102 if (lresult == ERROR_SUCCESS) {
103 lresult = RegSetValueEx(
104 hkey_progid,
"AppUserModelId", 0, REG_SZ, (BYTE *)prog_id, strlen(prog_id) + 1);
106 if (lresult != ERROR_SUCCESS) {
107 registry_error(root,
"Unable to register Blender App Id");
111 SNPRINTF(buffer,
"%s\\shell\\open", prog_id);
112 lresult = RegCreateKeyEx(
113 root, buffer, 0,
NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
NULL, &hkey_progid, &dwd);
115 lresult = RegSetValueEx(
116 hkey_progid,
"FriendlyAppName", 0, REG_SZ, (BYTE *)friendly_name, strlen(friendly_name) + 1);
118 SNPRINTF(buffer,
"%s\\shell\\open\\command", prog_id);
120 lresult = RegCreateKeyEx(
121 root, buffer, 0,
NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
NULL, &hkey_progid, &dwd);
123 if (lresult == ERROR_SUCCESS) {
124 SNPRINTF(buffer,
"\"%s\" \"%%1\"", executable);
125 lresult = RegSetValueEx(hkey_progid,
NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1);
126 RegCloseKey(hkey_progid);
128 if (lresult != ERROR_SUCCESS) {
129 registry_error(root,
"Unable to register Blender App Id");
133 SNPRINTF(buffer,
"%s\\DefaultIcon", prog_id);
134 lresult = RegCreateKeyEx(
135 root, buffer, 0,
NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
NULL, &hkey_progid, &dwd);
137 if (lresult == ERROR_SUCCESS) {
138 SNPRINTF(buffer,
"\"%s\", 1", executable);
139 lresult = RegSetValueEx(hkey_progid,
NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1);
140 RegCloseKey(hkey_progid);
142 if (lresult != ERROR_SUCCESS) {
143 registry_error(root,
"Unable to register Blender App Id");
152 fprintf(stderr,
"Registration not possible from Microsoft Store installation.");
157 char blender_path[MAX_PATH];
162 const char *prog_id = BLENDER_WIN_APPID;
163 const char *friendly_name = BLENDER_WIN_APPID_FRIENDLY_NAME;
165 GetModuleFileName(0, blender_path,
sizeof(blender_path));
168 if (strlen(blender_path) > (
sizeof(blender_path) - 10))
172 blender_app = strstr(blender_path,
"blender.exe");
176 strcpy(blender_app,
"blender-launcher.exe");
178 if (!open_registry_hive(all_users, &root)) {
182 if (!register_blender_prog_id(prog_id, blender_path, friendly_name, all_users)) {
183 registry_error(root,
"Unable to register Blend document type");
187 lresult = RegCreateKeyEx(
188 root,
".blend", 0,
NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
NULL, &hkey, &dwd);
189 if (lresult == ERROR_SUCCESS) {
191 lresult = RegSetValueEx(hkey,
NULL, 0, REG_SZ, (BYTE *)prog_id, strlen(prog_id) + 1);
193 if (lresult != ERROR_SUCCESS) {
194 registry_error(root,
"Unable to register Blend document type");
200 lresult = RegCreateKeyEx(root,
201 ".blend\\OpenWithProgids",
204 REG_OPTION_NON_VOLATILE,
210 if (lresult != ERROR_SUCCESS) {
211 registry_error(root,
"Unable to register Blend document type");
215 lresult = RegSetValueEx(hkey, prog_id, 0, REG_NONE,
NULL, 0);
219 if (lresult != ERROR_SUCCESS) {
220 registry_error(root,
"Unable to register Blend document type");
225 fprintf(stderr,
"Update of pinned launcher failed.");
229# ifdef WITH_BLENDER_THUMBNAILER
231 char reg_cmd[MAX_PATH * 2];
235 GetSystemDirectory(system_dir,
sizeof(system_dir));
236 const char *thumbnail_handler =
"BlendThumb.dll";
237 SNPRINTF(reg_cmd,
"%s\\regsvr32 /s \"%s\\%s\"", system_dir, install_dir, thumbnail_handler);
245 "Blend file extension registered for %s.",
246 all_users ?
"all users" :
"the current user");
255 fprintf(stderr,
"Unregistration not possible from Microsoft Store installation.");
263 if (!open_registry_hive(all_users, &root)) {
269 RegDeleteTree(root, BLENDER_WIN_APPID);
271 lresult = RegOpenKeyEx(root,
".blend", 0, KEY_ALL_ACCESS, &hkey);
272 if (lresult == ERROR_SUCCESS) {
273 char buffer[256] = {0};
274 DWORD size =
sizeof(buffer);
275 lresult = RegGetValueA(hkey,
NULL,
NULL, RRF_RT_REG_SZ,
NULL, &buffer, &size);
276 if (lresult == ERROR_SUCCESS &&
STREQ(buffer, BLENDER_WIN_APPID)) {
277 RegSetValueEx(hkey,
NULL, 0, REG_SZ, 0, 0);
281# ifdef WITH_BLENDER_THUMBNAILER
283 char reg_cmd[MAX_PATH * 2];
287 GetSystemDirectory(system_dir,
sizeof(system_dir));
288 const char *thumbnail_handler =
"BlendThumb.dll";
289 SNPRINTF(reg_cmd,
"%s\\regsvr32 /u /s \"%s\\%s\"", system_dir, install_dir, thumbnail_handler);
294 lresult = RegOpenKeyEx(hkey,
"OpenWithProgids", 0, KEY_ALL_ACCESS, &hkey);
295 if (lresult == ERROR_SUCCESS) {
296 RegDeleteValue(hkey, BLENDER_WIN_APPID);
302 "Blend file extension unregistered for %s.",
303 all_users ?
"all users" :
"the current user");
315static bool BLI_windows_file_operation_is_registered(
const char *extension,
const char *operation)
318 HRESULT hr = AssocQueryKey(ASSOCF_INIT_IGNOREUNKNOWN,
319 ASSOCKEY_SHELLEXECCLASS,
332 if (
STREQ(operation,
"open") ||
STREQ(operation,
"properties")) {
337 return BLI_windows_file_operation_is_registered(
"Directory", operation);
341 return BLI_windows_file_operation_is_registered(extension, operation);
356 SHELLEXECUTEINFOW shellinfo = {0};
357 shellinfo.cbSize =
sizeof(SHELLEXECUTEINFO);
358 shellinfo.fMask = SEE_MASK_INVOKEIDLIST;
359 shellinfo.lpVerb = woperation;
360 shellinfo.lpFile = wpath;
361 shellinfo.nShow = SW_SHOW;
363 return ShellExecuteExW(&shellinfo);
371 char blender_path[MAX_PATH];
372 GetModuleFileName(0, blender_path, MAX_PATH);
374 SHELLEXECUTEINFOA shellinfo = {0};
375 shellinfo.cbSize =
sizeof(SHELLEXECUTEINFO);
376 shellinfo.fMask = wait ? SEE_MASK_NOCLOSEPROCESS : SEE_MASK_DEFAULT;
377 shellinfo.hwnd =
NULL;
378 shellinfo.lpVerb = elevated ?
"runas" :
NULL;
379 shellinfo.lpFile = blender_path;
381 shellinfo.lpDirectory =
NULL;
382 shellinfo.nShow = silent ? SW_HIDE : SW_SHOW;
383 shellinfo.hInstApp =
NULL;
384 shellinfo.hProcess = 0;
387 if (!ShellExecuteExA(&shellinfo)) {
394 if (shellinfo.hProcess != 0) {
395 WaitForSingleObject(shellinfo.hProcess, INFINITE);
396 GetExitCodeProcess(shellinfo.hProcess, &exitCode);
397 CloseHandle(shellinfo.hProcess);
398 return (exitCode == 0);
406 char str[MAX_PATH + 1];
411 if (GetWindowsDirectory(
str, MAX_PATH + 1)) {
420 if (GetModuleFileName(
NULL,
str, MAX_PATH + 1)) {
422 "Error! Could not get the Windows Directory - "
423 "Defaulting to Blender installation Dir!\n");
435 "Error! Could not get the Windows Directory - "
436 "Defaulting to first valid drive! Path might be invalid!\n");
437 tmp = GetLogicalDrives();
438 for (i = 2; i < 26; i++) {
439 if ((tmp >> i) & 1) {
444 if (GetFileAttributes(root) != 0xFFFFFFFF) {
451 printf(
"ERROR in 'BLI_windows_get_default_root_dir': can't find a valid drive!\n");
462 long long *r_driverVersion)
464 IDXGIFactory *pFactory =
NULL;
465 IDXGIAdapter *pAdapter =
NULL;
466 if (CreateDXGIFactory(__uuidof(IDXGIFactory), (
void **)&pFactory) == S_OK) {
467 for (UINT i = 0; pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++i) {
468 LARGE_INTEGER version;
469 if (pAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &version) == S_OK) {
470 DXGI_ADAPTER_DESC desc;
471 if (pAdapter->GetDesc(&desc) == S_OK) {
472 if (wcsstr(desc.Description, deviceSubString)) {
473 *r_driverVersion = version.QuadPart;
File and directory operations.
bool BLI_is_dir(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void void BLI_path_split_dir_part(const char *filepath, char *dir, size_t dir_maxncpy) ATTR_NONNULL(1
const char * BLI_path_extension(const char *filepath) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
#define SNPRINTF(dst, format,...)
int char * BLI_strcasestr(const char *s, const char *find) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
Compatibility-like things for windows.
bool BLI_windows_external_operation_supported(const char *filepath, const char *operation)
bool BLI_windows_unregister_blend_extension(bool all_users)
bool BLI_windows_execute_self(const char *parameters, const bool wait, const bool elevated, const bool silent)
bool BLI_windows_get_directx_driver_version(const wchar_t *deviceSubString, long long *r_driverVersion)
void BLI_windows_get_default_root_dir(char root_dir[4])
bool BLI_windows_update_pinned_launcher(const char *launcher_path)
bool BLI_windows_external_operation_execute(const char *filepath, const char *operation)
int BLI_windows_get_executable_dir(char r_dirpath[])
bool BLI_windows_is_store_install(void)
bool BLI_windows_register_blend_extension(bool all_users)
Read Guarded memory(de)allocation.
double parameters[NUM_PARAMETERS]
int conv_utf_8_to_16(const char *in8, wchar_t *out16, size_t size16)