Source code of Windows XP (NT5)
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.

602 lines
23 KiB

  1. // apphacks.c : Defines the entry point for the console application.
  2. //
  3. // This little utility is supposed to allow me a way to enter in data into
  4. // Image File Execution Options without doing it by hand all the time. Used
  5. // specifically for apphack flags and taking version info out of the EXE to see
  6. // if a match exists
  7. #define UNICODE 1
  8. #include <windows.h>
  9. #include <commdlg.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <ctype.h>
  13. #include <winver.h>
  14. #include <apcompat.h>
  15. #define MIN_VERSION_RESOURCE 512
  16. #define IMAGE_EXEC_OPTIONS TEXT("software\\microsoft\\windows NT\\currentversion\\Image File Execution Options\\")
  17. extern TCHAR* CheckExtension(TCHAR*);
  18. extern VOID SetRegistryVal(TCHAR* , TCHAR* , PTCHAR,DWORD);
  19. extern VOID DetailError1 (DWORD );
  20. extern BOOLEAN g_fNotPermanent;
  21. PVOID g_lpPrevRegSettings;
  22. UINT uVersionInfo[5][8]={ {4,0,1381,VER_PLATFORM_WIN32_NT,3,0,0,0},
  23. {4,0,1381,VER_PLATFORM_WIN32_NT,4,0,0,0},
  24. {4,0,1381,VER_PLATFORM_WIN32_NT,5,0,0,0},
  25. {4,10,1998,VER_PLATFORM_WIN32_WINDOWS,0,0,0,0},
  26. {4,0,950,VER_PLATFORM_WIN32_WINDOWS,0,0,0,0}
  27. };
  28. PTCHAR pszVersionInfo[5]={
  29. TEXT("Service Pack 3"),
  30. TEXT("Service Pack 4"),
  31. TEXT("Service Pack 5"),
  32. TEXT(""),
  33. TEXT("")
  34. };
  35. BOOLEAN g_GooAppendFlag;
  36. VOID SetRegistryValGoo(TCHAR* szTitle, TCHAR* szVal,PUCHAR szBuffer,DWORD dwType,UINT length)
  37. {
  38. long lResult;
  39. TCHAR szSubKey[MAX_PATH];
  40. HKEY hKey;
  41. wsprintf(szSubKey,
  42. TEXT("software\\microsoft\\windows NT\\currentversion\\Image File Execution Options\\%s"),
  43. szTitle);
  44. lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  45. szSubKey,
  46. 0,
  47. TEXT("\0"),
  48. 0,
  49. KEY_WRITE,
  50. NULL,
  51. &hKey,
  52. NULL);
  53. if(lResult == ERROR_SUCCESS)
  54. {
  55. RegSetValueEx(hKey,
  56. szVal,
  57. 0,
  58. dwType,
  59. (CONST BYTE*)szBuffer,
  60. length);
  61. RegCloseKey(hKey);
  62. }
  63. }
  64. VOID DeleteRegistryValueGoo(TCHAR*szTitle)
  65. {
  66. long lResult;
  67. TCHAR szSubKey[MAX_PATH];
  68. HKEY hKey;
  69. wsprintf(szSubKey,
  70. TEXT("software\\microsoft\\windows NT\\currentversion\\Image File Execution Options\\%s"),
  71. szTitle);
  72. lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  73. szSubKey,
  74. 0,
  75. KEY_WRITE,
  76. &hKey
  77. );
  78. if(lResult == ERROR_SUCCESS)
  79. {
  80. RegDeleteValue(hKey,TEXT("ApplicationGoo") );
  81. RegCloseKey(hKey);
  82. }
  83. }
  84. /*
  85. Check whether the registry contains an entry for "applicationgoo" for the given *.exe.
  86. If it does, check the "resource info." to determine whether they are same.
  87. If they are the same, don't worry, your work is already done. If not,
  88. the new one needs to get appended to the old one.
  89. */
  90. BOOLEAN CheckGooEntry(PVOID pVersionInfo,
  91. PAPP_COMPAT_GOO pExistingVersionInfo,
  92. BOOL fImageHasResourceInfo,
  93. DWORD VersionInfoSize,
  94. DWORD dwSize,
  95. LARGE_INTEGER *pAppCompatFlag,
  96. PAPP_VARIABLE_INFO pOsVersionInfo,
  97. ULONG TotalVersionInfoLength,
  98. TCHAR* pszPath // Executable path.
  99. )
  100. {
  101. BOOLEAN fNeedAppend = FALSE;
  102. // Added for the addition and deletion from the registry.
  103. PAPP_COMPAT_GOO pReplaceAppCompatGoo;
  104. PPRE_APP_COMPAT_INFO pAppCompatEntry, pStoredAppCompatEntry = NULL;
  105. PPRE_APP_COMPAT_INFO pDestAppCompatEntry, pReplaceAppCompatEntry;
  106. ULONG TotalGooLength, InputCompareLength, ReplaceCopyLength;
  107. ULONG OutputCompareLength, CopyLength, OffSet;
  108. PVOID ResourceInfo;
  109. UINT iLoop = 0;
  110. BOOL fMatchGot = FALSE;
  111. PVOID pExistingAppCompatFlag;
  112. PVOID pExistingOsVersionInfo;
  113. BOOLEAN fAppCompatMatch = FALSE, fOsVersionMatch = FALSE;
  114. TCHAR szTitle[MAX_PATH];
  115. ULONG ReplaceGooLength;
  116. pAppCompatEntry = pExistingVersionInfo ->AppCompatEntry;
  117. TotalGooLength = pExistingVersionInfo ->dwTotalGooSize - \
  118. sizeof(pExistingVersionInfo ->dwTotalGooSize);
  119. //Loop till we get a matching entry in the registry.
  120. while (TotalGooLength ){
  121. InputCompareLength = pAppCompatEntry->dwResourceInfoSize;
  122. ResourceInfo = pAppCompatEntry + 1;
  123. if(fImageHasResourceInfo){
  124. if( InputCompareLength > VersionInfoSize)
  125. InputCompareLength = VersionInfoSize;
  126. OutputCompareLength = \
  127. (ULONG)RtlCompareMemory(
  128. ResourceInfo,
  129. pVersionInfo,
  130. InputCompareLength
  131. );
  132. }
  133. else{
  134. OutputCompareLength = 0;
  135. }
  136. if( InputCompareLength != OutputCompareLength){
  137. // No match found...Need to continue thru till I find one or exhaust.
  138. TotalGooLength -= pAppCompatEntry->dwEntryTotalSize;
  139. (PUCHAR) pAppCompatEntry += pAppCompatEntry->dwEntryTotalSize;
  140. iLoop++;
  141. continue;
  142. }
  143. // We are a match !!
  144. pStoredAppCompatEntry = pAppCompatEntry;
  145. fMatchGot = TRUE;
  146. // Since we are a match, we won't add the ApplicationGoo but we need to check the
  147. // ApcompatFlag and the OSVersionInfo.
  148. if( (!pAppCompatFlag) && (!pOsVersionInfo) )
  149. break;
  150. OffSet = sizeof(PRE_APP_COMPAT_INFO) + \
  151. pStoredAppCompatEntry->dwResourceInfoSize;
  152. if(pAppCompatFlag){
  153. (PUCHAR)pExistingAppCompatFlag = (PUCHAR) ( pStoredAppCompatEntry) + OffSet;
  154. InputCompareLength = sizeof(LARGE_INTEGER);
  155. OutputCompareLength = \
  156. (ULONG) RtlCompareMemory(
  157. pAppCompatFlag,
  158. pExistingAppCompatFlag,
  159. InputCompareLength
  160. );
  161. if(OutputCompareLength == InputCompareLength)
  162. fAppCompatMatch = TRUE;
  163. }
  164. if(pOsVersionInfo){
  165. (PUCHAR)pExistingOsVersionInfo = (PUCHAR) (pStoredAppCompatEntry) + OffSet + \
  166. sizeof(LARGE_INTEGER);
  167. InputCompareLength = pStoredAppCompatEntry->dwEntryTotalSize - \
  168. (sizeof(PRE_APP_COMPAT_INFO) + \
  169. pStoredAppCompatEntry->dwResourceInfoSize +\
  170. sizeof(LARGE_INTEGER)
  171. );
  172. if(InputCompareLength > TotalVersionInfoLength)
  173. InputCompareLength = TotalVersionInfoLength;
  174. OutputCompareLength = \
  175. (ULONG) RtlCompareMemory(
  176. pOsVersionInfo,
  177. pExistingOsVersionInfo,
  178. InputCompareLength
  179. );
  180. if(OutputCompareLength == InputCompareLength)
  181. fOsVersionMatch = TRUE;
  182. }
  183. if( ( fOsVersionMatch == TRUE) &&
  184. ( fAppCompatMatch == TRUE) )
  185. break;
  186. else{ // one of these or both are different...
  187. /*
  188. The idea here is to replace that part of the AppCompatEntry, which is a
  189. mis-match. We go ahead and prepare the pReplaceAppCompatEntry
  190. */
  191. ReplaceCopyLength = sizeof(PRE_APP_COMPAT_INFO) + \
  192. pStoredAppCompatEntry->dwResourceInfoSize + \
  193. sizeof(LARGE_INTEGER) + \
  194. TotalVersionInfoLength ;
  195. pReplaceAppCompatEntry = GlobalAlloc(GMEM_FIXED, ReplaceCopyLength);
  196. RtlCopyMemory((PUCHAR)pReplaceAppCompatEntry, (PUCHAR)pStoredAppCompatEntry, OffSet);
  197. RtlCopyMemory((PUCHAR)(pReplaceAppCompatEntry) + OffSet,(PUCHAR)pAppCompatFlag,sizeof(LARGE_INTEGER) );
  198. RtlCopyMemory((PUCHAR)(pReplaceAppCompatEntry)+(OffSet+sizeof(LARGE_INTEGER)),
  199. (PUCHAR)pOsVersionInfo,TotalVersionInfoLength);
  200. //Now prepare the GOO structure.
  201. ReplaceGooLength = pExistingVersionInfo ->dwTotalGooSize - \
  202. pStoredAppCompatEntry->dwEntryTotalSize + \
  203. ReplaceCopyLength;
  204. pReplaceAppCompatGoo = GlobalAlloc(GMEM_FIXED, ReplaceGooLength);
  205. pReplaceAppCompatGoo->dwTotalGooSize = ReplaceGooLength;
  206. pAppCompatEntry = pExistingVersionInfo->AppCompatEntry;
  207. pDestAppCompatEntry = ((PAPP_COMPAT_GOO)pReplaceAppCompatGoo)->AppCompatEntry;
  208. ReplaceGooLength -= sizeof(pExistingVersionInfo->dwTotalGooSize);
  209. while(ReplaceGooLength){
  210. CopyLength = pAppCompatEntry->dwEntryTotalSize;
  211. if(pAppCompatEntry != pStoredAppCompatEntry){
  212. RtlCopyMemory(pDestAppCompatEntry,pAppCompatEntry ,CopyLength);
  213. (PUCHAR)pDestAppCompatEntry += CopyLength;
  214. }
  215. else{
  216. RtlCopyMemory(pDestAppCompatEntry,pReplaceAppCompatEntry,ReplaceCopyLength);
  217. pDestAppCompatEntry->dwEntryTotalSize = ReplaceCopyLength;
  218. (PUCHAR)pDestAppCompatEntry += ReplaceCopyLength;
  219. (PUCHAR)pAppCompatEntry += pAppCompatEntry->dwEntryTotalSize;
  220. ReplaceGooLength -= ReplaceCopyLength;
  221. continue;
  222. }
  223. (PUCHAR)pAppCompatEntry += CopyLength;
  224. ReplaceGooLength -= CopyLength;
  225. } // End while
  226. // Delete the key from the registry and add back the updated one.
  227. GetFileTitle(pszPath,szTitle,MAX_PATH);
  228. if(CheckExtension(szTitle) == NULL)
  229. lstrcat(szTitle,TEXT(".exe"));
  230. DeleteRegistryValueGoo(szTitle);
  231. SetRegistryValGoo(szTitle,
  232. TEXT("ApplicationGoo"),
  233. (PUCHAR)pReplaceAppCompatGoo,
  234. REG_BINARY,
  235. pReplaceAppCompatGoo->dwTotalGooSize
  236. );
  237. GlobalFree(pReplaceAppCompatEntry);
  238. GlobalFree(pReplaceAppCompatGoo);
  239. } // Else..
  240. break;
  241. } // End while (TotalGooLength )
  242. if(FALSE == fMatchGot){
  243. // No match available for this version.
  244. fNeedAppend = TRUE;
  245. // Reset the iteration count.
  246. iLoop = 0;
  247. }
  248. if(g_fNotPermanent){
  249. // The user has chosen not to make the registry settings permanent and we have the
  250. // "Append" flag set indicating that there were entries appended to the ApplicationGoo.
  251. // We need to remove the correct entry for this executable.
  252. // The idea here is to copy the whole of "ApplicationGoo" to a global buffer leaving just
  253. // the one that needs to be deleted. Our job is made easier as we have the stored AppCompat
  254. // entry. We just need to go till there and copy the rest on to the global buffer.
  255. if(pStoredAppCompatEntry){
  256. pAppCompatEntry = pExistingVersionInfo->AppCompatEntry;
  257. TotalGooLength = pExistingVersionInfo->dwTotalGooSize;
  258. g_lpPrevRegSettings = (PAPP_COMPAT_GOO)GlobalAlloc(GMEM_FIXED, TotalGooLength );
  259. ((PAPP_COMPAT_GOO)g_lpPrevRegSettings)->dwTotalGooSize = pExistingVersionInfo->dwTotalGooSize -
  260. pStoredAppCompatEntry->dwEntryTotalSize ;
  261. pDestAppCompatEntry = ((PAPP_COMPAT_GOO)g_lpPrevRegSettings)->AppCompatEntry;
  262. TotalGooLength -= sizeof(pExistingVersionInfo->dwTotalGooSize);
  263. while(TotalGooLength){
  264. CopyLength = pAppCompatEntry->dwEntryTotalSize;
  265. if(pAppCompatEntry != pStoredAppCompatEntry){
  266. RtlCopyMemory(pDestAppCompatEntry,pAppCompatEntry ,CopyLength);
  267. (PUCHAR)pDestAppCompatEntry += CopyLength;
  268. g_GooAppendFlag = TRUE;
  269. }
  270. (PUCHAR)pAppCompatEntry += CopyLength;
  271. TotalGooLength -= CopyLength;
  272. } // End while.
  273. }
  274. else{ // We do not have a stored AppCompatEntry. This means our target is to remove the
  275. // the first entry and leave the rest intact. i.e copy the rest onto the global buffer
  276. // for it to be copied.
  277. TotalGooLength = pExistingVersionInfo->dwTotalGooSize;
  278. g_lpPrevRegSettings = (PAPP_COMPAT_GOO)GlobalAlloc(GMEM_FIXED, TotalGooLength );
  279. RtlCopyMemory(g_lpPrevRegSettings,pExistingVersionInfo, TotalGooLength);
  280. g_GooAppendFlag = TRUE;
  281. }
  282. }
  283. return fNeedAppend;
  284. }
  285. int MakeAppCompatGoo(TCHAR* TmpBuffer,LARGE_INTEGER* pAppCompatFlag, UINT uOsVer)
  286. {
  287. BOOLEAN fImageHasVersionInfo = FALSE;
  288. BOOLEAN fOsVersionLie = FALSE;
  289. BOOLEAN fEntryPresent = FALSE;
  290. TCHAR Buffer[MAX_PATH];
  291. TCHAR StringBuffer[MAX_PATH];
  292. TCHAR RegPath[MAX_PATH];
  293. TCHAR InChar;
  294. LONG status;
  295. HKEY hKey;
  296. PTCHAR pBuf;
  297. PTCHAR pAppGooBuf;
  298. PUCHAR pData;
  299. PTCHAR OutBuffer;
  300. PWCHAR uniBuffer;
  301. DWORD VersionInfoSize;
  302. DWORD dwHandle;
  303. DWORD dwBytesWritten;
  304. DWORD dwType;
  305. DWORD dwSize;
  306. ULONG i, j;
  307. ULONG EXELength;
  308. ULONG AppCompatHigh;
  309. ULONG AppCompatLow;
  310. ULONG TotalGooSize;
  311. ULONG TotalVersionInfoLength=0;
  312. ULONG OutBufferSize;
  313. PVOID lpData;
  314. PVOID ResourceInfo;
  315. PVOID VersionInfo;
  316. PAPP_COMPAT_GOO AppCompatGoo;
  317. PAPP_VARIABLE_INFO VariableInfo=NULL;
  318. PAPP_VARIABLE_INFO AppVariableInfo=NULL;
  319. EFFICIENTOSVERSIONINFOEXW OSVersionInfo, *pOsVersionInfo;
  320. // Remove the trailing and leading " " if PRESENT.
  321. if(*TmpBuffer == TEXT('\"') ){
  322. lstrcpy(Buffer, TmpBuffer+1);
  323. *(Buffer + (lstrlen(Buffer) - 1) )= TEXT('\0');
  324. }
  325. else
  326. lstrcpy(Buffer, TmpBuffer);
  327. // Quick check to see if its got any version info in its header
  328. VersionInfoSize = GetFileVersionInfoSize(&Buffer[0], &dwHandle);
  329. if (VersionInfoSize) {
  330. // It does, so alloc space for it to pull it in below
  331. VersionInfo = LocalAlloc(GMEM_FIXED, VersionInfoSize);
  332. if (VersionInfo) {
  333. // Get the version info
  334. if (GetFileVersionInfo(&Buffer[0], dwHandle, VersionInfoSize, VersionInfo)) {
  335. // Set global flag to be inspected later
  336. fImageHasVersionInfo = TRUE;
  337. }
  338. }
  339. }
  340. // Enter the app compat flags (decimal) - its defined as a LARGE_INTEGER
  341. AppCompatHigh = 0x0;
  342. AppCompatLow = 0x0;
  343. AppCompatLow = pAppCompatFlag->LowPart;
  344. AppCompatHigh = pAppCompatFlag->HighPart;
  345. // Determine goo size, start with main goo
  346. TotalGooSize = sizeof(APP_COMPAT_GOO);
  347. // Add sizeof compatibility flags (large integer)
  348. TotalGooSize += sizeof(LARGE_INTEGER);
  349. // if we actually got version information add the length of that. We take the minimum
  350. // of whatever the EXE has or 0x200 bytes to try and identify the app. I've found that
  351. // anything less than 0x200 bytes doesn't supply enough info to be useful.
  352. if (fImageHasVersionInfo) {
  353. VersionInfoSize = min(VersionInfoSize, MIN_VERSION_RESOURCE);
  354. TotalGooSize += VersionInfoSize;
  355. }
  356. // See if they requested version lying, if so we got a bunch more horseshit todo
  357. if (AppCompatLow & KACF_VERSIONLIE) {
  358. fOsVersionLie = TRUE;
  359. OSVersionInfo.dwMajorVersion = uVersionInfo[uOsVer][0];
  360. OSVersionInfo.dwMinorVersion = uVersionInfo[uOsVer][1];
  361. OSVersionInfo.dwBuildNumber = uVersionInfo[uOsVer][2];
  362. OSVersionInfo.dwPlatformId = uVersionInfo[uOsVer][3];
  363. OSVersionInfo.wServicePackMajor = (WORD)uVersionInfo[uOsVer][4];
  364. OSVersionInfo.wServicePackMinor = (WORD)uVersionInfo[uOsVer][5];
  365. OSVersionInfo.wSuiteMask = (WORD)uVersionInfo[uOsVer][6];
  366. OSVersionInfo.wProductType = (BYTE)uVersionInfo[uOsVer][7];
  367. lstrcpy( (TCHAR*) OSVersionInfo.szCSDVersion, pszVersionInfo[uOsVer]);
  368. // Start with the length of the full struct
  369. TotalVersionInfoLength = sizeof(EFFICIENTOSVERSIONINFOEXW);
  370. // subtract the size of the szCSDVersion field
  371. TotalVersionInfoLength -= sizeof(OSVersionInfo.szCSDVersion);
  372. // add the strlen amount plus 1 for the NULL wchar
  373. TotalVersionInfoLength += lstrlen((TCHAR*)OSVersionInfo.szCSDVersion )*sizeof(WCHAR)+sizeof(WCHAR);
  374. // Add the size of the variable length structure header (since VerInfo is var length)
  375. TotalVersionInfoLength += sizeof(APP_VARIABLE_INFO);
  376. // Add the total version info length to the goo size
  377. TotalGooSize += TotalVersionInfoLength;
  378. // Allocate space for the variable length version info
  379. AppVariableInfo = (PAPP_VARIABLE_INFO) LocalAlloc(GMEM_FIXED, sizeof(APP_VARIABLE_INFO) + TotalVersionInfoLength);
  380. if (!AppVariableInfo) {
  381. return -1;
  382. }
  383. // fill in the pertinent data in the variable length info header
  384. AppVariableInfo->dwVariableInfoSize = sizeof(APP_VARIABLE_INFO) + TotalVersionInfoLength;
  385. AppVariableInfo->dwVariableType = AVT_OSVERSIONINFO;
  386. // Do a pointer +1 operation here to get past the header to the actual data
  387. VariableInfo = AppVariableInfo + 1;
  388. // Copy the actual data in
  389. memcpy(VariableInfo, &OSVersionInfo, TotalVersionInfoLength);
  390. }
  391. //
  392. // See if an entry already exists in the registry. If so, we'll have to glom
  393. // this entry into the other already existing one.
  394. //
  395. // Get the registry path all figured out
  396. memset(&RegPath[0], 0, sizeof(RegPath));
  397. lstrcat(&RegPath[0], IMAGE_EXEC_OPTIONS);
  398. EXELength = lstrlen(&Buffer[0]);
  399. pBuf = &Buffer[0];
  400. pBuf += EXELength;
  401. // work backward in the path til we find the the last backslash
  402. while ((*pBuf != '\\') && (pBuf != &Buffer[0])) {
  403. pBuf--;
  404. }
  405. if (*pBuf == '\\') {
  406. pBuf++;
  407. }
  408. if(CheckExtension(pBuf) == NULL)
  409. lstrcat(pBuf,TEXT(".exe"));
  410. // cat the image.exe name to the end of the registry path
  411. lstrcat(&RegPath[0], pBuf);
  412. // try to open this key
  413. status = RegOpenKey(HKEY_LOCAL_MACHINE, &RegPath[0], &hKey);
  414. if (status == ERROR_SUCCESS) {
  415. dwSize = 1;
  416. // do a query once with small size to figure out how big the binary entry is
  417. status = RegQueryValueEx(hKey, TEXT("ApplicationGoo"), NULL, &dwType, NULL, &dwSize);
  418. if( status == ERROR_SUCCESS){
  419. //
  420. // There's an entry already there. Take the size of this Goo entry and add it
  421. // to the TotalGooSize LESS the size of the first dword in the APP_COMPAT_GOO
  422. // struct (as there already was one there).
  423. //
  424. // Added here after checkin
  425. if(dwSize > 1){
  426. lpData = LocalAlloc(GMEM_FIXED, dwSize);
  427. if(lpData){
  428. status = RegQueryValueEx(hKey, TEXT("ApplicationGoo"), NULL, &dwType, (PUCHAR) lpData, &dwSize);
  429. // if(VersionInfo) ...Remove this as it is not necessary.
  430. // if(fOsVersionLie)
  431. // pOsVersionInfo = VariableInfo;
  432. fEntryPresent = CheckGooEntry( VersionInfo,
  433. (PAPP_COMPAT_GOO)lpData,
  434. fImageHasVersionInfo,
  435. VersionInfoSize,
  436. dwSize,
  437. pAppCompatFlag,
  438. AppVariableInfo,
  439. TotalVersionInfoLength,
  440. Buffer
  441. );
  442. }
  443. }
  444. // End add
  445. if(fEntryPresent)
  446. TotalGooSize += dwSize - sizeof(AppCompatGoo->dwTotalGooSize);
  447. else{ // Nothing to append....return as it is the same.
  448. if(fImageHasVersionInfo)
  449. LocalFree(VersionInfo);
  450. if(fOsVersionLie)
  451. LocalFree(AppVariableInfo);
  452. return 0;
  453. }
  454. RegCloseKey(hKey);
  455. }
  456. }
  457. // Allocate the memory for the entire app compat goo
  458. AppCompatGoo = (PAPP_COMPAT_GOO) LocalAlloc(GMEM_FIXED, TotalGooSize);
  459. if (!AppCompatGoo) {
  460. return -1;
  461. }
  462. // fill in the total size
  463. AppCompatGoo->dwTotalGooSize = TotalGooSize;
  464. // if there was version info for this entry we need to fill that in now, else zero
  465. if (fImageHasVersionInfo) {
  466. AppCompatGoo->AppCompatEntry[0].dwResourceInfoSize = VersionInfoSize;
  467. }
  468. else {
  469. AppCompatGoo->AppCompatEntry[0].dwResourceInfoSize = 0;
  470. }
  471. AppCompatGoo->AppCompatEntry[0].dwEntryTotalSize = \
  472. sizeof(AppCompatGoo->AppCompatEntry[0].dwEntryTotalSize) +
  473. sizeof(AppCompatGoo->AppCompatEntry[0].dwResourceInfoSize) +
  474. TotalVersionInfoLength + // In case app needed VER lying
  475. sizeof(LARGE_INTEGER); // For app compatibility flags
  476. // Entry size is whatever it was plus any resource info we've got
  477. AppCompatGoo->AppCompatEntry[0].dwEntryTotalSize += \
  478. AppCompatGoo->AppCompatEntry[0].dwResourceInfoSize;
  479. // do the pointer +1 thing so we can be pointing at the data area
  480. ResourceInfo = AppCompatGoo->AppCompatEntry + 1;
  481. // copy the data in
  482. memcpy(ResourceInfo, VersionInfo, VersionInfoSize);
  483. // filling in the app compat flags here
  484. pData = (PUCHAR) ResourceInfo + AppCompatGoo->AppCompatEntry[0].dwResourceInfoSize;
  485. memcpy(pData, &AppCompatLow, sizeof(AppCompatLow));
  486. pData += sizeof(AppCompatLow);
  487. memcpy(pData, &AppCompatHigh, sizeof(AppCompatHigh));
  488. pData += sizeof(AppCompatHigh);
  489. // if there was any version resource info, copy that in here too
  490. if (AppVariableInfo) {
  491. memcpy(pData, AppVariableInfo, TotalVersionInfoLength);
  492. }
  493. pData += TotalVersionInfoLength;
  494. //
  495. // If an already existing entry was there, we need to ask append what was there to the
  496. // tail of the entry. (i.e. what's already there gets auto appended to the tail). If
  497. // someone wants to write a 1-N positioning for entries within the Goo - they'll have to
  498. // add that support here
  499. //
  500. if (fEntryPresent) {
  501. // Start at offset + 4 cuz the previous Total Goo size must be skipped.
  502. memcpy(pData, (PUCHAR) lpData+4, dwSize - sizeof(AppCompatGoo->dwTotalGooSize));
  503. }
  504. pData = (PUCHAR) AppCompatGoo;
  505. SetRegistryValGoo(pBuf, TEXT("ApplicationGoo"),pData,REG_BINARY,AppCompatGoo->dwTotalGooSize);
  506. if(fImageHasVersionInfo)
  507. LocalFree(VersionInfo);
  508. if(fOsVersionLie)
  509. LocalFree(AppVariableInfo);
  510. if(fEntryPresent)
  511. LocalFree(lpData);
  512. LocalFree(AppCompatGoo);
  513. return 0;
  514. }