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.

3019 lines
98 KiB

  1. /*
  2. *
  3. * Resource Updating Functions
  4. */
  5. #if WINNT /* for UNICODE_STRING */
  6. #include <nt.h>
  7. #include <ntrtl.h>
  8. #include <nturtl.h>
  9. #include <malloc.h>
  10. #include <stdlib.h>
  11. #endif
  12. #include <windows.h>
  13. #include <imagehlp.h>
  14. #pragma hdrstop
  15. #include "cabpack.h"
  16. #include "sdsutils.h"
  17. #define DPrintf( a )
  18. #define DPrintfn( a )
  19. #define DPrintfu( a )
  20. #define RtlAllocateHeap(a,b,c) malloc( c )
  21. #define RtlFreeHeap(a,b,c) free( c )
  22. /*
  23. * BUGBUG - OPTIMIZATION PROBLEM?
  24. * BUGBUG - The program mysteriously does not work correctly unless
  25. * BUGBUG optimization is turned off in the early section of this file.
  26. * BUGBUG I don't have time to debug this, if you do please tell me what
  27. * BUGBUG is wrong
  28. */
  29. #pragma optimize( "", off )
  30. #define cbPadMax 16L
  31. char *pchPad = "PADDINGXXPADDING";
  32. char *pchZero = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
  33. extern CDF g_CDF; //global struct
  34. extern HINSTANCE g_hInst; // Pointer to Instance
  35. WCHAR *
  36. MakeUnicodeCopy( LPCSTR psz )
  37. {
  38. LPWSTR result;
  39. if (((ULONG_PTR) psz) & (ULONG_PTR)0xFFFF0000) {
  40. result = (LPWSTR) malloc( (lstrlen(psz) + 1) * sizeof(WCHAR) );
  41. // BUGBUG ERROR CHECKING!!! Internal tool only
  42. mbstowcs( result, psz, lstrlen(psz) + 1);
  43. return( result );
  44. } else {
  45. return( (WCHAR *) psz );
  46. }
  47. }
  48. /****************************************************************************
  49. **
  50. ** API entry points
  51. **
  52. ****************************************************************************/
  53. /*++
  54. Routine Description
  55. Begins an update of resources. Save away the name
  56. and current resources in a list, using EnumResourceXxx
  57. api set.
  58. Parameters:
  59. lpFileName - Supplies the name of the executable file that the
  60. resource specified by lpType/lpName/language will be updated
  61. in. This file must be able to be opened for writing (ie, not
  62. currently executing, etc.) The file may be fully qualified,
  63. or if not, the current directory is assumed. It must be a
  64. valid Windows executable file.
  65. bDeleteExistingResources - if TRUE, existing resources are
  66. deleted, and only new resources will appear in the result.
  67. Otherwise, all resources in the input file will be in the
  68. output file unless specifically deleted or replaced.
  69. Return Value:
  70. NULL - The file specified was not able to be opened for writing.
  71. Either it was not an executable image, the executable image is
  72. already loaded, or the filename did not exist. More information may
  73. be available via GetLastError api.
  74. HANDLE - A handle to be passed to the UpdateResource and
  75. EndUpdateResources function.
  76. --*/
  77. HANDLE
  78. LocalBeginUpdateResource( LPCSTR pwch, BOOL bDeleteExistingResources )
  79. {
  80. HMODULE hModule;
  81. PUPDATEDATA pUpdate;
  82. HANDLE hUpdate;
  83. LPSTR pFileName;
  84. DWORD attr;
  85. SetLastError(NO_ERROR);
  86. DEBUGMSG("LocalBeginUpdateResource() - Start");
  87. // Pointer Sanity check
  88. if (pwch == NULL) {
  89. SetLastError(ERROR_INVALID_PARAMETER);
  90. return NULL;
  91. }
  92. // Allocate Resource Editing State (contains lists of resources)
  93. hUpdate = GlobalAlloc(GHND, sizeof(UPDATEDATA));
  94. if (hUpdate == NULL) {
  95. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  96. return NULL;
  97. }
  98. pUpdate = (PUPDATEDATA)GlobalLock(hUpdate);
  99. if (pUpdate == NULL) {
  100. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  101. return NULL;
  102. }
  103. // Set reasonable start condition
  104. pUpdate->Status = NO_ERROR;
  105. // Copy Filename into state table
  106. pUpdate->hFileName = GlobalAlloc(GHND, (lstrlen(pwch)+1) * sizeof(TCHAR) );
  107. if (pUpdate->hFileName == NULL) {
  108. GlobalUnlock(hUpdate);
  109. GlobalFree(hUpdate);
  110. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  111. return NULL;
  112. }
  113. pFileName = (LPSTR)GlobalLock(pUpdate->hFileName);
  114. if (pFileName == NULL) {
  115. GlobalUnlock(hUpdate);
  116. GlobalFree(hUpdate);
  117. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  118. return NULL;
  119. }
  120. lstrcpy(pFileName, pwch);
  121. GlobalUnlock(pUpdate->hFileName);
  122. // Make sure file is writable, not a directory, etc.
  123. attr = GetFileAttributes(pFileName);
  124. if (attr == 0xffffffff) {
  125. GlobalUnlock(hUpdate);
  126. GlobalFree(hUpdate);
  127. return NULL;
  128. } else if (attr & (FILE_ATTRIBUTE_READONLY |
  129. FILE_ATTRIBUTE_SYSTEM |
  130. FILE_ATTRIBUTE_HIDDEN |
  131. FILE_ATTRIBUTE_DIRECTORY)) {
  132. GlobalUnlock(hUpdate);
  133. GlobalFree(hUpdate);
  134. SetLastError(ERROR_WRITE_PROTECT);
  135. return NULL;
  136. }
  137. // If not deleting all resources, load them all in
  138. // by enumerating all the resources
  139. if (! bDeleteExistingResources) {
  140. hModule = LoadLibraryEx(pwch, NULL,LOAD_LIBRARY_AS_DATAFILE| DONT_RESOLVE_DLL_REFERENCES);
  141. if (hModule == NULL) {
  142. GlobalUnlock(hUpdate);
  143. GlobalFree(hUpdate);
  144. if (GetLastError() == NO_ERROR)
  145. SetLastError(ERROR_BAD_EXE_FORMAT);
  146. return NULL;
  147. } else {
  148. EnumResourceTypes(hModule, EnumTypesFunc, (LONG_PTR) pUpdate);
  149. }
  150. FreeLibrary(hModule);
  151. }
  152. if (pUpdate->Status != NO_ERROR) {
  153. GlobalUnlock(hUpdate);
  154. GlobalFree(hUpdate);
  155. return NULL;
  156. }
  157. GlobalUnlock(hUpdate);
  158. DEBUGMSG("LocalBeginUpdateResource() - Finish");
  159. return hUpdate;
  160. }
  161. /*++
  162. Routine Description
  163. This routine adds, deletes or modifies the input resource
  164. in the list initialized by BeginUpdateResource. The modify
  165. case is simple, the add is easy, the delete is hard.
  166. The ASCII entry point converts inputs to UNICODE.
  167. Parameters:
  168. hUpdateFile - The handle returned by the BeginUpdateResources
  169. function.
  170. lpType - Points to a null-terminated character string that
  171. represents the type name of the resource to be updated or
  172. added. May be an integer value passed to MAKEINTRESOURCE
  173. macro. For predefined resource types, the lpType parameter
  174. should be one of the following values:
  175. RT_ACCELERATOR - Accelerator table
  176. RT_BITMAP - Bitmap resource
  177. RT_DIALOG - Dialog box
  178. RT_FONT - Font resource
  179. RT_FONTDIR - Font directory resource
  180. RT_MENU - Menu resource
  181. RT_RCDATA - User-defined resource (raw data)
  182. RT_VERSION - Version resource
  183. RT_ICON - Icon resource
  184. RT_CURSOR - Cursor resource
  185. lpName - Points to a null-terminated character string that
  186. represents the name of the resource to be updated or added.
  187. May be an integer value passed to MAKEINTRESOURCE macro.
  188. language - Is the word value that specifies the language of the
  189. resource to be updated. A complete list of values is
  190. available in winnls.h.
  191. lpData - A pointer to the raw data to be inserted into the
  192. executable image's resource table and data. If the data is
  193. one of the predefined types, it must be valid and properly
  194. aligned. If lpData is NULL, the specified resource is to be
  195. deleted from the executable image.
  196. cb - count of bytes in the data.
  197. Return Value:
  198. TRUE - The resource specified was successfully replaced in, or added
  199. to, the specified executable image.
  200. FALSE/NULL - The resource specified was not successfully added to or
  201. updated in the executable image. More information may be available
  202. via GetLastError api.
  203. --*/
  204. BOOL
  205. LocalUpdateResource(
  206. HANDLE hUpdate,
  207. LPCTSTR lpType,
  208. LPCTSTR lpName,
  209. WORD language,
  210. LPVOID lpData,
  211. ULONG cb
  212. )
  213. {
  214. PUPDATEDATA pUpdate;
  215. PSDATA Type;
  216. PSDATA Name;
  217. PVOID lpCopy;
  218. LONG fRet;
  219. LPWSTR lpwType;
  220. LPWSTR lpwName;
  221. DEBUGMSG("LocalUpdateResource() Start");
  222. // Reset Error
  223. SetLastError(0);
  224. // Get pointer to Resource Update Session
  225. pUpdate = (PUPDATEDATA) GlobalLock(hUpdate);
  226. lpwType = MakeUnicodeCopy( lpType );
  227. lpwName = MakeUnicodeCopy( lpName );
  228. if (lpwName == NULL || lpwType == NULL) {
  229. if (lpwType && lpwType != (LPWSTR) lpType)
  230. free( lpwType );
  231. if (lpwName && lpwName != (LPWSTR) lpName)
  232. free( lpwName );
  233. pUpdate->Status = ERROR_NOT_ENOUGH_MEMORY;
  234. GlobalUnlock(hUpdate);
  235. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  236. return FALSE;
  237. }
  238. Name = AddStringOrID(lpwName, pUpdate);
  239. if (Name == NULL) {
  240. if (lpwType != (LPWSTR) lpType)
  241. free( lpwType );
  242. if (lpwName != (LPWSTR) lpName)
  243. free( lpwName );
  244. pUpdate->Status = ERROR_NOT_ENOUGH_MEMORY;
  245. GlobalUnlock(hUpdate);
  246. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  247. return FALSE;
  248. }
  249. Type = AddStringOrID(lpwType, pUpdate);
  250. if (Type == NULL) {
  251. if (lpwType != (LPWSTR) lpType)
  252. free( lpwType );
  253. if (lpwName != (LPWSTR) lpName)
  254. free( lpwName );
  255. pUpdate->Status = ERROR_NOT_ENOUGH_MEMORY;
  256. GlobalUnlock(hUpdate);
  257. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  258. return FALSE;
  259. }
  260. if (lpwType != (LPWSTR) lpType)
  261. free( lpwType );
  262. if (lpwName != (LPWSTR) lpName)
  263. free( lpwName );
  264. if (cb == 0) {
  265. lpCopy = NULL;
  266. } else {
  267. // RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( RES_TAG ), cb);
  268. lpCopy = malloc( cb );
  269. if (lpCopy == NULL) {
  270. pUpdate->Status = ERROR_NOT_ENOUGH_MEMORY;
  271. GlobalUnlock(hUpdate);
  272. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  273. return FALSE;
  274. }
  275. memcpy( lpCopy, lpData, cb);
  276. }
  277. fRet = AddResource(Type, Name, language, pUpdate, lpCopy, cb);
  278. GlobalUnlock(hUpdate);
  279. DEBUGMSG("LocalUpdateResource(): End");
  280. if (fRet == NO_ERROR) {
  281. return TRUE;
  282. } else {
  283. SetLastError(fRet);
  284. if (lpData != NULL)
  285. free( lpData );
  286. return FALSE;
  287. }
  288. }
  289. /*++
  290. Routine Description
  291. Finishes the UpdateResource action. Copies the
  292. input file to a temporary, adds the resources left
  293. in the list (hUpdate) to the exe.
  294. Parameters:
  295. hUpdateFile - The handle returned by the BeginUpdateResources
  296. function.
  297. fDiscard - If TRUE, discards all the updates, frees all memory.
  298. Return Value:
  299. FALSE - The file specified was not able to be written. More
  300. information may be available via GetLastError api.
  301. TRUE - The accumulated resources specified by UpdateResource calls
  302. were written to the executable file specified by the hUpdateFile
  303. handle.
  304. --*/
  305. BOOL
  306. LocalEndUpdateResource(
  307. HANDLE hUpdate,
  308. BOOL fDiscard
  309. )
  310. {
  311. LPTSTR pFileName;
  312. PUPDATEDATA pUpdate;
  313. TCHAR pTempFileName[MAX_PATH];
  314. INT cch;
  315. LPTSTR p;
  316. LONG rc;
  317. SetLastError(0);
  318. pUpdate = (PUPDATEDATA)GlobalLock(hUpdate);
  319. DEBUGMSG("LocalEndUpdateResource()");
  320. if (fDiscard) {
  321. rc = NO_ERROR;
  322. } else {
  323. pFileName = (LPTSTR)GlobalLock(pUpdate->hFileName);
  324. strcpy(pTempFileName, pFileName);
  325. cch = lstrlen(pTempFileName);
  326. p = pTempFileName + cch;
  327. while (*p != '\\' && p >= pTempFileName)
  328. p--;
  329. *(p+1) = 0;
  330. rc = GetTempFileName(pTempFileName, "RCX", 0, pTempFileName);
  331. if (rc == 0) {
  332. rc = GetTempPath(MAX_PATH, pTempFileName);
  333. if (rc == 0) {
  334. pTempFileName[0] = '.';
  335. pTempFileName[1] = '\\';
  336. pTempFileName[2] = 0;
  337. }
  338. rc = GetTempFileName(pTempFileName, "RCX", 0, pTempFileName);
  339. if (rc == 0) {
  340. rc = GetLastError();
  341. } else {
  342. rc = WriteResFile(hUpdate, pTempFileName);
  343. if (rc == NO_ERROR) {
  344. DeleteFile(pFileName);
  345. MoveFile(pTempFileName, pFileName);
  346. } else {
  347. SetLastError(rc);
  348. DeleteFile(pTempFileName);
  349. }
  350. }
  351. } else {
  352. rc = WriteResFile(hUpdate, pTempFileName);
  353. if (rc == NO_ERROR) {
  354. DeleteFile(pFileName);
  355. MoveFile(pTempFileName, pFileName);
  356. } else {
  357. SetLastError(rc);
  358. DeleteFile(pTempFileName);
  359. }
  360. }
  361. GlobalUnlock(pUpdate->hFileName);
  362. GlobalFree(pUpdate->hFileName);
  363. }
  364. FreeData(pUpdate);
  365. GlobalUnlock(hUpdate);
  366. GlobalFree(hUpdate);
  367. DEBUGMSG("LocalEndUpdateResource(): End");
  368. return rc?FALSE:TRUE;
  369. }
  370. /**********************************************************************
  371. **
  372. ** End of API entry points.
  373. **
  374. ** Beginning of private entry points for worker routines to do the
  375. ** real work.
  376. **
  377. ***********************************************************************/
  378. BOOL _stdcall
  379. EnumTypesFunc(
  380. HANDLE hModule,
  381. LPCSTR lpType,
  382. LONG_PTR lParam
  383. )
  384. {
  385. EnumResourceNames(hModule, lpType, EnumNamesFunc, lParam);
  386. return TRUE;
  387. }
  388. BOOL _stdcall
  389. EnumNamesFunc(
  390. HANDLE hModule,
  391. LPCSTR lpType,
  392. LPCSTR lpName,
  393. LONG_PTR lParam
  394. )
  395. {
  396. EnumResourceLanguages(hModule, lpType, lpName, EnumLangsFunc, lParam);
  397. return TRUE;
  398. }
  399. BOOL _stdcall
  400. EnumLangsFunc(
  401. HANDLE hModule,
  402. LPCSTR lpType,
  403. LPCSTR lpName,
  404. WORD language,
  405. LONG_PTR lParam
  406. )
  407. {
  408. HANDLE hResInfo;
  409. LONG fError;
  410. PSDATA Type;
  411. PSDATA Name;
  412. ULONG cb;
  413. PVOID lpData;
  414. HANDLE hResource;
  415. PVOID lpResource;
  416. LPWSTR lpwType;
  417. LPWSTR lpwName;
  418. hResInfo = FindResourceEx(hModule, lpType, lpName, language);
  419. if (hResInfo == NULL) {
  420. return FALSE;
  421. }
  422. lpwType = MakeUnicodeCopy( lpType );
  423. lpwName = MakeUnicodeCopy( lpName );
  424. if (lpwType == NULL || lpwName == NULL) {
  425. ((PUPDATEDATA)lParam)->Status = ERROR_NOT_ENOUGH_MEMORY;
  426. return FALSE;
  427. }
  428. Type = AddStringOrID(lpwType, (PUPDATEDATA)lParam);
  429. if (lpType != (LPSTR) lpwType)
  430. free( lpwType );
  431. if (Type == NULL) {
  432. ((PUPDATEDATA)lParam)->Status = ERROR_NOT_ENOUGH_MEMORY;
  433. return FALSE;
  434. }
  435. Name = AddStringOrID(lpwName, (PUPDATEDATA)lParam);
  436. if (lpName != (LPSTR) lpwName)
  437. free( lpwName );
  438. if (Name == NULL) {
  439. ((PUPDATEDATA)lParam)->Status = ERROR_NOT_ENOUGH_MEMORY;
  440. return FALSE;
  441. }
  442. cb = SizeofResource(hModule, hResInfo);
  443. if (cb == 0) {
  444. return FALSE;
  445. }
  446. lpData = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( RES_TAG ), cb);
  447. if (lpData == NULL) {
  448. return FALSE;
  449. }
  450. RtlZeroMemory(lpData, cb);
  451. hResource = LoadResource(hModule, hResInfo);
  452. if (hResource == NULL) {
  453. RtlFreeHeap(RtlProcessHeap(), 0, lpData);
  454. return FALSE;
  455. }
  456. lpResource = (PVOID)LockResource(hResource);
  457. if (lpResource == NULL) {
  458. RtlFreeHeap(RtlProcessHeap(), 0, lpData);
  459. return FALSE;
  460. }
  461. RtlCopyMemory(lpData, lpResource, cb);
  462. (VOID)UnlockResource(hResource);
  463. (VOID)FreeResource(hResource);
  464. fError = AddResource(Type, Name, language, (PUPDATEDATA)lParam, lpData, cb);
  465. if (fError != NO_ERROR) {
  466. ((PUPDATEDATA)lParam)->Status = ERROR_NOT_ENOUGH_MEMORY;
  467. return FALSE;
  468. }
  469. return TRUE;
  470. }
  471. /*
  472. * BUGBUG END OF OPTIMIZATION PROBLEM
  473. */
  474. #pragma optimize( "", on )
  475. VOID
  476. FreeOne(
  477. PRESNAME pRes
  478. )
  479. {
  480. RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)pRes->OffsetToDataEntry);
  481. RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)pRes);
  482. }
  483. VOID
  484. FreeData(
  485. PUPDATEDATA pUpd
  486. )
  487. {
  488. PRESTYPE pType;
  489. PRESNAME pRes;
  490. PSDATA pstring, pStringTmp;
  491. for (pType=pUpd->ResTypeHeadID ; pUpd->ResTypeHeadID ; pType=pUpd->ResTypeHeadID) {
  492. pUpd->ResTypeHeadID = pUpd->ResTypeHeadID->pnext;
  493. for (pRes=pType->NameHeadID ; pType->NameHeadID ; pRes=pType->NameHeadID ) {
  494. pType->NameHeadID = pType->NameHeadID->pnext;
  495. FreeOne(pRes);
  496. }
  497. for (pRes=pType->NameHeadName ; pType->NameHeadName ; pRes=pType->NameHeadName ) {
  498. pType->NameHeadName = pType->NameHeadName->pnext;
  499. FreeOne(pRes);
  500. }
  501. RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)pType);
  502. }
  503. for (pType=pUpd->ResTypeHeadName ; pUpd->ResTypeHeadName ; pType=pUpd->ResTypeHeadName) {
  504. pUpd->ResTypeHeadName = pUpd->ResTypeHeadName->pnext;
  505. for (pRes=pType->NameHeadID ; pType->NameHeadID ; pRes=pType->NameHeadID ) {
  506. pType->NameHeadID = pType->NameHeadID->pnext;
  507. FreeOne(pRes);
  508. }
  509. for (pRes=pType->NameHeadName ; pType->NameHeadName ; pRes=pType->NameHeadName ) {
  510. pType->NameHeadName = pType->NameHeadName->pnext;
  511. FreeOne(pRes);
  512. }
  513. }
  514. pstring = pUpd->StringHead;
  515. while (pstring != NULL) {
  516. pStringTmp = pstring->uu.ss.pnext;
  517. if (pstring->discriminant == IS_STRING)
  518. RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)pstring->szStr);
  519. RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)pstring);
  520. pstring = pStringTmp;
  521. }
  522. return;
  523. }
  524. /*+++
  525. Routines to register strings
  526. ---*/
  527. //
  528. // Resources are DWORD aligned and may be in any order.
  529. //
  530. #define TABLE_ALIGN 4
  531. #define DATA_ALIGN 4L
  532. PSDATA
  533. AddStringOrID(
  534. LPCWSTR lp,
  535. PUPDATEDATA pupd
  536. )
  537. {
  538. USHORT cb;
  539. PSDATA pstring;
  540. PPSDATA ppstring;
  541. if (((ULONG_PTR)lp & (ULONG_PTR)0xFFFF0000) == 0) {
  542. //
  543. // an ID
  544. //
  545. pstring = (PSDATA)RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( RES_TAG ), sizeof(SDATA));
  546. if (pstring == NULL)
  547. return NULL;
  548. RtlZeroMemory((PVOID)pstring, sizeof(SDATA));
  549. pstring->discriminant = IS_ID;
  550. pstring->uu.Ordinal = (WORD)((ULONG_PTR)lp & (ULONG_PTR)0x0000ffff);
  551. }
  552. else {
  553. //
  554. // a string
  555. //
  556. cb = wcslen(lp) + 1;
  557. ppstring = &pupd->StringHead;
  558. while ((pstring = *ppstring) != NULL) {
  559. if (!wcsncmp(pstring->szStr, lp, cb))
  560. break;
  561. ppstring = &(pstring->uu.ss.pnext);
  562. }
  563. if (!pstring) {
  564. //
  565. // allocate a new one
  566. //
  567. pstring = (PSDATA)RtlAllocateHeap(RtlProcessHeap(),
  568. MAKE_TAG( RES_TAG ) | HEAP_ZERO_MEMORY,
  569. sizeof(SDATA)
  570. );
  571. if (pstring == NULL)
  572. return NULL;
  573. RtlZeroMemory((PVOID)pstring, sizeof(SDATA));
  574. pstring->szStr = (WCHAR*)RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( RES_TAG ),
  575. cb*sizeof(WCHAR));
  576. if (pstring->szStr == NULL) {
  577. RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)pstring);
  578. return NULL;
  579. }
  580. pstring->discriminant = IS_STRING;
  581. pstring->OffsetToString = pupd->cbStringTable;
  582. pstring->cbData = sizeof(pstring->cbsz) + cb * sizeof(WCHAR);
  583. pstring->cbsz = cb - 1; /* don't include zero terminator */
  584. RtlCopyMemory(pstring->szStr, lp, cb*sizeof(WCHAR));
  585. pupd->cbStringTable += pstring->cbData;
  586. pstring->uu.ss.pnext=NULL;
  587. *ppstring=pstring;
  588. }
  589. }
  590. return(pstring);
  591. }
  592. //
  593. // add a resource into the resource directory hiearchy
  594. //
  595. LONG
  596. AddResource(
  597. IN PSDATA Type,
  598. IN PSDATA Name,
  599. IN WORD Language,
  600. IN PUPDATEDATA pupd,
  601. IN PVOID lpData,
  602. IN ULONG cb
  603. )
  604. {
  605. PRESTYPE pType;
  606. PPRESTYPE ppType;
  607. PRESNAME pName;
  608. PRESNAME pNameM;
  609. PPRESNAME ppName = NULL;
  610. BOOL fTypeID=(Type->discriminant == IS_ID);
  611. BOOL fNameID=(Name->discriminant == IS_ID);
  612. BOOL fSame=FALSE;
  613. //
  614. // figure out which list to store it in
  615. //
  616. ppType = fTypeID ? &pupd->ResTypeHeadID : &pupd->ResTypeHeadName;
  617. //
  618. // Try to find the Type in the list
  619. //
  620. while ((pType=*ppType) != NULL) {
  621. if (pType->Type->uu.Ordinal == Type->uu.Ordinal) {
  622. ppName = fNameID ? &pType->NameHeadID : &pType->NameHeadName;
  623. break;
  624. }
  625. if (fTypeID) {
  626. if (Type->uu.Ordinal < pType->Type->uu.Ordinal)
  627. break;
  628. }
  629. else {
  630. if (wcsncmp(Type->szStr, pType->Type->szStr, Type->cbsz) < 0)
  631. break;
  632. }
  633. ppType = &(pType->pnext);
  634. }
  635. //
  636. // Create a new type if needed
  637. //
  638. if (ppName == NULL) {
  639. pType = (PRESTYPE)RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( RES_TAG ), sizeof(RESTYPE));
  640. if (pType == NULL)
  641. return ERROR_NOT_ENOUGH_MEMORY;
  642. RtlZeroMemory((PVOID)pType, sizeof(RESTYPE));
  643. pType->pnext = *ppType;
  644. *ppType = pType;
  645. pType->Type = Type;
  646. ppName = fNameID ? &pType->NameHeadID : &pType->NameHeadName;
  647. }
  648. //
  649. // Find proper place for name
  650. //
  651. while ( (pName = *ppName) != NULL) {
  652. if (fNameID) {
  653. if (Name->uu.Ordinal == pName->Name->uu.Ordinal) {
  654. fSame = TRUE;
  655. break;
  656. }
  657. if (Name->uu.Ordinal < pName->Name->uu.Ordinal)
  658. break;
  659. }
  660. else {
  661. if (wcsncmp(Name->szStr, pName->Name->szStr, Name->cbsz) == 0) {
  662. fSame = TRUE;
  663. break;
  664. }
  665. if (wcsncmp(Name->szStr, pName->Name->szStr, Name->cbsz) < 0)
  666. break;
  667. }
  668. ppName = &(pName->pnext);
  669. }
  670. //
  671. // check for delete/modify
  672. //
  673. if (fSame) { /* same name, new language */
  674. if (pName->NumberOfLanguages == 1) { /* one language currently ? */
  675. if (Language == pName->LanguageId) { /* REPLACE || DELETE */
  676. pName->DataSize = cb;
  677. if (lpData == NULL) { /* DELETE */
  678. return DeleteResourceFromList(pupd, pType, pName, Language, fTypeID, fNameID);
  679. }
  680. RtlFreeHeap(RtlProcessHeap(),0,(PVOID)pName->OffsetToDataEntry);
  681. (PVOID)pName->OffsetToDataEntry = lpData;
  682. return NO_ERROR;
  683. }
  684. else {
  685. if (lpData == NULL) { /* no data but new? */
  686. return ERROR_INVALID_PARAMETER; /* badness */
  687. }
  688. return InsertResourceIntoLangList(pupd, Type, Name, pType, pName, Language, fNameID, cb, lpData);
  689. }
  690. }
  691. else { /* many languages currently */
  692. pNameM = pName; /* save head of lang list */
  693. while ( (pName = *ppName) != NULL) {/* find insertion point */
  694. if (pName->Name != pNameM->Name ||
  695. Language <= pName->LanguageId) /* here? */
  696. break; /* yes */
  697. ppName = &(pName->pnext); /* traverse language list */
  698. }
  699. if (pName && Language == pName->LanguageId) { /* language found? */
  700. if (lpData == NULL) { /* DELETE */
  701. return DeleteResourceFromList(pupd, pType, pName, Language, fTypeID, fNameID);
  702. }
  703. pName->DataSize = cb; /* REPLACE */
  704. RtlFreeHeap(RtlProcessHeap(),0,(PVOID)pName->OffsetToDataEntry);
  705. (PVOID)pName->OffsetToDataEntry = lpData;
  706. return NO_ERROR;
  707. }
  708. else { /* add new language */
  709. return InsertResourceIntoLangList(pupd, Type, Name, pType, pNameM, Language, fNameID, cb, lpData);
  710. }
  711. }
  712. }
  713. else { /* unique name */
  714. if (lpData == NULL) { /* can't delete new name */
  715. return ERROR_INVALID_PARAMETER;
  716. }
  717. }
  718. //
  719. // add new name/language
  720. //
  721. if (!fSame) {
  722. if (fNameID)
  723. pType->NumberOfNamesID++;
  724. else
  725. pType->NumberOfNamesName++;
  726. }
  727. pName = (PRESNAME)RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( RES_TAG ), sizeof(RESNAME));
  728. if (pName == NULL)
  729. return ERROR_NOT_ENOUGH_MEMORY;
  730. RtlZeroMemory((PVOID)pName, sizeof(RESNAME));
  731. pName->pnext = *ppName;
  732. *ppName = pName;
  733. pName->Name = Name;
  734. pName->Type = Type;
  735. pName->NumberOfLanguages = 1;
  736. pName->LanguageId = Language;
  737. pName->DataSize = cb;
  738. (PVOID)pName->OffsetToDataEntry = lpData;
  739. return NO_ERROR;
  740. }
  741. BOOL
  742. DeleteResourceFromList(
  743. PUPDATEDATA pUpd,
  744. PRESTYPE pType,
  745. PRESNAME pName,
  746. INT Language,
  747. INT fType,
  748. INT fName
  749. )
  750. {
  751. PPRESTYPE ppType;
  752. PPRESNAME ppName;
  753. PRESNAME pNameT;
  754. /* find previous type node */
  755. ppType = fType ? &pUpd->ResTypeHeadID : &pUpd->ResTypeHeadName;
  756. while (*ppType != pType) {
  757. ppType = &((*ppType)->pnext);
  758. }
  759. /* find previous type node */
  760. ppName = fName ? &pType->NameHeadID : &pType->NameHeadName;
  761. pNameT = NULL;
  762. while (*ppName != pName) {
  763. if (pNameT == NULL) { /* find first Name in lang list */
  764. if (fName) {
  765. if ((*ppName)->Name->uu.Ordinal == pName->Name->uu.Ordinal) {
  766. pNameT = *ppName;
  767. }
  768. }
  769. else {
  770. if (wcsncmp((*ppName)->Name->szStr, pName->Name->szStr, (*ppName)->Name->cbsz) == 0) {
  771. pNameT = *ppName;
  772. }
  773. }
  774. }
  775. ppName = &((*ppName)->pnext);
  776. }
  777. if (pNameT == NULL) { /* first of this name? */
  778. pNameT = pName->pnext; /* then (possibly) make next head of lang */
  779. if (pNameT != NULL) {
  780. if (fName) {
  781. if (pNameT->Name->uu.Ordinal == pName->Name->uu.Ordinal) {
  782. pNameT->NumberOfLanguages = pName->NumberOfLanguages - 1;
  783. }
  784. }
  785. else {
  786. if (wcsncmp(pNameT->Name->szStr, pName->Name->szStr, pNameT->Name->cbsz) == 0) {
  787. pNameT->NumberOfLanguages = pName->NumberOfLanguages - 1;
  788. }
  789. }
  790. }
  791. }
  792. else
  793. pNameT->NumberOfLanguages--;
  794. if (pNameT) {
  795. if (pNameT->NumberOfLanguages == 0) {
  796. if (fName)
  797. pType->NumberOfNamesID -= 1;
  798. else
  799. pType->NumberOfNamesName -= 1;
  800. }
  801. }
  802. *ppName = pName->pnext; /* link to next */
  803. RtlFreeHeap(RtlProcessHeap(), 0, (PVOID)pName->OffsetToDataEntry);
  804. RtlFreeHeap(RtlProcessHeap(), 0, pName); /* and free */
  805. if (*ppName == NULL) { /* type list completely empty? */
  806. *ppType = pType->pnext; /* link to next */
  807. RtlFreeHeap(RtlProcessHeap(), 0, pType); /* and free */
  808. }
  809. return NO_ERROR;
  810. }
  811. BOOL
  812. InsertResourceIntoLangList(
  813. PUPDATEDATA pUpd,
  814. PSDATA Type,
  815. PSDATA Name,
  816. PRESTYPE pType,
  817. PRESNAME pName,
  818. INT Language,
  819. INT fName,
  820. INT cb,
  821. PVOID lpData
  822. )
  823. {
  824. PRESNAME pNameM;
  825. PRESNAME pNameNew;
  826. PPRESNAME ppName;
  827. pNameNew = (PRESNAME)RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( RES_TAG ), sizeof(RESNAME));
  828. if (pNameNew == NULL)
  829. return ERROR_NOT_ENOUGH_MEMORY;
  830. RtlZeroMemory((PVOID)pNameNew, sizeof(RESNAME));
  831. pNameNew->Name = Name;
  832. pNameNew->Type = Type;
  833. pNameNew->LanguageId = (WORD)Language;
  834. pNameNew->DataSize = cb;
  835. (PVOID)pNameNew->OffsetToDataEntry = lpData;
  836. if (Language < pName->LanguageId) { /* have to add to the front */
  837. pNameNew->NumberOfLanguages = pName->NumberOfLanguages + 1;
  838. pName->NumberOfLanguages = 1;
  839. ppName = fName ? &pType->NameHeadID : &pType->NameHeadName;
  840. /* don't have to look for NULL at end of list !!! */
  841. while (pName != *ppName) { /* find insertion point */
  842. ppName = &((*ppName)->pnext); /* traverse language list */
  843. }
  844. pNameNew->pnext = *ppName; /* insert */
  845. *ppName = pNameNew;
  846. }
  847. else {
  848. pNameM = pName;
  849. pName->NumberOfLanguages += 1;
  850. while (pName != NULL) { /* find insertion point */
  851. if (Language <= pName->LanguageId) /* here? */
  852. break; /* yes */
  853. pNameM = pName;
  854. pName = pName->pnext; /* traverse language list */
  855. }
  856. pName = pNameM->pnext;
  857. pNameM->pnext = pNameNew;
  858. pNameNew->pnext = pName;
  859. }
  860. return NO_ERROR;
  861. }
  862. /*
  863. * Utility routines
  864. */
  865. ULONG
  866. FilePos(int fh)
  867. {
  868. return _llseek(fh, 0L, SEEK_CUR);
  869. }
  870. ULONG
  871. MuMoveFilePos( INT fh, ULONG pos )
  872. {
  873. return _llseek( fh, pos, SEEK_SET );
  874. }
  875. ULONG
  876. MuWrite( INT fh, UCHAR*p, ULONG n )
  877. {
  878. ULONG n1;
  879. LPVOID lpMsg;
  880. TCHAR szBuf[MAX_STRING];
  881. n1 = _lwrite(fh, p, n);
  882. if ( n1 == HFILE_ERROR )
  883. {
  884. ULONG cb;
  885. PUCHAR pb;
  886. ULONG cbDone, nBytes;
  887. // try on small buffer again
  888. pb = p;
  889. nBytes = n;
  890. while ( nBytes )
  891. {
  892. if (nBytes <= BUFSIZE)
  893. cb = nBytes;
  894. else
  895. cb = BUFSIZE;
  896. cbDone = _lwrite( fh, pb, cb);
  897. if ( cbDone != HFILE_ERROR )
  898. {
  899. nBytes -= cbDone;
  900. pb += cbDone;
  901. }
  902. else
  903. {
  904. if ( FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  905. NULL, GetLastError(),
  906. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  907. (LPSTR)&lpMsg, 0, NULL ) )
  908. {
  909. TCHAR szTmp[MAX_STRING];
  910. LoadSz( IDS_ERR_WRITEFILE, szTmp, sizeof(szTmp) );
  911. wsprintf( szBuf, szTmp, n, lpMsg );
  912. MessageBox( NULL, szBuf, g_CDF.achTitle, MB_ICONERROR|MB_OK|
  913. ((RunningOnWin95BiDiLoc() && IsBiDiLocalizedBinary(g_hInst,RT_VERSION, MAKEINTRESOURCE(VS_VERSION_INFO))) ? (MB_RIGHT | MB_RTLREADING) : 0));
  914. LocalFree( lpMsg );
  915. }
  916. return cbDone; // error return
  917. }
  918. }
  919. return 0; //purely simulate the old normal return here.
  920. }
  921. else if ( n1 != n)
  922. return n1;
  923. else
  924. return 0;
  925. }
  926. ULONG
  927. MuRead(INT fh, UCHAR*p, ULONG n )
  928. {
  929. ULONG n1;
  930. if ((n1 = _lread( fh, p, n )) != n) {
  931. return n1;
  932. }
  933. else
  934. return 0;
  935. }
  936. BOOL
  937. MuCopy( INT srcfh, INT dstfh, ULONG nbytes )
  938. {
  939. ULONG n;
  940. ULONG cb=0L;
  941. PUCHAR pb;
  942. pb = (PUCHAR)RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( RES_TAG ), BUFSIZE);
  943. if (pb == NULL)
  944. return 0;
  945. RtlZeroMemory((PVOID)pb, BUFSIZE);
  946. while (nbytes) {
  947. if (nbytes <= BUFSIZE)
  948. n = nbytes;
  949. else
  950. n = BUFSIZE;
  951. nbytes -= n;
  952. if (!MuRead( srcfh, pb, n )) {
  953. cb += n;
  954. MuWrite( dstfh, pb, n );
  955. }
  956. else {
  957. RtlFreeHeap(RtlProcessHeap(), 0, pb);
  958. return cb;
  959. }
  960. }
  961. RtlFreeHeap(RtlProcessHeap(), 0, pb);
  962. return cb;
  963. }
  964. VOID
  965. SetResdata(
  966. PIMAGE_RESOURCE_DATA_ENTRY pResData,
  967. ULONG offset,
  968. ULONG size)
  969. {
  970. pResData->OffsetToData = offset;
  971. pResData->Size = size;
  972. pResData->CodePage = DEFAULT_CODEPAGE;
  973. pResData->Reserved = 0L;
  974. }
  975. VOID
  976. SetRestab(
  977. PIMAGE_RESOURCE_DIRECTORY pRestab,
  978. LONG time,
  979. WORD cNamed,
  980. WORD cId)
  981. {
  982. pRestab->Characteristics = 0L;
  983. pRestab->TimeDateStamp = time;
  984. pRestab->MajorVersion = MAJOR_RESOURCE_VERSION;
  985. pRestab->MinorVersion = MINOR_RESOURCE_VERSION;
  986. pRestab->NumberOfNamedEntries = cNamed;
  987. pRestab->NumberOfIdEntries = cId;
  988. }
  989. PIMAGE_SECTION_HEADER
  990. FindSection(
  991. PIMAGE_SECTION_HEADER pObjBottom,
  992. PIMAGE_SECTION_HEADER pObjTop,
  993. LPSTR pName
  994. )
  995. {
  996. while (pObjBottom < pObjTop) {
  997. if (strcmp(pObjBottom->Name, pName) == 0)
  998. return pObjBottom;
  999. pObjBottom++;
  1000. }
  1001. return NULL;
  1002. }
  1003. ULONG
  1004. AssignResourceToSection(
  1005. PRESNAME *ppRes, /* resource to assign */
  1006. ULONG ExtraSectionOffset, /* offset between .rsrc and .rsrc1 */
  1007. ULONG Offset, /* next available offset in section */
  1008. LONG Size, /* Maximum size of .rsrc */
  1009. PLONG pSizeRsrc1
  1010. )
  1011. {
  1012. ULONG cb;
  1013. /* Assign this res to this section */
  1014. cb = ROUNDUP((*ppRes)->DataSize, CBLONG);
  1015. if (Offset < ExtraSectionOffset && Offset + cb > (ULONG)Size) {
  1016. *pSizeRsrc1 = Offset;
  1017. Offset = ExtraSectionOffset;
  1018. DPrintf((DebugBuf, "<<< Secondary resource section @%#08lx >>>\n", Offset));
  1019. }
  1020. (*ppRes)->OffsetToData = Offset;
  1021. *ppRes = (*ppRes)->pnext;
  1022. DPrintf((DebugBuf, " --> %#08lx bytes at %#08lx\n", cb, Offset));
  1023. return Offset + cb;
  1024. }
  1025. /***************************** Main Worker Function ***************************
  1026. * LONG PEWriteResFile
  1027. *
  1028. * This function writes the resources to the named executable file.
  1029. * It assumes that resources have no fixups (even any existing resources
  1030. * that it removes from the executable.) It places all the resources into
  1031. * one or two sections. The resources are packed tightly into the section,
  1032. * being aligned on dword boundaries. Each section is padded to a file
  1033. * sector size (no invalid or zero-filled pages), and each
  1034. * resource is padded to the afore-mentioned dword boundary. This
  1035. * function uses the capabilities of the NT system to enable it to easily
  1036. * manipulate the data: to wit, it assumes that the system can allocate
  1037. * any sized piece of data, in particular the section and resource tables.
  1038. * If it did not, it might have to deal with temporary files (the system
  1039. * may have to grow the swap file, but that's what the system is for.)
  1040. *
  1041. * Return values are:
  1042. * TRUE - file was written succesfully.
  1043. * FALSE - file was not written succesfully.
  1044. *
  1045. * Effects:
  1046. *
  1047. * History:
  1048. * Thur Apr 27, 1989 by Floyd Rogers [floydr]
  1049. * Created.
  1050. * 12/8/89 sanfords Added multiple section support.
  1051. * 12/11/90 floydr Modified for new (NT) Linear Exe format
  1052. * 1/18/92 vich Modified for new (NT) Portable Exe format
  1053. * 5/8/92 bryant General cleanup so resonexe can work with unicode
  1054. * 6/9/92 floydr incorporate bryan's changes
  1055. * 6/15/92 floydr debug section separate from debug table
  1056. * 9/25/92 floydr account for .rsrc not being last-1
  1057. * 9/28/92 floydr account for adding lots of resources by adding
  1058. * a second .rsrc section.
  1059. \****************************************************************************/
  1060. /* */
  1061. LONG
  1062. PEWriteResFile(
  1063. INT inpfh,
  1064. INT outfh,
  1065. ULONG cbOldexe,
  1066. PUPDATEDATA pUpdate
  1067. )
  1068. {
  1069. IMAGE_NT_HEADERS Old; /* original header */
  1070. IMAGE_NT_HEADERS New; /* working header */
  1071. PRESNAME pRes;
  1072. PRESNAME pResSave;
  1073. PRESTYPE pType;
  1074. ULONG clock = GetTickCount(); /* current time */
  1075. ULONG cbName=0; /* count of bytes in name strings */
  1076. ULONG cbType=0; /* count of bytes in type strings */
  1077. ULONG cTypeStr=0; /* count of strings */
  1078. ULONG cNameStr=0; /* count of strings */
  1079. LONG cb; /* temp byte count and file index */
  1080. ULONG cTypes = 0L; /* count of resource types */
  1081. ULONG cNames = 0L; /* Count of names for multiple languages/name */
  1082. ULONG cRes = 0L; /* count of resources */
  1083. ULONG cbRestab; /* count of resources */
  1084. LONG cbNew = 0L; /* general count */
  1085. ULONG ibObjTab;
  1086. ULONG ibObjTabEnd;
  1087. ULONG ibSave;
  1088. ULONG adjust=0;
  1089. PIMAGE_SECTION_HEADER pObjtblOld,
  1090. pObjtblNew,
  1091. pObjDebug,
  1092. pObjResourceOld,
  1093. pObjResourceNew,
  1094. pObjResourceOldX,
  1095. pObjDebugDirOld,
  1096. pObjDebugDirNew,
  1097. pObjNew,
  1098. pObjOld,
  1099. pObjLast;
  1100. PUCHAR p;
  1101. PIMAGE_RESOURCE_DIRECTORY pResTab;
  1102. PIMAGE_RESOURCE_DIRECTORY pResTabN;
  1103. PIMAGE_RESOURCE_DIRECTORY pResTabL;
  1104. PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirL;
  1105. PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirN;
  1106. PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirT;
  1107. PIMAGE_RESOURCE_DATA_ENTRY pResData;
  1108. PUSHORT pResStr;
  1109. PUSHORT pResStrEnd;
  1110. PSDATA pPreviousName;
  1111. LONG nObjResource=-1;
  1112. LONG nObjResourceX=-1;
  1113. ULONG cbResource;
  1114. ULONG cbMustPad = 0;
  1115. ULONG ibMaxDbgOffsetOld;
  1116. MuMoveFilePos(inpfh, cbOldexe);
  1117. MuRead(inpfh, (PUCHAR)&Old, sizeof(IMAGE_NT_HEADERS));
  1118. ibObjTab = cbOldexe + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
  1119. Old.FileHeader.SizeOfOptionalHeader;
  1120. ibObjTabEnd = ibObjTab + Old.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
  1121. if (*(PUSHORT)&Old.Signature != IMAGE_NT_SIGNATURE)
  1122. return ERROR_INVALID_EXE_SIGNATURE;
  1123. if ((Old.FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) == 0 &&
  1124. (Old.FileHeader.Characteristics & IMAGE_FILE_DLL) == 0) {
  1125. return ERROR_EXE_MARKED_INVALID;
  1126. }
  1127. DPrintfn((DebugBuf, "\n"));
  1128. /* New header is like old one. */
  1129. RtlCopyMemory(&New, &Old, sizeof(IMAGE_NT_HEADERS));
  1130. /* Read section table */
  1131. pObjtblOld = (PIMAGE_SECTION_HEADER)RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( RES_TAG ),
  1132. Old.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER));
  1133. if (pObjtblOld == NULL) {
  1134. cb = ERROR_NOT_ENOUGH_MEMORY;
  1135. goto AbortExit;
  1136. }
  1137. RtlZeroMemory((PVOID)pObjtblOld, Old.FileHeader.NumberOfSections*sizeof(IMAGE_SECTION_HEADER));
  1138. DPrintf((DebugBuf, "Old section table: %#08lx bytes at %#08lx(mem)\n",
  1139. Old.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER),
  1140. pObjtblOld));
  1141. MuMoveFilePos(inpfh, ibObjTab);
  1142. MuRead(inpfh, (PUCHAR)pObjtblOld,
  1143. Old.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER));
  1144. pObjLast = pObjtblOld + Old.FileHeader.NumberOfSections;
  1145. ibMaxDbgOffsetOld = 0;
  1146. for (pObjOld=pObjtblOld ; pObjOld<pObjLast ; pObjOld++) {
  1147. if (pObjOld->PointerToRawData > ibMaxDbgOffsetOld) {
  1148. ibMaxDbgOffsetOld = pObjOld->PointerToRawData + pObjOld->SizeOfRawData;
  1149. }
  1150. }
  1151. DPrintf((DebugBuf, "Maximum debug offset in old file: %08x\n", ibMaxDbgOffsetOld ));
  1152. /*
  1153. * First, count up the resources. We need this information
  1154. * to discover how much room for header information to allocate
  1155. * in the resource section. cRes tells us how
  1156. * many language directory entries/tables. cNames and cTypes
  1157. * is used for the respective tables and/or entries. cbName totals
  1158. * the bytes required to store the alpha names (including the leading
  1159. * length word). cNameStr counts these strings.
  1160. */
  1161. DPrintf((DebugBuf, "Beginning loop to count resources\n"));
  1162. /* first, count those in the named type list */
  1163. cbResource = 0;
  1164. //DPrintf((DebugBuf, "Walk type: NAME list\n"));
  1165. pType = pUpdate->ResTypeHeadName;
  1166. while (pType != NULL) {
  1167. if (pType->NameHeadName != NULL || pType->NameHeadID != NULL) {
  1168. //DPrintf((DebugBuf, "Resource type "));
  1169. //DPrintfu((pType->Type->szStr));
  1170. //DPrintfn((DebugBuf, "\n"));
  1171. cTypes++;
  1172. cTypeStr++;
  1173. cbType += (pType->Type->cbsz + 1) * sizeof(WORD);
  1174. //DPrintf((DebugBuf, "Walk name: Alpha list\n"));
  1175. pPreviousName = NULL;
  1176. pRes = pType->NameHeadName;
  1177. while (pRes) {
  1178. //DPrintf((DebugBuf, "Resource "));
  1179. //DPrintfu((pRes->Name->szStr));
  1180. //DPrintfn((DebugBuf, "\n"));
  1181. cRes++;
  1182. if (pPreviousName == NULL ||
  1183. wcsncmp(pPreviousName->szStr,
  1184. pRes->Name->szStr,
  1185. pRes->Name->cbsz) != 0) {
  1186. cbName += (pRes->Name->cbsz + 1) * sizeof(WORD);
  1187. cNameStr++;
  1188. cNames++;
  1189. }
  1190. cbResource += ROUNDUP(pRes->DataSize, CBLONG);
  1191. pPreviousName = pRes->Name;
  1192. pRes = pRes->pnext;
  1193. }
  1194. //DPrintf((DebugBuf, "Walk name: ID list\n"));
  1195. pPreviousName = NULL;
  1196. pRes = pType->NameHeadID;
  1197. while (pRes) {
  1198. //DPrintf((DebugBuf, "Resource %hu\n", pRes->Name->uu.Ordinal));
  1199. cRes++;
  1200. if (pPreviousName == NULL ||
  1201. pPreviousName->uu.Ordinal != pRes->Name->uu.Ordinal) {
  1202. cNames++;
  1203. }
  1204. cbResource += ROUNDUP(pRes->DataSize, CBLONG);
  1205. pPreviousName = pRes->Name;
  1206. pRes = pRes->pnext;
  1207. }
  1208. }
  1209. pType = pType->pnext;
  1210. }
  1211. /* second, count those in the ID type list */
  1212. //DPrintf((DebugBuf, "Walk type: ID list\n"));
  1213. pType = pUpdate->ResTypeHeadID;
  1214. while (pType != NULL) {
  1215. if (pType->NameHeadName != NULL || pType->NameHeadID != NULL) {
  1216. //DPrintf((DebugBuf, "Resource type %hu\n", pType->Type->uu.Ordinal));
  1217. cTypes++;
  1218. //DPrintf((DebugBuf, "Walk name: Alpha list\n"));
  1219. pPreviousName = NULL;
  1220. pRes = pType->NameHeadName;
  1221. while (pRes) {
  1222. //DPrintf((DebugBuf, "Resource "));
  1223. //DPrintfu((pRes->Name->szStr));
  1224. //DPrintfn((DebugBuf, "\n"));
  1225. cRes++;
  1226. if (pPreviousName == NULL ||
  1227. wcsncmp(pPreviousName->szStr,
  1228. pRes->Name->szStr,
  1229. pRes->Name->cbsz) != 0) {
  1230. cNames++;
  1231. cbName += (pRes->Name->cbsz + 1) * sizeof(WORD);
  1232. cNameStr++;
  1233. }
  1234. cbResource += ROUNDUP(pRes->DataSize, CBLONG);
  1235. pPreviousName = pRes->Name;
  1236. pRes = pRes->pnext;
  1237. }
  1238. //DPrintf((DebugBuf, "Walk name: ID list\n"));
  1239. pPreviousName = NULL;
  1240. pRes = pType->NameHeadID;
  1241. while (pRes) {
  1242. //DPrintf((DebugBuf, "Resource %hu\n", pRes->Name->uu.Ordinal));
  1243. cRes++;
  1244. if (pPreviousName == NULL ||
  1245. pPreviousName->uu.Ordinal != pRes->Name->uu.Ordinal) {
  1246. cNames++;
  1247. }
  1248. cbResource += ROUNDUP(pRes->DataSize, CBLONG);
  1249. pPreviousName = pRes->Name;
  1250. pRes = pRes->pnext;
  1251. }
  1252. }
  1253. pType = pType->pnext;
  1254. }
  1255. cb = REMAINDER(cbName + cbType, CBLONG);
  1256. /* Add up the number of bytes needed to store the directory. There is
  1257. * one type table with cTypes entries. They point to cTypes name tables
  1258. * that have a total of cNames entries. Each of them points to a language
  1259. * table and there are a total of cRes entries in all the language tables.
  1260. * Finally, we have the space needed for the Directory string entries,
  1261. * some extra padding to attain the desired alignment, and the space for
  1262. * cRes data entry headers.
  1263. */
  1264. cbRestab = sizeof(IMAGE_RESOURCE_DIRECTORY) + /* root dir (types) */
  1265. cTypes * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY) +
  1266. cTypes * sizeof(IMAGE_RESOURCE_DIRECTORY) + /* subdir2 (names) */
  1267. cNames * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY) +
  1268. cNames * sizeof(IMAGE_RESOURCE_DIRECTORY) + /* subdir3 (langs) */
  1269. cRes * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY) +
  1270. (cbName + cbType) + /* name/type strings */
  1271. cb + /* padding */
  1272. cRes * sizeof(IMAGE_RESOURCE_DATA_ENTRY); /* data entries */
  1273. cbResource += cbRestab; /* add in the resource table */
  1274. // Find any current resource sections
  1275. pObjResourceOld = FindSection(pObjtblOld, pObjLast, ".rsrc");
  1276. pObjResourceOldX = FindSection(pObjtblOld, pObjLast, ".rsrc1");
  1277. if (pObjResourceOld == NULL) {
  1278. cb = 0x7fffffff; /* can fill forever */
  1279. }
  1280. else if (pObjResourceOld + 1 == pObjResourceOldX) {
  1281. nObjResource = (LONG)(pObjResourceOld - pObjtblOld);
  1282. DPrintf((DebugBuf,"Old Resource section #%lu\n", nObjResource+1));
  1283. DPrintf((DebugBuf,"Merging old Resource extra section #%lu\n", nObjResource+2));
  1284. cb = 0x7fffffff; /* merge resource sections */
  1285. }
  1286. else if ((pObjResourceOld + 1) >= pObjLast) {
  1287. nObjResource = (LONG)(pObjResourceOld - pObjtblOld);
  1288. cb = 0x7fffffff; /* can fill forever (.rsrc is the last entry) */
  1289. }
  1290. else {
  1291. nObjResource = (LONG)(pObjResourceOld - pObjtblOld);
  1292. DPrintf((DebugBuf,"Old Resource section #%lu\n", nObjResource+1));
  1293. cb = (pObjResourceOld+1)->VirtualAddress -
  1294. pObjResourceOld->VirtualAddress;
  1295. if (cbRestab > (ULONG)cb) {
  1296. DPrintf((DebugBuf, "Resource Table Too Large\n"));
  1297. return ERROR_INVALID_DATA;
  1298. }
  1299. }
  1300. /*
  1301. * Discover where the first discardable section is. This is where
  1302. * we will stick any new resource section.
  1303. *
  1304. * Note that we are ignoring discardable sections such as .CRT -
  1305. * this is so that we don't cause any relocation problems.
  1306. * Let's hope that .reloc is the one we want!!!
  1307. */
  1308. pObjOld = FindSection(pObjtblOld, pObjLast, ".reloc");
  1309. if (pObjResourceOld != NULL && cbResource > (ULONG)cb) {
  1310. if (pObjOld == pObjResourceOld + 1) {
  1311. DPrintf((DebugBuf, "Large resource section pushes .reloc\n"));
  1312. cb = 0x7fffffff; /* can fill forever */
  1313. }
  1314. else if (pObjResourceOldX == NULL) {
  1315. DPrintf((DebugBuf, "Too much resource data for old .rsrc section\n"));
  1316. nObjResourceX = (LONG)(pObjOld - pObjtblOld);
  1317. adjust = pObjOld->VirtualAddress - pObjResourceOld->VirtualAddress;
  1318. }
  1319. else { /* have already merged .rsrc & .rsrc1, if possible */
  1320. DPrintf((DebugBuf, ".rsrc1 section not empty\n"));
  1321. nObjResourceX = (LONG)(pObjResourceOldX - pObjtblOld);
  1322. adjust = pObjResourceOldX->VirtualAddress -
  1323. pObjResourceOld ->VirtualAddress;
  1324. }
  1325. }
  1326. /*
  1327. * Walk the type lists and figure out where the Data entry header will
  1328. * go. Keep a running total of the size for each data element so we
  1329. * can store this in the section header.
  1330. */
  1331. DPrintf((DebugBuf, "Beginning loop to assign resources to addresses\n"));
  1332. /* first, those in the named type list */
  1333. cbResource = cbRestab; /* assign resource table to 1st rsrc section */
  1334. /* adjust == offset to .rsrc1 */
  1335. /* cb == size availble in .rsrc */
  1336. cbNew = 0; /* count of bytes in second .rsrc */
  1337. DPrintf((DebugBuf, "Walk type: NAME list\n"));
  1338. pType = pUpdate->ResTypeHeadName;
  1339. while (pType != NULL) {
  1340. if (pType->NameHeadName != NULL || pType->NameHeadID != NULL) {
  1341. DPrintf((DebugBuf, "Resource type "));
  1342. DPrintfu((pType->Type->szStr));
  1343. DPrintfn((DebugBuf, "\n"));
  1344. pRes = pType->NameHeadName;
  1345. while (pRes) {
  1346. DPrintf((DebugBuf, "Resource "));
  1347. DPrintfu((pRes->Name->szStr));
  1348. DPrintfn((DebugBuf, "\n"));
  1349. cbResource = AssignResourceToSection(&pRes,
  1350. adjust, cbResource, cb, &cbNew);
  1351. }
  1352. pRes = pType->NameHeadID;
  1353. while (pRes) {
  1354. DPrintf((DebugBuf, "Resource %hu\n", pRes->Name->uu.Ordinal));
  1355. cbResource = AssignResourceToSection(&pRes,
  1356. adjust, cbResource, cb, &cbNew);
  1357. }
  1358. }
  1359. pType = pType->pnext;
  1360. }
  1361. /* then, count those in the ID type list */
  1362. DPrintf((DebugBuf, "Walk type: ID list\n"));
  1363. pType = pUpdate->ResTypeHeadID;
  1364. while (pType != NULL) {
  1365. if (pType->NameHeadName != NULL || pType->NameHeadID != NULL) {
  1366. DPrintf((DebugBuf, "Resource type %hu\n", pType->Type->uu.Ordinal));
  1367. pRes = pType->NameHeadName;
  1368. while (pRes) {
  1369. DPrintf((DebugBuf, "Resource "));
  1370. DPrintfu((pRes->Name->szStr));
  1371. DPrintfn((DebugBuf, "\n"));
  1372. cbResource = AssignResourceToSection(&pRes,
  1373. adjust, cbResource, cb, &cbNew);
  1374. }
  1375. pRes = pType->NameHeadID;
  1376. while (pRes) {
  1377. DPrintf((DebugBuf, "Resource %hu\n", pRes->Name->uu.Ordinal));
  1378. cbResource = AssignResourceToSection(&pRes,
  1379. adjust, cbResource, cb, &cbNew);
  1380. }
  1381. }
  1382. pType = pType->pnext;
  1383. }
  1384. /*
  1385. * At this point:
  1386. * cbResource has offset of first byte past the last resource.
  1387. * cbNew has the count of bytes in the first resource section,
  1388. * if there are two sections.
  1389. */
  1390. if (cbNew == 0)
  1391. cbNew = cbResource;
  1392. /*
  1393. * Discover where the Debug info is (if any)?
  1394. */
  1395. pObjDebug = FindSection(pObjtblOld, pObjLast, ".debug");
  1396. if (pObjDebug != NULL) {
  1397. if (Old.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress == 0) {
  1398. DPrintf((DebugBuf, ".debug section but no debug directory\n"));
  1399. return ERROR_INVALID_DATA;
  1400. }
  1401. if (pObjDebug != pObjLast-1) {
  1402. DPrintf((DebugBuf, "debug section not last section in file\n"));
  1403. return ERROR_INVALID_DATA;
  1404. }
  1405. DPrintf((DebugBuf, "Debug section: %#08lx bytes @%#08lx\n",
  1406. pObjDebug->SizeOfRawData,
  1407. pObjDebug->PointerToRawData));
  1408. }
  1409. pObjDebugDirOld = NULL;
  1410. for (pObjOld=pObjtblOld ; pObjOld<pObjLast ; pObjOld++) {
  1411. if (Old.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress >= pObjOld->VirtualAddress &&
  1412. Old.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress < pObjOld->VirtualAddress+pObjOld->SizeOfRawData) {
  1413. pObjDebugDirOld = pObjOld;
  1414. break;
  1415. }
  1416. }
  1417. /*
  1418. * Discover where the first discardable section is. This is where
  1419. * we will stick any new resource section.
  1420. *
  1421. * Note that we are ignoring discardable sections such as .CRT -
  1422. * this is so that we don't cause any relocation problems.
  1423. * Let's hope that .reloc is the one we want!!!
  1424. */
  1425. pObjOld = FindSection(pObjtblOld, pObjLast, ".reloc");
  1426. if (nObjResource == -1) { /* no old resource section */
  1427. if (pObjOld != NULL)
  1428. nObjResource = (LONG)(pObjOld - pObjtblOld);
  1429. else if (pObjDebug != NULL)
  1430. nObjResource = (LONG)(pObjDebug - pObjtblOld);
  1431. else
  1432. nObjResource = New.FileHeader.NumberOfSections;
  1433. New.FileHeader.NumberOfSections++;
  1434. }
  1435. DPrintf((DebugBuf, "Resources assigned to section #%lu\n", nObjResource+1));
  1436. if (nObjResourceX != -1) {
  1437. if (pObjResourceOldX != NULL) {
  1438. nObjResourceX = (LONG)(pObjResourceOldX - pObjtblOld);
  1439. New.FileHeader.NumberOfSections--;
  1440. }
  1441. else if (pObjOld != NULL)
  1442. nObjResourceX = (LONG)(pObjOld - pObjtblOld);
  1443. else if (pObjDebug != NULL)
  1444. nObjResourceX = (LONG)(pObjDebug - pObjtblOld);
  1445. else
  1446. nObjResourceX = New.FileHeader.NumberOfSections;
  1447. New.FileHeader.NumberOfSections++;
  1448. DPrintf((DebugBuf, "Extra resources assigned to section #%lu\n",
  1449. nObjResourceX+1));
  1450. }
  1451. else if (pObjResourceOldX != NULL) { /* Was old .rsrc1 section? */
  1452. DPrintf((DebugBuf, "Extra resource section deleted\n"));
  1453. New.FileHeader.NumberOfSections--; /* yes, delete it */
  1454. }
  1455. /*
  1456. * If we had to add anything to the header (section table),
  1457. * then we have to update the header size and rva's in the header.
  1458. */
  1459. adjust = (New.FileHeader.NumberOfSections -
  1460. Old.FileHeader.NumberOfSections) * sizeof(IMAGE_SECTION_HEADER);
  1461. cb = Old.OptionalHeader.SizeOfHeaders -
  1462. (Old.FileHeader.NumberOfSections*sizeof(IMAGE_SECTION_HEADER) +
  1463. sizeof(IMAGE_NT_HEADERS) + cbOldexe );
  1464. if (adjust > (ULONG)cb) {
  1465. int i;
  1466. adjust -= cb;
  1467. DPrintf((DebugBuf, "Adjusting header RVAs by %#08lx\n", adjust));
  1468. for (i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES ; i++) {
  1469. if (New.OptionalHeader.DataDirectory[i].VirtualAddress &&
  1470. New.OptionalHeader.DataDirectory[i].VirtualAddress < New.OptionalHeader.SizeOfHeaders) {
  1471. DPrintf((DebugBuf, "Adjusting unit[%s] RVA from %#08lx to %#08lx\n",
  1472. apszUnit[i],
  1473. New.OptionalHeader.DataDirectory[i].VirtualAddress,
  1474. New.OptionalHeader.DataDirectory[i].VirtualAddress + adjust));
  1475. New.OptionalHeader.DataDirectory[i].VirtualAddress += adjust;
  1476. }
  1477. }
  1478. New.OptionalHeader.SizeOfHeaders += adjust;
  1479. }
  1480. /* Allocate storage for new section table */
  1481. cb = New.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
  1482. pObjtblNew = (PIMAGE_SECTION_HEADER)RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( RES_TAG ), (short)cb);
  1483. if (pObjtblNew == NULL) {
  1484. cb = ERROR_NOT_ENOUGH_MEMORY;
  1485. goto AbortExit;
  1486. }
  1487. RtlZeroMemory((PVOID)pObjtblNew, cb);
  1488. DPrintf((DebugBuf, "New section table: %#08lx bytes at %#08lx\n", cb, pObjtblNew));
  1489. pObjResourceNew = pObjtblNew + nObjResource;
  1490. /*
  1491. * copy old section table to new
  1492. */
  1493. adjust = 0; /* adjustment to virtual address */
  1494. for (pObjOld=pObjtblOld,pObjNew=pObjtblNew ; pObjOld<pObjLast ; pObjOld++) {
  1495. if (pObjOld == pObjResourceOldX) {
  1496. if (nObjResourceX == -1) {
  1497. // we have to move back all the other section.
  1498. // the .rsrc1 is bigger than what we need
  1499. // adjust must be a negative number
  1500. if (pObjOld+1 < pObjLast) {
  1501. adjust -= (pObjOld+1)->VirtualAddress - pObjOld->VirtualAddress;
  1502. }
  1503. }
  1504. continue;
  1505. }
  1506. else if (pObjNew == pObjResourceNew) {
  1507. DPrintf((DebugBuf, "Resource Section %i\n", nObjResource+1));
  1508. cb = ROUNDUP(cbNew, New.OptionalHeader.FileAlignment);
  1509. if (pObjResourceOld == NULL) {
  1510. adjust = ROUNDUP(cbNew, New.OptionalHeader.SectionAlignment);
  1511. RtlZeroMemory(pObjNew, sizeof(IMAGE_SECTION_HEADER));
  1512. strcpy(pObjNew->Name, ".rsrc");
  1513. pObjNew->VirtualAddress = pObjOld->VirtualAddress;
  1514. pObjNew->PointerToRawData = pObjOld->PointerToRawData;
  1515. pObjNew->Characteristics = IMAGE_SCN_MEM_READ |
  1516. IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA;
  1517. pObjNew->SizeOfRawData = cb;
  1518. pObjNew->Misc.VirtualSize = ROUNDUP(cb, New.OptionalHeader.SectionAlignment);
  1519. }
  1520. else {
  1521. *pObjNew = *pObjOld; /* copy obj table entry */
  1522. pObjNew->SizeOfRawData = cb;
  1523. pObjNew->Misc.VirtualSize = ROUNDUP(cb, New.OptionalHeader.SectionAlignment);
  1524. if (pObjNew->SizeOfRawData == pObjOld->SizeOfRawData) {
  1525. adjust = 0;
  1526. }
  1527. else if (pObjNew->SizeOfRawData > pObjOld->SizeOfRawData) {
  1528. adjust += ROUNDUP(cbNew, New.OptionalHeader.SectionAlignment);
  1529. if (pObjOld+1 < pObjLast) {
  1530. // if there is more stuff after pObjOld, shift it as well
  1531. adjust -= ((pObjOld+1)->VirtualAddress-pObjOld->VirtualAddress);
  1532. }
  1533. }
  1534. else { /* is smaller, but pad so will be valid */
  1535. adjust = 0;
  1536. pObjNew->SizeOfRawData = pObjResourceOld->SizeOfRawData;
  1537. pObjNew->Misc.VirtualSize = ROUNDUP(pObjNew->SizeOfRawData, New.OptionalHeader.SectionAlignment);
  1538. /* don't need to set VirtualSize - will be the same */
  1539. cbMustPad = pObjResourceOld->SizeOfRawData;
  1540. }
  1541. }
  1542. pObjNew++;
  1543. if (pObjResourceOld == NULL)
  1544. goto rest_of_table;
  1545. }
  1546. else if (nObjResourceX != -1 && pObjNew == pObjtblNew + nObjResourceX) {
  1547. DPrintf((DebugBuf, "Additional Resource Section %i\n",
  1548. nObjResourceX+1));
  1549. RtlZeroMemory(pObjNew, sizeof(IMAGE_SECTION_HEADER));
  1550. strcpy(pObjNew->Name, ".rsrc1");
  1551. /*
  1552. * Before we copy the virtual address we have to move back the
  1553. * .reloc * virtual address. Otherwise we will keep moving the
  1554. * reloc VirtualAddress forward.
  1555. * We will have to move back the address of .rsrc1
  1556. */
  1557. if (pObjResourceOldX == NULL) {
  1558. // This is the first time we have a .rsrc1
  1559. pObjNew->VirtualAddress = pObjOld->VirtualAddress;
  1560. pObjNew->Characteristics = IMAGE_SCN_MEM_READ |
  1561. IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA;
  1562. adjust = ROUNDUP(cbResource, New.OptionalHeader.SectionAlignment) +
  1563. pObjResourceNew->VirtualAddress - pObjNew->VirtualAddress;
  1564. DPrintf((DebugBuf, "Added .rsrc1. VirtualAddress %lu\t adjust: %lu\n", pObjNew->VirtualAddress, adjust ));
  1565. }
  1566. else {
  1567. // we already have an .rsrc1 use the position of that and
  1568. // calculate the new adjust
  1569. pObjNew->VirtualAddress = pObjResourceOldX->VirtualAddress;
  1570. pObjNew->Characteristics = IMAGE_SCN_MEM_READ |
  1571. IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA;
  1572. DPrintf((DebugBuf, ".rsrc1 Keep old position.\t\tVirtualAddress %lu\t", pObjNew->VirtualAddress ));
  1573. // Check if we have enough room in the old .rsrc1
  1574. // Include the full size of the section, data + roundup
  1575. if (cbResource -
  1576. (pObjResourceOldX->VirtualAddress - pObjResourceOld->VirtualAddress) <=
  1577. pObjOld->VirtualAddress - pObjNew->VirtualAddress ) {
  1578. // we have to move back all the other section.
  1579. // the .rsrc1 is bigger than what we need
  1580. // adjust must be a negative number
  1581. // calc new adjust size
  1582. adjust = ROUNDUP(cbResource, New.OptionalHeader.SectionAlignment) +
  1583. pObjResourceNew->VirtualAddress -
  1584. pObjOld->VirtualAddress;
  1585. DPrintf((DebugBuf, "adjust: %ld\tsmall: New %lu\tOld %lu\n", adjust,
  1586. cbResource -
  1587. (pObjResourceOldX->VirtualAddress - pObjResourceOld->VirtualAddress),
  1588. pObjOld->VirtualAddress - pObjNew->VirtualAddress));
  1589. }
  1590. else {
  1591. // we have to move the section again.
  1592. // The .rsrc1 is too small
  1593. adjust = ROUNDUP(cbResource, New.OptionalHeader.SectionAlignment) +
  1594. pObjResourceNew->VirtualAddress -
  1595. pObjOld->VirtualAddress;
  1596. DPrintf((DebugBuf, "adjust: %lu\tsmall: New %lu\tOld %lu\n", adjust,
  1597. cbResource -
  1598. (pObjResourceOldX->VirtualAddress - pObjResourceOld->VirtualAddress),
  1599. pObjOld->VirtualAddress - pObjNew->VirtualAddress));
  1600. }
  1601. }
  1602. pObjNew++;
  1603. goto rest_of_table;
  1604. }
  1605. else if (pObjNew < pObjResourceNew) {
  1606. DPrintf((DebugBuf, "copying section table entry %i@%#08lx\n",
  1607. pObjOld - pObjtblOld + 1, pObjNew));
  1608. *pObjNew++ = *pObjOld; /* copy obj table entry */
  1609. }
  1610. else {
  1611. rest_of_table:
  1612. DPrintf((DebugBuf, "copying section table entry %i@%#08lx\n",
  1613. pObjOld - pObjtblOld + 1, pObjNew));
  1614. DPrintf((DebugBuf, "adjusting VirtualAddress by %#08lx\n", adjust));
  1615. *pObjNew++ = *pObjOld;
  1616. (pObjNew-1)->VirtualAddress += adjust;
  1617. }
  1618. }
  1619. pObjNew = pObjtblNew + New.FileHeader.NumberOfSections - 1;
  1620. New.OptionalHeader.SizeOfImage = ROUNDUP(pObjNew->VirtualAddress +
  1621. pObjNew->SizeOfRawData,
  1622. New.OptionalHeader.SectionAlignment);
  1623. /* allocate room to build the resource directory/tables in */
  1624. pResTab = (PIMAGE_RESOURCE_DIRECTORY)RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( RES_TAG ), cbRestab);
  1625. if (pResTab == NULL) {
  1626. cb = ERROR_NOT_ENOUGH_MEMORY;
  1627. goto AbortExit;
  1628. }
  1629. /* First, setup the "root" type directory table. It will be followed by */
  1630. /* Types directory entries. */
  1631. RtlZeroMemory((PVOID)pResTab, cbRestab);
  1632. DPrintf((DebugBuf, "resource directory tables: %#08lx bytes at %#08lx(mem)\n", cbRestab, pResTab));
  1633. p = (PUCHAR)pResTab;
  1634. pResTab->Characteristics = 0L;
  1635. pResTab->TimeDateStamp = clock;
  1636. pResTab->MajorVersion = MAJOR_RESOURCE_VERSION;
  1637. pResTab->MinorVersion = MINOR_RESOURCE_VERSION;
  1638. pResTab->NumberOfNamedEntries = (USHORT)cTypeStr;
  1639. pResTab->NumberOfIdEntries = (USHORT)(cTypes - cTypeStr);
  1640. /* Calculate the start of the various parts of the resource table. */
  1641. /* We need the start of the Type/Name/Language directories as well */
  1642. /* as the start of the UNICODE strings and the actual data nodes. */
  1643. pResDirT = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pResTab + 1);
  1644. pResDirN = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(((PUCHAR)pResDirT) +
  1645. cTypes * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
  1646. pResDirL = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(((PUCHAR)pResDirN) +
  1647. cTypes * sizeof(IMAGE_RESOURCE_DIRECTORY) +
  1648. cNames * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
  1649. pResData = (PIMAGE_RESOURCE_DATA_ENTRY)(((PUCHAR)pResDirL) +
  1650. cNames * sizeof(IMAGE_RESOURCE_DIRECTORY) +
  1651. cRes * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
  1652. pResStr = (PUSHORT)(((PUCHAR)pResData) +
  1653. cRes * sizeof(IMAGE_RESOURCE_DATA_ENTRY));
  1654. pResStrEnd = (PUSHORT)(((PUCHAR)pResStr) + cbName + cbType);
  1655. /*
  1656. * Loop over type table, building the PE resource table.
  1657. */
  1658. /*
  1659. * *****************************************************************
  1660. * This code doesn't sort the table - the TYPEINFO and RESINFO **
  1661. * insertion code in rcp.c (AddResType and SaveResFile) do the **
  1662. * insertion by ordinal type and name, so we don't have to sort **
  1663. * it at this point. **
  1664. * *****************************************************************
  1665. */
  1666. DPrintf((DebugBuf, "building resource directory\n"));
  1667. // First, add all the entries in the Types: Alpha list.
  1668. DPrintf((DebugBuf, "Walk the type: Alpha list\n"));
  1669. pType = pUpdate->ResTypeHeadName;
  1670. while (pType) {
  1671. DPrintf((DebugBuf, "resource type "));
  1672. DPrintfu((pType->Type->szStr));
  1673. DPrintfn((DebugBuf, "\n"));
  1674. pResDirT->Name = (ULONG)((((PUCHAR)pResStr) - p) |
  1675. IMAGE_RESOURCE_NAME_IS_STRING);
  1676. pResDirT->OffsetToData = (ULONG)((((PUCHAR)pResDirN) - p) |
  1677. IMAGE_RESOURCE_DATA_IS_DIRECTORY);
  1678. pResDirT++;
  1679. *pResStr = pType->Type->cbsz;
  1680. wcsncpy((WCHAR*)(pResStr+1), pType->Type->szStr, pType->Type->cbsz);
  1681. pResStr += pType->Type->cbsz + 1;
  1682. pResTabN = (PIMAGE_RESOURCE_DIRECTORY)pResDirN;
  1683. SetRestab(pResTabN, clock,
  1684. (USHORT)pType->NumberOfNamesName, (USHORT)pType->NumberOfNamesID);
  1685. pResDirN = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pResTabN + 1);
  1686. pPreviousName = NULL;
  1687. pRes = pType->NameHeadName;
  1688. while (pRes) {
  1689. DPrintf((DebugBuf, "resource "));
  1690. DPrintfu((pRes->Name->szStr));
  1691. DPrintfn((DebugBuf, "\n"));
  1692. if (pPreviousName == NULL ||
  1693. wcsncmp(pPreviousName->szStr,
  1694. pRes->Name->szStr,
  1695. pRes->Name->cbsz) != 0) {
  1696. // Setup a new name directory
  1697. pResDirN->Name = (ULONG)((((PUCHAR)pResStr)-p) |
  1698. IMAGE_RESOURCE_NAME_IS_STRING);
  1699. pResDirN->OffsetToData = (ULONG)((((PUCHAR)pResDirL)-p) |
  1700. IMAGE_RESOURCE_DATA_IS_DIRECTORY);
  1701. pResDirN++;
  1702. // Copy the alpha name to a string entry
  1703. *pResStr = pRes->Name->cbsz;
  1704. wcsncpy((WCHAR*)(pResStr+1),pRes->Name->szStr,pRes->Name->cbsz);
  1705. pResStr += pRes->Name->cbsz + 1;
  1706. pPreviousName = pRes->Name;
  1707. // Setup the Language table
  1708. pResTabL = (PIMAGE_RESOURCE_DIRECTORY)pResDirL;
  1709. SetRestab(pResTabL, clock,
  1710. (USHORT)0, (USHORT)pRes->NumberOfLanguages);
  1711. pResDirL = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pResTabL + 1);
  1712. }
  1713. // Setup a new Language directory
  1714. pResDirL->Name = pRes->LanguageId;
  1715. pResDirL->OffsetToData = (ULONG)(((PUCHAR)pResData) - p);
  1716. pResDirL++;
  1717. // Setup a new resource data entry
  1718. SetResdata(pResData,
  1719. pRes->OffsetToData+pObjtblNew[nObjResource].VirtualAddress,
  1720. pRes->DataSize);
  1721. pResData++;
  1722. pRes = pRes->pnext;
  1723. }
  1724. pPreviousName = NULL;
  1725. pRes = pType->NameHeadID;
  1726. while (pRes) {
  1727. DPrintf((DebugBuf, "resource %hu\n", pRes->Name->uu.Ordinal));
  1728. if (pPreviousName == NULL ||
  1729. pPreviousName->uu.Ordinal != pRes->Name->uu.Ordinal) {
  1730. // Setup the name directory to point to the next language
  1731. // table
  1732. pResDirN->Name = pRes->Name->uu.Ordinal;
  1733. pResDirN->OffsetToData = (ULONG)((((PUCHAR)pResDirL)-p) |
  1734. IMAGE_RESOURCE_DATA_IS_DIRECTORY);
  1735. pResDirN++;
  1736. pPreviousName = pRes->Name;
  1737. // Init a new Language table
  1738. pResTabL = (PIMAGE_RESOURCE_DIRECTORY)pResDirL;
  1739. SetRestab(pResTabL, clock,
  1740. (USHORT)0, (USHORT)pRes->NumberOfLanguages);
  1741. pResDirL = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pResTabL + 1);
  1742. }
  1743. // Setup a new language directory entry to point to the next
  1744. // resource
  1745. pResDirL->Name = pRes->LanguageId;
  1746. pResDirL->OffsetToData = (ULONG)(((PUCHAR)pResData) - p);
  1747. pResDirL++;
  1748. // Setup a new resource data entry
  1749. SetResdata(pResData,
  1750. pRes->OffsetToData+pObjtblNew[nObjResource].VirtualAddress,
  1751. pRes->DataSize);
  1752. pResData++;
  1753. pRes = pRes->pnext;
  1754. }
  1755. pType = pType->pnext;
  1756. }
  1757. // Do the same thing, but this time, use the Types: ID list.
  1758. DPrintf((DebugBuf, "Walk the type: ID list\n"));
  1759. pType = pUpdate->ResTypeHeadID;
  1760. while (pType) {
  1761. DPrintf((DebugBuf, "resource type %hu\n", pType->Type->uu.Ordinal));
  1762. pResDirT->Name = (ULONG)pType->Type->uu.Ordinal;
  1763. pResDirT->OffsetToData = (ULONG)((((PUCHAR)pResDirN) - p) |
  1764. IMAGE_RESOURCE_DATA_IS_DIRECTORY);
  1765. pResDirT++;
  1766. pResTabN = (PIMAGE_RESOURCE_DIRECTORY)pResDirN;
  1767. SetRestab(pResTabN, clock,
  1768. (USHORT)pType->NumberOfNamesName, (USHORT)pType->NumberOfNamesID);
  1769. pResDirN = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pResTabN + 1);
  1770. pPreviousName = NULL;
  1771. pRes = pType->NameHeadName;
  1772. while (pRes) {
  1773. DPrintf((DebugBuf, "resource "));
  1774. DPrintfu((pRes->Name->szStr));
  1775. DPrintfn((DebugBuf, "\n"));
  1776. if (pPreviousName == NULL ||
  1777. wcsncmp(pPreviousName->szStr,
  1778. pRes->Name->szStr,
  1779. pRes->Name->cbsz) != 0) {
  1780. // Setup a new name directory
  1781. pResDirN->Name = (ULONG)((((PUCHAR)pResStr)-p) |
  1782. IMAGE_RESOURCE_NAME_IS_STRING);
  1783. pResDirN->OffsetToData = (ULONG)((((PUCHAR)pResDirL)-p) |
  1784. IMAGE_RESOURCE_DATA_IS_DIRECTORY);
  1785. pResDirN++;
  1786. // Copy the alpha name to a string entry.
  1787. *pResStr = pRes->Name->cbsz;
  1788. wcsncpy((WCHAR*)(pResStr+1),pRes->Name->szStr,pRes->Name->cbsz);
  1789. pResStr += pRes->Name->cbsz + 1;
  1790. pPreviousName = pRes->Name;
  1791. // Setup the Language table
  1792. pResTabL = (PIMAGE_RESOURCE_DIRECTORY)pResDirL;
  1793. SetRestab(pResTabL, clock,
  1794. (USHORT)0, (USHORT)pRes->NumberOfLanguages);
  1795. pResDirL = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pResTabL + 1);
  1796. }
  1797. // Setup a new Language directory
  1798. pResDirL->Name = pRes->LanguageId;
  1799. pResDirL->OffsetToData = (ULONG)(((PUCHAR)pResData) - p);
  1800. pResDirL++;
  1801. // Setup a new resource data entry
  1802. SetResdata(pResData,
  1803. pRes->OffsetToData+pObjtblNew[nObjResource].VirtualAddress,
  1804. pRes->DataSize);
  1805. pResData++;
  1806. pRes = pRes->pnext;
  1807. }
  1808. pPreviousName = NULL;
  1809. pRes = pType->NameHeadID;
  1810. while (pRes) {
  1811. DPrintf((DebugBuf, "resource %hu\n", pRes->Name->uu.Ordinal));
  1812. if (pPreviousName == NULL ||
  1813. pPreviousName->uu.Ordinal != pRes->Name->uu.Ordinal) {
  1814. // Setup the name directory to point to the next language
  1815. // table
  1816. pResDirN->Name = pRes->Name->uu.Ordinal;
  1817. pResDirN->OffsetToData = (ULONG)((((PUCHAR)pResDirL)-p) |
  1818. IMAGE_RESOURCE_DATA_IS_DIRECTORY);
  1819. pResDirN++;
  1820. pPreviousName = pRes->Name;
  1821. // Init a new Language table
  1822. pResTabL = (PIMAGE_RESOURCE_DIRECTORY)pResDirL;
  1823. SetRestab(pResTabL, clock,
  1824. (USHORT)0, (USHORT)pRes->NumberOfLanguages);
  1825. pResDirL = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(pResTabL + 1);
  1826. }
  1827. // Setup a new language directory entry to point to the next
  1828. // resource
  1829. pResDirL->Name = pRes->LanguageId;
  1830. pResDirL->OffsetToData = (ULONG)(((PUCHAR)pResData) - p);
  1831. pResDirL++;
  1832. // Setup a new resource data entry
  1833. SetResdata(pResData,
  1834. pRes->OffsetToData+pObjtblNew[nObjResource].VirtualAddress,
  1835. pRes->DataSize);
  1836. pResData++;
  1837. pRes = pRes->pnext;
  1838. }
  1839. pType = pType->pnext;
  1840. }
  1841. DPrintf((DebugBuf, "Zeroing %u bytes after strings at %#08lx(mem)\n",
  1842. (pResStrEnd - pResStr) * sizeof(*pResStr), pResStr));
  1843. while (pResStr < pResStrEnd) {
  1844. *pResStr++ = 0;
  1845. }
  1846. #if DBG
  1847. {
  1848. USHORT j = 0;
  1849. PUSHORT pus = (PUSHORT)pResTab;
  1850. while (pus < (PUSHORT)pResData) {
  1851. DPrintf((DebugBuf, "%04x\t%04x %04x %04x %04x %04x %04x %04x %04x\n",
  1852. j,
  1853. *pus,
  1854. *(pus + 1),
  1855. *(pus + 2),
  1856. *(pus + 3),
  1857. *(pus + 4),
  1858. *(pus + 5),
  1859. *(pus + 6),
  1860. *(pus + 7)));
  1861. pus += 8;
  1862. j += 16;
  1863. }
  1864. }
  1865. #endif /* DBG */
  1866. /*
  1867. * copy the Old exe header and stub, and allocate room for the PE header.
  1868. */
  1869. DPrintf((DebugBuf, "copying through PE header: %#08lx bytes @0x0\n",
  1870. cbOldexe + sizeof(IMAGE_NT_HEADERS)));
  1871. MuMoveFilePos(inpfh, 0L);
  1872. MuCopy(inpfh, outfh, cbOldexe + sizeof(IMAGE_NT_HEADERS));
  1873. /*
  1874. * Copy rest of file header
  1875. */
  1876. DPrintf((DebugBuf, "skipping section table: %#08lx bytes @%#08lx\n",
  1877. New.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER),
  1878. FilePos(outfh)));
  1879. DPrintf((DebugBuf, "copying hdr data: %#08lx bytes @%#08lx ==> @%#08lx\n",
  1880. Old.OptionalHeader.SizeOfHeaders - ibObjTabEnd,
  1881. ibObjTabEnd,
  1882. ibObjTabEnd + New.OptionalHeader.SizeOfHeaders -
  1883. Old.OptionalHeader.SizeOfHeaders));
  1884. MuMoveFilePos(outfh, ibObjTabEnd + New.OptionalHeader.SizeOfHeaders -
  1885. Old.OptionalHeader.SizeOfHeaders);
  1886. MuMoveFilePos(inpfh, ibObjTabEnd);
  1887. MuCopy(inpfh, outfh, Old.OptionalHeader.SizeOfHeaders - ibObjTabEnd);
  1888. /*
  1889. * copy existing image sections
  1890. */
  1891. /* Align data sections on sector boundary */
  1892. cb = REMAINDER(New.OptionalHeader.SizeOfHeaders, New.OptionalHeader.FileAlignment);
  1893. New.OptionalHeader.SizeOfHeaders += cb;
  1894. /* [Inateeg update next 3 lines] */
  1895. // Zero out the Bound Import Descriptor slot (we don't care about it for now)
  1896. New.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
  1897. New.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
  1898. cb = pObjtblOld->PointerToRawData - FilePos(outfh);
  1899. DPrintf((DebugBuf, "padding header with %#08lx bytes @%#08lx\n", cb, FilePos(outfh)));
  1900. while (cb >= cbPadMax) {
  1901. MuWrite(outfh, pchZero, cbPadMax);
  1902. cb -= cbPadMax;
  1903. }
  1904. MuWrite(outfh, pchZero, cb);
  1905. cb = ROUNDUP(Old.OptionalHeader.SizeOfHeaders, Old.OptionalHeader.FileAlignment);
  1906. MuMoveFilePos(inpfh, cb);
  1907. /* copy one section at a time */
  1908. New.OptionalHeader.SizeOfInitializedData = 0;
  1909. for (pObjOld = pObjtblOld , pObjNew = pObjtblNew ;
  1910. pObjOld < pObjLast ;
  1911. pObjNew++) {
  1912. if (pObjOld == pObjResourceOldX)
  1913. pObjOld++;
  1914. if (pObjNew == pObjResourceNew) {
  1915. /* Write new resource section */
  1916. DPrintf((DebugBuf, "Primary resource section %i to %#08lx\n",
  1917. nObjResource+1, FilePos(outfh)));
  1918. pObjNew->PointerToRawData = FilePos(outfh);
  1919. New.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = pObjResourceNew->VirtualAddress;
  1920. New.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = cbResource;
  1921. ibSave = FilePos(outfh);
  1922. DPrintf((DebugBuf,
  1923. "writing resource header data: %#08lx bytes @%#08lx\n",
  1924. cbRestab, ibSave));
  1925. MuWrite(outfh, (PUCHAR)pResTab, cbRestab);
  1926. pResSave = WriteResSection(pUpdate, outfh,
  1927. New.OptionalHeader.FileAlignment,
  1928. pObjResourceNew->SizeOfRawData-cbRestab,
  1929. NULL);
  1930. cb = FilePos(outfh);
  1931. DPrintf((DebugBuf, "wrote resource data: %#08lx bytes @%#08lx\n",
  1932. cb - ibSave - cbRestab, ibSave + cbRestab));
  1933. if (cbMustPad != 0) {
  1934. cbMustPad -= cb - ibSave;
  1935. DPrintf((DebugBuf, "writing MUNGE pad: %#04lx bytes @%#08lx\n",
  1936. cbMustPad, cb));
  1937. /* assumes that cbMustPad % cbpadMax == 0 */
  1938. while (cbMustPad > 0) {
  1939. MuWrite(outfh, pchPad, cbPadMax);
  1940. cbMustPad -= cbPadMax;
  1941. }
  1942. cb = FilePos(outfh);
  1943. }
  1944. if (nObjResourceX == -1) {
  1945. MuMoveFilePos(outfh, ibSave);
  1946. DPrintf((DebugBuf,
  1947. "re-writing resource directory: %#08x bytes @%#08lx\n",
  1948. cbRestab, ibSave));
  1949. MuWrite(outfh, (PUCHAR)pResTab, cbRestab);
  1950. MuMoveFilePos(outfh, cb);
  1951. cb = FilePos(inpfh);
  1952. MuMoveFilePos(inpfh, cb+pObjOld->SizeOfRawData);
  1953. }
  1954. New.OptionalHeader.SizeOfInitializedData += pObjNew->SizeOfRawData;
  1955. if (pObjResourceOld == NULL) {
  1956. pObjNew++;
  1957. goto next_section;
  1958. }
  1959. else
  1960. pObjOld++;
  1961. }
  1962. else if (nObjResourceX != -1 && pObjNew == pObjtblNew + nObjResourceX) {
  1963. /* Write new resource section */
  1964. DPrintf((DebugBuf, "Secondary resource section %i @%#08lx\n",
  1965. nObjResourceX+1, FilePos(outfh)));
  1966. pObjNew->PointerToRawData = FilePos(outfh);
  1967. (void)WriteResSection(pUpdate, outfh,
  1968. New.OptionalHeader.FileAlignment, 0xffffffff, pResSave);
  1969. cb = FilePos(outfh);
  1970. pObjNew->SizeOfRawData = cb - pObjNew->PointerToRawData;
  1971. pObjNew->Misc.VirtualSize = ROUNDUP(pObjNew->SizeOfRawData, New.OptionalHeader.SectionAlignment);
  1972. DPrintf((DebugBuf, "wrote resource data: %#08lx bytes @%#08lx\n",
  1973. pObjNew->SizeOfRawData, pObjNew->PointerToRawData));
  1974. MuMoveFilePos(outfh, ibSave);
  1975. DPrintf((DebugBuf,
  1976. "re-writing resource directory: %#08x bytes @%#08lx\n",
  1977. cbRestab, ibSave));
  1978. MuWrite(outfh, (PUCHAR)pResTab, cbRestab);
  1979. MuMoveFilePos(outfh, cb);
  1980. New.OptionalHeader.SizeOfInitializedData += pObjNew->SizeOfRawData;
  1981. pObjNew++;
  1982. goto next_section;
  1983. }
  1984. else {
  1985. if (pObjNew < pObjResourceNew &&
  1986. pObjOld->PointerToRawData != 0 &&
  1987. pObjOld->PointerToRawData != FilePos(outfh)) {
  1988. MuMoveFilePos(outfh, pObjOld->PointerToRawData);
  1989. }
  1990. next_section:
  1991. /* Nop this section, because the author doesn't know what he's doing
  1992. if ((Old.OptionalHeader.BaseOfCode == 0x400) &&
  1993. (Old.FileHeader.Machine == IMAGE_FILE_MACHINE_R3000 ||
  1994. Old.FileHeader.Machine == IMAGE_FILE_MACHINE_R4000
  1995. ) &&
  1996. (pObjOld->PointerToRawData != 0) &&
  1997. (pObjOld->VirtualAddress != New.OptionalHeader.BaseOfCode) &&
  1998. ((pObjOld->Characteristics&IMAGE_SCN_CNT_CODE) != 0)
  1999. ) {
  2000. cb = FilePos(outfh) & 0xFFF;
  2001. if (cb != 0) {
  2002. cb = (cb ^ 0xFFF) + 1;
  2003. DPrintf((DebugBuf, "padding driver code section %#08lx bytes @%#08lx\n", cb, FilePos(outfh)));
  2004. while (cb >= cbPadMax) {
  2005. MuWrite(outfh, pchZero, cbPadMax);
  2006. cb -= cbPadMax;
  2007. }
  2008. MuWrite(outfh, pchZero, cb);
  2009. }
  2010. }
  2011. End nop. */
  2012. DPrintf((DebugBuf, "copying section %i @%#08lx\n",
  2013. pObjNew-pObjtblNew+1, FilePos(outfh)));
  2014. if (pObjOld->PointerToRawData != 0) {
  2015. pObjNew->PointerToRawData = FilePos(outfh);
  2016. MuMoveFilePos(inpfh, pObjOld->PointerToRawData);
  2017. MuCopy(inpfh, outfh, pObjOld->SizeOfRawData);
  2018. }
  2019. if (pObjOld == pObjDebugDirOld) {
  2020. pObjDebugDirNew = pObjNew;
  2021. }
  2022. if ((pObjNew->Characteristics&IMAGE_SCN_CNT_INITIALIZED_DATA) != 0)
  2023. New.OptionalHeader.SizeOfInitializedData +=
  2024. pObjNew->SizeOfRawData;
  2025. pObjOld++;
  2026. }
  2027. }
  2028. if (pObjResourceOldX != NULL)
  2029. New.OptionalHeader.SizeOfInitializedData -=
  2030. pObjResourceOldX->SizeOfRawData;
  2031. /* Update the address of the relocation table */
  2032. pObjNew = FindSection(pObjtblNew,
  2033. pObjtblNew+New.FileHeader.NumberOfSections,
  2034. ".reloc");
  2035. if (pObjNew != NULL) {
  2036. New.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = pObjNew->VirtualAddress;
  2037. }
  2038. /*
  2039. * Write new section table out.
  2040. */
  2041. DPrintf((DebugBuf, "Writing new section table: %#08x bytes @%#08lx\n",
  2042. New.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER),
  2043. ibObjTab));
  2044. MuMoveFilePos(outfh, ibObjTab);
  2045. MuWrite(outfh, (PUCHAR)pObjtblNew, New.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER));
  2046. /* Seek to end of output file and issue truncating write */
  2047. adjust = _llseek(outfh, 0L, SEEK_END);
  2048. MuWrite(outfh, NULL, 0);
  2049. DPrintf((DebugBuf, "File size is: %#08lx\n", adjust));
  2050. /* If a debug section, fix up the debug table */
  2051. pObjNew = FindSection(pObjtblNew,
  2052. pObjtblNew+New.FileHeader.NumberOfSections,
  2053. ".debug");
  2054. cb = PatchDebug(inpfh, outfh,
  2055. pObjDebug, pObjNew,
  2056. pObjDebugDirOld, pObjDebugDirNew,
  2057. &Old, &New, ibMaxDbgOffsetOld, &adjust);
  2058. if (cb == NO_ERROR) {
  2059. if (pObjResourceOld == NULL) {
  2060. cb = (LONG)pObjResourceNew->SizeOfRawData;
  2061. }
  2062. else {
  2063. cb = (LONG)pObjResourceOld->SizeOfRawData -
  2064. (LONG)pObjResourceNew->SizeOfRawData;
  2065. }
  2066. cb = PatchRVAs(inpfh, outfh, pObjtblNew, cb,
  2067. &New, Old.OptionalHeader.SizeOfHeaders);
  2068. }
  2069. /* copy NOTMAPPED debug info */
  2070. if (pObjDebugDirOld != NULL && pObjDebug == NULL &&
  2071. New.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size
  2072. != 0) {
  2073. if (New.FileHeader.PointerToSymbolTable != 0)
  2074. New.FileHeader.PointerToSymbolTable = adjust; /* update symbol table ptr */
  2075. ibSave = _llseek(inpfh, 0L, SEEK_END); /* copy debug data */
  2076. _llseek(outfh, 0L, SEEK_END); /* to EOF */
  2077. MuMoveFilePos(inpfh, adjust); /* returned by PatchDebug */
  2078. DPrintf((DebugBuf, "Copying NOTMAPPED Debug Information, %#08lx bytes\n", ibSave-adjust));
  2079. MuCopy(inpfh, outfh, ibSave-adjust);
  2080. }
  2081. /*
  2082. * Write updated PE header
  2083. */
  2084. DPrintf((DebugBuf, "Writing updated file header: %#08x bytes @%#08lx\n",
  2085. sizeof(IMAGE_NT_HEADERS),
  2086. cbOldexe));
  2087. MuMoveFilePos(outfh, (long)cbOldexe);
  2088. MuWrite(outfh, (char*)&New, sizeof(IMAGE_NT_HEADERS));
  2089. /* free up allocated memory */
  2090. DPrintf((DebugBuf, "Freeing old section table: %#08lx(mem)\n", pObjtblOld));
  2091. RtlFreeHeap(RtlProcessHeap(), 0, pObjtblOld);
  2092. DPrintf((DebugBuf, "Freeing resource directory: %#08lx(mem)\n", pResTab));
  2093. RtlFreeHeap(RtlProcessHeap(), 0, pResTab);
  2094. AbortExit:
  2095. DPrintf((DebugBuf, "Freeing new section table: %#08lx(mem)\n", pObjtblNew));
  2096. RtlFreeHeap(RtlProcessHeap(), 0, pObjtblNew);
  2097. return cb;
  2098. }
  2099. /***************************************************************************
  2100. * WriteResSection
  2101. *
  2102. * This routine writes out the resources asked for into the current section.
  2103. * It pads resources to dword (4-byte) boundaries.
  2104. **************************************************************************/
  2105. PRESNAME
  2106. WriteResSection(
  2107. PUPDATEDATA pUpdate,
  2108. INT outfh,
  2109. ULONG align,
  2110. ULONG cbLeft,
  2111. PRESNAME pResSave
  2112. )
  2113. {
  2114. ULONG cbB=0; /* bytes in current section */
  2115. ULONG cbT; /* bytes in current section */
  2116. ULONG size;
  2117. PRESNAME pRes;
  2118. PRESTYPE pType;
  2119. BOOL fName;
  2120. PVOID lpData;
  2121. /* Output contents associated with each resource */
  2122. pType = pUpdate->ResTypeHeadName;
  2123. while (pType) {
  2124. pRes = pType->NameHeadName;
  2125. fName = TRUE;
  2126. loop1:
  2127. for ( ; pRes ; pRes = pRes->pnext) {
  2128. if (pResSave != NULL && pRes != pResSave)
  2129. continue;
  2130. pResSave = NULL;
  2131. #if DBG
  2132. if (pType->Type->discriminant == IS_STRING) {
  2133. DPrintf((DebugBuf, " "));
  2134. DPrintfu((pType->Type->szStr));
  2135. DPrintfn((DebugBuf, "."));
  2136. }
  2137. else {
  2138. DPrintf(( DebugBuf, " %d.", pType->Type->uu.Ordinal ));
  2139. }
  2140. if (pRes->Name->discriminant == IS_STRING) {
  2141. DPrintfu((pRes->Name->szStr));
  2142. }
  2143. else {
  2144. DPrintfn(( DebugBuf, "%d", pRes->Name->uu.Ordinal ));
  2145. }
  2146. #endif
  2147. lpData = (PVOID)pRes->OffsetToDataEntry;
  2148. DPrintfn((DebugBuf, "\n"));
  2149. /* if there is room in the current section, write it there */
  2150. size = pRes->DataSize;
  2151. if (cbLeft != 0 && cbLeft >= size) { /* resource fits? */
  2152. DPrintf((DebugBuf,
  2153. "Writing resource: %#04lx bytes @%#08lx\n",
  2154. size, FilePos(outfh)));
  2155. MuWrite(outfh, lpData, size);
  2156. /* pad resource */
  2157. cbT = REMAINDER(size, CBLONG);
  2158. #ifdef DBG
  2159. if (cbT != 0)
  2160. DPrintf((DebugBuf,
  2161. "Writing small pad: %#04lx bytes @%#08lx\n",
  2162. cbT, FilePos(outfh)));
  2163. #endif
  2164. MuWrite(outfh, pchPad, cbT); /* dword */
  2165. cbB += size + cbT;
  2166. cbLeft -= size + cbT; /* less left */
  2167. continue; /* next resource */
  2168. }
  2169. else { /* will fill up section */
  2170. DPrintf((DebugBuf, "Done with .rsrc section\n"));
  2171. goto write_pad;
  2172. }
  2173. }
  2174. if (fName) {
  2175. fName = FALSE;
  2176. pRes = pType->NameHeadID;
  2177. goto loop1;
  2178. }
  2179. pType = pType->pnext;
  2180. }
  2181. pType = pUpdate->ResTypeHeadID;
  2182. while (pType) {
  2183. pRes = pType->NameHeadName;
  2184. fName = TRUE;
  2185. loop2:
  2186. for ( ; pRes ; pRes = pRes->pnext) {
  2187. if (pResSave != NULL && pRes != pResSave)
  2188. continue;
  2189. pResSave = NULL;
  2190. #if DBG
  2191. if (pType->Type->discriminant == IS_STRING) {
  2192. DPrintf((DebugBuf, " "));
  2193. DPrintfu((pType->Type->szStr));
  2194. DPrintfn((DebugBuf, "."));
  2195. }
  2196. else {
  2197. DPrintf(( DebugBuf, " %d.", pType->Type->uu.Ordinal ));
  2198. }
  2199. if (pRes->Name->discriminant == IS_STRING) {
  2200. DPrintfu((pRes->Name->szStr));
  2201. }
  2202. else {
  2203. DPrintfn(( DebugBuf, "%d", pRes->Name->uu.Ordinal ));
  2204. }
  2205. #endif
  2206. lpData = (PVOID)pRes->OffsetToDataEntry;
  2207. DPrintfn((DebugBuf, "\n"));
  2208. /* if there is room in the current section, write it there */
  2209. size = pRes->DataSize;
  2210. if (cbLeft != 0 && cbLeft >= size) { /* resource fits? */
  2211. DPrintf((DebugBuf,
  2212. "Writing resource: %#04lx bytes @%#08lx\n",
  2213. size, FilePos(outfh)));
  2214. MuWrite(outfh, lpData, size);
  2215. /* pad resource */
  2216. cbT = REMAINDER(size, CBLONG);
  2217. #ifdef DBG
  2218. if (cbT != 0)
  2219. DPrintf((DebugBuf,
  2220. "Writing small pad: %#04lx bytes @%#08lx\n",
  2221. cbT, FilePos(outfh)));
  2222. #endif
  2223. MuWrite(outfh, pchPad, cbT); /* dword */
  2224. cbB += size + cbT;
  2225. cbLeft -= size + cbT; /* less left */
  2226. continue; /* next resource */
  2227. }
  2228. else { /* will fill up section */
  2229. DPrintf((DebugBuf, "Done with .rsrc section\n"));
  2230. goto write_pad;
  2231. }
  2232. }
  2233. if (fName) {
  2234. fName = FALSE;
  2235. pRes = pType->NameHeadID;
  2236. goto loop2;
  2237. }
  2238. pType = pType->pnext;
  2239. }
  2240. pRes = NULL;
  2241. write_pad:
  2242. /* pad to alignment boundary */
  2243. cbB = FilePos(outfh);
  2244. cbT = ROUNDUP(cbB, align);
  2245. cbLeft = cbT - cbB;
  2246. DPrintf((DebugBuf, "Writing file sector pad: %#04lx bytes @%#08lx\n",
  2247. cbLeft, FilePos(outfh)));
  2248. if (cbLeft != 0) {
  2249. while (cbLeft >= cbPadMax) {
  2250. MuWrite(outfh, pchPad, cbPadMax);
  2251. cbLeft -= cbPadMax;
  2252. }
  2253. MuWrite(outfh, pchPad, cbLeft);
  2254. }
  2255. return pRes;
  2256. }
  2257. #if DBG
  2258. void
  2259. wchprintf(WCHAR*wch)
  2260. {
  2261. UNICODE_STRING ustring;
  2262. STRING string;
  2263. char buf[257];
  2264. ustring.MaximumLength = ustring.Length = wcslen(wch) * sizeof(WCHAR);
  2265. ustring.Buffer = wch;
  2266. string.Length = 0;
  2267. string.MaximumLength = 256;
  2268. string.Buffer = buf;
  2269. RtlUnicodeStringToAnsiString(&string, &ustring, FALSE);
  2270. buf[string.Length] = '\000';
  2271. DPrintfn((DebugBuf, "%s", buf));
  2272. }
  2273. #endif
  2274. //
  2275. // adjust debug directory table
  2276. //
  2277. /* */
  2278. LONG
  2279. PatchDebug(int inpfh,
  2280. int outfh,
  2281. PIMAGE_SECTION_HEADER pDebugOld,
  2282. PIMAGE_SECTION_HEADER pDebugNew,
  2283. PIMAGE_SECTION_HEADER pDebugDirOld,
  2284. PIMAGE_SECTION_HEADER pDebugDirNew,
  2285. PIMAGE_NT_HEADERS pOld,
  2286. PIMAGE_NT_HEADERS pNew,
  2287. ULONG ibMaxDbgOffsetOld,
  2288. PULONG pPointerToRawData)
  2289. {
  2290. PIMAGE_DEBUG_DIRECTORY pDbgLast;
  2291. PIMAGE_DEBUG_DIRECTORY pDbgSave;
  2292. PIMAGE_DEBUG_DIRECTORY pDbg;
  2293. ULONG ib;
  2294. ULONG adjust;
  2295. ULONG ibNew;
  2296. if (pDebugDirOld == NULL ||
  2297. pNew->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size==0)
  2298. return NO_ERROR;
  2299. pDbgSave = pDbg = (PIMAGE_DEBUG_DIRECTORY)RtlAllocateHeap(
  2300. RtlProcessHeap(), MAKE_TAG( RES_TAG ),
  2301. pNew->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size);
  2302. if (pDbg == NULL)
  2303. return ERROR_NOT_ENOUGH_MEMORY;
  2304. if (pDebugOld) {
  2305. DPrintf((DebugBuf, "Patching dbg directory: @%#08lx ==> @%#08lx\n",
  2306. pDebugOld->PointerToRawData, pDebugNew->PointerToRawData));
  2307. }
  2308. else
  2309. adjust = *pPointerToRawData; /* passed in EOF of new file */
  2310. ib = pOld->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress - pDebugDirOld->VirtualAddress;
  2311. MuMoveFilePos(inpfh, pDebugDirOld->PointerToRawData+ib);
  2312. pDbgLast = pDbg + (pNew->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size)/sizeof(IMAGE_DEBUG_DIRECTORY);
  2313. MuRead(inpfh, (PUCHAR)pDbg, pNew->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size);
  2314. if (pDebugOld == NULL) {
  2315. /* find 1st entry - use for offset */
  2316. DPrintf((DebugBuf, "Adjust: %#08lx\n",adjust));
  2317. for (ibNew=0xffffffff ; pDbg<pDbgLast ; pDbg++)
  2318. if (pDbg->PointerToRawData >= ibMaxDbgOffsetOld &&
  2319. pDbg->PointerToRawData < ibNew
  2320. )
  2321. ibNew = pDbg->PointerToRawData;
  2322. if (ibNew != 0xffffffff)
  2323. *pPointerToRawData = ibNew;
  2324. else
  2325. *pPointerToRawData = _llseek(inpfh, 0L, SEEK_END);
  2326. for (pDbg=pDbgSave ; pDbg<pDbgLast ; pDbg++) {
  2327. DPrintf((DebugBuf, "Old debug file offset: %#08lx\n",
  2328. pDbg->PointerToRawData));
  2329. if (pDbg->PointerToRawData >= ibMaxDbgOffsetOld)
  2330. pDbg->PointerToRawData += adjust - ibNew;
  2331. DPrintf((DebugBuf, "New debug file offset: %#08lx\n",
  2332. pDbg->PointerToRawData));
  2333. }
  2334. }
  2335. else {
  2336. for ( ; pDbg<pDbgLast ; pDbg++) {
  2337. DPrintf((DebugBuf, "Old debug addr: %#08lx, file offset: %#08lx\n",
  2338. pDbg->AddressOfRawData,
  2339. pDbg->PointerToRawData));
  2340. pDbg->AddressOfRawData += pDebugNew->VirtualAddress -
  2341. pDebugOld->VirtualAddress;
  2342. pDbg->PointerToRawData += pDebugNew->PointerToRawData -
  2343. pDebugOld->PointerToRawData;
  2344. DPrintf((DebugBuf, "New debug addr: %#08lx, file offset: %#08lx\n",
  2345. pDbg->AddressOfRawData,
  2346. pDbg->PointerToRawData));
  2347. }
  2348. }
  2349. MuMoveFilePos(outfh, pDebugDirNew->PointerToRawData+ib);
  2350. MuWrite(outfh, (PUCHAR)pDbgSave, pNew->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size);
  2351. RtlFreeHeap(RtlProcessHeap(), 0, pDbgSave);
  2352. return NO_ERROR;
  2353. }
  2354. //
  2355. // This routine patches various RVAs in the file to compensate
  2356. // for extra section table entries.
  2357. //
  2358. LONG
  2359. PatchRVAs(int inpfh,
  2360. int outfh,
  2361. PIMAGE_SECTION_HEADER po32,
  2362. ULONG pagedelta,
  2363. PIMAGE_NT_HEADERS pNew,
  2364. ULONG OldSize)
  2365. {
  2366. ULONG hdrdelta;
  2367. ULONG offset, rvaiat, offiat, iat;
  2368. IMAGE_EXPORT_DIRECTORY Exp;
  2369. IMAGE_IMPORT_DESCRIPTOR Imp;
  2370. ULONG i, cmod, cimp;
  2371. hdrdelta = pNew->OptionalHeader.SizeOfHeaders - OldSize;
  2372. if (hdrdelta == 0) {
  2373. return NO_ERROR;
  2374. }
  2375. //
  2376. // Patch export section RVAs
  2377. //
  2378. DPrintf((DebugBuf, "Export offset=%08lx, hdrsize=%08lx\n",
  2379. pNew->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress,
  2380. pNew->OptionalHeader.SizeOfHeaders));
  2381. if ((offset = pNew->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) == 0)
  2382. {
  2383. DPrintf((DebugBuf, "No exports to patch\n"));
  2384. }
  2385. else if (offset >= pNew->OptionalHeader.SizeOfHeaders)
  2386. {
  2387. DPrintf((DebugBuf, "No exports in header to patch\n"));
  2388. }
  2389. else
  2390. {
  2391. MuMoveFilePos(inpfh, offset - hdrdelta);
  2392. MuRead(inpfh, (PUCHAR) &Exp, sizeof(Exp));
  2393. Exp.Name += hdrdelta;
  2394. (ULONG)Exp.AddressOfFunctions += hdrdelta;
  2395. (ULONG)Exp.AddressOfNames += hdrdelta;
  2396. (ULONG)Exp.AddressOfNameOrdinals += hdrdelta;
  2397. MuMoveFilePos(outfh, offset);
  2398. MuWrite(outfh, (PUCHAR) &Exp, sizeof(Exp));
  2399. }
  2400. //
  2401. // Patch import section RVAs
  2402. //
  2403. DPrintf((DebugBuf, "Import offset=%08lx, hdrsize=%08lx\n",
  2404. pNew->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,
  2405. pNew->OptionalHeader.SizeOfHeaders));
  2406. if ((offset = pNew->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress) == 0)
  2407. {
  2408. DPrintf((DebugBuf, "No imports to patch\n"));
  2409. }
  2410. else if (offset >= pNew->OptionalHeader.SizeOfHeaders)
  2411. {
  2412. DPrintf((DebugBuf, "No imports in header to patch\n"));
  2413. }
  2414. else
  2415. {
  2416. for (cimp = cmod = 0; ; cmod++)
  2417. {
  2418. MuMoveFilePos(inpfh, offset + cmod * sizeof(Imp) - hdrdelta);
  2419. MuRead(inpfh, (PUCHAR) &Imp, sizeof(Imp));
  2420. if (Imp.FirstThunk == 0)
  2421. {
  2422. break;
  2423. }
  2424. Imp.Name += hdrdelta;
  2425. MuMoveFilePos(outfh, offset + cmod * sizeof(Imp));
  2426. MuWrite(outfh, (PUCHAR) &Imp, sizeof(Imp));
  2427. rvaiat = (ULONG)Imp.FirstThunk;
  2428. DPrintf((DebugBuf, "RVAIAT = %#08lx\n", (ULONG)rvaiat));
  2429. for (i = 0; i < pNew->FileHeader.NumberOfSections; i++) {
  2430. if (rvaiat >= po32[i].VirtualAddress &&
  2431. rvaiat < po32[i].VirtualAddress + po32[i].SizeOfRawData) {
  2432. offiat = rvaiat - po32[i].VirtualAddress + po32[i].PointerToRawData;
  2433. goto found;
  2434. }
  2435. }
  2436. DPrintf((DebugBuf, "IAT not found\n"));
  2437. return ERROR_INVALID_DATA;
  2438. found:
  2439. DPrintf((DebugBuf, "IAT offset: @%#08lx ==> @%#08lx\n",
  2440. offiat - pagedelta,
  2441. offiat));
  2442. MuMoveFilePos(inpfh, offiat - pagedelta);
  2443. MuMoveFilePos(outfh, offiat);
  2444. for (;;) {
  2445. MuRead(inpfh, (PUCHAR) &iat, sizeof(iat));
  2446. if (iat == 0) {
  2447. break;
  2448. }
  2449. if ((iat & IMAGE_ORDINAL_FLAG) == 0) { // if import by name
  2450. DPrintf((DebugBuf, "Patching IAT: %08lx + %04lx ==> %08lx\n",
  2451. iat,
  2452. hdrdelta,
  2453. iat + hdrdelta));
  2454. iat += hdrdelta;
  2455. cimp++;
  2456. }
  2457. MuWrite(outfh, (PUCHAR) &iat, sizeof(iat)); // Avoids seeking
  2458. }
  2459. }
  2460. DPrintf((DebugBuf, "%u import module name RVAs patched\n", cmod));
  2461. DPrintf((DebugBuf, "%u IAT name RVAs patched\n", cimp));
  2462. if (cmod == 0)
  2463. {
  2464. DPrintf((DebugBuf, "No import modules to patch\n"));
  2465. }
  2466. if (cimp == 0)
  2467. {
  2468. DPrintf((DebugBuf, "No import name RVAs to patch\n"));
  2469. }
  2470. }
  2471. return NO_ERROR;
  2472. }
  2473. /*---------------------------------------------------------------------------*/
  2474. /* */
  2475. /* RecalcChecksum(CHAR *pszFile) */
  2476. /* */
  2477. /* Generates a correct checksum for pszFile. Returns TRUE for success */
  2478. /* */
  2479. /*---------------------------------------------------------------------------*/
  2480. BOOL RecalcChecksum(CHAR *pszFile)
  2481. {
  2482. BOOL fSuccess = FALSE;
  2483. HANDLE hFile = CreateFile(pszFile, GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  2484. if (hFile)
  2485. {
  2486. BY_HANDLE_FILE_INFORMATION fi;
  2487. // We only do this for files smaller than 2^32-1 bytes
  2488. if (GetFileInformationByHandle(hFile, &fi) && (0 == fi.nFileSizeHigh))
  2489. {
  2490. HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
  2491. if (hMapping)
  2492. {
  2493. LPVOID pvView = MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, 0);
  2494. if (pvView)
  2495. {
  2496. DWORD dwCheckCurrent;
  2497. DWORD dwCheckNew;
  2498. PIMAGE_NT_HEADERS pih = CheckSumMappedFile(pvView, fi.nFileSizeLow, &dwCheckCurrent, &dwCheckNew);
  2499. if (pih)
  2500. {
  2501. pih->OptionalHeader.CheckSum = dwCheckNew;
  2502. fSuccess = TRUE;
  2503. }
  2504. UnmapViewOfFile(pvView);
  2505. }
  2506. CloseHandle(hMapping);
  2507. }
  2508. }
  2509. CloseHandle(hFile);
  2510. }
  2511. return fSuccess;
  2512. }
  2513. /*---------------------------------------------------------------------------*/
  2514. /* */
  2515. /* WriteResFile() - */
  2516. /* */
  2517. /*---------------------------------------------------------------------------*/
  2518. LONG
  2519. WriteResFile(
  2520. HANDLE hUpdate,
  2521. CHAR *pDstname)
  2522. {
  2523. HANDLE inh;
  2524. HANDLE outh;
  2525. INT inpfh;
  2526. INT outfh;
  2527. ULONG onewexe;
  2528. IMAGE_DOS_HEADER oldexe;
  2529. PUPDATEDATA pUpdate;
  2530. INT rc;
  2531. CHAR *pFilename;
  2532. pUpdate = (PUPDATEDATA)GlobalLock(hUpdate);
  2533. pFilename = (CHAR*)GlobalLock(pUpdate->hFileName);
  2534. /* open the original exe file */
  2535. inh = CreateFile(pFilename, GENERIC_READ, 0 /*exclusive access*/, NULL /* security attr */, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  2536. GlobalUnlock(pUpdate->hFileName);
  2537. if ( inh == INVALID_HANDLE_VALUE ) {
  2538. GlobalUnlock(hUpdate);
  2539. return ERROR_OPEN_FAILED;
  2540. }
  2541. inpfh = (INT)HandleToLong(inh);
  2542. /* read the old format EXE header */
  2543. rc = _lread(inpfh, (char*)&oldexe, sizeof(oldexe));
  2544. if (rc != sizeof(oldexe)) {
  2545. _lclose(inpfh);
  2546. GlobalUnlock(hUpdate);
  2547. return ERROR_READ_FAULT;
  2548. }
  2549. /* make sure its really an EXE file */
  2550. if (oldexe.e_magic != IMAGE_DOS_SIGNATURE) {
  2551. _lclose(inpfh);
  2552. GlobalUnlock(hUpdate);
  2553. return ERROR_INVALID_EXE_SIGNATURE;
  2554. }
  2555. /* make sure theres a new EXE header floating around somewhere */
  2556. if (!(onewexe = oldexe.e_lfanew)) {
  2557. _lclose(inpfh);
  2558. GlobalUnlock(hUpdate);
  2559. return ERROR_BAD_EXE_FORMAT;
  2560. }
  2561. outh = CreateFile(pDstname, GENERIC_READ|GENERIC_WRITE, 0 /*exclusive access*/, NULL /* security attr */, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  2562. if (outh != INVALID_HANDLE_VALUE ) {
  2563. outfh = (INT)HandleToLong(outh);
  2564. rc = PEWriteResFile(inpfh, outfh, onewexe, pUpdate);
  2565. _lclose(outfh);
  2566. }
  2567. _lclose(inpfh);
  2568. /* Fix up the checksum for the destination file */
  2569. RecalcChecksum(pDstname);
  2570. GlobalUnlock(hUpdate);
  2571. return rc;
  2572. }