2023-05-31 16:19:06 +02:00
|
|
|
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup bli
|
2022-02-16 13:02:53 +11:00
|
|
|
* WIN32-POSIX compatibility layer, MS-Windows-specific functions.
|
2011-02-27 20:37:56 +00:00
|
|
|
*/
|
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
#ifdef WIN32
|
|
|
|
|
|
2011-04-08 12:49:38 +00:00
|
|
|
# include <conio.h>
|
2023-04-19 08:02:42 +10:00
|
|
|
# include <shlwapi.h>
|
2020-03-19 09:33:03 +01:00
|
|
|
# include <stdio.h>
|
|
|
|
|
# include <stdlib.h>
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2010-09-15 16:13:32 +00:00
|
|
|
# include "MEM_guardedalloc.h"
|
2011-01-07 23:54:58 +00:00
|
|
|
|
2021-07-20 15:01:05 +10:00
|
|
|
# define WIN32_SKIP_HKEY_PROTECTION /* Need to use HKEY. */
|
2023-04-18 20:39:30 +02:00
|
|
|
# include "BLI_fileops.h"
|
2012-09-03 22:04:14 +00:00
|
|
|
# include "BLI_path_util.h"
|
2013-03-05 07:02:59 +00:00
|
|
|
# include "BLI_string.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
# include "BLI_utildefines.h"
|
|
|
|
|
# include "BLI_winstuff.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2012-03-20 02:17:37 +00:00
|
|
|
# include "utf_winfunc.h"
|
|
|
|
|
# include "utfconv.h"
|
|
|
|
|
|
2012-05-12 15:13:06 +00:00
|
|
|
/* FILE_MAXDIR + FILE_MAXFILE */
|
2003-05-22 18:06:25 +00:00
|
|
|
|
2023-05-29 19:56:06 +10:00
|
|
|
int BLI_windows_get_executable_dir(char r_dirpath[/*FILE_MAXDIR*/])
|
2011-12-17 00:52:36 +00:00
|
|
|
{
|
2023-05-29 19:56:06 +10:00
|
|
|
char filepath[FILE_MAX];
|
|
|
|
|
char dir[FILE_MAX];
|
2004-01-07 21:03:11 +00:00
|
|
|
int a;
|
2021-06-26 21:35:18 +10:00
|
|
|
/* Change to utf support. */
|
2023-05-29 19:56:06 +10:00
|
|
|
GetModuleFileName(NULL, filepath, sizeof(filepath));
|
|
|
|
|
BLI_path_split_dir_part(filepath, dir, sizeof(dir)); /* shouldn't be relative */
|
2004-01-07 21:03:11 +00:00
|
|
|
a = strlen(dir);
|
2019-03-27 13:16:10 +11:00
|
|
|
if (dir[a - 1] == '\\') {
|
|
|
|
|
dir[a - 1] = 0;
|
|
|
|
|
}
|
2018-06-17 16:32:54 +02:00
|
|
|
|
2023-05-29 19:56:06 +10:00
|
|
|
BLI_strncpy(r_dirpath, dir, FILE_MAXDIR);
|
2018-06-17 16:32:54 +02:00
|
|
|
|
2003-06-11 20:26:35 +00:00
|
|
|
return 1;
|
2003-05-22 18:06:25 +00:00
|
|
|
}
|
|
|
|
|
|
2023-05-26 13:30:14 +10:00
|
|
|
bool BLI_windows_is_store_install(void)
|
|
|
|
|
{
|
2023-05-24 21:19:56 +02:00
|
|
|
char install_dir[FILE_MAXDIR];
|
|
|
|
|
BLI_windows_get_executable_dir(install_dir);
|
|
|
|
|
return (BLI_strcasestr(install_dir, "\\WindowsApps\\") != NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void registry_error(HKEY root, const char *message)
|
2011-03-29 13:00:03 +00:00
|
|
|
{
|
2019-03-27 13:16:10 +11:00
|
|
|
if (root) {
|
2011-03-29 13:00:03 +00:00
|
|
|
RegCloseKey(root);
|
2019-03-27 13:16:10 +11:00
|
|
|
}
|
2023-05-24 21:19:56 +02:00
|
|
|
fprintf(stderr, "%s\n", message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool open_registry_hive(bool all_users, HKEY *r_root)
|
|
|
|
|
{
|
|
|
|
|
if (RegOpenKeyEx(all_users ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
|
|
|
|
|
"Software\\Classes",
|
|
|
|
|
0,
|
|
|
|
|
KEY_ALL_ACCESS,
|
|
|
|
|
r_root) != ERROR_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
registry_error(*r_root, "Unable to open the registry with the required permissions");
|
|
|
|
|
return false;
|
2019-03-27 13:16:10 +11:00
|
|
|
}
|
2023-05-24 21:19:56 +02:00
|
|
|
return true;
|
2011-03-29 13:00:03 +00:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2023-05-24 21:19:56 +02:00
|
|
|
static bool register_blender_prog_id(const char *prog_id,
|
|
|
|
|
const char *executable,
|
|
|
|
|
const char *friendly_name,
|
|
|
|
|
bool all_users)
|
2011-12-17 00:52:36 +00:00
|
|
|
{
|
2002-10-12 11:37:38 +00:00
|
|
|
LONG lresult;
|
2011-03-29 13:00:03 +00:00
|
|
|
HKEY root = 0;
|
2023-05-24 21:19:56 +02:00
|
|
|
HKEY hkey_progid = 0;
|
2011-03-29 13:00:03 +00:00
|
|
|
char buffer[256];
|
2023-05-24 21:19:56 +02:00
|
|
|
DWORD dwd = 0;
|
2011-03-29 13:00:03 +00:00
|
|
|
|
2023-05-24 21:19:56 +02:00
|
|
|
if (!open_registry_hive(all_users, &root)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2011-03-29 13:00:03 +00:00
|
|
|
|
2023-05-24 21:19:56 +02:00
|
|
|
lresult = RegCreateKeyEx(
|
|
|
|
|
root, prog_id, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey_progid, &dwd);
|
2011-03-29 13:00:03 +00:00
|
|
|
|
2023-05-24 21:19:56 +02:00
|
|
|
if (lresult == ERROR_SUCCESS) {
|
|
|
|
|
lresult = RegSetValueEx(
|
|
|
|
|
hkey_progid, NULL, 0, REG_SZ, (BYTE *)friendly_name, strlen(friendly_name) + 1);
|
|
|
|
|
}
|
|
|
|
|
if (lresult == ERROR_SUCCESS) {
|
|
|
|
|
lresult = RegSetValueEx(
|
|
|
|
|
hkey_progid, "AppUserModelId", 0, REG_SZ, (BYTE *)prog_id, strlen(prog_id) + 1);
|
2014-08-29 17:36:59 +06:00
|
|
|
}
|
2012-03-07 04:53:43 +00:00
|
|
|
if (lresult != ERROR_SUCCESS) {
|
2023-05-24 21:19:56 +02:00
|
|
|
registry_error(root, "Unable to register Blender App Id");
|
|
|
|
|
return false;
|
2011-03-29 13:00:03 +00:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2023-05-24 21:19:56 +02:00
|
|
|
SNPRINTF(buffer, "%s\\shell\\open", prog_id);
|
|
|
|
|
lresult = RegCreateKeyEx(
|
|
|
|
|
root, buffer, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey_progid, &dwd);
|
|
|
|
|
|
|
|
|
|
lresult = RegSetValueEx(
|
|
|
|
|
hkey_progid, "FriendlyAppName", 0, REG_SZ, (BYTE *)friendly_name, strlen(friendly_name) + 1);
|
|
|
|
|
|
|
|
|
|
SNPRINTF(buffer, "%s\\shell\\open\\command", prog_id);
|
|
|
|
|
|
2011-03-29 13:00:03 +00:00
|
|
|
lresult = RegCreateKeyEx(
|
2023-05-24 21:19:56 +02:00
|
|
|
root, buffer, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey_progid, &dwd);
|
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (lresult == ERROR_SUCCESS) {
|
2023-05-24 21:19:56 +02:00
|
|
|
SNPRINTF(buffer, "\"%s\" \"%%1\"", executable);
|
|
|
|
|
lresult = RegSetValueEx(hkey_progid, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1);
|
|
|
|
|
RegCloseKey(hkey_progid);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2019-03-27 13:16:10 +11:00
|
|
|
if (lresult != ERROR_SUCCESS) {
|
2023-05-24 21:19:56 +02:00
|
|
|
registry_error(root, "Unable to register Blender App Id");
|
2021-06-14 10:15:37 -07:00
|
|
|
return false;
|
2019-03-27 13:16:10 +11:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2023-05-24 21:19:56 +02:00
|
|
|
SNPRINTF(buffer, "%s\\DefaultIcon", prog_id);
|
|
|
|
|
lresult = RegCreateKeyEx(
|
|
|
|
|
root, buffer, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey_progid, &dwd);
|
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if (lresult == ERROR_SUCCESS) {
|
2023-05-24 21:19:56 +02:00
|
|
|
SNPRINTF(buffer, "\"%s\", 1", executable);
|
|
|
|
|
lresult = RegSetValueEx(hkey_progid, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1);
|
|
|
|
|
RegCloseKey(hkey_progid);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
2019-03-27 13:16:10 +11:00
|
|
|
if (lresult != ERROR_SUCCESS) {
|
2023-05-24 21:19:56 +02:00
|
|
|
registry_error(root, "Unable to register Blender App Id");
|
2021-06-14 10:15:37 -07:00
|
|
|
return false;
|
2019-03-27 13:16:10 +11:00
|
|
|
}
|
2023-05-24 21:19:56 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2023-05-24 21:19:56 +02:00
|
|
|
bool BLI_windows_register_blend_extension(const bool all_users)
|
|
|
|
|
{
|
|
|
|
|
if (BLI_windows_is_store_install()) {
|
|
|
|
|
fprintf(stderr, "Registration not possible from Microsoft Store installation.");
|
|
|
|
|
return false;
|
2011-03-29 13:00:03 +00:00
|
|
|
}
|
2023-05-24 21:19:56 +02:00
|
|
|
|
|
|
|
|
HKEY root = 0;
|
|
|
|
|
char blender_path[MAX_PATH];
|
|
|
|
|
char *blender_app;
|
|
|
|
|
HKEY hkey = 0;
|
|
|
|
|
LONG lresult;
|
|
|
|
|
DWORD dwd = 0;
|
|
|
|
|
const char *prog_id = BLENDER_WIN_APPID;
|
|
|
|
|
const char *friendly_name = BLENDER_WIN_APPID_FRIENDLY_NAME;
|
|
|
|
|
|
|
|
|
|
GetModuleFileName(0, blender_path, sizeof(blender_path));
|
|
|
|
|
|
|
|
|
|
/* Prevent overflow when we add -launcher to the executable name. */
|
|
|
|
|
if (strlen(blender_path) > (sizeof(blender_path) - 10))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
/* Replace the actual app name with the wrapper. */
|
|
|
|
|
blender_app = strstr(blender_path, "blender.exe");
|
|
|
|
|
if (!blender_app) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
strcpy(blender_app, "blender-launcher.exe");
|
|
|
|
|
|
|
|
|
|
if (!open_registry_hive(all_users, &root)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!register_blender_prog_id(prog_id, blender_path, friendly_name, all_users)) {
|
|
|
|
|
registry_error(root, "Unable to register Blend document type");
|
2021-06-14 10:15:37 -07:00
|
|
|
return false;
|
2019-03-27 13:16:10 +11:00
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2011-03-29 13:00:03 +00:00
|
|
|
lresult = RegCreateKeyEx(
|
2012-05-12 15:13:06 +00:00
|
|
|
root, ".blend", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd);
|
2002-10-12 11:37:38 +00:00
|
|
|
if (lresult == ERROR_SUCCESS) {
|
2023-05-24 21:19:56 +02:00
|
|
|
/* Set this instance the default. */
|
|
|
|
|
lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)prog_id, strlen(prog_id) + 1);
|
|
|
|
|
|
|
|
|
|
if (lresult != ERROR_SUCCESS) {
|
|
|
|
|
registry_error(root, "Unable to register Blend document type");
|
|
|
|
|
RegCloseKey(hkey);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
RegCloseKey(hkey);
|
|
|
|
|
|
|
|
|
|
lresult = RegCreateKeyEx(root,
|
|
|
|
|
".blend\\OpenWithProgids",
|
|
|
|
|
0,
|
|
|
|
|
NULL,
|
|
|
|
|
REG_OPTION_NON_VOLATILE,
|
|
|
|
|
KEY_ALL_ACCESS,
|
|
|
|
|
NULL,
|
|
|
|
|
&hkey,
|
|
|
|
|
&dwd);
|
|
|
|
|
|
|
|
|
|
if (lresult != ERROR_SUCCESS) {
|
|
|
|
|
registry_error(root, "Unable to register Blend document type");
|
|
|
|
|
RegCloseKey(hkey);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
lresult = RegSetValueEx(hkey, prog_id, 0, REG_NONE, NULL, 0);
|
2002-10-12 11:37:38 +00:00
|
|
|
RegCloseKey(hkey);
|
|
|
|
|
}
|
2023-05-24 21:19:56 +02:00
|
|
|
|
2019-03-27 13:16:10 +11:00
|
|
|
if (lresult != ERROR_SUCCESS) {
|
2023-05-24 21:19:56 +02:00
|
|
|
registry_error(root, "Unable to register Blend document type");
|
2021-06-14 10:15:37 -07:00
|
|
|
return false;
|
2019-03-27 13:16:10 +11:00
|
|
|
}
|
2018-06-17 16:32:54 +02:00
|
|
|
|
2021-10-28 21:03:47 +02:00
|
|
|
# ifdef WITH_BLENDER_THUMBNAILER
|
2022-08-31 14:26:47 +10:00
|
|
|
{
|
2023-05-24 21:19:56 +02:00
|
|
|
char reg_cmd[MAX_PATH * 2];
|
|
|
|
|
char install_dir[FILE_MAXDIR];
|
|
|
|
|
char system_dir[FILE_MAXDIR];
|
|
|
|
|
BLI_windows_get_executable_dir(install_dir);
|
|
|
|
|
GetSystemDirectory(system_dir, sizeof(system_dir));
|
|
|
|
|
const char *thumbnail_handler = "BlendThumb.dll";
|
|
|
|
|
SNPRINTF(reg_cmd, "%s\\regsvr32 /s \"%s\\%s\"", system_dir, install_dir, thumbnail_handler);
|
|
|
|
|
system(reg_cmd);
|
2022-08-31 14:26:47 +10:00
|
|
|
}
|
2021-10-28 21:03:47 +02:00
|
|
|
# endif
|
2011-03-29 13:00:03 +00:00
|
|
|
|
|
|
|
|
RegCloseKey(root);
|
2023-05-24 21:19:56 +02:00
|
|
|
char message[256];
|
|
|
|
|
SNPRINTF(message,
|
|
|
|
|
"Blend file extension registered for %s.",
|
|
|
|
|
all_users ? "all users" : "the current user");
|
|
|
|
|
printf("%s\n", message);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool BLI_windows_unregister_blend_extension(const bool all_users)
|
|
|
|
|
{
|
|
|
|
|
if (BLI_windows_is_store_install()) {
|
|
|
|
|
fprintf(stderr, "Unregistration not possible from Microsoft Store installation.");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HKEY root = 0;
|
|
|
|
|
HKEY hkey = 0;
|
|
|
|
|
LONG lresult;
|
|
|
|
|
|
|
|
|
|
if (!open_registry_hive(all_users, &root)) {
|
|
|
|
|
return false;
|
2011-03-29 13:00:03 +00:00
|
|
|
}
|
2023-05-24 21:19:56 +02:00
|
|
|
|
|
|
|
|
/* Don't stop on failure. We want to allow unregister after unregister. */
|
|
|
|
|
|
|
|
|
|
RegDeleteTree(root, BLENDER_WIN_APPID);
|
|
|
|
|
|
|
|
|
|
lresult = RegOpenKeyEx(root, ".blend", 0, KEY_ALL_ACCESS, &hkey);
|
|
|
|
|
if (lresult == ERROR_SUCCESS) {
|
|
|
|
|
char buffer[256] = {0};
|
|
|
|
|
DWORD size = sizeof(buffer);
|
|
|
|
|
lresult = RegGetValueA(hkey, NULL, NULL, RRF_RT_REG_SZ, NULL, &buffer, &size);
|
|
|
|
|
if (lresult == ERROR_SUCCESS && STREQ(buffer, BLENDER_WIN_APPID)) {
|
|
|
|
|
RegSetValueEx(hkey, NULL, 0, REG_SZ, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# ifdef WITH_BLENDER_THUMBNAILER
|
|
|
|
|
{
|
|
|
|
|
char reg_cmd[MAX_PATH * 2];
|
|
|
|
|
char install_dir[FILE_MAXDIR];
|
|
|
|
|
char system_dir[FILE_MAXDIR];
|
|
|
|
|
BLI_windows_get_executable_dir(install_dir);
|
|
|
|
|
GetSystemDirectory(system_dir, sizeof(system_dir));
|
|
|
|
|
const char *thumbnail_handler = "BlendThumb.dll";
|
2023-05-24 15:26:21 -07:00
|
|
|
SNPRINTF(reg_cmd, "%s\\regsvr32 /u /s \"%s\\%s\"", system_dir, install_dir, thumbnail_handler);
|
2023-05-24 21:19:56 +02:00
|
|
|
system(reg_cmd);
|
|
|
|
|
}
|
|
|
|
|
# endif
|
|
|
|
|
|
|
|
|
|
lresult = RegOpenKeyEx(hkey, "OpenWithProgids", 0, KEY_ALL_ACCESS, &hkey);
|
|
|
|
|
if (lresult == ERROR_SUCCESS) {
|
|
|
|
|
RegDeleteValue(hkey, BLENDER_WIN_APPID);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RegCloseKey(root);
|
|
|
|
|
char message[256];
|
|
|
|
|
SNPRINTF(message,
|
|
|
|
|
"Blend file extension unregistered for %s.",
|
|
|
|
|
all_users ? "all users" : "the current user");
|
|
|
|
|
printf("%s\n", message);
|
|
|
|
|
|
2021-06-14 10:15:37 -07:00
|
|
|
return true;
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
2023-04-19 08:02:41 +10:00
|
|
|
/**
|
|
|
|
|
* Check the registry to see if there is an operation association to a file
|
|
|
|
|
* extension. Extension *should almost always contain a dot like `.txt`,
|
2023-04-18 20:39:30 +02:00
|
|
|
* but this does allow querying non - extensions *like "Directory", "Drive",
|
|
|
|
|
* "AllProtocols", etc - anything in Classes with a "shell" branch.
|
|
|
|
|
*/
|
|
|
|
|
static bool BLI_windows_file_operation_is_registered(const char *extension, const char *operation)
|
|
|
|
|
{
|
|
|
|
|
HKEY hKey;
|
|
|
|
|
HRESULT hr = AssocQueryKey(ASSOCF_INIT_IGNOREUNKNOWN,
|
|
|
|
|
ASSOCKEY_SHELLEXECCLASS,
|
|
|
|
|
(LPCTSTR)extension,
|
|
|
|
|
(LPCTSTR)operation,
|
|
|
|
|
&hKey);
|
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool BLI_windows_external_operation_supported(const char *filepath, const char *operation)
|
|
|
|
|
{
|
|
|
|
|
if (STREQ(operation, "open") || STREQ(operation, "properties")) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (BLI_is_dir(filepath)) {
|
|
|
|
|
return BLI_windows_file_operation_is_registered("Directory", operation);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *extension = BLI_path_extension(filepath);
|
|
|
|
|
return BLI_windows_file_operation_is_registered(extension, operation);
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-18 13:58:02 -07:00
|
|
|
bool BLI_windows_external_operation_execute(const char *filepath, const char *operation)
|
2023-04-18 20:39:30 +02:00
|
|
|
{
|
|
|
|
|
WCHAR wpath[FILE_MAX];
|
|
|
|
|
if (conv_utf_8_to_16(filepath, wpath, ARRAY_SIZE(wpath)) != 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WCHAR woperation[FILE_MAX];
|
|
|
|
|
if (conv_utf_8_to_16(operation, woperation, ARRAY_SIZE(woperation)) != 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SHELLEXECUTEINFOW shellinfo = {0};
|
|
|
|
|
shellinfo.cbSize = sizeof(SHELLEXECUTEINFO);
|
|
|
|
|
shellinfo.fMask = SEE_MASK_INVOKEIDLIST;
|
|
|
|
|
shellinfo.lpVerb = woperation;
|
|
|
|
|
shellinfo.lpFile = wpath;
|
|
|
|
|
shellinfo.nShow = SW_SHOW;
|
|
|
|
|
|
|
|
|
|
return ShellExecuteExW(&shellinfo);
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-24 21:19:56 +02:00
|
|
|
bool BLI_windows_execute_self(const char *parameters,
|
|
|
|
|
const bool wait,
|
|
|
|
|
const bool elevated,
|
|
|
|
|
const bool silent)
|
|
|
|
|
{
|
|
|
|
|
char blender_path[MAX_PATH];
|
|
|
|
|
GetModuleFileName(0, blender_path, MAX_PATH);
|
|
|
|
|
|
|
|
|
|
SHELLEXECUTEINFOA shellinfo = {0};
|
|
|
|
|
shellinfo.cbSize = sizeof(SHELLEXECUTEINFO);
|
|
|
|
|
shellinfo.fMask = wait ? SEE_MASK_NOCLOSEPROCESS : SEE_MASK_DEFAULT;
|
|
|
|
|
shellinfo.hwnd = NULL;
|
|
|
|
|
shellinfo.lpVerb = elevated ? "runas" : NULL;
|
|
|
|
|
shellinfo.lpFile = blender_path;
|
|
|
|
|
shellinfo.lpParameters = parameters;
|
|
|
|
|
shellinfo.lpDirectory = NULL;
|
|
|
|
|
shellinfo.nShow = silent ? SW_HIDE : SW_SHOW;
|
|
|
|
|
shellinfo.hInstApp = NULL;
|
|
|
|
|
shellinfo.hProcess = 0;
|
|
|
|
|
|
|
|
|
|
DWORD exitCode = 0;
|
|
|
|
|
if (!ShellExecuteExA(&shellinfo)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (!wait) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (shellinfo.hProcess != 0) {
|
|
|
|
|
WaitForSingleObject(shellinfo.hProcess, INFINITE);
|
|
|
|
|
GetExitCodeProcess(shellinfo.hProcess, &exitCode);
|
|
|
|
|
CloseHandle(shellinfo.hProcess);
|
|
|
|
|
return (exitCode == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-01 13:09:02 +11:00
|
|
|
void BLI_windows_get_default_root_dir(char root[4])
|
2011-12-17 00:52:36 +00:00
|
|
|
{
|
2012-05-12 15:13:06 +00:00
|
|
|
char str[MAX_PATH + 1];
|
2018-06-17 16:32:54 +02:00
|
|
|
|
|
|
|
|
/* the default drive to resolve a directory without a specified drive
|
2012-03-03 20:19:11 +00:00
|
|
|
* should be the Windows installation drive, since this was what the OS
|
|
|
|
|
* assumes. */
|
2012-05-12 15:13:06 +00:00
|
|
|
if (GetWindowsDirectory(str, MAX_PATH + 1)) {
|
2007-02-28 20:11:10 +00:00
|
|
|
root[0] = str[0];
|
|
|
|
|
root[1] = ':';
|
|
|
|
|
root[2] = '\\';
|
|
|
|
|
root[3] = '\0';
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2018-06-17 16:32:54 +02:00
|
|
|
/* if GetWindowsDirectory fails, something has probably gone wrong,
|
2012-03-03 20:19:11 +00:00
|
|
|
* we are trying the blender install dir though */
|
2012-05-12 15:13:06 +00:00
|
|
|
if (GetModuleFileName(NULL, str, MAX_PATH + 1)) {
|
2015-11-16 11:59:15 +11:00
|
|
|
printf(
|
|
|
|
|
"Error! Could not get the Windows Directory - "
|
|
|
|
|
"Defaulting to Blender installation Dir!\n");
|
2007-02-28 20:11:10 +00:00
|
|
|
root[0] = str[0];
|
2006-08-20 14:41:13 +00:00
|
|
|
root[1] = ':';
|
|
|
|
|
root[2] = '\\';
|
|
|
|
|
root[3] = '\0';
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2007-02-28 20:11:10 +00:00
|
|
|
DWORD tmp;
|
|
|
|
|
int i;
|
|
|
|
|
int rc = 0;
|
|
|
|
|
/* now something has gone really wrong - still trying our best guess */
|
2015-11-16 11:59:15 +11:00
|
|
|
printf(
|
|
|
|
|
"Error! Could not get the Windows Directory - "
|
|
|
|
|
"Defaulting to first valid drive! Path might be invalid!\n");
|
2012-05-12 15:13:06 +00:00
|
|
|
tmp = GetLogicalDrives();
|
|
|
|
|
for (i = 2; i < 26; i++) {
|
|
|
|
|
if ((tmp >> i) & 1) {
|
|
|
|
|
root[0] = 'a' + i;
|
2007-02-28 20:11:10 +00:00
|
|
|
root[1] = ':';
|
|
|
|
|
root[2] = '\\';
|
|
|
|
|
root[3] = '\0';
|
|
|
|
|
if (GetFileAttributes(root) != 0xFFFFFFFF) {
|
|
|
|
|
rc = i;
|
2012-10-21 05:46:41 +00:00
|
|
|
break;
|
2007-02-28 20:11:10 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (0 == rc) {
|
2020-08-26 15:50:48 +02:00
|
|
|
printf("ERROR in 'BLI_windows_get_default_root_dir': can't find a valid drive!\n");
|
2007-02-28 20:11:10 +00:00
|
|
|
root[0] = 'C';
|
|
|
|
|
root[1] = ':';
|
|
|
|
|
root[2] = '\\';
|
|
|
|
|
root[3] = '\0';
|
|
|
|
|
}
|
2012-10-21 05:46:41 +00:00
|
|
|
}
|
2006-08-20 14:41:13 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
#else
|
|
|
|
|
|
2009-01-17 00:51:42 +00:00
|
|
|
/* intentionally empty for UNIX */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
|
#endif
|