21# define WIN32_SKIP_HKEY_PROTECTION
39 GetModuleFileName(
nullptr, filepath,
sizeof(filepath));
42 if (dir[a - 1] ==
'\\') {
55 return (
BLI_strcasestr(install_dir,
"\\WindowsApps\\") !=
nullptr);
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(root,
99 REG_OPTION_NON_VOLATILE,
105 if (lresult == ERROR_SUCCESS) {
106 lresult = RegSetValueEx(
107 hkey_progid,
nullptr, 0, REG_SZ, (BYTE *)friendly_name, strlen(friendly_name) + 1);
109 if (lresult == ERROR_SUCCESS) {
110 lresult = RegSetValueEx(
111 hkey_progid,
"AppUserModelId", 0, REG_SZ, (BYTE *)prog_id, strlen(prog_id) + 1);
113 if (lresult != ERROR_SUCCESS) {
114 registry_error(root,
"Unable to register Blender App Id");
118 SNPRINTF(buffer,
"%s\\shell\\open", prog_id);
119 lresult = RegCreateKeyEx(root,
123 REG_OPTION_NON_VOLATILE,
129 lresult = RegSetValueEx(
130 hkey_progid,
"FriendlyAppName", 0, REG_SZ, (BYTE *)friendly_name, strlen(friendly_name) + 1);
132 SNPRINTF(buffer,
"%s\\shell\\open\\command", prog_id);
134 lresult = RegCreateKeyEx(root,
138 REG_OPTION_NON_VOLATILE,
144 if (lresult == ERROR_SUCCESS) {
145 SNPRINTF(buffer,
"\"%s\" \"%%1\"", executable);
146 lresult = RegSetValueEx(hkey_progid,
nullptr, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1);
147 RegCloseKey(hkey_progid);
149 if (lresult != ERROR_SUCCESS) {
150 registry_error(root,
"Unable to register Blender App Id");
154 SNPRINTF(buffer,
"%s\\DefaultIcon", prog_id);
155 lresult = RegCreateKeyEx(root,
159 REG_OPTION_NON_VOLATILE,
165 if (lresult == ERROR_SUCCESS) {
166 SNPRINTF(buffer,
"\"%s\", 1", executable);
167 lresult = RegSetValueEx(hkey_progid,
nullptr, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1);
168 RegCloseKey(hkey_progid);
170 if (lresult != ERROR_SUCCESS) {
171 registry_error(root,
"Unable to register Blender App Id");
180 fprintf(stderr,
"Registration not possible from Microsoft Store installation.");
185 char blender_path[MAX_PATH];
190 const char *prog_id = BLENDER_WIN_APPID;
191 const char *friendly_name = BLENDER_WIN_APPID_FRIENDLY_NAME;
193 GetModuleFileName(0, blender_path,
sizeof(blender_path));
196 if (strlen(blender_path) > (
sizeof(blender_path) - 10))
200 blender_app = strstr(blender_path,
"blender.exe");
204 strcpy(blender_app,
"blender-launcher.exe");
206 if (!open_registry_hive(all_users, &root)) {
210 if (!register_blender_prog_id(prog_id, blender_path, friendly_name, all_users)) {
211 registry_error(root,
"Unable to register Blend document type");
215 lresult = RegCreateKeyEx(
216 root,
".blend", 0,
nullptr, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
nullptr, &hkey, &dwd);
217 if (lresult == ERROR_SUCCESS) {
219 lresult = RegSetValueEx(hkey,
nullptr, 0, REG_SZ, (BYTE *)prog_id, strlen(prog_id) + 1);
221 if (lresult != ERROR_SUCCESS) {
222 registry_error(root,
"Unable to register Blend document type");
228 lresult = RegCreateKeyEx(root,
229 ".blend\\OpenWithProgids",
232 REG_OPTION_NON_VOLATILE,
238 if (lresult != ERROR_SUCCESS) {
239 registry_error(root,
"Unable to register Blend document type");
243 lresult = RegSetValueEx(hkey, prog_id, 0, REG_NONE,
nullptr, 0);
247 if (lresult != ERROR_SUCCESS) {
248 registry_error(root,
"Unable to register Blend document type");
253 fprintf(stderr,
"Update of pinned launcher failed.");
257# ifdef WITH_BLENDER_THUMBNAILER
259 char reg_cmd[MAX_PATH * 2];
263 GetSystemDirectory(system_dir,
sizeof(system_dir));
264 const char *thumbnail_handler =
"BlendThumb.dll";
265 SNPRINTF(reg_cmd,
"%s\\regsvr32 /s \"%s\\%s\"", system_dir, install_dir, thumbnail_handler);
273 "Blend file extension registered for %s.",
274 all_users ?
"all users" :
"the current user");
283 fprintf(stderr,
"Unregistration not possible from Microsoft Store installation.");
291 if (!open_registry_hive(all_users, &root)) {
297 RegDeleteTree(root, BLENDER_WIN_APPID);
299 lresult = RegOpenKeyEx(root,
".blend", 0, KEY_ALL_ACCESS, &hkey);
300 if (lresult == ERROR_SUCCESS) {
301 char buffer[256] = {0};
302 DWORD
size =
sizeof(buffer);
303 lresult = RegGetValueA(hkey,
nullptr,
nullptr, RRF_RT_REG_SZ,
nullptr, &buffer, &
size);
304 if (lresult == ERROR_SUCCESS &&
STREQ(buffer, BLENDER_WIN_APPID)) {
305 RegSetValueEx(hkey,
nullptr, 0, REG_SZ, 0, 0);
309# ifdef WITH_BLENDER_THUMBNAILER
311 char reg_cmd[MAX_PATH * 2];
315 GetSystemDirectory(system_dir,
sizeof(system_dir));
316 const char *thumbnail_handler =
"BlendThumb.dll";
317 SNPRINTF(reg_cmd,
"%s\\regsvr32 /u /s \"%s\\%s\"", system_dir, install_dir, thumbnail_handler);
322 lresult = RegOpenKeyEx(hkey,
"OpenWithProgids", 0, KEY_ALL_ACCESS, &hkey);
323 if (lresult == ERROR_SUCCESS) {
324 RegDeleteValue(hkey, BLENDER_WIN_APPID);
330 "Blend file extension unregistered for %s.",
331 all_users ?
"all users" :
"the current user");
343static bool BLI_windows_file_operation_is_registered(
const char *extension,
const char *operation)
346 HRESULT hr = AssocQueryKey(ASSOCF_INIT_IGNOREUNKNOWN,
347 ASSOCKEY_SHELLEXECCLASS,
360 if (
STREQ(operation,
"open") ||
STREQ(operation,
"properties")) {
365 return BLI_windows_file_operation_is_registered(
"Directory", operation);
369 return BLI_windows_file_operation_is_registered(extension, operation);
384 SHELLEXECUTEINFOW shellinfo = {0};
385 shellinfo.cbSize =
sizeof(SHELLEXECUTEINFO);
386 shellinfo.fMask = SEE_MASK_INVOKEIDLIST;
387 shellinfo.lpVerb = woperation;
388 shellinfo.lpFile = wpath;
389 shellinfo.nShow = SW_SHOW;
391 return ShellExecuteExW(&shellinfo);
399 char blender_path[MAX_PATH];
400 GetModuleFileName(0, blender_path, MAX_PATH);
402 SHELLEXECUTEINFOA shellinfo = {0};
403 shellinfo.cbSize =
sizeof(SHELLEXECUTEINFO);
404 shellinfo.fMask = wait ? SEE_MASK_NOCLOSEPROCESS : SEE_MASK_DEFAULT;
405 shellinfo.hwnd =
nullptr;
406 shellinfo.lpVerb = elevated ?
"runas" :
nullptr;
407 shellinfo.lpFile = blender_path;
408 shellinfo.lpParameters = parameters;
409 shellinfo.lpDirectory =
nullptr;
410 shellinfo.nShow = silent ? SW_HIDE : SW_SHOW;
411 shellinfo.hInstApp =
nullptr;
412 shellinfo.hProcess = 0;
415 if (!ShellExecuteExA(&shellinfo)) {
422 if (shellinfo.hProcess != 0) {
423 WaitForSingleObject(shellinfo.hProcess, INFINITE);
424 GetExitCodeProcess(shellinfo.hProcess, &exitCode);
425 CloseHandle(shellinfo.hProcess);
426 return (exitCode == 0);
434 char str[MAX_PATH + 1];
439 if (GetWindowsDirectory(
str, MAX_PATH + 1)) {
448 if (GetModuleFileName(
nullptr,
str, MAX_PATH + 1)) {
450 "Error! Could not get the Windows Directory - "
451 "Defaulting to Blender installation Dir!\n");
463 "Error! Could not get the Windows Directory - "
464 "Defaulting to first valid drive! Path might be invalid!\n");
465 tmp = GetLogicalDrives();
466 for (
i = 2;
i < 26;
i++) {
467 if ((tmp >>
i) & 1) {
472 if (GetFileAttributes(root) != 0xFFFFFFFF) {
479 printf(
"ERROR in 'BLI_windows_get_default_root_dir': can't find a valid drive!\n");
490 long long *r_driverVersion)
492 IDXGIFactory *pFactory =
nullptr;
493 IDXGIAdapter *pAdapter =
nullptr;
494 if (CreateDXGIFactory(__uuidof(IDXGIFactory), (
void **)&pFactory) == S_OK) {
495 for (UINT
i = 0; pFactory->EnumAdapters(
i, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++
i) {
496 LARGE_INTEGER version;
497 if (pAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &version) == S_OK) {
498 DXGI_ADAPTER_DESC desc;
499 if (pAdapter->GetDesc(&desc) == S_OK) {
500 if (wcsstr(desc.Description, deviceSubString)) {
501 *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.
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
int conv_utf_8_to_16(const char *in8, wchar_t *out16, size_t size16)