Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

448 lines
11 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1996 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: apphack.c
  6. * Content: app compatiblity hacking code
  7. * History:
  8. * Date By Reason
  9. * ==== == ======
  10. * 27-may-96 craige initial implementation
  11. * 28-sep-96 craige allow binary data in registry (f*cking .inf
  12. * can't put in dword into the registry)
  13. *
  14. ***************************************************************************/
  15. #include "ddrawpr.h"
  16. #include "apphack.h"
  17. #define STRCMP lstrcmpi
  18. static int sortRtn( LPAPPHACKS *p1, LPAPPHACKS *p2 )
  19. {
  20. return STRCMP( (*p1)->szName, (*p2)->szName );
  21. }
  22. static int searchRtn( LPSTR key, LPAPPHACKS *p2 )
  23. {
  24. return STRCMP( key, (*p2)->szName );
  25. }
  26. __inline static BOOL fileRead( HANDLE hfile, void *data, int len )
  27. {
  28. DWORD len_read;
  29. if( !ReadFile( hfile, data, (DWORD) len, &len_read, NULL ) ||
  30. len_read != (DWORD) len )
  31. {
  32. return FALSE;
  33. }
  34. return TRUE;
  35. } /* fileRead */
  36. __inline static BOOL fileSeek( HANDLE hfile, DWORD offset )
  37. {
  38. if( SetFilePointer( hfile, offset, NULL, FILE_BEGIN ) != offset )
  39. {
  40. return FALSE;
  41. }
  42. return TRUE;
  43. } /* fileSeek */
  44. void FreeAppHackData(void)
  45. {
  46. LPAPPHACKS next;
  47. LPAPPHACKS lphack = lpAppList;
  48. while( lphack != NULL )
  49. {
  50. next = lphack->lpNext;
  51. MemFree( lphack );
  52. lphack = next;
  53. }
  54. if( lpAppArray != NULL )
  55. {
  56. MemFree( lpAppArray );
  57. }
  58. lpAppArray = NULL;
  59. lpAppList = NULL;
  60. dwAppArraySize = 0;
  61. bHaveReadReg = FALSE;
  62. }
  63. /*
  64. * HackMeBaby
  65. *
  66. * And we'll have fun fun fun 'til your daddy takes your app hacks away...
  67. */
  68. DWORD HackMeBaby( void )
  69. {
  70. char fname[_MAX_PATH];
  71. char name[_MAX_PATH];
  72. HANDLE hfile;
  73. int i;
  74. LPAPPHACKS lphack;
  75. LPAPPHACKS *lplphack;
  76. DWORD dwScreenSaver;
  77. IMAGE_NT_HEADERS nth;
  78. IMAGE_DOS_HEADER dh;
  79. DWORD appid;
  80. HKEY hkey;
  81. /*
  82. * bail on the existing info if requested
  83. */
  84. if( bReloadReg )
  85. {
  86. DPF( 3, "Reloading the compatibility info from the registry" );
  87. if( lpAppList != NULL )
  88. {
  89. DPF( 4, "Freeing existing compatiblity list" );
  90. }
  91. FreeAppHackData();
  92. }
  93. /*
  94. * read the registry for any app hacks
  95. */
  96. if( !bHaveReadReg )
  97. {
  98. int index;
  99. int count;
  100. bHaveReadReg = TRUE;
  101. if( !RegOpenKey( HKEY_LOCAL_MACHINE,
  102. REGSTR_PATH_DDRAW "\\" REGSTR_KEY_APPCOMPAT, &hkey ) )
  103. {
  104. index = 0;
  105. count = 0;
  106. DPF( 4, "Reading App Compatiblity Information" );
  107. /*
  108. * run through all keys
  109. */
  110. while( !RegEnumKey( hkey, index, name, sizeof( name ) ) )
  111. {
  112. HKEY hsubkey;
  113. DPF( 5, " Found info for %s", name );
  114. /*
  115. * get info for this specific app
  116. */
  117. if( !RegOpenKey( hkey, name, &hsubkey ) )
  118. {
  119. DWORD type;
  120. DWORD cb;
  121. DWORD id;
  122. DWORD flags;
  123. cb = sizeof( name );
  124. if( !RegQueryValueEx( hsubkey, REGSTR_VAL_DDRAW_NAME,
  125. NULL, &type, name, &cb ) )
  126. {
  127. if( type == REG_SZ )
  128. {
  129. cb = sizeof( flags );
  130. if( !RegQueryValueEx( hsubkey, REGSTR_VAL_DDRAW_FLAGS,
  131. NULL, &type, (LPSTR) &flags, &cb ) )
  132. {
  133. if( (type == REG_DWORD) ||
  134. (type == REG_BINARY && cb == sizeof( flags )) )
  135. {
  136. if( !(flags & ~DDRAW_APPCOMPAT_VALID) )
  137. {
  138. cb = 4;
  139. if( !RegQueryValueEx( hsubkey, REGSTR_VAL_DDRAW_APPID,
  140. NULL, &type, (LPSTR) &id, &cb ) )
  141. {
  142. if( (type == REG_DWORD) ||
  143. (type == REG_BINARY && cb == sizeof( flags )) )
  144. {
  145. /*
  146. * finally! we have all the data. save it
  147. */
  148. lphack = MemAlloc( sizeof( *lphack ) + strlen( name ) + 1 );
  149. if( lphack != NULL )
  150. {
  151. lphack->dwAppId = id;
  152. lphack->dwFlags = flags;
  153. lphack->szName = &((LPSTR)lphack)[sizeof( *lphack )];
  154. lphack->lpNext = lpAppList;
  155. lpAppList = lphack;
  156. strcpy( lphack->szName, name );
  157. count++;
  158. DPF( 5, " Name = %s", lphack->szName );
  159. DPF( 5, " Flags = 0x%08lx", lphack->dwFlags );
  160. DPF( 5, " AppId = 0x%08lx", lphack->dwAppId );
  161. }
  162. else
  163. {
  164. DPF( 0, " Out of memory!!!" );
  165. }
  166. }
  167. else
  168. {
  169. DPF( 0, " AppID not a DWORD for app %s", name );
  170. }
  171. }
  172. }
  173. else
  174. {
  175. DPF( 0, " Invalid flags %08lx for app %s", flags, name );
  176. }
  177. }
  178. else
  179. {
  180. DPF( 0, " Flags not a DWORD for app %s", name );
  181. }
  182. }
  183. else
  184. {
  185. DPF( 0, " No flags found for app %s", name );
  186. }
  187. }
  188. else
  189. {
  190. DPF( 0, " Executable name not a string!!!" );
  191. }
  192. }
  193. else
  194. {
  195. DPF( 0, " Executable name not found!!!" );
  196. }
  197. RegCloseKey( hsubkey );
  198. }
  199. else
  200. {
  201. DPF( 0, " RegOpenKey for %ld FAILED!" );
  202. }
  203. /*
  204. * next reg entry...
  205. */
  206. index++;
  207. }
  208. DPF( 5, "Enumerated %ld keys, found %ld valid ones", index, count );
  209. /*
  210. * go make an array we can sort and use later...
  211. */
  212. if( count > 0 )
  213. {
  214. lpAppArray = MemAlloc( (count+1) * sizeof( LPAPPHACKS ) );
  215. if( lpAppArray != NULL )
  216. {
  217. LPAPPHACKS lphack;
  218. dwAppArraySize = 0;
  219. lphack = lpAppList;
  220. while( lphack != NULL )
  221. {
  222. lpAppArray[ dwAppArraySize ] = lphack;
  223. lphack = lphack->lpNext;
  224. dwAppArraySize++;
  225. }
  226. qsort( lpAppArray, count, sizeof( LPAPPHACKS ),
  227. (LPVOID) sortRtn );
  228. }
  229. for( count = 0; count< (int) dwAppArraySize; count++ )
  230. {
  231. DPF( 5, " %s", lpAppArray[count]->szName );
  232. }
  233. }
  234. RegCloseKey( hkey );
  235. }
  236. else
  237. {
  238. #ifdef WIN95
  239. DPF( 0, "Failed to find registry root" );
  240. #endif
  241. }
  242. /*
  243. * The first time through, we will also check to see if a gamma
  244. * calibrator is registered. All we'll do here is read the registry
  245. * key and if it's non-NULL, we'll assume that one exists.
  246. */
  247. if( !RegOpenKey( HKEY_LOCAL_MACHINE,
  248. REGSTR_PATH_DDRAW "\\" REGSTR_KEY_GAMMA_CALIBRATOR, &hkey ) )
  249. {
  250. DWORD type;
  251. DWORD cb;
  252. cb = sizeof( szGammaCalibrator );
  253. if( !RegQueryValueEx( hkey, REGSTR_VAL_GAMMA_CALIBRATOR,
  254. NULL, &type, szGammaCalibrator, &cb ) )
  255. {
  256. if( ( type == REG_SZ ) &&
  257. ( szGammaCalibrator[0] != '\0' ) )
  258. {
  259. bGammaCalibratorExists = TRUE;
  260. }
  261. }
  262. RegCloseKey( hkey );
  263. }
  264. }
  265. else
  266. {
  267. DPF( 3, "Registry already scanned, not doing it again" );
  268. }
  269. /*
  270. * find out what process we are dealing with
  271. */
  272. hfile = GetModuleHandle( NULL );
  273. GetModuleFileName( hfile, fname, sizeof( fname ) );
  274. DPF( 5, "full name = %s", fname );
  275. i = strlen( fname )-1;
  276. while( i >=0 && fname[i] != '\\' )
  277. {
  278. i--;
  279. }
  280. i++;
  281. strcpy( name, &fname[i] );
  282. DPF( 5, "name = %s", name );
  283. lplphack = bsearch( name, lpAppArray, dwAppArraySize, sizeof( LPAPPHACKS ),
  284. (LPVOID) searchRtn );
  285. /*
  286. * If it has an .SCR extension, assume it's a screensaver.
  287. */
  288. dwScreenSaver = 0;
  289. #ifdef WIN95
  290. if( ( strlen(name) > 4 ) && !STRCMP( &name[ strlen(name) - 4 ], ".SCR" ) )
  291. {
  292. dwScreenSaver = DDRAW_APPCOMPAT_SCREENSAVER;
  293. }
  294. #endif
  295. /*
  296. * go find the timestamp in the file
  297. */
  298. appid = 0;
  299. do
  300. {
  301. hfile = CreateFile( fname, GENERIC_READ, FILE_SHARE_READ,
  302. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
  303. if( hfile == INVALID_HANDLE_VALUE )
  304. {
  305. DPF( 0, "Could not open file %s", fname );
  306. break;
  307. }
  308. if( !fileRead( hfile, &dh, sizeof( dh ) ) )
  309. {
  310. DPF( 0, "Could not read DOS header for file %s", fname );
  311. break;
  312. }
  313. if( dh.e_magic != IMAGE_DOS_SIGNATURE )
  314. {
  315. DPF( 0, "Invalid DOS header for file %s", fname );
  316. break;
  317. }
  318. if( !fileSeek( hfile, dh.e_lfanew ) )
  319. {
  320. DPF( 0, "Could not seek to PE header in file %s", fname );
  321. break;
  322. }
  323. if( !fileRead( hfile, &nth, sizeof( nth ) ) )
  324. {
  325. DPF( 0, "Could not read PE header for file %s", fname );
  326. break;
  327. }
  328. if( nth.Signature != IMAGE_NT_SIGNATURE )
  329. {
  330. DPF( 0, "Bogus PE header for file %s", fname );
  331. break;
  332. }
  333. appid = nth.FileHeader.TimeDateStamp;
  334. if( appid == 0 )
  335. {
  336. DPF( 0, "TimeDataStap is 0 for file %s", fname );
  337. break;
  338. }
  339. DPF( 5, "Obtained appid: 0x%08lx", appid );
  340. CloseHandle( hfile );
  341. hfile = NULL;
  342. } while(0); //fake try-except
  343. // Now write the values into some known place
  344. if (appid)
  345. {
  346. DWORD dw;
  347. if( !RegCreateKey( HKEY_LOCAL_MACHINE,
  348. REGSTR_PATH_DDRAW "\\" REGSTR_KEY_LASTAPP, &hkey ) )
  349. {
  350. RegSetValueEx(hkey, REGSTR_VAL_DDRAW_NAME, 0, REG_SZ, (LPBYTE)name, strlen(name)+1);
  351. RegSetValueEx(hkey, REGSTR_VAL_DDRAW_APPID, 0, REG_DWORD, (LPBYTE)&appid, sizeof(appid));
  352. RegCloseKey(hkey);
  353. }
  354. }
  355. if( lplphack != NULL && appid )
  356. {
  357. HANDLE hfile;
  358. /*
  359. * back up to the first match with this name
  360. */
  361. lphack = *lplphack;
  362. while( lplphack != lpAppArray )
  363. {
  364. lplphack--;
  365. if( STRCMP( (*lplphack)->szName, name ) )
  366. {
  367. lplphack++;
  368. break;
  369. }
  370. lphack = *lplphack;
  371. }
  372. /*
  373. * now run through all matches we found
  374. */
  375. hfile = NULL;
  376. while( 1 )
  377. {
  378. /*
  379. * is this one of the ones that matches the calling process?
  380. */
  381. if( *lplphack == NULL )
  382. {
  383. break;
  384. }
  385. lphack = *lplphack;
  386. if( STRCMP( lphack->szName, name ) )
  387. {
  388. break;
  389. }
  390. /*
  391. * validate timestamp in registry against the one in the file
  392. */
  393. if( lphack->dwAppId == appid )
  394. {
  395. DPF( 5, "****** Compatiblity data 0x%08lx found for %s",
  396. lphack->dwFlags, name );
  397. return lphack->dwFlags | dwScreenSaver;
  398. }
  399. lplphack++;
  400. }
  401. if( hfile != NULL )
  402. {
  403. CloseHandle( hfile );
  404. }
  405. }
  406. return dwScreenSaver;
  407. } /* HackMeBaby */