DXGL r735 - Code Review

Jump to navigation Jump to search
Repository:DXGL
Revision:r734‎ | r735 | r736 >
Date:06:37, 27 August 2017
Author:admin
Status:new
Tags:
Comment:
Add untested implementation of INI options NoOverwrite, NoUninstall, and BundledDDrawSHA256.
Modified paths:
  • /cfgmgr/cfgmgr.c (modified) (history)
  • /cfgmgr/cfgmgr.h (modified) (history)
  • /dxglcfg/dxglcfg.c (modified) (history)
  • /dxglcfg2/dxglcfg2.c (modified) (history)

Diff [purge]

Index: cfgmgr/cfgmgr.c
@@ -1372,4 +1372,80 @@
13731373 sizeout = 1;
13741374 RegSetValueEx(hKey, _T("Configuration Version"), 0, REG_DWORD, &sizeout, 4);
13751375 RegCloseKey(hKey);
 1376+}
 1377+
 1378+int ReadINIOptionsCallback(app_ini_options *options, const char *section, const char *name,
 1379+ const char *value)
 1380+{
 1381+ if (!stricmp(section, "system"))
 1382+ {
 1383+ if (!stricmp(name, "NoOverwrite")) options->NoOverwrite = INIBoolValue(value);
 1384+ if (!stricmp(name, "BundledDDrawSHA256"))
 1385+ {
 1386+ strncpy(options->sha256comp, value, 65);
 1387+ options->sha256comp[64] = 0;
 1388+ if (options->sha256comp[63] == 0) options->sha256comp[0] = 0;
 1389+ }
 1390+ if (!stricmp(name, "NoUninstall")) options->NoUninstall = INIBoolValue(value);
 1391+ }
 1392+ return 1;
 1393+}
 1394+
 1395+void ReadAppINIOptions(LPCTSTR path, app_ini_options *options)
 1396+{
 1397+ int i;
 1398+ Sha256Context sha_context;
 1399+ SHA256_HASH sha256;
 1400+ TCHAR sha256string[65];
 1401+ FILE *file;
 1402+ HANDLE file2;
 1403+ char buffer[512];
 1404+ DWORD bytesread;
 1405+ TCHAR path2[MAX_PATH + 1];
 1406+ ZeroMemory(options->sha256, 65*sizeof(char));
 1407+ ZeroMemory(options->sha256comp, 65*sizeof(char));
 1408+ _tcsncpy(path2, path, MAX_PATH + 1);
 1409+ _tcscat(path2, _T("dxgl.ini"));
 1410+ // Check for INI file and read it.
 1411+ file = _tfopen(path2, _T("r"));
 1412+ if (file)
 1413+ {
 1414+ ini_parse_file(file, ReadINIOptionsCallback, options);
 1415+ fclose(file);
 1416+ }
 1417+ else
 1418+ {
 1419+ options->NoOverwrite = FALSE;
 1420+ options->NoUninstall = FALSE;
 1421+ }
 1422+ // Check for existing ddraw.dll and get SHA256 sum
 1423+ if ((options->sha256comp[0] != 0) && !options->NoOverwrite)
 1424+ {
 1425+ _tcsncpy(path2, path, MAX_PATH + 1);
 1426+ _tcscat(path2, _T("ddraw.dll"));
 1427+ Sha256Initialise(&sha_context);
 1428+ file2 = CreateFile(path2, GENERIC_READ, FILE_SHARE_READ, NULL,
 1429+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
 1430+ if(!file2)
 1431+ {
 1432+ options->sha256[0] = 0;
 1433+ }
 1434+ else
 1435+ {
 1436+ while (1)
 1437+ {
 1438+ ReadFile(file, buffer, 512, &bytesread, NULL);
 1439+ if (!bytesread) break;
 1440+ Sha256Update(&sha_context, buffer, bytesread);
 1441+ if (bytesread < 512) break;
 1442+ }
 1443+ Sha256Finalise(&sha_context, &sha256);
 1444+ CloseHandle(file2);
 1445+ for (i = 0; i < (256 / 8); i++)
 1446+ {
 1447+ options->sha256[i * 2] = hexdigit(sha256.bytes[i] >> 4);
 1448+ options->sha256[(i * 2) + 1] = hexdigit(sha256.bytes[i] & 0xF);
 1449+ }
 1450+ }
 1451+ }
13761452 }
\ No newline at end of file
Index: cfgmgr/cfgmgr.h
@@ -76,6 +76,14 @@
7777
7878 typedef struct
7979 {
 80+ BOOL NoOverwrite;
 81+ char sha256[65];
 82+ char sha256comp[65];
 83+ BOOL NoUninstall;
 84+} app_ini_options;
 85+
 86+typedef struct
 87+{
8088 TCHAR InstallPath[MAX_PATH + 1];
8189 TCHAR InstallPathLowercase[MAX_PATH + 1];
8290 TCHAR EXEFile[MAX_PATH + 1];
@@ -96,6 +104,7 @@
97105 void SetConfig(const DXGLCFG *cfg, const DXGLCFG *mask, LPCTSTR name);
98106 void GetDirFromPath(LPTSTR path);
99107 void UpgradeConfig();
 108+void ReadAppINIOptions(LPCTSTR path, app_ini_options *options);
100109 BOOL CheckProfileExists(LPTSTR path);
101110 LPTSTR MakeNewConfig(LPTSTR path);
102111
Index: dxglcfg/dxglcfg.c
@@ -80,62 +80,126 @@
8181 BOOL tristate;
8282 TCHAR strdefault[] = _T("(global default)");
8383
84 -DWORD AddApp(LPCTSTR path, BOOL copyfile, BOOL admin)
 84+DWORD AddApp(LPCTSTR path, BOOL copyfile, BOOL admin, BOOL force, HWND hwnd)
8585 {
8686 BOOL installed = FALSE;
8787 BOOL dxgl_installdir = FALSE;
88 - BOOL old_dxgl = FALSE;
89 - TCHAR command[MAX_PATH+32];
 88+ BOOL old_dxgl = TRUE;
 89+ TCHAR command[MAX_PATH + 37];
9090 SHELLEXECUTEINFO shex;
9191 DWORD exitcode;
 92+ app_ini_options inioptions;
9293 if (copyfile)
9394 {
94 - DWORD sizeout = (MAX_PATH+1)*sizeof(TCHAR);
95 - TCHAR installpath[MAX_PATH+1];
96 - TCHAR srcpath[MAX_PATH+1];
97 - TCHAR destpath[MAX_PATH+1];
 95+ DWORD sizeout = (MAX_PATH + 1) * sizeof(TCHAR);
 96+ TCHAR installpath[MAX_PATH + 1];
 97+ TCHAR srcpath[MAX_PATH + 1];
 98+ TCHAR inipath[MAX_PATH + 1];
 99+ TCHAR backuppath[MAX_PATH + 1];
 100+ TCHAR destpath[MAX_PATH + 1];
98101 HKEY hKeyInstall;
99 - LONG error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,_T("Software\\DXGL"),0,KEY_READ,&hKeyInstall);
100 - if(error == ERROR_SUCCESS)
 102+ LONG error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\DXGL"), 0, KEY_READ, &hKeyInstall);
 103+ if (error == ERROR_SUCCESS)
101104 {
102105 dxgl_installdir = TRUE;
103 - error = RegQueryValueEx(hKeyInstall,_T("InstallDir"),NULL,NULL,(LPBYTE)installpath,&sizeout);
104 - if(error == ERROR_SUCCESS) installed = TRUE;
 106+ error = RegQueryValueEx(hKeyInstall, _T("InstallDir"), NULL, NULL, (LPBYTE)installpath, &sizeout);
 107+ if (error == ERROR_SUCCESS) installed = TRUE;
105108 }
106 - if(hKeyInstall) RegCloseKey(hKeyInstall);
107 - if(!installed)
 109+ if (hKeyInstall) RegCloseKey(hKeyInstall);
 110+ if (!installed)
108111 {
109 - GetModuleFileName(NULL,installpath,MAX_PATH+1);
 112+ GetModuleFileName(NULL, installpath, MAX_PATH + 1);
110113 }
111 - if(dxgl_installdir) _tcscat(installpath,_T("\\"));
112 - else (_tcsrchr(installpath,_T('\\')))[1] = 0;
113 - _tcsncpy(srcpath,installpath,MAX_PATH+1);
114 - _tcscat(srcpath,_T("ddraw.dll"));
115 - _tcsncpy(destpath,path,MAX_PATH+1);
116 - (_tcsrchr(destpath,_T('\\')))[1] = 0;
117 - _tcscat(destpath,_T("ddraw.dll"));
118 - error = CopyFile(srcpath,destpath,TRUE);
119 - error_loop:
120 - if(!error)
 114+ if (dxgl_installdir) _tcscat(installpath, _T("\\"));
 115+ else (_tcsrchr(installpath, _T('\\')))[1] = 0;
 116+ _tcsncpy(srcpath, installpath, MAX_PATH + 1);
 117+ _tcscat(srcpath, _T("ddraw.dll"));
 118+ _tcsncpy(destpath, path, MAX_PATH + 1);
 119+ (_tcsrchr(destpath, _T('\\')))[1] = 0;
 120+ _tcscat(destpath, _T("ddraw.dll"));
 121+ _tcsncpy(backuppath, path, MAX_PATH + 1);
 122+ (_tcsrchr(backuppath, _T('\\')))[1] = 0;
 123+ _tcscat(backuppath, _T("ddraw.dll.dxgl-backup"));
 124+ _tcsncpy(inipath, path, MAX_PATH + 1);
 125+ (_tcsrchr(inipath, _T('\\')))[1] = 0;
 126+ // Check for DXGL ini file and existing ddraw.dll
 127+ ReadAppINIOptions(inipath, &inioptions);
 128+ error = CopyFile(srcpath, destpath, TRUE);
 129+ error_loop:
 130+ if (!error)
121131 {
122132 error = GetLastError();
123 - if(error == ERROR_FILE_EXISTS)
 133+ if (error == ERROR_FILE_EXISTS)
124134 {
 135+ if (inioptions.NoOverwrite)
 136+ {
 137+ MessageBox(hwnd, _T("Cannot install DXGL. An INI file has \
 138+been found in your game folder prohibiting overwriting the existing DirectDraw \
 139+library.\r\n\r\nIf you want to install DXGL, edit the dxgl.ini file in your game \
 140+folder and set the NoOverwite value to false.\r\n\r\n\
 141+A profile will still be created for your game but may not be compatible with the \
 142+DirectDraw library in your game folder."), _T("Error"), MB_OK | MB_ICONERROR);
 143+ return 0; // Continue to install registry key anyway
 144+ }
 145+ if (!memcmp(inioptions.sha256, inioptions.sha256comp, 64))
 146+ // Detected original ddraw matches INI hash
 147+ {
 148+ error = CopyFile(srcpath, backuppath, FALSE);
 149+ if (!error)
 150+ {
 151+ error = GetLastError();
 152+ if ((error == ERROR_ACCESS_DENIED) && !admin)
 153+ {
 154+ _tcscpy(command, _T(" install "));
 155+ _tcscat(command, path);
 156+ ZeroMemory(&shex, sizeof(SHELLEXECUTEINFO));
 157+ shex.cbSize = sizeof(SHELLEXECUTEINFO);
 158+ shex.lpVerb = _T("runas");
 159+ shex.fMask = SEE_MASK_NOCLOSEPROCESS;
 160+ _tcscat(installpath, _T("\\dxglcfg.exe"));
 161+ shex.lpFile = installpath;
 162+ shex.lpParameters = command;
 163+ ShellExecuteEx(&shex);
 164+ WaitForSingleObject(shex.hProcess, INFINITE);
 165+ GetExitCodeProcess(shex.hProcess, &exitcode);
 166+ return exitcode;
 167+ }
 168+ }
 169+ }
125170 HMODULE hmod = LoadLibrary(destpath);
126171 if(hmod)
127172 {
128 - if(GetProcAddress(hmod,"IsDXGLDDraw")) old_dxgl = TRUE;
 173+ if(GetProcAddress(hmod,"IsDXGLDDraw") || force) old_dxgl = TRUE;
 174+ else old_dxgl = FALSE;
129175 FreeLibrary(hmod);
130176 }
 177+ else
 178+ {
 179+ if (force) old_dxgl = TRUE;
 180+ else old_dxgl = FALSE;
 181+ }
131182 if(old_dxgl)
132183 {
133184 error = CopyFile(srcpath,destpath,FALSE);
134185 goto error_loop;
135186 }
 187+ else
 188+ {
 189+ // Prompt to overwrite
 190+ if (MessageBox(hwnd, _T("A custom DirectDraw library has been detected in \
 191+your game folder. Would you like to replace it with DXGL?\r\n\r\n\
 192+Warning: Installing DXGL will remove any customizations that the existing custom DirectDraw \
 193+library may have."), _T("DXGL Config"), MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2) == IDYES)
 194+ {
 195+ error = CopyFile(srcpath, destpath, FALSE);
 196+ goto error_loop;
 197+ }
 198+ }
136199 }
137200 if((error == ERROR_ACCESS_DENIED) && !admin)
138201 {
139 - _tcscpy(command,_T(" install "));
 202+ if(old_dxgl) _tcscpy(command,_T(" install "));
 203+ else _tcscpy(command, _T(" forceinstall "));
140204 _tcscat(command,path);
141205 ZeroMemory(&shex,sizeof(SHELLEXECUTEINFO));
142206 shex.cbSize = sizeof(SHELLEXECUTEINFO);
@@ -155,7 +219,7 @@
156220 return 0;
157221 }
158222
159 -DWORD DelApp(LPCTSTR path, BOOL admin)
 223+DWORD DelApp(LPCTSTR path, BOOL admin, HWND hwnd)
160224 {
161225 BOOL installed = FALSE;
162226 TCHAR command[MAX_PATH + 32];
@@ -162,10 +226,14 @@
163227 BOOL old_dxgl = TRUE;
164228 DWORD sizeout = (MAX_PATH+1)*sizeof(TCHAR);
165229 TCHAR installpath[MAX_PATH+1];
 230+ TCHAR inipath[MAX_PATH + 1];
 231+ TCHAR backuppath[MAX_PATH + 1];
166232 HKEY hKeyInstall;
167233 HMODULE hmod;
168234 SHELLEXECUTEINFO shex;
169235 DWORD exitcode;
 236+ HANDLE exists;
 237+ app_ini_options inioptions;
170238 LONG error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\DXGL"), 0, KEY_READ, &hKeyInstall);
171239 if(error == ERROR_SUCCESS)
172240 {
@@ -177,6 +245,24 @@
178246 {
179247 GetModuleFileName(NULL,installpath,MAX_PATH+1);
180248 }
 249+ _tcsncpy(inipath, path, MAX_PATH + 1);
 250+ (_tcsrchr(inipath, _T('\\')))[1] = 0;
 251+ _tcsncpy(backuppath, path, MAX_PATH + 1);
 252+ (_tcsrchr(backuppath, _T('\\')))[1] = 0;
 253+ _tcscat(backuppath, _T("ddraw.dll.dxgl-backup"));
 254+ // Check for DXGL ini file and existing ddraw.dll
 255+ ReadAppINIOptions(inipath, &inioptions);
 256+ if (inioptions.NoOverwrite || inioptions.NoUninstall)
 257+ {
 258+ MessageBox(hwnd,_T("DXGL has not been removed from your game folder. \
 259+An INI file has been found in your game folder prohibiting the DirectDraw \
 260+library in your game folder from being deleted.\r\n\r\n\
 261+If this is in error, you will have to manually delete ddraw.dll from your \
 262+game folder. If your game was distributed by Steam or a similar service \
 263+please verify your game files after removing the file, in case the game \
 264+shipped with a custom DirectDraw library."), _T("Warning"), MB_OK | MB_ICONWARNING);
 265+ return 0; // Continue to delete registry profile.
 266+ }
181267 hmod = LoadLibrary(path);
182268 if(hmod)
183269 {
@@ -183,11 +269,11 @@
184270 if(!GetProcAddress(hmod,"IsDXGLDDraw")) old_dxgl = FALSE;
185271 FreeLibrary(hmod);
186272 }
 273+ else old_dxgl = FALSE;
187274 if(!old_dxgl) return 0;
188275 if(!DeleteFile(path))
189276 {
190277 error = GetLastError();
191 - if(error == ERROR_FILE_NOT_FOUND) return 0;
192278 if((error == ERROR_ACCESS_DENIED) && !admin)
193279 {
194280 _tcscpy(command,_T(" remove "));
@@ -204,8 +290,37 @@
205291 GetExitCodeProcess(shex.hProcess,&exitcode);
206292 return exitcode;
207293 }
208 - return error;
 294+ else if (error != ERROR_FILE_NOT_FOUND) return error;
209295 }
 296+ exists = CreateFile(backuppath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
 297+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
 298+ if (exists == INVALID_HANDLE_VALUE) return 0;
 299+ else
 300+ {
 301+ CloseHandle(exists);
 302+ error = MoveFile(backuppath, path);
 303+ if (!error)
 304+ {
 305+ error = GetLastError();
 306+ if ((error == ERROR_ACCESS_DENIED) && !admin)
 307+ {
 308+ _tcscpy(command, _T(" remove "));
 309+ _tcscat(command, path);
 310+ ZeroMemory(&shex, sizeof(SHELLEXECUTEINFO));
 311+ shex.cbSize = sizeof(SHELLEXECUTEINFO);
 312+ shex.lpVerb = _T("runas");
 313+ shex.fMask = SEE_MASK_NOCLOSEPROCESS;
 314+ _tcscat(installpath, _T("\\dxglcfg.exe"));
 315+ shex.lpFile = installpath;
 316+ shex.lpParameters = command;
 317+ ShellExecuteEx(&shex);
 318+ WaitForSingleObject(shex.hProcess, INFINITE);
 319+ GetExitCodeProcess(shex.hProcess, &exitcode);
 320+ return exitcode;
 321+ }
 322+ else return error;
 323+ }
 324+ }
210325 return 0;
211326 }
212327
@@ -1340,7 +1455,7 @@
13411456 _T("Profile already exists"), MB_OK | MB_ICONWARNING);
13421457 break;
13431458 }
1344 - err = AddApp(filename.lpstrFile, TRUE, FALSE);
 1459+ err = AddApp(filename.lpstrFile, TRUE, FALSE, FALSE, hWnd);
13451460 if (!err)
13461461 {
13471462 LPTSTR newkey = MakeNewConfig(filename.lpstrFile);
@@ -1465,7 +1580,7 @@
14661581 _tcscat(path, _T("\\ddraw.dll"));
14671582 if (GetFileAttributes(path) != INVALID_FILE_ATTRIBUTES)
14681583 {
1469 - if (DelApp(path, FALSE)) failed = TRUE;
 1584+ if (DelApp(path, FALSE, hWnd)) failed = TRUE;
14701585 }
14711586 free(path);
14721587 free(regbuffer);
@@ -1511,6 +1626,9 @@
15121627 TCHAR installpath[MAX_PATH + 1];
15131628 TCHAR srcpath[MAX_PATH + 1];
15141629 TCHAR destpath[MAX_PATH + 1];
 1630+ TCHAR inipath[MAX_PATH + 1];
 1631+ TCHAR backuppath[MAX_PATH + 1];
 1632+ app_ini_options inioptions;
15151633 HMODULE hmod;
15161634 UpgradeConfig();
15171635 regbuffersize = 1024;
@@ -1555,8 +1673,12 @@
15561674 if (regbuffer[0] != 0)
15571675 {
15581676 _tcsncpy(destpath, regbuffer, MAX_PATH + 1);
1559 - _tcscat(destpath, _T("\\"));
1560 - _tcscat(destpath, _T("ddraw.dll"));
 1677+ _tcscat(destpath, _T("\\ddraw.dll"));
 1678+ _tcsncpy(inipath, regbuffer, MAX_PATH + 1);
 1679+ _tcscat(inipath, _T("\\dxgl.ini"));
 1680+ _tcsncpy(backuppath, regbuffer, MAX_PATH + 1);
 1681+ _tcscat(backuppath, _T("\\ddraw.dll.dxgl-backup"));
 1682+ ReadAppINIOptions(inipath, &inioptions);
15611683 error = CopyFile(srcpath, destpath, TRUE);
15621684 if (!error)
15631685 {
@@ -1563,6 +1685,10 @@
15641686 error = GetLastError();
15651687 if (error == ERROR_FILE_EXISTS)
15661688 {
 1689+ if (inioptions.NoOverwrite) continue;
 1690+ if (!memcmp(inioptions.sha256, inioptions.sha256comp, 64))
 1691+ // Detected original ddraw matches INI hash
 1692+ CopyFile(srcpath, backuppath, FALSE);
15671693 old_dxgl = FALSE;
15681694 hmod = LoadLibrary(destpath);
15691695 if (hmod)
@@ -1600,6 +1726,10 @@
16011727 TCHAR installpath[MAX_PATH + 1];
16021728 TCHAR srcpath[MAX_PATH + 1];
16031729 TCHAR destpath[MAX_PATH + 1];
 1730+ TCHAR inipath[MAX_PATH + 1];
 1731+ TCHAR backuppath[MAX_PATH + 1];
 1732+ HANDLE exists;
 1733+ app_ini_options inioptions;
16041734 HMODULE hmod;
16051735 int i = 0;
16061736 UpgradeConfig(); // Just to make sure the registry format is correct
@@ -1645,8 +1775,13 @@
16461776 if (regbuffer[0] != 0)
16471777 {
16481778 _tcsncpy(destpath, regbuffer, MAX_PATH + 1);
1649 - _tcscat(destpath, _T("\\"));
1650 - _tcscat(destpath, _T("ddraw.dll"));
 1779+ _tcscat(destpath, _T("\\ddraw.dll"));
 1780+ _tcsncpy(inipath, regbuffer, MAX_PATH + 1);
 1781+ _tcscat(inipath, _T("\\dxgl.ini"));
 1782+ _tcsncpy(backuppath, regbuffer, MAX_PATH + 1);
 1783+ _tcscat(backuppath, _T("\\ddraw.dll.dxgl-backup"));
 1784+ ReadAppINIOptions(inipath, &inioptions);
 1785+ if (inioptions.NoOverwrite || inioptions.NoUninstall) continue;
16511786 if (GetFileAttributes(destpath) != INVALID_FILE_ATTRIBUTES)
16521787 {
16531788 old_dxgl = FALSE;
@@ -1658,7 +1793,18 @@
16591794 }
16601795 if (_tcscmp(srcpath, destpath))
16611796 {
1662 - if (old_dxgl) DeleteFile(destpath);
 1797+ if (old_dxgl)
 1798+ {
 1799+ DeleteFile(destpath);
 1800+ exists = CreateFile(backuppath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
 1801+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
 1802+ if (exists == INVALID_HANDLE_VALUE) continue;
 1803+ else
 1804+ {
 1805+ CloseHandle(exists);
 1806+ MoveFile(backuppath, destpath);
 1807+ }
 1808+ }
16631809 }
16641810 }
16651811 }
@@ -1705,11 +1851,15 @@
17061852 }
17071853 if(!_tcsnicmp(lpCmdLine,_T("install "),8))
17081854 {
1709 - return AddApp(lpCmdLine+8,TRUE,TRUE);
 1855+ return AddApp(lpCmdLine+8,TRUE,TRUE,FALSE,NULL);
17101856 }
 1857+ if(!_tcsnicmp(lpCmdLine,_T("forceinstall "),13))
 1858+ {
 1859+ return AddApp(lpCmdLine+8,TRUE,TRUE,TRUE,NULL);
 1860+ }
17111861 if(!_tcsnicmp(lpCmdLine,_T("remove "),7))
17121862 {
1713 - return DelApp(lpCmdLine+7,TRUE);
 1863+ return DelApp(lpCmdLine+7,TRUE,NULL);
17141864 }
17151865 icc.dwSize = sizeof(icc);
17161866 icc.dwICC = ICC_WIN95_CLASSES;
Index: dxglcfg2/dxglcfg2.c
@@ -128,62 +128,126 @@
129129 _T("8/15/16/24/32-bit")
130130 };
131131
132 -DWORD AddApp(LPCTSTR path, BOOL copyfile, BOOL admin)
 132+DWORD AddApp(LPCTSTR path, BOOL copyfile, BOOL admin, BOOL force, HWND hwnd)
133133 {
134134 BOOL installed = FALSE;
135135 BOOL dxgl_installdir = FALSE;
136 - BOOL old_dxgl = FALSE;
137 - TCHAR command[MAX_PATH+32];
 136+ BOOL old_dxgl = TRUE;
 137+ TCHAR command[MAX_PATH + 37];
138138 SHELLEXECUTEINFO shex;
139139 DWORD exitcode;
 140+ app_ini_options inioptions;
140141 if (copyfile)
141142 {
142 - DWORD sizeout = (MAX_PATH+1)*sizeof(TCHAR);
143 - TCHAR installpath[MAX_PATH+1];
144 - TCHAR srcpath[MAX_PATH+1];
145 - TCHAR destpath[MAX_PATH+1];
 143+ DWORD sizeout = (MAX_PATH + 1) * sizeof(TCHAR);
 144+ TCHAR installpath[MAX_PATH + 1];
 145+ TCHAR srcpath[MAX_PATH + 1];
 146+ TCHAR inipath[MAX_PATH + 1];
 147+ TCHAR backuppath[MAX_PATH + 1];
 148+ TCHAR destpath[MAX_PATH + 1];
146149 HKEY hKeyInstall;
147 - LONG error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,_T("Software\\DXGL"),0,KEY_READ,&hKeyInstall);
148 - if(error == ERROR_SUCCESS)
 150+ LONG error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\DXGL"), 0, KEY_READ, &hKeyInstall);
 151+ if (error == ERROR_SUCCESS)
149152 {
150153 dxgl_installdir = TRUE;
151 - error = RegQueryValueEx(hKeyInstall,_T("InstallDir"),NULL,NULL,(LPBYTE)installpath,&sizeout);
152 - if(error == ERROR_SUCCESS) installed = TRUE;
 154+ error = RegQueryValueEx(hKeyInstall, _T("InstallDir"), NULL, NULL, (LPBYTE)installpath, &sizeout);
 155+ if (error == ERROR_SUCCESS) installed = TRUE;
153156 }
154 - if(hKeyInstall) RegCloseKey(hKeyInstall);
155 - if(!installed)
 157+ if (hKeyInstall) RegCloseKey(hKeyInstall);
 158+ if (!installed)
156159 {
157 - GetModuleFileName(NULL,installpath,MAX_PATH+1);
 160+ GetModuleFileName(NULL, installpath, MAX_PATH + 1);
158161 }
159 - if(dxgl_installdir) _tcscat(installpath,_T("\\"));
160 - else (_tcsrchr(installpath,_T('\\')))[1] = 0;
161 - _tcsncpy(srcpath,installpath,MAX_PATH+1);
162 - _tcscat(srcpath,_T("ddraw.dll"));
163 - _tcsncpy(destpath,path,MAX_PATH+1);
164 - (_tcsrchr(destpath,_T('\\')))[1] = 0;
165 - _tcscat(destpath,_T("ddraw.dll"));
166 - error = CopyFile(srcpath,destpath,TRUE);
167 - error_loop:
168 - if(!error)
 162+ if (dxgl_installdir) _tcscat(installpath, _T("\\"));
 163+ else (_tcsrchr(installpath, _T('\\')))[1] = 0;
 164+ _tcsncpy(srcpath, installpath, MAX_PATH + 1);
 165+ _tcscat(srcpath, _T("ddraw.dll"));
 166+ _tcsncpy(destpath, path, MAX_PATH + 1);
 167+ (_tcsrchr(destpath, _T('\\')))[1] = 0;
 168+ _tcscat(destpath, _T("ddraw.dll"));
 169+ _tcsncpy(backuppath, path, MAX_PATH + 1);
 170+ (_tcsrchr(backuppath, _T('\\')))[1] = 0;
 171+ _tcscat(backuppath, _T("ddraw.dll.dxgl-backup"));
 172+ _tcsncpy(inipath, path, MAX_PATH + 1);
 173+ (_tcsrchr(inipath, _T('\\')))[1] = 0;
 174+ // Check for DXGL ini file and existing ddraw.dll
 175+ ReadAppINIOptions(inipath, &inioptions);
 176+ error = CopyFile(srcpath, destpath, TRUE);
 177+ error_loop:
 178+ if (!error)
169179 {
170180 error = GetLastError();
171 - if(error == ERROR_FILE_EXISTS)
 181+ if (error == ERROR_FILE_EXISTS)
172182 {
 183+ if (inioptions.NoOverwrite)
 184+ {
 185+ MessageBox(hwnd, _T("Cannot install DXGL. An INI file has \
 186+been placed in your game folder prohibiting overwriting the existing DirectDraw \
 187+library.\r\n\r\nIf you want to install DXGL, edit the dxgl.ini file in your game \
 188+folder and set the NoOverwite value to false.\r\n\r\n\
 189+A profile will still be created for your game but may not be compatible with the \
 190+DirectDraw library in your game folder."), _T("Error"), MB_OK | MB_ICONERROR);
 191+ return 0; // Continue to install registry key anyway
 192+ }
 193+ if (!memcmp(inioptions.sha256, inioptions.sha256comp, 64))
 194+ // Detected original ddraw matches INI hash
 195+ {
 196+ error = CopyFile(srcpath, backuppath, FALSE);
 197+ if (!error)
 198+ {
 199+ error = GetLastError();
 200+ if ((error == ERROR_ACCESS_DENIED) && !admin)
 201+ {
 202+ _tcscpy(command, _T(" install "));
 203+ _tcscat(command, path);
 204+ ZeroMemory(&shex, sizeof(SHELLEXECUTEINFO));
 205+ shex.cbSize = sizeof(SHELLEXECUTEINFO);
 206+ shex.lpVerb = _T("runas");
 207+ shex.fMask = SEE_MASK_NOCLOSEPROCESS;
 208+ _tcscat(installpath, _T("\\dxglcfg.exe"));
 209+ shex.lpFile = installpath;
 210+ shex.lpParameters = command;
 211+ ShellExecuteEx(&shex);
 212+ WaitForSingleObject(shex.hProcess, INFINITE);
 213+ GetExitCodeProcess(shex.hProcess, &exitcode);
 214+ return exitcode;
 215+ }
 216+ }
 217+ }
173218 HMODULE hmod = LoadLibrary(destpath);
174219 if(hmod)
175220 {
176 - if(GetProcAddress(hmod,"IsDXGLDDraw")) old_dxgl = TRUE;
 221+ if(GetProcAddress(hmod,"IsDXGLDDraw") || force) old_dxgl = TRUE;
 222+ else old_dxgl = FALSE;
177223 FreeLibrary(hmod);
178224 }
 225+ else
 226+ {
 227+ if (force) old_dxgl = TRUE;
 228+ else old_dxgl = FALSE;
 229+ }
179230 if(old_dxgl)
180231 {
181232 error = CopyFile(srcpath,destpath,FALSE);
182233 goto error_loop;
183234 }
 235+ else
 236+ {
 237+ // Prompt to overwrite
 238+ if (MessageBox(hwnd, _T("A custom DirectDraw library has been detected in \
 239+your game folder. Would you like to replace it with DXGL?\r\n\r\n\
 240+Warning: Installing DXGL will remove any customizations that the existing custom DirectDraw \
 241+library may have."), _T("DXGL Config"), MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2) == IDYES)
 242+ {
 243+ error = CopyFile(srcpath, destpath, FALSE);
 244+ goto error_loop;
 245+ }
 246+ }
184247 }
185248 if((error == ERROR_ACCESS_DENIED) && !admin)
186249 {
187 - _tcscpy(command,_T(" install "));
 250+ if(old_dxgl) _tcscpy(command,_T(" install "));
 251+ else _tcscpy(command, _T(" forceinstall "));
188252 _tcscat(command,path);
189253 ZeroMemory(&shex,sizeof(SHELLEXECUTEINFO));
190254 shex.cbSize = sizeof(SHELLEXECUTEINFO);
@@ -203,7 +267,7 @@
204268 return 0;
205269 }
206270
207 -DWORD DelApp(LPCTSTR path, BOOL admin)
 271+DWORD DelApp(LPCTSTR path, BOOL admin, HWND hwnd)
208272 {
209273 BOOL installed = FALSE;
210274 TCHAR command[MAX_PATH + 32];
@@ -210,10 +274,14 @@
211275 BOOL old_dxgl = TRUE;
212276 DWORD sizeout = (MAX_PATH+1)*sizeof(TCHAR);
213277 TCHAR installpath[MAX_PATH+1];
 278+ TCHAR inipath[MAX_PATH + 1];
 279+ TCHAR backuppath[MAX_PATH + 1];
214280 HKEY hKeyInstall;
215281 HMODULE hmod;
216282 SHELLEXECUTEINFO shex;
217283 DWORD exitcode;
 284+ HANDLE exists;
 285+ app_ini_options inioptions;
218286 LONG error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\DXGL"), 0, KEY_READ, &hKeyInstall);
219287 if(error == ERROR_SUCCESS)
220288 {
@@ -225,6 +293,24 @@
226294 {
227295 GetModuleFileName(NULL,installpath,MAX_PATH+1);
228296 }
 297+ _tcsncpy(inipath, path, MAX_PATH + 1);
 298+ (_tcsrchr(inipath, _T('\\')))[1] = 0;
 299+ _tcsncpy(backuppath, path, MAX_PATH + 1);
 300+ (_tcsrchr(backuppath, _T('\\')))[1] = 0;
 301+ _tcscat(backuppath, _T("ddraw.dll.dxgl-backup"));
 302+ // Check for DXGL ini file and existing ddraw.dll
 303+ ReadAppINIOptions(inipath, &inioptions);
 304+ if (inioptions.NoOverwrite || inioptions.NoUninstall)
 305+ {
 306+ MessageBox(hwnd,_T("DXGL has not been removed from your game folder. \
 307+An INI file has been found in your game folder prohibiting the DirectDraw \
 308+library in your game folder from being deleted.\r\n\r\n\
 309+If this is in error, you will have to manually delete ddraw.dll from your \
 310+game folder. If your game was distributed by Steam or a similar service \
 311+please verify your game files after removing the file, in case the game \
 312+shipped with a custom DirectDraw library."), _T("Warning"), MB_OK | MB_ICONWARNING);
 313+ return 0; // Continue to delete registry profile.
 314+ }
229315 hmod = LoadLibrary(path);
230316 if(hmod)
231317 {
@@ -231,11 +317,11 @@
232318 if(!GetProcAddress(hmod,"IsDXGLDDraw")) old_dxgl = FALSE;
233319 FreeLibrary(hmod);
234320 }
 321+ else old_dxgl = FALSE;
235322 if(!old_dxgl) return 0;
236323 if(!DeleteFile(path))
237324 {
238325 error = GetLastError();
239 - if(error == ERROR_FILE_NOT_FOUND) return 0;
240326 if((error == ERROR_ACCESS_DENIED) && !admin)
241327 {
242328 _tcscpy(command,_T(" remove "));
@@ -252,8 +338,37 @@
253339 GetExitCodeProcess(shex.hProcess,&exitcode);
254340 return exitcode;
255341 }
256 - return error;
 342+ else if (error != ERROR_FILE_NOT_FOUND) return error;
257343 }
 344+ exists = CreateFile(backuppath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
 345+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
 346+ if (exists == INVALID_HANDLE_VALUE) return 0;
 347+ else
 348+ {
 349+ CloseHandle(exists);
 350+ error = MoveFile(backuppath, path);
 351+ if (!error)
 352+ {
 353+ error = GetLastError();
 354+ if ((error == ERROR_ACCESS_DENIED) && !admin)
 355+ {
 356+ _tcscpy(command, _T(" remove "));
 357+ _tcscat(command, path);
 358+ ZeroMemory(&shex, sizeof(SHELLEXECUTEINFO));
 359+ shex.cbSize = sizeof(SHELLEXECUTEINFO);
 360+ shex.lpVerb = _T("runas");
 361+ shex.fMask = SEE_MASK_NOCLOSEPROCESS;
 362+ _tcscat(installpath, _T("\\dxglcfg.exe"));
 363+ shex.lpFile = installpath;
 364+ shex.lpParameters = command;
 365+ ShellExecuteEx(&shex);
 366+ WaitForSingleObject(shex.hProcess, INFINITE);
 367+ GetExitCodeProcess(shex.hProcess, &exitcode);
 368+ return exitcode;
 369+ }
 370+ else return error;
 371+ }
 372+ }
258373 return 0;
259374 }
260375
@@ -1617,7 +1732,7 @@
16181733 _T("Profile already exists"), MB_OK | MB_ICONWARNING);
16191734 break;
16201735 }
1621 - err = AddApp(filename.lpstrFile, TRUE, FALSE);
 1736+ err = AddApp(filename.lpstrFile, TRUE, FALSE, FALSE, hWnd);
16221737 if (!err)
16231738 {
16241739 LPTSTR newkey = MakeNewConfig(filename.lpstrFile);
@@ -1742,7 +1857,7 @@
17431858 _tcscat(path, _T("\\ddraw.dll"));
17441859 if (GetFileAttributes(path) != INVALID_FILE_ATTRIBUTES)
17451860 {
1746 - if (DelApp(path, FALSE)) failed = TRUE;
 1861+ if (DelApp(path, FALSE, hWnd)) failed = TRUE;
17471862 }
17481863 free(path);
17491864 free(regbuffer);
@@ -1877,6 +1992,10 @@
18781993 TCHAR installpath[MAX_PATH + 1];
18791994 TCHAR srcpath[MAX_PATH + 1];
18801995 TCHAR destpath[MAX_PATH + 1];
 1996+ TCHAR inipath[MAX_PATH + 1];
 1997+ TCHAR backuppath[MAX_PATH + 1];
 1998+ HANDLE exists;
 1999+ app_ini_options inioptions;
18812000 HMODULE hmod;
18822001 int i = 0;
18832002 UpgradeConfig(); // Just to make sure the registry format is correct
@@ -1922,8 +2041,13 @@
19232042 if (regbuffer[0] != 0)
19242043 {
19252044 _tcsncpy(destpath, regbuffer, MAX_PATH + 1);
1926 - _tcscat(destpath, _T("\\"));
1927 - _tcscat(destpath, _T("ddraw.dll"));
 2045+ _tcscat(destpath, _T("\\ddraw.dll"));
 2046+ _tcsncpy(inipath, regbuffer, MAX_PATH + 1);
 2047+ _tcscat(inipath, _T("\\dxgl.ini"));
 2048+ _tcsncpy(backuppath, regbuffer, MAX_PATH + 1);
 2049+ _tcscat(backuppath, _T("\\ddraw.dll.dxgl-backup"));
 2050+ ReadAppINIOptions(inipath, &inioptions);
 2051+ if (inioptions.NoOverwrite || inioptions.NoUninstall) continue;
19282052 if (GetFileAttributes(destpath) != INVALID_FILE_ATTRIBUTES)
19292053 {
19302054 old_dxgl = FALSE;
@@ -1935,7 +2059,18 @@
19362060 }
19372061 if (_tcscmp(srcpath, destpath))
19382062 {
1939 - if (old_dxgl) DeleteFile(destpath);
 2063+ if (old_dxgl)
 2064+ {
 2065+ DeleteFile(destpath);
 2066+ exists = CreateFile(backuppath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
 2067+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
 2068+ if (exists == INVALID_HANDLE_VALUE) continue;
 2069+ else
 2070+ {
 2071+ CloseHandle(exists);
 2072+ MoveFile(backuppath, destpath);
 2073+ }
 2074+ }
19402075 }
19412076 }
19422077 }
@@ -1982,11 +2117,15 @@
19832118 }
19842119 if(!_tcsnicmp(lpCmdLine,_T("install "),8))
19852120 {
1986 - return AddApp(lpCmdLine+8,TRUE,TRUE);
 2121+ return AddApp(lpCmdLine+8,TRUE,TRUE,FALSE,NULL);
19872122 }
 2123+ if(!_tcsnicmp(lpCmdLine,_T("forceinstall "),13))
 2124+ {
 2125+ return AddApp(lpCmdLine+8,TRUE,TRUE,TRUE,NULL);
 2126+ }
19882127 if(!_tcsnicmp(lpCmdLine,_T("remove "),7))
19892128 {
1990 - return DelApp(lpCmdLine+7,TRUE);
 2129+ return DelApp(lpCmdLine+7,TRUE,NULL);
19912130 }
19922131 icc.dwSize = sizeof(icc);
19932132 icc.dwICC = ICC_WIN95_CLASSES;