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.

1196 lines
38 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // File: win32.cpp
  4. //
  5. // Contents: Implementation for the Windows 32 Read/Write module
  6. //
  7. // Classes: one
  8. //
  9. // History: 05-Jul-93 alessanm created
  10. //
  11. //----------------------------------------------------------------------------
  12. #include <afxwin.h>
  13. #include "..\common\rwdll.h"
  14. #include "..\common\rw32hlpr.h"
  15. #include <limits.h>
  16. #include <malloc.h>
  17. /////////////////////////////////////////////////////////////////////////////
  18. // Initialization of MFC Extension DLL
  19. #include "afxdllx.h" // standard MFC Extension DLL routines
  20. static AFX_EXTENSION_MODULE NEAR extensionDLL = { NULL, NULL };
  21. /////////////////////////////////////////////////////////////////////////////
  22. // Check sum function
  23. DWORD FixCheckSum( LPCSTR ImageName, LPCSTR OrigFileName, LPCSTR SymbolPath );
  24. /////////////////////////////////////////////////////////////////////////////
  25. // General Declarations
  26. #define RWTAG "WIN32"
  27. static RESSECTDATA ResSectData;
  28. static ULONG gType;
  29. static ULONG gLng;
  30. static ULONG gResId;
  31. static WCHAR gwszResId[256];
  32. static WCHAR gwszTypeId[256];
  33. /////////////////////////////////////////////////////////////////////////////
  34. // Function Declarations
  35. static LONG WriteResInfo(
  36. LPLPBYTE lpBuf, LONG* uiBufSize,
  37. WORD wTypeId, LPSTR lpszTypeId, BYTE bMaxTypeLen,
  38. WORD wNameId, LPSTR lpszNameId, BYTE bMaxNameLen,
  39. DWORD dwLang,
  40. DWORD dwSize, DWORD dwFileOffset );
  41. static UINT GetUpdatedRes(
  42. BYTE far * far* lplpBuffer,
  43. UINT* uiSize,
  44. WORD* wTypeId, LPSTR lplpszTypeId,
  45. WORD* wNameId, LPSTR lplpszNameId,
  46. DWORD* dwlang, DWORD* dwSize );
  47. static UINT GetRes(
  48. BYTE far * far* lplpBuffer,
  49. UINT* puiBufSize,
  50. WORD* wTypeId, LPSTR lplpszTypeId,
  51. WORD* wNameId, LPSTR lplpszNameId,
  52. DWORD* dwLang, DWORD* dwSize, DWORD* dwFileOffset );
  53. static UINT FindResourceSection( CFile*, ULONG_PTR * );
  54. static LONG ReadFile(CFile*, UCHAR *, LONG);
  55. static UINT ParseDirectory( CFile*,
  56. LPLPBYTE lpBuf, UINT* uiBufSize,
  57. BYTE,
  58. PIMAGE_RESOURCE_DIRECTORY,
  59. PIMAGE_RESOURCE_DIRECTORY );
  60. static UINT ParseDirectoryEntry( CFile*,
  61. LPLPBYTE lpBuf, UINT* uiBufSize,
  62. BYTE,
  63. PIMAGE_RESOURCE_DIRECTORY,
  64. PIMAGE_RESOURCE_DIRECTORY_ENTRY );
  65. static UINT ParseSubDir( CFile*,
  66. LPLPBYTE lpBuf, UINT* uiBufSize,
  67. BYTE,
  68. PIMAGE_RESOURCE_DIRECTORY,
  69. PIMAGE_RESOURCE_DIRECTORY_ENTRY );
  70. static UINT ProcessData( CFile*,
  71. LPLPBYTE lpBuf, UINT* uiBufSize,
  72. PIMAGE_RESOURCE_DIRECTORY,
  73. PIMAGE_RESOURCE_DATA_ENTRY );
  74. /////////////////////////////////////////////////////////////////////////////
  75. // Public C interface implementation
  76. //[registration]
  77. extern "C"
  78. BOOL FAR PASCAL RWGetTypeString(LPSTR lpszTypeName)
  79. {
  80. strcpy( lpszTypeName, RWTAG );
  81. return FALSE;
  82. }
  83. extern "C"
  84. BOOL FAR PASCAL RWValidateFileType (LPCSTR lpszFilename)
  85. {
  86. TRACE("WIN32.DLL: RWValidateFileType()\n");
  87. CFile file;
  88. // we Open the file to see if it is a file we can handle
  89. if (!file.Open( lpszFilename, CFile::typeBinary | CFile::modeRead | CFile::shareDenyNone))
  90. return FALSE;
  91. // Read the file signature
  92. WORD w;
  93. file.Read((WORD*)&w, sizeof(WORD));
  94. if (w==IMAGE_DOS_SIGNATURE) {
  95. file.Seek( 0x18, CFile::begin );
  96. file.Read((WORD*)&w, sizeof(WORD));
  97. if (w<0x0040) {
  98. // this is not a Windows Executable
  99. file.Close();
  100. return FALSE;
  101. }
  102. // get offset to header
  103. file.Seek( 0x3c, CFile::begin );
  104. file.Read((WORD*)&w, sizeof(WORD));
  105. // get windows magic word
  106. file.Seek( w, CFile::begin );
  107. file.Read((WORD*)&w, sizeof(WORD));
  108. if (w==LOWORD(IMAGE_NT_SIGNATURE)) {
  109. file.Read((WORD*)&w, sizeof(WORD));
  110. if (w==HIWORD(IMAGE_NT_SIGNATURE)) {
  111. // this is a Windows NT Executable
  112. // we can handle the situation
  113. file.Close();
  114. return TRUE;
  115. }
  116. }
  117. }
  118. file.Close();
  119. return FALSE;
  120. }
  121. extern "C"
  122. DllExport
  123. UINT
  124. APIENTRY
  125. RWReadTypeInfo(
  126. LPCSTR lpszFilename,
  127. LPVOID lpBuffer,
  128. UINT* puiSize
  129. )
  130. {
  131. TRACE("WIN32.DLL: RWReadTypeInfo()\n");
  132. UINT uiError = ERROR_NO_ERROR;
  133. BYTE far * lpBuf = (BYTE far *)lpBuffer;
  134. UINT uiBufSize = *puiSize;
  135. CFile file;
  136. // check if it is a valid win32 file
  137. if (!RWValidateFileType(lpszFilename))
  138. return ERROR_RW_INVALID_FILE;
  139. // Make sure we are using the right code page and global settings
  140. // Get the pointer to the function
  141. HINSTANCE hDllInst = LoadLibrary("iodll.dll");
  142. if (hDllInst)
  143. {
  144. UINT (FAR PASCAL * lpfnGetSettings)(LPSETTINGS);
  145. // Get the pointer to the function to get the settings
  146. lpfnGetSettings = (UINT (FAR PASCAL *)(LPSETTINGS))
  147. GetProcAddress( hDllInst, "RSGetGlobals" );
  148. if (lpfnGetSettings!=NULL) {
  149. SETTINGS settings;
  150. (*lpfnGetSettings)(&settings);
  151. g_cp = settings.cp;
  152. g_bAppend = settings.bAppend;
  153. g_bUpdOtherResLang = settings.bUpdOtherResLang;
  154. strcpy( g_char, settings.szDefChar );
  155. }
  156. FreeLibrary(hDllInst);
  157. }
  158. // Parse the resource tree and extract the information
  159. // Open the file and try to read the information on the resource in it.
  160. if (!file.Open(lpszFilename, CFile::modeRead | CFile::typeBinary | CFile::shareDenyNone))
  161. return ERROR_FILE_OPEN;
  162. // we try to read as much information as we can
  163. // Because this is a res file we can read all the information we need.
  164. UINT uiBufStartSize = uiBufSize;
  165. UCHAR * pResources = LPNULL;
  166. uiError = FindResourceSection( &file, (ULONG_PTR *)&pResources );
  167. if (uiError) {
  168. file.Close();
  169. return uiError;
  170. }
  171. uiError = ParseDirectory( &file,
  172. (LPLPBYTE) &lpBuffer, &uiBufSize,
  173. 0,
  174. (PIMAGE_RESOURCE_DIRECTORY)pResources,
  175. (PIMAGE_RESOURCE_DIRECTORY)pResources );
  176. free(pResources);
  177. file.Close();
  178. *puiSize = uiBufStartSize-uiBufSize;
  179. return uiError;
  180. }
  181. extern "C"
  182. DllExport
  183. DWORD
  184. APIENTRY
  185. RWGetImage(
  186. LPCSTR lpszFilename,
  187. DWORD dwImageOffset,
  188. LPVOID lpBuffer,
  189. DWORD dwSize
  190. )
  191. {
  192. UINT uiError = ERROR_NO_ERROR;
  193. BYTE far * lpBuf = (BYTE far *)lpBuffer;
  194. DWORD dwBufSize = dwSize;
  195. // we can consider the use of a CMemFile so we get the same speed as memory access.
  196. CFile file;
  197. // Open the file and try to read the information on the resource in it.
  198. if (!file.Open(lpszFilename, CFile::modeRead | CFile::typeBinary | CFile::shareDenyNone))
  199. return (DWORD)ERROR_FILE_OPEN;
  200. if ( dwImageOffset!=(DWORD)file.Seek( dwImageOffset, CFile::begin) )
  201. return (DWORD)ERROR_FILE_INVALID_OFFSET;
  202. if (dwSize>UINT_MAX) {
  203. // we have to read the image in different steps
  204. return (DWORD)0L;
  205. } else uiError = file.Read( lpBuf, (UINT)dwSize);
  206. file.Close();
  207. return (DWORD)uiError;
  208. }
  209. extern "C"
  210. DllExport
  211. UINT
  212. APIENTRY
  213. RWParseImageEx(
  214. LPCSTR lpszType,
  215. LPCSTR lpszResId,
  216. LPVOID lpImageBuf,
  217. DWORD dwImageSize,
  218. LPVOID lpBuffer,
  219. DWORD dwSize,
  220. LPCSTR lpRCFilename
  221. )
  222. {
  223. UINT uiError = ERROR_NO_ERROR;
  224. BYTE far * lpBuf = (BYTE far *)lpBuffer;
  225. DWORD dwBufSize = dwSize;
  226. // The Type we can parse are only the standard ones
  227. // This function should fill the lpBuffer with an array of ResItem structure
  228. if (HIWORD(lpszType))
  229. {
  230. if (strcmp(lpszType, "REGINST") ==0)
  231. {
  232. return (ParseEmbeddedFile( lpImageBuf, dwImageSize, lpBuffer, dwSize ));
  233. }
  234. }
  235. switch ((UINT)LOWORD(lpszType)) {
  236. case 1:
  237. case 12:
  238. uiError = ParseEmbeddedFile( lpImageBuf, dwImageSize, lpBuffer, dwSize );
  239. break;
  240. case 2:
  241. case 14:
  242. uiError = ParseEmbeddedFile( lpImageBuf, dwImageSize, lpBuffer, dwSize );
  243. break;
  244. case 3:
  245. uiError = ParseEmbeddedFile( lpImageBuf, dwImageSize, lpBuffer, dwSize );
  246. break;
  247. case 4:
  248. uiError = ParseMenu( lpImageBuf, dwImageSize, lpBuffer, dwSize );
  249. break;
  250. case 5:
  251. uiError = ParseDialog( lpImageBuf, dwImageSize, lpBuffer, dwSize );
  252. break;
  253. case 6:
  254. uiError = ParseString( lpImageBuf, dwImageSize, lpBuffer, dwSize );
  255. break;
  256. case 9:
  257. uiError = ParseAccel( lpImageBuf, dwImageSize, lpBuffer, dwSize );
  258. break;
  259. case 11:
  260. uiError = ParseMsgTbl( lpImageBuf, dwImageSize, lpBuffer, dwSize );
  261. break;
  262. case 16:
  263. uiError = ParseVerst( lpImageBuf, dwImageSize, lpBuffer, dwSize );
  264. break;
  265. case 23:
  266. case 240:
  267. case 2110:
  268. case 1024:
  269. uiError = ParseEmbeddedFile( lpImageBuf, dwImageSize, lpBuffer, dwSize );
  270. break;
  271. case 7:
  272. case 8:
  273. case 13:
  274. case 15:
  275. break;
  276. //
  277. // To support RCDATA and user defined function we will call back the iodll,
  278. // get the file name and check if we have a DLL that will handle RCDATA.
  279. // We expect the DLL name to be RCfilename.dll.
  280. // This Dll will export a function called RWParseImageEx. This function will
  281. // be called by the RW to fill the buffer, all this without the iodll knowing.
  282. //
  283. case 10:
  284. default:
  285. //
  286. // Get the file name from the iodll
  287. //
  288. if(lpRCFilename && strcmp(lpRCFilename, ""))
  289. {
  290. // try to Load the dll
  291. HINSTANCE hRCDllInst = LoadLibrary(lpRCFilename);
  292. if (hRCDllInst)
  293. {
  294. UINT (FAR PASCAL * lpfnParseImageEx)(LPCSTR, LPCSTR, LPVOID, DWORD, LPVOID, DWORD, LPCSTR);
  295. // Get the pointer to the function to extract the resources
  296. lpfnParseImageEx = (UINT (FAR PASCAL *)(LPCSTR, LPCSTR, LPVOID, DWORD, LPVOID, DWORD, LPCSTR))
  297. GetProcAddress( hRCDllInst, "RWParseImageEx" );
  298. if (lpfnParseImageEx)
  299. {
  300. uiError = (*lpfnParseImageEx)(lpszType,
  301. lpszResId,
  302. lpImageBuf,
  303. dwImageSize,
  304. lpBuffer,
  305. dwSize,
  306. NULL);
  307. }
  308. FreeLibrary(hRCDllInst);
  309. }
  310. }
  311. break;
  312. }
  313. return uiError;
  314. }
  315. extern "C"
  316. DllExport
  317. UINT
  318. APIENTRY
  319. RWParseImage(
  320. LPCSTR lpszType,
  321. LPVOID lpImageBuf,
  322. DWORD dwImageSize,
  323. LPVOID lpBuffer,
  324. DWORD dwSize
  325. )
  326. {
  327. //
  328. // Just a wrapper to be compatible...
  329. //
  330. return RWParseImageEx(lpszType, NULL, lpImageBuf, dwImageSize, lpBuffer, dwSize, NULL);
  331. }
  332. extern"C"
  333. DllExport
  334. UINT
  335. APIENTRY
  336. RWWriteFile(
  337. LPCSTR lpszSrcFilename,
  338. LPCSTR lpszTgtFilename,
  339. HANDLE hResFileModule,
  340. LPVOID lpBuffer,
  341. UINT uiSize,
  342. HINSTANCE hDllInst,
  343. LPCSTR lpszSymbolPath
  344. )
  345. {
  346. UINT uiError = ERROR_NO_ERROR;
  347. UINT uiBufSize = uiSize;
  348. CFile fileIn;
  349. CFile fileOut;
  350. BOOL bfileIn = TRUE;
  351. // Open the file and try to read the information on the resource in it.
  352. CFileStatus status;
  353. if (CFile::GetStatus( lpszSrcFilename, status )) {
  354. // check if the size of the file is not null
  355. if (!status.m_size)
  356. CFile::Remove(lpszSrcFilename);
  357. }
  358. if (!fileIn.Open(lpszSrcFilename, CFile::modeRead | CFile::typeBinary | CFile::shareDenyNone))
  359. return ERROR_FILE_OPEN;
  360. if (!fileOut.Open(lpszTgtFilename, CFile::modeWrite | CFile::modeCreate | CFile::typeBinary))
  361. return ERROR_FILE_CREATE;
  362. // Create a copy of the US file
  363. uiError = CopyFile( &fileIn, &fileOut );
  364. fileIn.Close();
  365. fileOut.Close();
  366. // Get the pointer to the function
  367. hDllInst = LoadLibrary("iodll.dll");
  368. if (!hDllInst)
  369. return ERROR_DLL_LOAD;
  370. DWORD (FAR PASCAL * lpfnGetImage)(HANDLE, LPCSTR, LPCSTR, DWORD, LPVOID, DWORD);
  371. // Get the pointer to the function to extract the resources image
  372. lpfnGetImage = (DWORD (FAR PASCAL *)(HANDLE, LPCSTR, LPCSTR, DWORD, LPVOID, DWORD))
  373. GetProcAddress( hDllInst, "RSGetResImage" );
  374. if (lpfnGetImage==NULL) {
  375. FreeLibrary(hDllInst);
  376. return (UINT)GetLastError()+LAST_ERROR;
  377. }
  378. // We read the resources from the file and then we check if the resource has been updated
  379. // or if we can just copy it
  380. WORD wTypeId;
  381. char szTypeId[128];
  382. WORD wNameId;
  383. char szNameId[128];
  384. DWORD dwSize;
  385. DWORD dwLang;
  386. WORD wUpdTypeId = 0;
  387. static char szUpdTypeId[128];
  388. WORD wUpdNameId;
  389. static char szUpdNameId[128];
  390. static WCHAR szwTypeId[128];
  391. static WCHAR szwNameId[128];
  392. DWORD dwUpdLang = 0;
  393. DWORD dwUpdSize = 0;
  394. UINT uiBufStartSize = uiBufSize;
  395. DWORD dwImageBufSize;
  396. DWORD dwLstErr = 0l;
  397. BYTE * lpImageBuf;
  398. static WCHAR szwTgtFilename[400];
  399. SetLastError(0);
  400. // Convert the Target file name to a unicode name
  401. _MBSTOWCS(szwTgtFilename, (char *)lpszTgtFilename, 400 );
  402. // Get the updated resource and replace them
  403. HANDLE hUpd = BeginUpdateResourceW( (LPCWSTR)&szwTgtFilename[0], !g_bAppend );
  404. dwLstErr = GetLastError();
  405. if (!hUpd) {
  406. FreeLibrary(hDllInst);
  407. return((UINT)dwLstErr);
  408. }
  409. // Parse the original file an get the list of resources
  410. UINT uiBSize = 100000;
  411. BYTE far * lpBuf = new far BYTE[uiBSize];
  412. BYTE far * lpStartBuf = lpBuf;
  413. if (!lpBuf) {
  414. FreeLibrary(hDllInst);
  415. return ERROR_NEW_FAILED;
  416. }
  417. uiError = RWReadTypeInfo( lpszSrcFilename, (LPVOID)lpBuf, &uiBSize );
  418. if (uiError!=ERROR_NO_ERROR) {
  419. FreeLibrary(hDllInst);
  420. delete lpBuf;
  421. return uiError;
  422. }
  423. DWORD dwDummy;
  424. while(uiBSize>0) {
  425. if (uiBSize)
  426. GetRes( &lpBuf,
  427. &uiBSize,
  428. &wTypeId, &szTypeId[0],
  429. &wNameId, &szNameId[0],
  430. &dwLang,
  431. &dwSize,
  432. &dwDummy
  433. );
  434. dwLang = MAKELONG(LOWORD(dwLang),LOWORD(dwLang));
  435. if ((!wUpdTypeId) && (uiBufSize))
  436. GetUpdatedRes( (BYTE**)&lpBuffer,
  437. &uiBufSize,
  438. &wUpdTypeId, &szUpdTypeId[0],
  439. &wUpdNameId, &szUpdNameId[0],
  440. &dwUpdLang,
  441. &dwUpdSize
  442. );
  443. // check if the resource has been updated or not
  444. if ( (wUpdTypeId==wTypeId) &&
  445. ( (CString)szUpdTypeId==(CString)szTypeId) &&
  446. (wUpdNameId==wNameId) &&
  447. ( (CString)szUpdNameId==(CString)szNameId) &&
  448. (LOWORD(dwLang) == LOWORD(dwUpdLang))
  449. ) {
  450. dwLang = dwUpdLang;
  451. dwSize = dwUpdSize;
  452. wUpdTypeId = 0;
  453. }
  454. // all resources of specific language need to be marked
  455. if (LOWORD(dwLang) == LOWORD(dwUpdLang) && g_bUpdOtherResLang)
  456. {
  457. dwLang = dwUpdLang;
  458. }
  459. // The resource has been updated get the image from the IODLL
  460. lpImageBuf = new BYTE[dwSize];
  461. // convert the Name to unicode
  462. LPWSTR lpUpdType = LPNULL;
  463. LPWSTR lpUpdRes = LPNULL;
  464. LPCSTR lpType = LPNULL;
  465. LPCSTR lpRes = LPNULL;
  466. if (wTypeId) {
  467. lpUpdType = (LPWSTR) MAKEINTRESOURCE((WORD)wTypeId);
  468. lpType = MAKEINTRESOURCE((WORD)wTypeId);
  469. } else {
  470. SetLastError(0);
  471. _MBSTOWCS(szwTypeId, szTypeId, 128 );
  472. // Check for error
  473. if(GetLastError()) {
  474. FreeLibrary(hDllInst);
  475. return ERROR_DLL_LOAD;
  476. }
  477. lpUpdType = (LPWSTR) &szwTypeId[0];
  478. lpType = &szTypeId[0];
  479. }
  480. if (wNameId) {
  481. lpUpdRes = (LPWSTR) MAKEINTRESOURCE((WORD)wNameId);
  482. lpRes = MAKEINTRESOURCE((WORD)wNameId);
  483. } else {
  484. SetLastError(0);
  485. _MBSTOWCS(szwNameId, szNameId, 128 );
  486. // Check for error
  487. if(GetLastError()) {
  488. FreeLibrary(hDllInst);
  489. return ERROR_DLL_LOAD;
  490. }
  491. lpUpdRes = (LPWSTR) &szwNameId[0];
  492. lpRes = &szNameId[0];
  493. }
  494. dwImageBufSize = (*lpfnGetImage)( hResFileModule,
  495. lpType,
  496. lpRes,
  497. (DWORD)LOWORD(dwLang),
  498. lpImageBuf,
  499. dwSize
  500. );
  501. if (dwImageBufSize>dwSize ) {
  502. // The buffer is too small
  503. delete []lpImageBuf;
  504. lpImageBuf = new BYTE[dwImageBufSize];
  505. dwUpdSize = (*lpfnGetImage)( hResFileModule,
  506. lpType,
  507. lpRes,
  508. (DWORD)LOWORD(dwLang),
  509. lpImageBuf,
  510. dwImageBufSize
  511. );
  512. if ((dwUpdSize-dwImageBufSize)!=0 ) {
  513. delete []lpImageBuf;
  514. lpImageBuf = LPNULL;
  515. }
  516. }else if (dwImageBufSize==0){
  517. delete []lpImageBuf;
  518. lpImageBuf = LPNULL;
  519. }
  520. SetLastError(0);
  521. TRACE1("\t\tUpdateResourceW: %d\n", (WORD)dwUpdLang);
  522. if(!UpdateResourceW( hUpd,
  523. lpUpdType,
  524. lpUpdRes,
  525. HIWORD(dwLang),
  526. (LPVOID)lpImageBuf,
  527. dwImageBufSize ))
  528. {
  529. dwLstErr = GetLastError();
  530. }
  531. if (lpImageBuf) delete []lpImageBuf;
  532. }
  533. SetLastError(0);
  534. EndUpdateResourceW( hUpd, FALSE );
  535. dwLstErr = GetLastError();
  536. if (dwLstErr)
  537. dwLstErr +=LAST_ERROR;
  538. // Fix the check sum
  539. DWORD error;
  540. if(error = FixCheckSum(lpszTgtFilename,lpszSrcFilename, lpszSymbolPath))
  541. dwLstErr = error;
  542. delete lpStartBuf;
  543. FreeLibrary(hDllInst);
  544. return (UINT)dwLstErr;
  545. }
  546. extern "C"
  547. DllExport
  548. UINT
  549. APIENTRY
  550. RWUpdateImageEx(
  551. LPCSTR lpszType,
  552. LPVOID lpNewBuf,
  553. DWORD dwNewSize,
  554. LPVOID lpOldImage,
  555. DWORD dwOldImageSize,
  556. LPVOID lpNewImage,
  557. DWORD* pdwNewImageSize,
  558. LPCSTR lpRCFilename
  559. )
  560. {
  561. UINT uiError = ERROR_NO_ERROR;
  562. // The Type we can parse are only the standard ones
  563. switch ((UINT)LOWORD(lpszType)) {
  564. case 4:
  565. uiError = UpdateMenu( lpNewBuf, dwNewSize,
  566. lpOldImage, dwOldImageSize,
  567. lpNewImage, pdwNewImageSize );
  568. break;
  569. case 5:
  570. uiError = UpdateDialog( lpNewBuf, dwNewSize,
  571. lpOldImage, dwOldImageSize,
  572. lpNewImage, pdwNewImageSize );
  573. break;
  574. case 6:
  575. uiError = UpdateString( lpNewBuf, dwNewSize,
  576. lpOldImage, dwOldImageSize,
  577. lpNewImage, pdwNewImageSize );
  578. break;
  579. case 9:
  580. uiError = UpdateAccel( lpNewBuf, dwNewSize,
  581. lpOldImage, dwOldImageSize,
  582. lpNewImage, pdwNewImageSize );
  583. break;
  584. case 11:
  585. uiError = UpdateMsgTbl( lpNewBuf, dwNewSize,
  586. lpOldImage, dwOldImageSize,
  587. lpNewImage, pdwNewImageSize );
  588. break;
  589. case 16:
  590. uiError = UpdateVerst( lpNewBuf, dwNewSize,
  591. lpOldImage, dwOldImageSize,
  592. lpNewImage, pdwNewImageSize );
  593. break;
  594. default:
  595. //
  596. // Get the file name from the iodll
  597. //
  598. if(lpRCFilename && strcmp(lpRCFilename, ""))
  599. {
  600. // try to Load the dll
  601. HINSTANCE hRCDllInst = LoadLibrary(lpRCFilename);
  602. if (hRCDllInst)
  603. {
  604. UINT (FAR PASCAL * lpfnGenerateImageEx)(LPCSTR, LPVOID, DWORD, LPVOID, DWORD, LPVOID, DWORD*, LPCSTR);
  605. lpfnGenerateImageEx = (UINT (FAR PASCAL *)(LPCSTR, LPVOID, DWORD, LPVOID, DWORD, LPVOID, DWORD*, LPCSTR))
  606. GetProcAddress( hRCDllInst, "RWUpdateImageEx" );
  607. if (lpfnGenerateImageEx)
  608. {
  609. uiError = (*lpfnGenerateImageEx)( lpszType,
  610. lpNewBuf,
  611. dwNewSize,
  612. lpOldImage,
  613. dwOldImageSize,
  614. lpNewImage,
  615. pdwNewImageSize,
  616. NULL );
  617. }
  618. else
  619. {
  620. *pdwNewImageSize = 0L;
  621. uiError = ERROR_RW_NOTREADY;
  622. }
  623. FreeLibrary(hRCDllInst);
  624. }
  625. else
  626. {
  627. *pdwNewImageSize = 0L;
  628. uiError = ERROR_RW_NOTREADY;
  629. }
  630. }
  631. else
  632. {
  633. *pdwNewImageSize = 0L;
  634. uiError = ERROR_RW_NOTREADY;
  635. }
  636. break;
  637. }
  638. return uiError;
  639. }
  640. extern "C"
  641. DllExport
  642. UINT
  643. APIENTRY
  644. RWUpdateImage(
  645. LPCSTR lpszType,
  646. LPVOID lpNewBuf,
  647. DWORD dwNewSize,
  648. LPVOID lpOldImage,
  649. DWORD dwOldImageSize,
  650. LPVOID lpNewImage,
  651. DWORD* pdwNewImageSize
  652. )
  653. {
  654. return RWUpdateImageEx(lpszType, lpNewBuf, dwNewSize,
  655. lpOldImage, dwOldImageSize, lpNewImage, pdwNewImageSize,
  656. NULL);
  657. }
  658. ///////////////////////////////////////////////////////////////////////////
  659. // Functions implementation
  660. static UINT
  661. GetResInfo( CFile* pfile,
  662. WORD* pwTypeId, LPSTR lpszTypeId, BYTE bMaxTypeLen,
  663. WORD* pwNameId, LPSTR lpszNameId, BYTE bMaxNameLen,
  664. WORD* pwFlags,
  665. DWORD* pdwSize, DWORD* pdwFileOffset )
  666. {
  667. // Here we will parese the win32 file and will extract the information on the
  668. // resources included in the file.
  669. // Let's go and get the .rsrc sections
  670. UINT uiError = ERROR_NO_ERROR;
  671. return 1;
  672. }
  673. static UINT FindResourceSection( CFile* pfile, ULONG_PTR * pRes )
  674. {
  675. UINT uiError = ERROR_NO_ERROR;
  676. LONG lRead;
  677. // We check again that is a file we can handle
  678. WORD w;
  679. pfile->Read((WORD*)&w, sizeof(WORD));
  680. if (w!=IMAGE_DOS_SIGNATURE) return ERROR_RW_INVALID_FILE;
  681. pfile->Seek( 0x18, CFile::begin );
  682. pfile->Read((WORD*)&w, sizeof(WORD));
  683. if (w<0x0040) {
  684. // this is not a Windows Executable
  685. return ERROR_RW_INVALID_FILE;
  686. }
  687. // get offset to new header
  688. pfile->Seek( 0x3c, CFile::begin );
  689. pfile->Read((WORD*)&w, sizeof(WORD));
  690. // read windows new header
  691. static IMAGE_NT_HEADERS NTHdr;
  692. pfile->Seek( w, CFile::begin );
  693. pfile->Read(&NTHdr, sizeof(IMAGE_NT_HEADERS));
  694. // Check if the magic word is the right one
  695. if (NTHdr.Signature!=IMAGE_NT_SIGNATURE)
  696. return ERROR_RW_INVALID_FILE;
  697. // Check if the we have 64-bit image
  698. #ifdef _WIN64
  699. if (NTHdr.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)
  700. pfile->Seek(IMAGE_SIZEOF_NT_OPTIONAL32_HEADER -
  701. IMAGE_SIZEOF_NT_OPTIONAL64_HEADER,
  702. CFile::current);
  703. #else
  704. if (NTHdr.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
  705. pfile->Seek(IMAGE_SIZEOF_NT_OPTIONAL64_HEADER -
  706. IMAGE_SIZEOF_NT_OPTIONAL32_HEADER,
  707. CFile::current);
  708. #endif
  709. // this is a Windows NT Executable
  710. // we can handle the situation
  711. // Later we want to check for the file type
  712. // Read the section table
  713. UINT uisize = sizeof(IMAGE_SECTION_HEADER)
  714. * NTHdr.FileHeader.NumberOfSections;
  715. PIMAGE_SECTION_HEADER pSectTbl =
  716. new IMAGE_SECTION_HEADER[NTHdr.FileHeader.NumberOfSections];
  717. if (pSectTbl==LPNULL)
  718. return ERROR_NEW_FAILED;
  719. // Clean the memory we allocated
  720. memset( (PVOID)pSectTbl, 0, uisize);
  721. lRead = pfile->Read(pSectTbl, uisize);
  722. if (lRead!=(LONG)uisize) {
  723. delete []pSectTbl;
  724. return ERROR_FILE_READ;
  725. }
  726. PIMAGE_SECTION_HEADER pResSect = NULL;
  727. PIMAGE_SECTION_HEADER pResSect1 = NULL;
  728. // Check all the sections for the .rsrc or .rsrc1
  729. USHORT us =0;
  730. for (PIMAGE_SECTION_HEADER pSect = pSectTbl;
  731. us < NTHdr.FileHeader.NumberOfSections; us++ ) {
  732. if ( !strcmp((char*)pSect->Name, ".rsrc") && (!pResSect)) {
  733. pResSect = pSect;
  734. } else if (!strcmp((char*)pSect->Name, ".rsrc1") && (!pResSect1)) {
  735. // This mean that the binary we are parsing
  736. // has been already updated using UpdateResource()
  737. pResSect1 = pSect;
  738. }
  739. pSect++;
  740. }
  741. if (!pResSect) {
  742. delete []pSectTbl;
  743. return ERROR_RW_NO_RESOURCES;
  744. }
  745. // Read the resources in memory
  746. ResSectData.ulOffsetToResources = pResSect->PointerToRawData;
  747. ResSectData.ulOffsetToResources1 = pResSect1 ? pResSect1->PointerToRawData
  748. : LPNULL;
  749. ResSectData.ulVirtualAddress = pResSect->VirtualAddress;
  750. ResSectData.ulSizeOfResources = pResSect->SizeOfRawData;
  751. ResSectData.ulVirtualAddress1 = pResSect1 ? pResSect1->VirtualAddress
  752. : LPNULL;
  753. ResSectData.ulSizeOfResources1 = pResSect1 ? pResSect1->SizeOfRawData
  754. : 0L;
  755. UCHAR * pResources = (UCHAR *) malloc((ResSectData.ulSizeOfResources
  756. +ResSectData.ulSizeOfResources1));
  757. if (pResources==LPNULL) {
  758. delete []pSectTbl;
  759. return ERROR_NEW_FAILED;
  760. }
  761. // We read the data for the first section
  762. pfile->Seek( (LONG)ResSectData.ulOffsetToResources, CFile::begin);
  763. lRead = ReadFile(pfile, pResources, (LONG)ResSectData.ulSizeOfResources);
  764. if (lRead!=(LONG)ResSectData.ulSizeOfResources) {
  765. delete []pSectTbl;
  766. free(pResources);
  767. return ERROR_FILE_READ;
  768. }
  769. // We read the data for the second section
  770. if (ResSectData.ulSizeOfResources1 > 0L) {
  771. pfile->Seek( (LONG)ResSectData.ulOffsetToResources1, CFile::begin);
  772. lRead = ReadFile( pfile, (pResources+ResSectData.ulSizeOfResources),
  773. (LONG)ResSectData.ulSizeOfResources1);
  774. if (lRead!=(LONG)ResSectData.ulSizeOfResources1) {
  775. delete []pSectTbl;
  776. free(pResources);
  777. return ERROR_FILE_READ;
  778. }
  779. }
  780. delete []pSectTbl;
  781. // We want to copy the pointer to the resources
  782. *pRes = (ULONG_PTR)pResources;
  783. return uiError;
  784. }
  785. static UINT ParseDirectory( CFile* pfile,
  786. LPLPBYTE lplpBuf, UINT* puiBufSize,
  787. BYTE bLevel,
  788. PIMAGE_RESOURCE_DIRECTORY pResStart,
  789. PIMAGE_RESOURCE_DIRECTORY pResDir)
  790. {
  791. PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirStart;
  792. // Get the pointer to the first entry
  793. pResDirStart = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
  794. ((BYTE far *)pResDir + sizeof( IMAGE_RESOURCE_DIRECTORY));
  795. UINT uiError = 0;
  796. UINT uiCount = pResDir->NumberOfNamedEntries
  797. + pResDir->NumberOfIdEntries;
  798. for ( PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirEntry = pResDirStart;
  799. pResDirEntry < pResDirStart+uiCount && uiError == 0;
  800. ++pResDirEntry )
  801. {
  802. if (bLevel==0) GetNameOrOrdU( (PUCHAR) pResStart,
  803. pResDirEntry->Name,
  804. (LPWSTR)&gwszTypeId,
  805. &gType );
  806. if (bLevel==1) GetNameOrOrdU( (PUCHAR) pResStart,
  807. pResDirEntry->Name,
  808. (LPWSTR)&gwszResId,
  809. &gResId );
  810. if (bLevel==2) gLng = pResDirEntry->Name;
  811. // Check if the user want to get all the resources
  812. // or only some of them
  813. uiError = ParseDirectoryEntry( pfile,
  814. lplpBuf, puiBufSize,
  815. bLevel,
  816. pResStart,
  817. pResDirEntry );
  818. }
  819. return uiError;
  820. }
  821. static UINT ParseDirectoryEntry( CFile * pfile,
  822. LPLPBYTE lplpBuf, UINT* puiBufSize,
  823. BYTE bLevel,
  824. PIMAGE_RESOURCE_DIRECTORY pResStart,
  825. PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirEntry)
  826. {
  827. UINT uiError;
  828. // Check if it is a SubDir or if it is a final Node
  829. if (pResDirEntry->OffsetToData & IMAGE_RESOURCE_DATA_IS_DIRECTORY) {
  830. // It is a SubDir
  831. uiError = ParseSubDir( pfile,
  832. lplpBuf, puiBufSize,
  833. bLevel,
  834. pResStart,
  835. pResDirEntry );
  836. } else {
  837. uiError = ProcessData( pfile,
  838. lplpBuf, puiBufSize,
  839. pResStart,
  840. (PIMAGE_RESOURCE_DATA_ENTRY)((BYTE far *)pResStart
  841. + pResDirEntry->OffsetToData));
  842. }
  843. return uiError;
  844. }
  845. static UINT ParseSubDir( CFile * pfile,
  846. LPLPBYTE lplpBuf, UINT* puiBufSize,
  847. BYTE bLevel,
  848. PIMAGE_RESOURCE_DIRECTORY pResStart,
  849. PIMAGE_RESOURCE_DIRECTORY_ENTRY pResDirEntry)
  850. {
  851. PIMAGE_RESOURCE_DIRECTORY pResDir;
  852. pResDir = (PIMAGE_RESOURCE_DIRECTORY)((BYTE far *)pResStart
  853. + (pResDirEntry->OffsetToData &
  854. (~IMAGE_RESOURCE_DATA_IS_DIRECTORY)));
  855. return( ++bLevel < MAXLEVELS ? ParseDirectory( pfile,
  856. lplpBuf, puiBufSize,
  857. bLevel,
  858. pResStart,
  859. pResDir)
  860. : ERROR_RW_TOO_MANY_LEVELS);
  861. }
  862. static UINT ProcessData( CFile * pfile,
  863. LPLPBYTE lplpBuf, UINT* puiBufSize,
  864. PIMAGE_RESOURCE_DIRECTORY pResStart,
  865. PIMAGE_RESOURCE_DATA_ENTRY pResData)
  866. {
  867. UINT uiError = ERROR_NO_ERROR;
  868. // Let's calculate the offset to the data
  869. ULONG ulOffset = pResData->OffsetToData - ResSectData.ulVirtualAddress;
  870. if ( ulOffset >= ResSectData.ulSizeOfResources ) {
  871. if ( ResSectData.ulSizeOfResources1 > 0L ) {
  872. // What we need is in the .rsrc1 segment
  873. // Recalculate the offset;
  874. ulOffset = pResData->OffsetToData - ResSectData.ulVirtualAddress1;
  875. if ( ulOffset >= ResSectData.ulSizeOfResources +
  876. ResSectData.ulSizeOfResources1) {
  877. // There is an error in the offset
  878. return ERROR_FILE_INVALID_OFFSET;
  879. } else ulOffset += ResSectData.ulOffsetToResources1;
  880. } else return ERROR_FILE_INVALID_OFFSET;
  881. } else ulOffset += ResSectData.ulOffsetToResources;
  882. // Convert the UNICODE to SB string
  883. static char szResName[128];
  884. UINT cch = _WCSLEN(gwszResId);
  885. _WCSTOMBS( szResName, gwszResId, 128 );
  886. static char szTypeName[128];
  887. cch = _WCSLEN(gwszTypeId);
  888. _WCSTOMBS( szTypeName, gwszTypeId, 128 );
  889. TRACE("WIN32.DLL:\tType: %ld\tType Name: %s\tLang: %ld\tRes Id: %ld", gType, szTypeName, gLng, gResId);
  890. TRACE1("\tSize: %d", pResData->Size);
  891. TRACE2("\tRes Name: %s\tOffset: %lX\n", szResName, ulOffset );
  892. // fill the buffer
  893. WriteResInfo(lplpBuf, (LONG*)puiBufSize,
  894. (WORD)gType, szTypeName, 128,
  895. (WORD)gResId, szResName, 128,
  896. (DWORD)gLng,
  897. (DWORD)pResData->Size, (DWORD)ulOffset );
  898. return uiError;
  899. };
  900. static LONG WriteResInfo(
  901. LPLPBYTE lplpBuffer, LONG* plBufSize,
  902. WORD wTypeId, LPSTR lpszTypeId, BYTE bMaxTypeLen,
  903. WORD wNameId, LPSTR lpszNameId, BYTE bMaxNameLen,
  904. DWORD dwLang,
  905. DWORD dwSize, DWORD dwFileOffset )
  906. {
  907. LONG lSize = 0;
  908. lSize = PutWord( lplpBuffer, wTypeId, plBufSize );
  909. lSize += PutStringA( lplpBuffer, lpszTypeId, plBufSize );
  910. // Check if it is alligned
  911. lSize += Allign( lplpBuffer, plBufSize, lSize);
  912. lSize += PutWord( lplpBuffer, wNameId, plBufSize );
  913. lSize += PutStringA( lplpBuffer, lpszNameId, plBufSize );
  914. lSize += Allign( lplpBuffer, plBufSize, lSize);
  915. lSize += PutDWord( lplpBuffer, dwLang, plBufSize );
  916. lSize += PutDWord( lplpBuffer, dwSize, plBufSize );
  917. lSize += PutDWord( lplpBuffer, dwFileOffset, plBufSize );
  918. return (LONG)lSize;
  919. }
  920. static UINT GetUpdatedRes(
  921. BYTE far * far* lplpBuffer,
  922. UINT* puiBufSize,
  923. WORD* wTypeId, LPSTR lplpszTypeId,
  924. WORD* wNameId, LPSTR lplpszNameId,
  925. DWORD* dwLang, DWORD* dwSize )
  926. {
  927. UINT uiSize = 0l;
  928. LONG lSize = *puiBufSize;
  929. uiSize = GetWord( lplpBuffer, wTypeId, (LONG*)&lSize );
  930. uiSize += GetStringA( lplpBuffer, lplpszTypeId, (LONG*)&lSize );
  931. uiSize += SkipByte( lplpBuffer, PadPtr(uiSize), (LONG*)&lSize );
  932. uiSize += GetWord( lplpBuffer, wNameId, (LONG*)&lSize );
  933. uiSize += GetStringA( lplpBuffer, lplpszNameId, (LONG*)&lSize );
  934. uiSize += SkipByte( lplpBuffer, PadPtr(uiSize), (LONG*)&lSize );
  935. uiSize += GetDWord( lplpBuffer, dwLang, (LONG*)&lSize );
  936. uiSize += GetDWord( lplpBuffer, dwSize, (LONG*)&lSize );
  937. *puiBufSize = lSize;
  938. return 0;
  939. }
  940. static UINT GetRes(
  941. BYTE far * far* lplpBuffer,
  942. UINT* puiBufSize,
  943. WORD* wTypeId, LPSTR lplpszTypeId,
  944. WORD* wNameId, LPSTR lplpszNameId,
  945. DWORD* dwLang, DWORD* dwSize, DWORD* dwFileOffset )
  946. {
  947. UINT uiSize = 0l;
  948. LONG lSize = *puiBufSize;
  949. uiSize = GetWord( lplpBuffer, wTypeId, (LONG*)&lSize );
  950. uiSize += GetStringA( lplpBuffer, lplpszTypeId, (LONG*)&lSize );
  951. uiSize += SkipByte( lplpBuffer, PadPtr(uiSize), (LONG*)&lSize );
  952. uiSize += GetWord( lplpBuffer, wNameId, (LONG*)&lSize );
  953. uiSize += GetStringA( lplpBuffer, lplpszNameId, (LONG*)&lSize );
  954. uiSize += SkipByte( lplpBuffer, PadPtr(uiSize), (LONG*)&lSize );
  955. uiSize += GetDWord( lplpBuffer, dwLang, (LONG*)&lSize );
  956. uiSize += GetDWord( lplpBuffer, dwSize, (LONG*)&lSize );
  957. uiSize += GetDWord( lplpBuffer, dwFileOffset, (LONG*)&lSize );
  958. *puiBufSize = lSize;
  959. return uiSize;
  960. }
  961. static LONG ReadFile(CFile* pFile, UCHAR * pBuf, LONG lRead)
  962. {
  963. LONG lLeft = lRead;
  964. WORD wRead = 0;
  965. DWORD dwOffset = 0;
  966. while(lLeft>0){
  967. wRead =(WORD) (32738ul < lLeft ? 32738: lLeft);
  968. if (wRead!=_lread( (HFILE)pFile->m_hFile, (UCHAR *)pBuf+dwOffset, wRead))
  969. return 0l;
  970. lLeft -= wRead;
  971. dwOffset += wRead;
  972. }
  973. return dwOffset;
  974. }
  975. ////////////////////////////////////////////////////////////////////////////
  976. // DLL Specific code implementation
  977. ////////////////////////////////////////////////////////////////////////////
  978. // Library init
  979. ////////////////////////////////////////////////////////////////////////////
  980. // This function should be used verbatim. Any initialization or termination
  981. // requirements should be handled in InitPackage() and ExitPackage().
  982. //
  983. extern "C" int APIENTRY
  984. DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
  985. {
  986. if (dwReason == DLL_PROCESS_ATTACH)
  987. {
  988. // NOTE: global/static constructors have already been called!
  989. // Extension DLL one-time initialization - do not allocate memory
  990. // here, use the TRACE or ASSERT macros or call MessageBox
  991. AfxInitExtensionModule(extensionDLL, hInstance);
  992. }
  993. else if (dwReason == DLL_PROCESS_DETACH)
  994. {
  995. // Terminate the library before destructors are called
  996. AfxWinTerm();
  997. }
  998. if (dwReason == DLL_PROCESS_DETACH || dwReason == DLL_THREAD_DETACH)
  999. return 0; // CRT term Failed
  1000. return 1; // ok
  1001. }
  1002. /////////////////////////////////////////////////////////////////////////////