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)) {
201 blender_app = strstr(blender_path,
"blender.exe");
205 strcpy(blender_app,
"blender-launcher.exe");
207 if (!open_registry_hive(all_users, &root)) {
211 if (!register_blender_prog_id(prog_id, blender_path, friendly_name, all_users)) {
212 registry_error(root,
"Unable to register Blend document type");
216 lresult = RegCreateKeyEx(
217 root,
".blend", 0,
nullptr, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
nullptr, &hkey, &dwd);
218 if (lresult == ERROR_SUCCESS) {
220 lresult = RegSetValueEx(hkey,
nullptr, 0, REG_SZ, (BYTE *)prog_id, strlen(prog_id) + 1);
222 if (lresult != ERROR_SUCCESS) {
223 registry_error(root,
"Unable to register Blend document type");
229 lresult = RegCreateKeyEx(root,
230 ".blend\\OpenWithProgids",
233 REG_OPTION_NON_VOLATILE,
239 if (lresult != ERROR_SUCCESS) {
240 registry_error(root,
"Unable to register Blend document type");
244 lresult = RegSetValueEx(hkey, prog_id, 0, REG_NONE,
nullptr, 0);
248 if (lresult != ERROR_SUCCESS) {
249 registry_error(root,
"Unable to register Blend document type");
254 fprintf(stderr,
"Update of pinned launcher failed.");
258# ifdef WITH_BLENDER_THUMBNAILER
260 char reg_cmd[MAX_PATH * 2];
264 GetSystemDirectory(system_dir,
sizeof(system_dir));
265 const char *thumbnail_handler =
"BlendThumb.dll";
266 SNPRINTF(reg_cmd,
"%s\\regsvr32 /s \"%s\\%s\"", system_dir, install_dir, thumbnail_handler);
274 "Blend file extension registered for %s.",
275 all_users ?
"all users" :
"the current user");
284 fprintf(stderr,
"Unregistration not possible from Microsoft Store installation.");
292 if (!open_registry_hive(all_users, &root)) {
298 RegDeleteTree(root, BLENDER_WIN_APPID);
300 lresult = RegOpenKeyEx(root,
".blend", 0, KEY_ALL_ACCESS, &hkey);
301 if (lresult == ERROR_SUCCESS) {
302 char buffer[256] = {0};
303 DWORD
size =
sizeof(buffer);
304 lresult = RegGetValueA(hkey,
nullptr,
nullptr, RRF_RT_REG_SZ,
nullptr, &buffer, &
size);
305 if (lresult == ERROR_SUCCESS &&
STREQ(buffer, BLENDER_WIN_APPID)) {
306 RegSetValueEx(hkey,
nullptr, 0, REG_SZ, 0, 0);
310# ifdef WITH_BLENDER_THUMBNAILER
312 char reg_cmd[MAX_PATH * 2];
316 GetSystemDirectory(system_dir,
sizeof(system_dir));
317 const char *thumbnail_handler =
"BlendThumb.dll";
318 SNPRINTF(reg_cmd,
"%s\\regsvr32 /u /s \"%s\\%s\"", system_dir, install_dir, thumbnail_handler);
323 lresult = RegOpenKeyEx(hkey,
"OpenWithProgids", 0, KEY_ALL_ACCESS, &hkey);
324 if (lresult == ERROR_SUCCESS) {
325 RegDeleteValue(hkey, BLENDER_WIN_APPID);
331 "Blend file extension unregistered for %s.",
332 all_users ?
"all users" :
"the current user");
344static bool BLI_windows_file_operation_is_registered(
const char *extension,
const char *operation)
347 HRESULT hr = AssocQueryKey(ASSOCF_INIT_IGNOREUNKNOWN,
348 ASSOCKEY_SHELLEXECCLASS,
361 if (
STREQ(operation,
"open") ||
STREQ(operation,
"properties")) {
366 return BLI_windows_file_operation_is_registered(
"Directory", operation);
370 return BLI_windows_file_operation_is_registered(extension, operation);
385 SHELLEXECUTEINFOW shellinfo = {0};
386 shellinfo.cbSize =
sizeof(SHELLEXECUTEINFO);
387 shellinfo.fMask = SEE_MASK_INVOKEIDLIST;
388 shellinfo.lpVerb = woperation;
389 shellinfo.lpFile = wpath;
390 shellinfo.nShow = SW_SHOW;
392 return ShellExecuteExW(&shellinfo);
400 char blender_path[MAX_PATH];
401 GetModuleFileName(0, blender_path, MAX_PATH);
403 SHELLEXECUTEINFOA shellinfo = {0};
404 shellinfo.cbSize =
sizeof(SHELLEXECUTEINFO);
405 shellinfo.fMask = wait ? SEE_MASK_NOCLOSEPROCESS : SEE_MASK_DEFAULT;
406 shellinfo.hwnd =
nullptr;
407 shellinfo.lpVerb = elevated ?
"runas" :
nullptr;
408 shellinfo.lpFile = blender_path;
409 shellinfo.lpParameters = parameters;
410 shellinfo.lpDirectory =
nullptr;
411 shellinfo.nShow = silent ? SW_HIDE : SW_SHOW;
412 shellinfo.hInstApp =
nullptr;
413 shellinfo.hProcess = 0;
416 if (!ShellExecuteExA(&shellinfo)) {
423 if (shellinfo.hProcess != 0) {
424 WaitForSingleObject(shellinfo.hProcess, INFINITE);
425 GetExitCodeProcess(shellinfo.hProcess, &exitCode);
426 CloseHandle(shellinfo.hProcess);
427 return (exitCode == 0);
435 char str[MAX_PATH + 1];
440 if (GetWindowsDirectory(
str, MAX_PATH + 1)) {
449 if (GetModuleFileName(
nullptr,
str, MAX_PATH + 1)) {
451 "Error! Could not get the Windows Directory - "
452 "Defaulting to Blender installation Dir!\n");
464 "Error! Could not get the Windows Directory - "
465 "Defaulting to first valid drive! Path might be invalid!\n");
466 tmp = GetLogicalDrives();
467 for (
i = 2;
i < 26;
i++) {
468 if ((tmp >>
i) & 1) {
473 if (GetFileAttributes(root) != 0xFFFFFFFF) {
480 printf(
"ERROR in 'BLI_windows_get_default_root_dir': cannot find a valid drive!\n");
491 long long *r_driverVersion)
493 IDXGIFactory *pFactory =
nullptr;
494 IDXGIAdapter *pAdapter =
nullptr;
495 if (CreateDXGIFactory(__uuidof(IDXGIFactory), (
void **)&pFactory) == S_OK) {
496 for (UINT
i = 0; pFactory->EnumAdapters(
i, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++
i) {
497 LARGE_INTEGER version;
498 if (pAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &version) == S_OK) {
499 DXGI_ADAPTER_DESC desc;
500 if (pAdapter->GetDesc(&desc) == S_OK) {
501 if (wcsstr(desc.Description, deviceSubString)) {
502 *r_driverVersion = version.QuadPart;
523 HMODULE hMod = ::GetModuleHandleW(
L"ntdll.dll");
528 typedef NTSTATUS(WINAPI * RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
529 RtlGetVersionPtr rtl_get_version = (RtlGetVersionPtr)::GetProcAddress(hMod,
"RtlGetVersion");
530 if (rtl_get_version ==
nullptr) {
531 fprintf(stderr,
"BLI_windows_is_build_version_greater_or_equal: RtlGetVersion not found.");
535 RTL_OSVERSIONINFOW osVersioninfo{};
536 osVersioninfo.dwOSVersionInfoSize =
sizeof(RTL_OSVERSIONINFOW);
537 if (rtl_get_version(&osVersioninfo) != 0) {
538 fprintf(stderr,
"BLI_windows_is_build_version_greater_or_equal: RtlGetVersion failed.");
541 if (majorVersion != osVersioninfo.dwMajorVersion) {
542 return osVersioninfo.dwMajorVersion > majorVersion;
544 if (minorVersion != osVersioninfo.dwMinorVersion) {
545 return osVersioninfo.dwMajorVersion > minorVersion;
547 return osVersioninfo.dwBuildNumber >= buildNumber;
553 if (
int(qos_precedence) <
int(qos_precedence_last)) {
564 PROCESS_POWER_THROTTLING_STATE processPowerThrottlingState{};
565 processPowerThrottlingState.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION;
568 processPowerThrottlingState.ControlMask = 0;
569 processPowerThrottlingState.StateMask = 0;
572 processPowerThrottlingState.ControlMask = PROCESS_POWER_THROTTLING_EXECUTION_SPEED;
573 processPowerThrottlingState.StateMask = 0;
576 processPowerThrottlingState.ControlMask = PROCESS_POWER_THROTTLING_EXECUTION_SPEED;
577 processPowerThrottlingState.StateMask = PROCESS_POWER_THROTTLING_EXECUTION_SPEED;
580 HANDLE hProcess = GetCurrentProcess();
581 if (!SetProcessInformation(hProcess,
582 ProcessPowerThrottling,
583 &processPowerThrottlingState,
584 sizeof(PROCESS_POWER_THROTTLING_STATE)))
587 stderr,
"BLI_windows_set_process_qos: SetProcessInformation failed: %d\n", GetLastError());
590 qos_precedence_last = qos_precedence;
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_is_build_version_greater_or_equal(DWORD majorVersion, DWORD minorVersion, DWORD buildNumber)
bool BLI_windows_external_operation_execute(const char *filepath, const char *operation)
int BLI_windows_get_executable_dir(char r_dirpath[])
void BLI_windows_process_set_qos(QoSMode qos_mode, QoSPrecedence qos_precedence)
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)