Index: cfgmgr/cfgmgr.cpp |
— | — | @@ -32,12 +32,201 @@ |
33 | 33 | TCHAR regkeybase[] = _T("Software\\DXGL\\");
|
34 | 34 |
|
35 | 35 | DXGLCFG defaultmask;
|
| 36 | +UINT_PTR timerid;
|
36 | 37 |
|
| 38 | +INT_PTR CALLBACK CompatDialogCallback(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
| 39 | +{
|
| 40 | + switch (Msg)
|
| 41 | + {
|
| 42 | + case WM_INITDIALOG:
|
| 43 | + timerid = SetTimer(hWnd, NULL, 5000, NULL);
|
| 44 | + return TRUE;
|
| 45 | + case WM_TIMER:
|
| 46 | + if (wParam == timerid) EndDialog(hWnd, 0);
|
| 47 | + break;
|
| 48 | + default:
|
| 49 | + return FALSE;
|
| 50 | + }
|
| 51 | +}
|
| 52 | +
|
| 53 | +void ShowRestartDialog()
|
| 54 | +{
|
| 55 | + BOOL(*_GetModuleHandleEx)(DWORD dwFlags, LPCTSTR lpModuleName, HMODULE* phModule) = FALSE;
|
| 56 | + HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll"));
|
| 57 | + HMODULE hddraw;
|
| 58 | + if (hKernel32) _GetModuleHandleEx = (BOOL(*)(DWORD,LPCTSTR,HMODULE*))GetProcAddress(hKernel32, "GetModuleHandleEx");
|
| 59 | + if (_GetModuleHandleEx) _GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)ShowRestartDialog, &hddraw);
|
| 60 | + else hddraw = GetModuleHandle(_T("ddraw.dll")); //For old versions of Windows, may fail but they shouldn't have AppCompat anyways.
|
| 61 | + if (hKernel32) FreeLibrary(hKernel32);
|
| 62 | + DialogBox(hddraw, MAKEINTRESOURCE(IDD_COMPAT), NULL, CompatDialogCallback);
|
| 63 | + LPTSTR cmdline = GetCommandLine();
|
| 64 | + LPTSTR cmdline2 = (LPTSTR)malloc((_tcslen(cmdline) + 1)*sizeof(TCHAR));
|
| 65 | + _tcscpy(cmdline2, cmdline);
|
| 66 | + STARTUPINFO startupinfo;
|
| 67 | + PROCESS_INFORMATION procinfo;
|
| 68 | + ZeroMemory(&startupinfo, sizeof(STARTUPINFO));
|
| 69 | + startupinfo.cb = sizeof(STARTUPINFO);
|
| 70 | + CreateProcess(NULL, cmdline2, NULL, NULL, FALSE, 0, NULL, NULL, &startupinfo, &procinfo);
|
| 71 | + CloseHandle(procinfo.hProcess);
|
| 72 | + CloseHandle(procinfo.hThread);
|
| 73 | + free(cmdline2);
|
| 74 | + ExitProcess(0);
|
| 75 | +}
|
| 76 | +
|
37 | 77 | bool AddCompatFlag(LPTSTR flag)
|
38 | 78 | {
|
| 79 | + HKEY hKey;
|
| 80 | + HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll"));
|
| 81 | + BOOL(WINAPI *iswow64)(HANDLE, PBOOL) = NULL;
|
| 82 | + if (hKernel32) iswow64 = (BOOL(WINAPI*)(HANDLE, PBOOL))GetProcAddress(hKernel32, "IsWow64Process");
|
| 83 | + BOOL is64 = FALSE;
|
| 84 | + if (iswow64) iswow64(GetCurrentProcess(), &is64);
|
| 85 | + if (hKernel32) FreeLibrary(hKernel32);
|
| 86 | + LRESULT error;
|
| 87 | + TCHAR filename[MAX_PATH + 1];
|
| 88 | + TCHAR buffer[1024];
|
| 89 | + TCHAR *bufferpos;
|
39 | 90 |
|
| 91 | + return false;
|
40 | 92 | }
|
41 | 93 |
|
| 94 | +bool DelCompatFlag(LPTSTR flag)
|
| 95 | +{
|
| 96 | + HKEY hKey;
|
| 97 | + HKEY hKeyWrite;
|
| 98 | + HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll"));
|
| 99 | + BOOL(WINAPI *iswow64)(HANDLE, PBOOL) = NULL;
|
| 100 | + if (hKernel32) iswow64 = (BOOL(WINAPI*)(HANDLE, PBOOL))GetProcAddress(hKernel32, "IsWow64Process");
|
| 101 | + BOOL is64 = FALSE;
|
| 102 | + if (iswow64) iswow64(GetCurrentProcess(), &is64);
|
| 103 | + if (hKernel32) FreeLibrary(hKernel32);
|
| 104 | + LRESULT error;
|
| 105 | + TCHAR filename[MAX_PATH + 1];
|
| 106 | + TCHAR buffer[1024];
|
| 107 | + TCHAR *bufferpos;
|
| 108 | + tstring writekey;
|
| 109 | + bool accessdenied = false;
|
| 110 | + // Check system first.
|
| 111 | + if (is64) writekey.assign(_T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers"));
|
| 112 | + else writekey.assign(_T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers"));
|
| 113 | + error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, writekey.c_str(), 0, KEY_READ, &hKey);
|
| 114 | + if (error == ERROR_SUCCESS)
|
| 115 | + {
|
| 116 | + GetModuleFileName(NULL, filename, MAX_PATH);
|
| 117 | + ZeroMemory(buffer, 1024 * sizeof(TCHAR));
|
| 118 | + DWORD sizeout = 1024 * sizeof(TCHAR);
|
| 119 | + if (RegQueryValueEx(hKey, filename, NULL, NULL, (LPBYTE)buffer, &sizeout) == ERROR_SUCCESS)
|
| 120 | + {
|
| 121 | + bufferpos = _tcsstr(buffer, flag);
|
| 122 | + if (bufferpos)
|
| 123 | + {
|
| 124 | + memmove(bufferpos, bufferpos + _tcslen(flag), (_tcslen(bufferpos + _tcslen(flag)))*sizeof(TCHAR));
|
| 125 | + error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, writekey.c_str(), 0, KEY_WRITE, &hKeyWrite);
|
| 126 | + if (error == ERROR_SUCCESS)
|
| 127 | + {
|
| 128 | + error = RegSetValueEx(hKeyWrite, filename, 0, REG_SZ, (BYTE*)buffer, (_tcslen(bufferpos + _tcslen(flag)))*sizeof(TCHAR)+sizeof(TCHAR));
|
| 129 | + RegCloseKey(hKeyWrite);
|
| 130 | + }
|
| 131 | + if (error == ERROR_ACCESS_DENIED)
|
| 132 | + {
|
| 133 | + if (MessageBox(NULL, _T("DXGL has detected an incompatible AppCompat flag for the program you are currently running and requires administrative rights to remove it.\nWould you like to continue?"),
|
| 134 | + _T("AppCompat error"), MB_YESNO | MB_ICONWARNING) == IDYES)
|
| 135 | + {
|
| 136 | + tstring command;
|
| 137 | + if (is64) command.assign(_T("ADD \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers\" /reg:64 /f /v \""));
|
| 138 | + else command.assign(_T("ADD \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers\" /f /v \""));
|
| 139 | + command.append(filename);
|
| 140 | + command.append(_T("\" /t REG_SZ /d \""));
|
| 141 | + command.append(buffer);
|
| 142 | + command.append(_T("\""));
|
| 143 | + SHELLEXECUTEINFO info;
|
| 144 | + ZeroMemory(&info, sizeof(SHELLEXECUTEINFO));
|
| 145 | + info.cbSize = sizeof(SHELLEXECUTEINFO);
|
| 146 | + info.lpVerb = _T("runas");
|
| 147 | + info.lpFile = _T("reg.exe");
|
| 148 | + info.lpParameters = command.c_str();
|
| 149 | + info.nShow = SW_SHOWNORMAL;
|
| 150 | + info.fMask = SEE_MASK_NOCLOSEPROCESS;
|
| 151 | + ShellExecuteEx(&info);
|
| 152 | + WaitForSingleObject(info.hProcess, INFINITE);
|
| 153 | + GetExitCodeProcess(info.hProcess, (LPDWORD)&error);
|
| 154 | + }
|
| 155 | + if (!error)
|
| 156 | + {
|
| 157 | + ShowRestartDialog();
|
| 158 | + }
|
| 159 | + else MessageBox(NULL, _T("Registry value could not be updated. Your program may crash as a result."), _T("Error"), MB_OK | MB_ICONWARNING);
|
| 160 | + return false;
|
| 161 | + }
|
| 162 | + else if (error == ERROR_SUCCESS)
|
| 163 | + {
|
| 164 | + ShowRestartDialog();
|
| 165 | + }
|
| 166 | + }
|
| 167 | + }
|
| 168 | + RegCloseKey(hKey);
|
| 169 | + }
|
| 170 | + // Next check user.
|
| 171 | + writekey.assign(_T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers"));
|
| 172 | + error = RegOpenKeyEx(HKEY_CURRENT_USER, writekey.c_str(), 0, KEY_READ, &hKey);
|
| 173 | + if (error == ERROR_SUCCESS)
|
| 174 | + {
|
| 175 | + GetModuleFileName(NULL, filename, MAX_PATH);
|
| 176 | + ZeroMemory(buffer, 1024 * sizeof(TCHAR));
|
| 177 | + DWORD sizeout = 1024 * sizeof(TCHAR);
|
| 178 | + if (RegQueryValueEx(hKey, filename, NULL, NULL, (LPBYTE)buffer, &sizeout) == ERROR_SUCCESS)
|
| 179 | + {
|
| 180 | + bufferpos = _tcsstr(buffer, flag);
|
| 181 | + if (bufferpos)
|
| 182 | + {
|
| 183 | + memmove(bufferpos, bufferpos + _tcslen(flag), (_tcslen(bufferpos + _tcslen(flag)))*sizeof(TCHAR));
|
| 184 | + error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, writekey.c_str(), 0, KEY_WRITE, &hKeyWrite);
|
| 185 | + if (error == ERROR_SUCCESS)
|
| 186 | + {
|
| 187 | + error = RegSetValueEx(hKeyWrite, filename, 0, REG_SZ, (BYTE*)buffer, (_tcslen(bufferpos + _tcslen(flag)))*sizeof(TCHAR)+sizeof(TCHAR));
|
| 188 | + RegCloseKey(hKeyWrite);
|
| 189 | + }
|
| 190 | + if (error == ERROR_ACCESS_DENIED)
|
| 191 | + {
|
| 192 | + if (MessageBox(NULL, _T("DXGL has detected an incompatible AppCompat flag for the program you are currently running and requires administrative rights to remove it.\nWould you like to continue?"),
|
| 193 | + _T("AppCompat error"), MB_YESNO | MB_ICONWARNING) == IDYES)
|
| 194 | + {
|
| 195 | + tstring command;
|
| 196 | + command.assign(_T("ADD \"HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers\" /f /v \""));
|
| 197 | + command.append(filename);
|
| 198 | + command.append(_T("\" /t REG_SZ /d \""));
|
| 199 | + command.append(buffer);
|
| 200 | + command.append(_T("\""));
|
| 201 | + SHELLEXECUTEINFO info;
|
| 202 | + ZeroMemory(&info, sizeof(SHELLEXECUTEINFO));
|
| 203 | + info.cbSize = sizeof(SHELLEXECUTEINFO);
|
| 204 | + info.lpVerb = _T("runas");
|
| 205 | + info.lpFile = _T("reg.exe");
|
| 206 | + info.lpParameters = command.c_str();
|
| 207 | + info.nShow = SW_SHOWNORMAL;
|
| 208 | + info.fMask = SEE_MASK_NOCLOSEPROCESS;
|
| 209 | + ShellExecuteEx(&info);
|
| 210 | + WaitForSingleObject(info.hProcess, INFINITE);
|
| 211 | + GetExitCodeProcess(info.hProcess, (LPDWORD)&error);
|
| 212 | + }
|
| 213 | + if (!error)
|
| 214 | + {
|
| 215 | + ShowRestartDialog();
|
| 216 | + }
|
| 217 | + else MessageBox(NULL, _T("Registry value could not be updated. Your program may crash as a result."), _T("Error"), MB_OK | MB_ICONWARNING);
|
| 218 | + return false;
|
| 219 | + }
|
| 220 | + else if (error == ERROR_SUCCESS)
|
| 221 | + {
|
| 222 | + ShowRestartDialog();
|
| 223 | + }
|
| 224 | + }
|
| 225 | + }
|
| 226 | + RegCloseKey(hKey);
|
| 227 | + }
|
| 228 | + return true;
|
| 229 | +}
|
| 230 | +
|
42 | 231 | void GetDirFromPath(LPTSTR path)
|
43 | 232 | {
|
44 | 233 | int len = _tcslen(path);
|
— | — | @@ -342,6 +531,8 @@ |
343 | 532 | HMODULE hUser32 = NULL;
|
344 | 533 | if (initial)
|
345 | 534 | {
|
| 535 | + if (cfg->DPIScale == 2) AddCompatFlag(_T("HIGHDPIAWARE"));
|
| 536 | + else DelCompatFlag(_T("HIGHDPIAWARE"));
|
346 | 537 | if (cfg->DPIScale == 1)
|
347 | 538 | {
|
348 | 539 | bool DPIAwarePM = false;
|
— | — | @@ -369,101 +560,7 @@ |
370 | 561 | if (hSHCore) FreeLibrary(hSHCore);
|
371 | 562 | if (hUser32) FreeLibrary(hUser32);
|
372 | 563 | }
|
373 | | - HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll"));
|
374 | | - BOOL (WINAPI *iswow64)(HANDLE,PBOOL) = NULL;
|
375 | | - if(hKernel32) iswow64 = (BOOL(WINAPI*)(HANDLE,PBOOL))GetProcAddress(hKernel32,"IsWow64Process");
|
376 | | - BOOL is64 = FALSE;
|
377 | | - if(iswow64) iswow64(GetCurrentProcess(),&is64);
|
378 | | - if(hKernel32) FreeLibrary(hKernel32);
|
379 | | - LRESULT error;
|
380 | | - if(is64) error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,_T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers"),0,KEY_READ|KEY_WOW64_64KEY,&hKey);
|
381 | | - else error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,_T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers"),0,KEY_READ,&hKey);
|
382 | | - if(error == ERROR_SUCCESS)
|
383 | | - {
|
384 | | - GetModuleFileName(NULL,filename,MAX_PATH);
|
385 | | - TCHAR buffer[1024];
|
386 | | - ZeroMemory(buffer,1024*sizeof(TCHAR));
|
387 | | - DWORD sizeout = 1024*sizeof(TCHAR);
|
388 | | - if(RegQueryValueEx(hKey,filename,NULL,NULL,(LPBYTE)buffer,&sizeout) == ERROR_SUCCESS)
|
389 | | - {
|
390 | | - if(_tcsstr(buffer,_T("DWM8And16BitMitigation")))
|
391 | | - {
|
392 | | - MessageBox(NULL,_T("DXGL has detected an incompatible AppCompat flag for the program you are currently running. To continue, the registry value must be deleted.\nIf you see a UAC prompt, you must click Yes."),
|
393 | | - _T("AppCompat error"),MB_OK|MB_ICONHAND);
|
394 | | - error = RegDeleteValue(hKey,filename);
|
395 | | - if(error == ERROR_ACCESS_DENIED)
|
396 | | - {
|
397 | | - tstring command;
|
398 | | - if(is64) command.assign(_T("DELETE \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers\" /reg:64 /f /v \""));
|
399 | | - else command.assign(_T("DELETE \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers\" /f /v \""));
|
400 | | - command.append(filename);
|
401 | | - command.append(_T("\""));
|
402 | | - SHELLEXECUTEINFO info;
|
403 | | - ZeroMemory(&info,sizeof(SHELLEXECUTEINFO));
|
404 | | - info.cbSize = sizeof(SHELLEXECUTEINFO);
|
405 | | - info.lpVerb = _T("runas");
|
406 | | - info.lpFile = _T("reg.exe");
|
407 | | - info.lpParameters = command.c_str();
|
408 | | - info.nShow = SW_SHOWNORMAL;
|
409 | | - info.fMask = SEE_MASK_NOCLOSEPROCESS;
|
410 | | - ShellExecuteEx(&info);
|
411 | | - WaitForSingleObject(info.hProcess,INFINITE);
|
412 | | - GetExitCodeProcess(info.hProcess,(LPDWORD)&error);
|
413 | | - }
|
414 | | - if(!error)
|
415 | | - {
|
416 | | - MessageBox(NULL,_T("Registry value successfully deleted. Please restart the program."),_T("Success"),MB_OK|MB_ICONINFORMATION);
|
417 | | - exit(0);
|
418 | | - }
|
419 | | - else MessageBox(NULL,_T("Registry value could not be deleted. Your program may crash as a result."),_T("Error"),MB_OK|MB_ICONWARNING);
|
420 | | - }
|
421 | | - }
|
422 | | - RegCloseKey(hKey);
|
423 | | - }
|
424 | | - if(is64) error = RegOpenKeyEx(HKEY_CURRENT_USER,_T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers"),0,KEY_READ|KEY_WOW64_64KEY,&hKey);
|
425 | | - else error = RegOpenKeyEx(HKEY_CURRENT_USER,_T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers"),0,KEY_READ,&hKey);
|
426 | | - if(error == ERROR_SUCCESS)
|
427 | | - {
|
428 | | - GetModuleFileName(NULL,filename,MAX_PATH);
|
429 | | - TCHAR buffer[1024];
|
430 | | - ZeroMemory(buffer,1024*sizeof(TCHAR));
|
431 | | - DWORD sizeout = 1024*sizeof(TCHAR);
|
432 | | - if(RegQueryValueEx(hKey,filename,NULL,NULL,(LPBYTE)buffer,&sizeout) == ERROR_SUCCESS)
|
433 | | - {
|
434 | | - if(_tcsstr(buffer,_T("DWM8And16BitMitigation")))
|
435 | | - {
|
436 | | - MessageBox(NULL,_T("DXGL has detected an incompatible AppCompat flag for the program you are currently running. To continue, the registry value must be deleted.\nIf you see a UAC prompt, you must click Yes."),
|
437 | | - _T("AppCompat error"),MB_OK|MB_ICONHAND);
|
438 | | - error = RegDeleteValue(hKey,filename);
|
439 | | - if(error == ERROR_ACCESS_DENIED)
|
440 | | - {
|
441 | | - tstring command;
|
442 | | - if(is64) command.assign(_T("DELETE \"HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers\" /reg:64 /f /v \""));
|
443 | | - else command.assign(_T("DELETE \"HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers\" /f /v \""));
|
444 | | - command.append(filename);
|
445 | | - command.append(_T("\""));
|
446 | | - SHELLEXECUTEINFO info;
|
447 | | - ZeroMemory(&info,sizeof(SHELLEXECUTEINFO));
|
448 | | - info.cbSize = sizeof(SHELLEXECUTEINFO);
|
449 | | - info.lpVerb = _T("runas");
|
450 | | - info.lpFile = _T("reg.exe");
|
451 | | - info.lpParameters = command.c_str();
|
452 | | - info.nShow = SW_SHOWNORMAL;
|
453 | | - info.fMask = SEE_MASK_NOCLOSEPROCESS;
|
454 | | - ShellExecuteEx(&info);
|
455 | | - WaitForSingleObject(info.hProcess,INFINITE);
|
456 | | - GetExitCodeProcess(info.hProcess,(LPDWORD)&error);
|
457 | | - }
|
458 | | - if(!error)
|
459 | | - {
|
460 | | - MessageBox(NULL,_T("Registry value successfully deleted. Please restart the program."),_T("Success"),MB_OK|MB_ICONINFORMATION);
|
461 | | - exit(0);
|
462 | | - }
|
463 | | - else MessageBox(NULL,_T("Registry value could not be deleted. Your program may crash as a result."),_T("Error"),MB_OK|MB_ICONWARNING);
|
464 | | - }
|
465 | | - }
|
466 | | - RegCloseKey(hKey);
|
467 | | - }
|
| 564 | + DelCompatFlag(_T("DWM8and16BitMitigation"));
|
468 | 565 | }
|
469 | 566 | }
|
470 | 567 | void GetGlobalConfig(DXGLCFG *cfg)
|