Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2749 lines
79 KiB

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