| 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)
|