OSDN Git Service

Fix Issue #111: Undo Add does not work
[tortoisegit/TortoiseGitJp.git] / src / ResText / ResModule.cpp
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2003-2008 - TortoiseSVN\r
4 \r
5 // This program is free software; you can redistribute it and/or\r
6 // modify it under the terms of the GNU General Public License\r
7 // as published by the Free Software Foundation; either version 2\r
8 // of the License, or (at your option) any later version.\r
9 \r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 \r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, write to the Free Software Foundation,\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
18 #include "StdAfx.h"\r
19 #include "Utils.h"\r
20 #include ".\resmodule.h"\r
21 \r
22 #define MYERROR {CUtils::Error(); return FALSE;}\r
23 \r
24 CResModule::CResModule(void)\r
25         : m_bTranslatedStrings(0)\r
26         , m_bDefaultStrings(0)\r
27         , m_bTranslatedDialogStrings(0)\r
28         , m_bDefaultDialogStrings(0)\r
29         , m_bTranslatedMenuStrings(0)\r
30         , m_bDefaultMenuStrings(0)\r
31         , m_bTranslatedAcceleratorStrings(0)\r
32         , m_bDefaultAcceleratorStrings(0)\r
33         , m_wTargetLang(0)\r
34         , m_hResDll(NULL)\r
35         , m_hUpdateRes(NULL)\r
36         , m_bQuiet(false)\r
37         , m_bRTL(false)\r
38 {\r
39 }\r
40 \r
41 CResModule::~CResModule(void)\r
42 {\r
43 }\r
44 \r
45 BOOL CResModule::ExtractResources(std::vector<std::wstring> filelist, LPCTSTR lpszPOFilePath, BOOL bNoUpdate)\r
46 {\r
47         BOOL bRet = TRUE;\r
48         for (std::vector<std::wstring>::iterator I = filelist.begin(); I != filelist.end(); ++I)\r
49         {\r
50                 m_hResDll = LoadLibrary(I->c_str());\r
51                 if (m_hResDll == NULL)\r
52                         MYERROR;\r
53 \r
54                 size_t nEntries = m_StringEntries.size();\r
55                 // fill in the std::map with all translatable entries\r
56 \r
57                 if (!m_bQuiet)\r
58                         _ftprintf(stdout, _T("Extracting StringTable...."));\r
59                 EnumResourceNames(m_hResDll, RT_STRING,  EnumResNameCallback, (long)this);\r
60                 if (!m_bQuiet)\r
61                         _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);\r
62                 nEntries = m_StringEntries.size();\r
63 \r
64                 if (!m_bQuiet)\r
65                         _ftprintf(stdout, _T("Extracting Dialogs........"));\r
66                 EnumResourceNames(m_hResDll, RT_DIALOG,  EnumResNameCallback, (long)this);\r
67                 if (!m_bQuiet)\r
68                         _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);\r
69                 nEntries = m_StringEntries.size();\r
70 \r
71                 if (!m_bQuiet)\r
72                         _ftprintf(stdout, _T("Extracting Menus.........."));\r
73                 EnumResourceNames(m_hResDll, RT_MENU,    EnumResNameCallback, (long)this);\r
74                 if (!m_bQuiet)\r
75                         _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);\r
76                 nEntries = m_StringEntries.size();\r
77                 if (!m_bQuiet)\r
78                         _ftprintf(stdout, _T("Extracting Accelerators..."));\r
79                 EnumResourceNames(m_hResDll, RT_ACCELERATOR, EnumResNameCallback, (long)this);\r
80                 if (!m_bQuiet)\r
81                         _ftprintf(stdout, _T("%4d Accelerators\n"), m_StringEntries.size()-nEntries);\r
82                 nEntries = m_StringEntries.size();\r
83 \r
84                 // parse a probably existing file and update the translations which are\r
85                 // already done\r
86                 m_StringEntries.ParseFile(lpszPOFilePath, !bNoUpdate);\r
87                 \r
88                 FreeLibrary(m_hResDll);\r
89                 continue;\r
90         }\r
91         \r
92         // at last, save the new file\r
93         if (bRet)\r
94                 return m_StringEntries.SaveFile(lpszPOFilePath);\r
95         return FALSE;\r
96 }\r
97 \r
98 BOOL CResModule::ExtractResources(LPCTSTR lpszSrcLangDllPath, LPCTSTR lpszPoFilePath, BOOL bNoUpdate)\r
99 {\r
100         m_hResDll = LoadLibrary(lpszSrcLangDllPath);\r
101         if (m_hResDll == NULL)\r
102                 MYERROR;\r
103         \r
104         size_t nEntries = 0;\r
105         // fill in the std::map with all translatable entries\r
106 \r
107         if (!m_bQuiet)\r
108                 _ftprintf(stdout, _T("Extracting StringTable...."));\r
109         EnumResourceNames(m_hResDll, RT_STRING,  EnumResNameCallback, (long)this);\r
110         if (!m_bQuiet)\r
111                 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size());\r
112         nEntries = m_StringEntries.size();\r
113 \r
114         if (!m_bQuiet)\r
115                 _ftprintf(stdout, _T("Extracting Dialogs........"));\r
116         EnumResourceNames(m_hResDll, RT_DIALOG,  EnumResNameCallback, (long)this);\r
117         if (!m_bQuiet)\r
118                 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);\r
119         nEntries = m_StringEntries.size();\r
120 \r
121         if (!m_bQuiet)\r
122                 _ftprintf(stdout, _T("Extracting Menus.........."));\r
123         EnumResourceNames(m_hResDll, RT_MENU,    EnumResNameCallback, (long)this);\r
124         if (!m_bQuiet)\r
125                 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);\r
126         nEntries = m_StringEntries.size();\r
127 \r
128         if (!m_bQuiet)\r
129                 _ftprintf(stdout, _T("Extracting Accelerators..."));\r
130         EnumResourceNames(m_hResDll, RT_ACCELERATOR, EnumResNameCallback, (long)this);\r
131         if (!m_bQuiet)\r
132                 _ftprintf(stdout, _T("%4d Accelerators\n"), m_StringEntries.size()-nEntries);\r
133         nEntries = m_StringEntries.size();\r
134 \r
135         // parse a probably existing file and update the translations which are\r
136         // already done\r
137         m_StringEntries.ParseFile(lpszPoFilePath, !bNoUpdate);\r
138 \r
139         // at last, save the new file\r
140         if (!m_StringEntries.SaveFile(lpszPoFilePath))\r
141                 goto DONE_ERROR;\r
142 \r
143         FreeLibrary(m_hResDll);\r
144         return TRUE;\r
145 \r
146 DONE_ERROR:\r
147         if (m_hResDll)\r
148                 FreeLibrary(m_hResDll);\r
149         return FALSE;\r
150 }\r
151 \r
152 BOOL CResModule::CreateTranslatedResources(LPCTSTR lpszSrcLangDllPath, LPCTSTR lpszDestLangDllPath, LPCTSTR lpszPOFilePath)\r
153 {\r
154         if (!CopyFile(lpszSrcLangDllPath, lpszDestLangDllPath, FALSE))\r
155                 MYERROR;\r
156 \r
157         int count = 0;\r
158         do\r
159         {\r
160                 m_hResDll = LoadLibraryEx (lpszSrcLangDllPath, NULL, LOAD_LIBRARY_AS_DATAFILE|LOAD_IGNORE_CODE_AUTHZ_LEVEL);\r
161                 if (m_hResDll == NULL)\r
162                         Sleep(100);\r
163                 count++;\r
164         } while ((m_hResDll == NULL)&&(count < 5));\r
165 \r
166         if (m_hResDll == NULL)\r
167                 MYERROR;\r
168 \r
169         sDestFile = std::wstring(lpszDestLangDllPath);\r
170 \r
171         // get all translated strings\r
172         if (!m_StringEntries.ParseFile(lpszPOFilePath, FALSE))\r
173                 goto DONE_ERROR;\r
174         m_bTranslatedStrings = 0;\r
175         m_bDefaultStrings = 0;\r
176         m_bTranslatedDialogStrings = 0;\r
177         m_bDefaultDialogStrings = 0;\r
178         m_bTranslatedMenuStrings = 0;\r
179         m_bDefaultMenuStrings = 0;\r
180         m_bTranslatedAcceleratorStrings = 0;\r
181         m_bDefaultAcceleratorStrings = 0;\r
182 \r
183         if (!m_bQuiet)\r
184                 _ftprintf(stdout, _T("Translating StringTable..."));\r
185         EnumResourceNames(m_hResDll, RT_STRING, EnumResNameWriteCallback, (long)this);\r
186         if (!m_bQuiet)\r
187                 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedStrings, m_bDefaultStrings);\r
188 \r
189         if (!m_bQuiet)\r
190                 _ftprintf(stdout, _T("Translating Dialogs......."));\r
191         EnumResourceNames(m_hResDll, RT_DIALOG, EnumResNameWriteCallback, (long)this);\r
192         if (!m_bQuiet)\r
193                 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedDialogStrings, m_bDefaultDialogStrings);\r
194 \r
195         if (!m_bQuiet)\r
196                 _ftprintf(stdout, _T("Translating Menus........."));\r
197         EnumResourceNames(m_hResDll, RT_MENU, EnumResNameWriteCallback, (long)this);\r
198         if (!m_bQuiet)\r
199                 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedMenuStrings, m_bDefaultMenuStrings);\r
200 \r
201         if (!m_bQuiet)\r
202                 _ftprintf(stdout, _T("Translating Accelerators.."));\r
203         EnumResourceNames(m_hResDll, RT_ACCELERATOR, EnumResNameWriteCallback, (long)this);\r
204         if (!m_bQuiet)\r
205                 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedAcceleratorStrings, m_bDefaultAcceleratorStrings);\r
206 \r
207         FreeLibrary(m_hResDll);\r
208         return TRUE;\r
209 DONE_ERROR:\r
210         if (m_hResDll)\r
211                 FreeLibrary(m_hResDll);\r
212         return FALSE;\r
213 }\r
214 \r
215 BOOL CResModule::ExtractString(UINT nID)\r
216 {\r
217         HRSRC           hrsrc = FindResource(m_hResDll, MAKEINTRESOURCE(nID), RT_STRING);\r
218         HGLOBAL         hglStringTable;\r
219         LPWSTR          p;\r
220 \r
221         if (!hrsrc)\r
222                 MYERROR;\r
223         hglStringTable = LoadResource(m_hResDll, hrsrc);\r
224 \r
225         if (!hglStringTable)\r
226                 goto DONE_ERROR;\r
227         p = (LPWSTR)LockResource(hglStringTable);\r
228 \r
229         if (p == NULL)\r
230                 goto DONE_ERROR;\r
231         /*      [Block of 16 strings.  The strings are Pascal style with a WORD \r
232         length preceding the string.  16 strings are always written, even \r
233         if not all slots are full.  Any slots in the block with no string \r
234         have a zero WORD for the length.] \r
235         */\r
236 \r
237         //first check how much memory we need\r
238         LPWSTR pp = p;\r
239         for (int i=0; i<16; ++i)\r
240         {\r
241                 int len = GET_WORD(pp);\r
242                 pp++;\r
243                 std::wstring msgid = std::wstring(pp, len);\r
244                 WCHAR * pBuf = new WCHAR[MAX_STRING_LENGTH*2];\r
245                 SecureZeroMemory(pBuf, MAX_STRING_LENGTH*2*sizeof(WCHAR));\r
246                 wcscpy(pBuf, msgid.c_str());\r
247                 CUtils::StringExtend(pBuf);\r
248 \r
249                 if (wcslen(pBuf))\r
250                 {\r
251                         std::wstring str = std::wstring(pBuf);\r
252                         RESOURCEENTRY entry = m_StringEntries[str];\r
253                         entry.resourceIDs.insert(nID);\r
254                         if (wcschr(str.c_str(), '%'))\r
255                                 entry.flag = _T("#, c-format");\r
256                         m_StringEntries[str] = entry;\r
257                 }\r
258                 delete [] pBuf;\r
259                 pp += len;\r
260         }\r
261         UnlockResource(hglStringTable);\r
262         FreeResource(hglStringTable);\r
263         return TRUE;\r
264 DONE_ERROR:\r
265         UnlockResource(hglStringTable);\r
266         FreeResource(hglStringTable);\r
267         MYERROR;\r
268 }\r
269 \r
270 BOOL CResModule::ReplaceString(UINT nID, WORD wLanguage)\r
271 {\r
272         HRSRC           hrsrc = FindResourceEx(m_hResDll, RT_STRING, MAKEINTRESOURCE(nID), wLanguage);\r
273         HGLOBAL         hglStringTable;\r
274         LPWSTR          p;\r
275 \r
276         if (!hrsrc)\r
277                 MYERROR;\r
278         hglStringTable = LoadResource(m_hResDll, hrsrc);\r
279 \r
280         if (!hglStringTable)\r
281                 goto DONE_ERROR;\r
282         p = (LPWSTR)LockResource(hglStringTable);\r
283 \r
284         if (p == NULL)\r
285                 goto DONE_ERROR;\r
286 /*      [Block of 16 strings.  The strings are Pascal style with a WORD \r
287         length preceding the string.  16 strings are always written, even \r
288         if not all slots are full.  Any slots in the block with no string \r
289         have a zero WORD for the length.] \r
290 */\r
291         \r
292         //first check how much memory we need\r
293         size_t nMem = 0;\r
294         LPWSTR pp = p;\r
295         for (int i=0; i<16; ++i)\r
296         {\r
297                 nMem++;\r
298                 size_t len = GET_WORD(pp);\r
299                 pp++;\r
300                 std::wstring msgid = std::wstring(pp, len);\r
301                 WCHAR * pBuf = new WCHAR[MAX_STRING_LENGTH*2];\r
302                 SecureZeroMemory(pBuf, MAX_STRING_LENGTH*2*sizeof(WCHAR));\r
303                 wcscpy(pBuf, msgid.c_str());\r
304                 CUtils::StringExtend(pBuf);\r
305                 msgid = std::wstring(pBuf);\r
306 \r
307                 RESOURCEENTRY resEntry;\r
308                 resEntry = m_StringEntries[msgid];\r
309                 wcscpy(pBuf, resEntry.msgstr.c_str());\r
310                 CUtils::StringCollapse(pBuf);\r
311                 size_t newlen = wcslen(pBuf);\r
312                 if (newlen)\r
313                         nMem += newlen;\r
314                 else\r
315                         nMem += len;\r
316                 pp += len;\r
317                 delete [] pBuf;\r
318         }\r
319 \r
320         WORD * newTable = new WORD[nMem + (nMem % 2)];\r
321         SecureZeroMemory(newTable, (nMem + (nMem % 2))*2);\r
322 \r
323         size_t index = 0;\r
324         for (int i=0; i<16; ++i)\r
325         {\r
326                 int len = GET_WORD(p);\r
327                 p++;\r
328                 std::wstring msgid = std::wstring(p, len);\r
329                 WCHAR * pBuf = new WCHAR[MAX_STRING_LENGTH*2];\r
330                 SecureZeroMemory(pBuf, MAX_STRING_LENGTH*2*sizeof(WCHAR));\r
331                 wcscpy(pBuf, msgid.c_str());\r
332                 CUtils::StringExtend(pBuf);\r
333                 msgid = std::wstring(pBuf);\r
334 \r
335                 RESOURCEENTRY resEntry;\r
336                 resEntry = m_StringEntries[msgid];\r
337                 wcscpy(pBuf, resEntry.msgstr.c_str());\r
338                 CUtils::StringCollapse(pBuf);\r
339                 size_t newlen = wcslen(pBuf);\r
340                 if (newlen)\r
341                 {\r
342                         newTable[index++] = (WORD)newlen;\r
343                         wcsncpy((wchar_t *)&newTable[index], pBuf, newlen);\r
344                         index += newlen;\r
345                         m_bTranslatedStrings++;\r
346                 }\r
347                 else\r
348                 {\r
349                         newTable[index++] = (WORD)len;\r
350                         if (len)\r
351                                 wcsncpy((wchar_t *)&newTable[index], p, len);\r
352                         index += len;\r
353                         if (len)\r
354                                 m_bDefaultStrings++;\r
355                 }\r
356                 p += len;\r
357                 delete [] pBuf;\r
358         }\r
359 \r
360         if (!UpdateResource(m_hUpdateRes, RT_STRING, MAKEINTRESOURCE(nID), (m_wTargetLang ? m_wTargetLang : wLanguage), newTable, (DWORD)(nMem + (nMem % 2))*2))\r
361         {\r
362                 delete [] newTable;\r
363                 goto DONE_ERROR;\r
364         }\r
365         \r
366         if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_STRING, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))\r
367         {\r
368                 delete [] newTable;\r
369                 goto DONE_ERROR;\r
370         }\r
371         delete [] newTable;\r
372         UnlockResource(hglStringTable);\r
373         FreeResource(hglStringTable);\r
374         return TRUE;\r
375 DONE_ERROR:\r
376         UnlockResource(hglStringTable);\r
377         FreeResource(hglStringTable);\r
378         MYERROR;\r
379 }\r
380 \r
381 BOOL CResModule::ExtractMenu(UINT nID)\r
382 {\r
383         HRSRC           hrsrc = FindResource(m_hResDll, MAKEINTRESOURCE(nID), RT_MENU);\r
384         HGLOBAL         hglMenuTemplate;\r
385         WORD            version, offset;\r
386         DWORD dwHelpId;\r
387         const WORD *p, *p0;\r
388 \r
389         if (!hrsrc)\r
390                 MYERROR;\r
391 \r
392         hglMenuTemplate = LoadResource(m_hResDll, hrsrc);\r
393 \r
394         if (!hglMenuTemplate)\r
395                 MYERROR;\r
396 \r
397         p = (const WORD*)LockResource(hglMenuTemplate);\r
398 \r
399         if (p == NULL)\r
400                 MYERROR;\r
401 \r
402         // Standard MENU resource\r
403         //struct MenuHeader { \r
404         //      WORD   wVersion;           // Currently zero \r
405         //      WORD   cbHeaderSize;       // Also zero \r
406         //}; \r
407 \r
408         // MENUEX resource\r
409         //struct MenuExHeader {\r
410         //    WORD wVersion;           // One\r
411         //    WORD wOffset;\r
412         //    DWORD dwHelpId;\r
413         //};\r
414         p0 = p;\r
415         version = GET_WORD(p);\r
416 \r
417         p++;\r
418 \r
419         switch (version)\r
420         {\r
421         case 0:\r
422                 {\r
423                         offset = GET_WORD(p);\r
424                         p += offset;\r
425                         p++;\r
426                         if (!ParseMenuResource(p))\r
427                                 goto DONE_ERROR;\r
428                 }\r
429                 break;\r
430         case 1:\r
431                 {\r
432                         offset = GET_WORD(p);\r
433                         p++;\r
434                         dwHelpId = GET_DWORD(p);\r
435                         if (!ParseMenuExResource(p0 + offset))\r
436                                 goto DONE_ERROR;\r
437                 }\r
438                 break;\r
439         default:\r
440                 goto DONE_ERROR;\r
441         }\r
442 \r
443         UnlockResource(hglMenuTemplate);\r
444         FreeResource(hglMenuTemplate);\r
445         return TRUE;\r
446 \r
447 DONE_ERROR:\r
448         UnlockResource(hglMenuTemplate);\r
449         FreeResource(hglMenuTemplate);\r
450         MYERROR;\r
451 }\r
452 \r
453 BOOL CResModule::ReplaceMenu(UINT nID, WORD wLanguage)\r
454 {\r
455         HRSRC           hrsrc = FindResourceEx(m_hResDll, RT_MENU, MAKEINTRESOURCE(nID), wLanguage);\r
456         HGLOBAL         hglMenuTemplate;\r
457         WORD            version, offset;\r
458         LPWSTR          p;\r
459         WORD *p0;\r
460         DWORD dwHelpId;\r
461 \r
462         if (!hrsrc)\r
463                 MYERROR;        //just the language wasn't found\r
464 \r
465         hglMenuTemplate = LoadResource(m_hResDll, hrsrc);\r
466 \r
467         if (!hglMenuTemplate)\r
468                 MYERROR;\r
469 \r
470         p = (LPWSTR)LockResource(hglMenuTemplate);\r
471 \r
472         if (p == NULL)\r
473                 MYERROR;\r
474 \r
475         //struct MenuHeader { \r
476         //      WORD   wVersion;           // Currently zero \r
477         //      WORD   cbHeaderSize;       // Also zero \r
478         //};\r
479 \r
480         // MENUEX resource\r
481         //struct MenuExHeader {\r
482         //    WORD wVersion;           // One\r
483         //    WORD wOffset;\r
484         //    DWORD dwHelpId;\r
485         //};\r
486         p0 = (WORD *)p;\r
487         version = GET_WORD(p);\r
488 \r
489         p++;\r
490 \r
491         switch (version)\r
492         {\r
493         case 0:\r
494                 {\r
495                         offset = GET_WORD(p);\r
496                         p += offset;\r
497                         p++;\r
498                         size_t nMem = 0;\r
499                         if (!CountMemReplaceMenuResource((WORD *)p, &nMem, NULL))\r
500                                 goto DONE_ERROR;\r
501                         WORD * newMenu = new WORD[nMem + (nMem % 2)+2];\r
502                         SecureZeroMemory(newMenu, (nMem + (nMem % 2)+2)*2);\r
503                         size_t index = 2;               // MenuHeader has 2 WORDs zero\r
504                         if (!CountMemReplaceMenuResource((WORD *)p, &index, newMenu))\r
505                         {\r
506                                 delete [] newMenu;\r
507                                 goto DONE_ERROR;\r
508                         } \r
509 \r
510                         if (!UpdateResource(m_hUpdateRes, RT_MENU, MAKEINTRESOURCE(nID), (m_wTargetLang ? m_wTargetLang : wLanguage), newMenu, (DWORD)(nMem + (nMem % 2)+2)*2))\r
511                         {\r
512                                 delete [] newMenu;\r
513                                 goto DONE_ERROR;\r
514                         }\r
515 \r
516                         if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_MENU, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))\r
517                         {\r
518                                 delete [] newMenu;\r
519                                 goto DONE_ERROR;\r
520                         } \r
521                         delete [] newMenu;\r
522                 }\r
523                 break;\r
524         case 1:\r
525                 {\r
526                         offset = GET_WORD(p);\r
527                         p++;\r
528                         dwHelpId = GET_DWORD(p);\r
529                         size_t nMem = 0;\r
530                         if (!CountMemReplaceMenuExResource((WORD *)(p0 + offset), &nMem, NULL))\r
531                                 goto DONE_ERROR;\r
532                         WORD * newMenu = new WORD[nMem + (nMem % 2) + 4];\r
533                         SecureZeroMemory(newMenu, (nMem + (nMem % 2) + 4) * 2);\r
534                         CopyMemory(newMenu, p0, 2 * sizeof(WORD) + sizeof(DWORD));\r
535                         size_t index = 4;               // MenuExHeader has 2 x WORD + 1 x DWORD\r
536                         if (!CountMemReplaceMenuExResource((WORD *)(p0 + offset), &index, newMenu))\r
537                         {\r
538                                 delete [] newMenu;\r
539                                 goto DONE_ERROR;\r
540                         } \r
541 \r
542                         if (!UpdateResource(m_hUpdateRes, RT_MENU, MAKEINTRESOURCE(nID), (m_wTargetLang ? m_wTargetLang : wLanguage), newMenu, (DWORD)(nMem + (nMem % 2) + 4) * 2))\r
543                         {\r
544                                 delete [] newMenu;\r
545                                 goto DONE_ERROR;\r
546                         }\r
547 \r
548                         if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_MENU, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))\r
549                         {\r
550                                 delete [] newMenu;\r
551                                 goto DONE_ERROR;\r
552                         } \r
553                         delete [] newMenu;\r
554                 }\r
555                 break;\r
556         default:\r
557                 goto DONE_ERROR;\r
558         }\r
559 \r
560         UnlockResource(hglMenuTemplate);\r
561         FreeResource(hglMenuTemplate);\r
562         return TRUE;\r
563 \r
564 DONE_ERROR:\r
565         UnlockResource(hglMenuTemplate);\r
566         FreeResource(hglMenuTemplate);\r
567         MYERROR;\r
568 }\r
569 \r
570 const WORD* CResModule::ParseMenuResource(const WORD * res)\r
571 {\r
572         WORD            flags;\r
573         WORD            id = 0;\r
574         LPCWSTR         str;\r
575         WORD *p0;\r
576 \r
577         //struct PopupMenuItem { \r
578         //      WORD   fItemFlags; \r
579         //      WCHAR  szItemText[]; \r
580         //}; \r
581         //struct NormalMenuItem { \r
582         //      WORD   fItemFlags; \r
583         //      WORD   wMenuID; \r
584         //      WCHAR  szItemText[]; \r
585         //}; \r
586 \r
587         do\r
588         {\r
589                 p0 = (WORD *)res;\r
590                 flags = GET_WORD(res);\r
591                 res++;\r
592                 if (!(flags & MF_POPUP))\r
593                 {\r
594                         id = GET_WORD(res);     //normal menu item\r
595                         res++;\r
596                 }\r
597                 else\r
598                         id = (WORD)-1;                  //popup menu item\r
599 \r
600                 str = (LPCWSTR)res;\r
601                 size_t l = wcslen(str)+1;\r
602                 res += l;\r
603 \r
604                 if (flags & MF_POPUP)\r
605                 {\r
606                         TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];\r
607                         SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));\r
608                         _tcscpy(pBuf, str);\r
609                         CUtils::StringExtend(pBuf);\r
610 \r
611                         std::wstring wstr = std::wstring(pBuf);\r
612                         RESOURCEENTRY entry = m_StringEntries[wstr];\r
613                         if (id)\r
614                                 entry.resourceIDs.insert(id);\r
615 \r
616                         m_StringEntries[wstr] = entry;\r
617                         delete [] pBuf;\r
618 \r
619                         if ((res = ParseMenuResource(res))==0)\r
620                                 return NULL;\r
621                 }\r
622                 else if (id != 0)\r
623                 {\r
624                         TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];\r
625                         SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));\r
626                         _tcscpy(pBuf, str);\r
627                         CUtils::StringExtend(pBuf);\r
628 \r
629                         std::wstring wstr = std::wstring(pBuf);\r
630                         RESOURCEENTRY entry = m_StringEntries[wstr];\r
631                         entry.resourceIDs.insert(id);\r
632 \r
633                         TCHAR szTempBuf[1024];\r
634                         _stprintf(szTempBuf, _T("#: MenuEntry; ID:%d"), id);\r
635                         MENUENTRY menu_entry;\r
636                         menu_entry.wID = id;\r
637                         menu_entry.reference = szTempBuf;\r
638                         menu_entry.msgstr = wstr;\r
639 \r
640                         m_StringEntries[wstr] = entry;\r
641                         m_MenuEntries[id] = menu_entry;\r
642                         delete [] pBuf;\r
643                 }\r
644         } while (!(flags & MF_END));\r
645         return res;\r
646 }\r
647 \r
648 const WORD* CResModule::CountMemReplaceMenuResource(const WORD * res, size_t * wordcount, WORD * newMenu)\r
649 {\r
650         WORD            flags;\r
651         WORD            id = 0;\r
652 \r
653         //struct PopupMenuItem { \r
654         //      WORD   fItemFlags; \r
655         //      WCHAR  szItemText[]; \r
656         //}; \r
657         //struct NormalMenuItem { \r
658         //      WORD   fItemFlags; \r
659         //      WORD   wMenuID; \r
660         //      WCHAR  szItemText[]; \r
661         //}; \r
662 \r
663         do\r
664         {\r
665                 flags = GET_WORD(res);\r
666                 res++;\r
667                 if (newMenu == NULL)\r
668                         (*wordcount)++;\r
669                 else\r
670                         newMenu[(*wordcount)++] = flags;\r
671                 if (!(flags & MF_POPUP))\r
672                 {\r
673                         id = GET_WORD(res);     //normal menu item\r
674                         res++;\r
675                         if (newMenu == NULL)\r
676                                 (*wordcount)++;\r
677                         else\r
678                                 newMenu[(*wordcount)++] = id;\r
679                 }\r
680                 else\r
681                         id = (WORD)-1;                  //popup menu item\r
682 \r
683                 if (flags & MF_POPUP)\r
684                 {\r
685                         ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);\r
686                         res += wcslen((LPCWSTR)res) + 1;\r
687 \r
688                         if ((res = CountMemReplaceMenuResource(res, wordcount, newMenu))==0)\r
689                                 return NULL;\r
690                 }\r
691                 else if (id != 0)\r
692                 {\r
693                         ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);\r
694                         res += wcslen((LPCWSTR)res) + 1;\r
695                 }\r
696                 else\r
697                 {\r
698                         if (newMenu)\r
699                                 wcscpy((wchar_t *)&newMenu[(*wordcount)], (LPCWSTR)res);\r
700                         (*wordcount) += wcslen((LPCWSTR)res) + 1;\r
701                         res += wcslen((LPCWSTR)res) + 1;\r
702                 }\r
703         } while (!(flags & MF_END));\r
704         return res;\r
705 }\r
706 \r
707 const WORD* CResModule::ParseMenuExResource(const WORD * res)\r
708 {\r
709         DWORD dwType, dwState, menuId;\r
710         WORD bResInfo;\r
711         LPCWSTR         str;\r
712         WORD *p0;\r
713 \r
714         //struct MenuExItem {\r
715         //    DWORD dwType;\r
716         //    DWORD dwState;\r
717         //    DWORD menuId;\r
718         //    WORD bResInfo;\r
719         //    WCHAR szText[];\r
720         //    DWORD dwHelpId; - Popup menu only\r
721         //};\r
722 \r
723         do\r
724         {\r
725                 p0 = (WORD *)res;\r
726                 dwType = GET_DWORD(res);\r
727                 res += 2;\r
728                 dwState = GET_DWORD(res);\r
729                 res += 2;\r
730                 menuId = GET_DWORD(res);\r
731                 res += 2;\r
732                 bResInfo = GET_WORD(res);\r
733                 res++;\r
734 \r
735                 str = (LPCWSTR)res;\r
736                 size_t l = wcslen(str)+1;\r
737                 res += l;\r
738                 // Align to DWORD boundary\r
739                 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);\r
740 \r
741                 if (dwType & MFT_SEPARATOR)\r
742                         continue;\r
743 \r
744                 if (bResInfo & 0x01)\r
745                 {\r
746                         // Popup menu - note this can also have a non-zero ID\r
747                         if (menuId == 0)\r
748                                 menuId = (WORD)-1;\r
749                         TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];\r
750                         SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));\r
751                         _tcscpy(pBuf, str);\r
752                         CUtils::StringExtend(pBuf);\r
753 \r
754                         std::wstring wstr = std::wstring(pBuf);\r
755                         RESOURCEENTRY entry = m_StringEntries[wstr];\r
756                         // Popup has a DWORD help entry on a DWORD boundary - skip over it\r
757                         res += 2;\r
758 \r
759                         entry.resourceIDs.insert(menuId);\r
760                         TCHAR szTempBuf[1024];\r
761                         _stprintf(szTempBuf, _T("#: MenuExPopupEntry; ID:%d"), menuId);\r
762                         MENUENTRY menu_entry;\r
763                         menu_entry.wID = (WORD)menuId;\r
764                         menu_entry.reference = szTempBuf;\r
765                         menu_entry.msgstr = wstr;\r
766                         m_StringEntries[wstr] = entry;\r
767                         m_MenuEntries[(WORD)menuId] = menu_entry;\r
768                         delete [] pBuf;\r
769 \r
770                         if ((res = ParseMenuExResource(res)) == 0)\r
771                                 return NULL;\r
772                 } else if (menuId != 0)\r
773                 {\r
774                         TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];\r
775                         SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));\r
776                         _tcscpy(pBuf, str);\r
777                         CUtils::StringExtend(pBuf);\r
778 \r
779                         std::wstring wstr = std::wstring(pBuf);\r
780                         RESOURCEENTRY entry = m_StringEntries[wstr];\r
781                         entry.resourceIDs.insert(menuId);\r
782 \r
783                         TCHAR szTempBuf[1024];\r
784                         _stprintf(szTempBuf, _T("#: MenuExEntry; ID:%d"), menuId);\r
785                         MENUENTRY menu_entry;\r
786                         menu_entry.wID = (WORD)menuId;\r
787                         menu_entry.reference = szTempBuf;\r
788                         menu_entry.msgstr = wstr;\r
789                         m_StringEntries[wstr] = entry;\r
790                         m_MenuEntries[(WORD)menuId] = menu_entry;\r
791                         delete [] pBuf;\r
792                 }\r
793         } while (!(bResInfo & 0x80));\r
794         return res;\r
795 }\r
796 \r
797 const WORD* CResModule::CountMemReplaceMenuExResource(const WORD * res, size_t * wordcount, WORD * newMenu)\r
798 {\r
799         DWORD dwType, dwState, menuId;\r
800         WORD bResInfo;\r
801         WORD *p0;\r
802 \r
803         //struct MenuExItem {\r
804         //    DWORD dwType;\r
805         //    DWORD dwState;\r
806         //    DWORD menuId;\r
807         //    WORD bResInfo;\r
808         //    WCHAR szText[];\r
809         //    DWORD dwHelpId; - Popup menu only\r
810         //};\r
811 \r
812         do\r
813         {\r
814                 p0 = (WORD *)res;\r
815                 dwType = GET_DWORD(res);\r
816                 res += 2;\r
817                 dwState = GET_DWORD(res);\r
818                 res += 2;\r
819                 menuId = GET_DWORD(res);\r
820                 res += 2;\r
821                 bResInfo = GET_WORD(res);\r
822                 res++;\r
823 \r
824                 if (newMenu != NULL) {\r
825                         CopyMemory(&newMenu[*wordcount], p0, 7 * sizeof(WORD));\r
826                 }\r
827                 (*wordcount) += 7;\r
828 \r
829                 if (dwType & MFT_SEPARATOR) {\r
830                         // Align to DWORD\r
831                         (*wordcount)++;\r
832                         res++;\r
833                         continue;\r
834                 }\r
835 \r
836                 if (bResInfo & 0x01)\r
837                 {\r
838                         ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);\r
839                         res += wcslen((LPCWSTR)res) + 1;\r
840                         // Align to DWORD\r
841                         res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);\r
842                         if ((*wordcount) & 0x01)\r
843                                 (*wordcount)++;\r
844 \r
845                         if (newMenu != NULL)\r
846                                 CopyMemory(&newMenu[*wordcount], res, sizeof(DWORD));  // Copy Help ID\r
847 \r
848                         res += 2;\r
849                         (*wordcount) += 2;\r
850 \r
851                         if ((res = CountMemReplaceMenuExResource(res, wordcount, newMenu)) == 0)\r
852                                 return NULL;\r
853                 }\r
854                 else if (menuId != 0)\r
855                 {\r
856                         ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);\r
857                         res += wcslen((LPCWSTR)res) + 1;\r
858                 }\r
859                 else\r
860                 {\r
861                         if (newMenu)\r
862                                 wcscpy((wchar_t *)&newMenu[(*wordcount)], (LPCWSTR)res);\r
863                         (*wordcount) += wcslen((LPCWSTR)res) + 1;\r
864                         res += wcslen((LPCWSTR)res) + 1;\r
865                 }\r
866                 // Align to DWORD\r
867                 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);\r
868                 if ((*wordcount) & 0x01)\r
869                         (*wordcount)++;\r
870         } while (!(bResInfo & 0x80));\r
871         return res;\r
872 }\r
873 \r
874 BOOL CResModule::ExtractAccelerator(UINT nID)\r
875 {\r
876         HRSRC           hrsrc = FindResource(m_hResDll, MAKEINTRESOURCE(nID), RT_ACCELERATOR);\r
877         HGLOBAL         hglAccTable;\r
878         WORD            fFlags, wAnsi, wID;\r
879         const WORD*     p;\r
880         bool            bEnd(false);\r
881 \r
882         if (!hrsrc)\r
883                 MYERROR;\r
884 \r
885         hglAccTable = LoadResource(m_hResDll, hrsrc);\r
886 \r
887         if (!hglAccTable)\r
888                 goto DONE_ERROR;\r
889 \r
890         p = (const WORD*)LockResource(hglAccTable);\r
891 \r
892         if (p == NULL)\r
893                 MYERROR;\r
894 \r
895         /*\r
896         struct ACCELTABLEENTRY \r
897         {\r
898                 WORD fFlags;            FVIRTKEY, FSHIFT, FCONTROL, FALT, 0x80 - Last in a table\r
899                 WORD wAnsi;                     ANSI character\r
900                 WORD wId;                       Keyboard accelerator passed to windows\r
901                 WORD padding;           # bytes added to ensure aligned to DWORD boundary\r
902         };\r
903         */\r
904 \r
905         do \r
906         {\r
907                 fFlags = GET_WORD(p);\r
908                 p++;\r
909                 wAnsi = GET_WORD(p);\r
910                 p++;\r
911                 wID = GET_WORD(p);\r
912                 p++;\r
913                 p++;  // Skip over padding\r
914 \r
915                 if ((fFlags & 0x80) == 0x80) \r
916                 {                               // 0x80\r
917                         bEnd = true;\r
918                 }\r
919 \r
920                 if ((wAnsi < 0x30) ||\r
921                         (wAnsi > 0x5A) ||\r
922                         (wAnsi >= 0x3A && wAnsi <= 0x40))\r
923                         continue;\r
924 \r
925                 TCHAR * pBuf = new TCHAR[1024];\r
926                 SecureZeroMemory(pBuf, 1024 * sizeof(TCHAR));\r
927 \r
928                 // include the menu ID in the msgid to make sure that 'duplicate'\r
929                 // accelerator keys are listed in the po-file.\r
930                 // without this, we would get entries like this:\r
931                 //#. Accelerator Entry for Menu ID:32809; '&Filter'\r
932                 //#. Accelerator Entry for Menu ID:57636; '&Find'\r
933                 //#: Corresponding Menu ID:32771; '&Find'\r
934                 //msgid "V C +F"\r
935                 //msgstr "" \r
936                 //\r
937                 // Since "filter" and "find" are most likely translated to words starting\r
938                 // with different letters, we need to have a separate accelerator entry\r
939                 // for each of those\r
940                 _stprintf(pBuf, _T("ID:%d:"), wID);\r
941 \r
942                 // EXACTLY 5 characters long "ACS+X"\r
943                 // V = Virtual key (or blank if not used)\r
944                 // A = Alt key     (or blank if not used)\r
945                 // C = Ctrl key    (or blank if not used)\r
946                 // S = Shift key   (or blank if not used)\r
947                 // X = upper case character\r
948                 // e.g. "V CS+Q" == Ctrl + Shift + 'Q'\r
949                 if ((fFlags & FVIRTKEY) == FVIRTKEY)            // 0x01\r
950                         _tcscat(pBuf, _T("V"));\r
951                 else\r
952                         _tcscat(pBuf, _T(" "));\r
953 \r
954                 if ((fFlags & FALT) == FALT)                            // 0x10\r
955                         _tcscat(pBuf, _T("A"));\r
956                 else\r
957                         _tcscat(pBuf, _T(" "));\r
958 \r
959                 if ((fFlags & FCONTROL) == FCONTROL)            // 0x08\r
960                         _tcscat(pBuf, _T("C"));\r
961                 else\r
962                         _tcscat(pBuf, _T(" "));\r
963 \r
964                 if ((fFlags & FSHIFT) == FSHIFT)                        // 0x04\r
965                         _tcscat(pBuf, _T("S"));\r
966                 else\r
967                         _tcscat(pBuf, _T(" "));\r
968 \r
969                 _stprintf(pBuf, _T("%s+%c"), pBuf, wAnsi);\r
970 \r
971                 std::wstring wstr = std::wstring(pBuf);\r
972                 RESOURCEENTRY AKey_entry = m_StringEntries[wstr];\r
973 \r
974                 TCHAR szTempBuf[1024];\r
975                 SecureZeroMemory(szTempBuf, 1024 * sizeof(TCHAR));\r
976                 std::wstring wmenu = _T("");\r
977                 pME_iter = m_MenuEntries.find(wID);\r
978                 if (pME_iter != m_MenuEntries.end()) \r
979                 {\r
980                         wmenu = pME_iter->second.msgstr;\r
981                 }\r
982                 _stprintf(szTempBuf, _T("#. Accelerator Entry for Menu ID:%d; '%s'"), wID, wmenu.c_str());\r
983                 AKey_entry.automaticcomments.push_back(std::wstring(szTempBuf));\r
984 \r
985                 m_StringEntries[wstr] = AKey_entry;\r
986                 delete [] pBuf;\r
987         } while (!bEnd);\r
988 \r
989         UnlockResource(hglAccTable);\r
990         FreeResource(hglAccTable);\r
991         return TRUE;\r
992 \r
993 DONE_ERROR:\r
994         UnlockResource(hglAccTable);\r
995         FreeResource(hglAccTable);\r
996         MYERROR;\r
997 }\r
998 \r
999 BOOL CResModule::ReplaceAccelerator(UINT nID, WORD wLanguage)\r
1000 {\r
1001         LPACCEL         lpaccelNew;                     // pointer to new accelerator table\r
1002         HACCEL          haccelOld;                      // handle to old accelerator table\r
1003         int                     cAccelerators;          // number of accelerators in table\r
1004         HGLOBAL         hglAccTableNew;\r
1005         const WORD*     p;\r
1006         int                     i;\r
1007 \r
1008         haccelOld = LoadAccelerators(m_hResDll, MAKEINTRESOURCE(nID));\r
1009 \r
1010         if (haccelOld == NULL)\r
1011                 MYERROR;\r
1012 \r
1013         cAccelerators = CopyAcceleratorTable(haccelOld, NULL, 0);\r
1014 \r
1015         lpaccelNew = (LPACCEL) LocalAlloc(LPTR, cAccelerators * sizeof(ACCEL));\r
1016 \r
1017         if (lpaccelNew == NULL)\r
1018                 MYERROR;\r
1019 \r
1020         CopyAcceleratorTable(haccelOld, lpaccelNew, cAccelerators);\r
1021 \r
1022         // Find the accelerator that the user modified\r
1023         // and change its flags and virtual-key code\r
1024         // as appropriate.\r
1025 \r
1026         BYTE xfVirt;\r
1027         WORD xkey;\r
1028         for (i = 0; i < cAccelerators; i++) \r
1029         {\r
1030                 m_bDefaultAcceleratorStrings++;\r
1031                 if ((lpaccelNew[i].key < 0x30) ||\r
1032                         (lpaccelNew[i].key > 0x5A) ||\r
1033                         (lpaccelNew[i].key >= 0x3A && lpaccelNew[i].key <= 0x40))\r
1034                         continue;\r
1035 \r
1036                 TCHAR * pBuf = new TCHAR[1024];\r
1037                 SecureZeroMemory(pBuf, 1024 * sizeof(TCHAR));\r
1038 \r
1039                 _stprintf(pBuf, _T("ID:%d:"), lpaccelNew[i].cmd);\r
1040 \r
1041                 // get original key combination\r
1042                 if ((lpaccelNew[i].fVirt & FVIRTKEY) == FVIRTKEY)               // 0x01\r
1043                         _tcscat(pBuf, _T("V"));\r
1044                 else\r
1045                         _tcscat(pBuf, _T(" "));\r
1046 \r
1047                 if ((lpaccelNew[i].fVirt & FALT) == FALT)                               // 0x10\r
1048                         _tcscat(pBuf, _T("A"));\r
1049                 else\r
1050                         _tcscat(pBuf, _T(" "));\r
1051 \r
1052                 if ((lpaccelNew[i].fVirt & FCONTROL) == FCONTROL)               // 0x08\r
1053                         _tcscat(pBuf, _T("C"));\r
1054                 else\r
1055                         _tcscat(pBuf, _T(" "));\r
1056 \r
1057                 if ((lpaccelNew[i].fVirt & FSHIFT) == FSHIFT)                   // 0x04\r
1058                         _tcscat(pBuf, _T("S"));\r
1059                 else\r
1060                         _tcscat(pBuf, _T(" "));\r
1061 \r
1062                 _stprintf(pBuf, _T("%s+%c"), pBuf, lpaccelNew[i].key);\r
1063 \r
1064                 // Is it there?\r
1065                 std::map<std::wstring, RESOURCEENTRY>::iterator pAK_iter = m_StringEntries.find(pBuf);\r
1066                 if (pAK_iter != m_StringEntries.end()) \r
1067                 {\r
1068                         m_bTranslatedAcceleratorStrings++;\r
1069                         xfVirt = 0;\r
1070                         xkey = 0;\r
1071                         std::wstring wtemp = pAK_iter->second.msgstr;\r
1072                         wtemp = wtemp.substr(wtemp.find_last_of(':')+1);\r
1073                         if (wtemp.size() != 6)\r
1074                                 continue;\r
1075                         if (wtemp.compare(0, 1, _T("V")) == 0)\r
1076                                 xfVirt |= FVIRTKEY;\r
1077                         else if (wtemp.compare(0, 1, _T(" ")) != 0)\r
1078                                 continue;       // not a space - user must have made a mistake when translating\r
1079                         if (wtemp.compare(1, 1, _T("A")) == 0)\r
1080                                 xfVirt |= FALT;\r
1081                         else if (wtemp.compare(1, 1, _T(" ")) != 0)\r
1082                                 continue;       // not a space - user must have made a mistake when translating\r
1083                         if (wtemp.compare(2, 1, _T("C")) == 0)\r
1084                                 xfVirt |= FCONTROL;\r
1085                         else if (wtemp.compare(2, 1, _T(" ")) != 0)\r
1086                                 continue;       // not a space - user must have made a mistake when translating\r
1087                         if (wtemp.compare(3, 1, _T("S")) == 0)\r
1088                                 xfVirt |= FSHIFT;\r
1089                         else if (wtemp.compare(3, 1, _T(" ")) != 0)\r
1090                                 continue;       // not a space - user must have made a mistake when translating\r
1091                         if (wtemp.compare(4, 1, _T("+")) == 0)\r
1092                         {\r
1093                                 _stscanf(wtemp.substr(5, 1).c_str(), _T("%c"), &xkey);\r
1094                                 lpaccelNew[i].fVirt = xfVirt;\r
1095                                 lpaccelNew[i].key = xkey;\r
1096                         }\r
1097                 }\r
1098         }\r
1099 \r
1100         // Create the new accelerator table\r
1101         hglAccTableNew = LocalAlloc(LPTR, cAccelerators * 4 * sizeof(WORD));\r
1102         p = (WORD *)hglAccTableNew;\r
1103         lpaccelNew[cAccelerators-1].fVirt |= 0x80;\r
1104         for (i = 0; i < cAccelerators; i++) \r
1105         {\r
1106                 memcpy((void *)p, &lpaccelNew[i].fVirt, 1);\r
1107                 p++;\r
1108                 memcpy((void *)p, &lpaccelNew[i].key, sizeof(WORD));\r
1109                 p++;\r
1110                 memcpy((void *)p, &lpaccelNew[i].cmd, sizeof(WORD));\r
1111                 p++;\r
1112                 p++;\r
1113         }\r
1114 \r
1115         if (!UpdateResource(m_hUpdateRes, RT_ACCELERATOR, MAKEINTRESOURCE(nID),\r
1116                 (m_wTargetLang ? m_wTargetLang : wLanguage), hglAccTableNew /* haccelNew*/, cAccelerators * 4 * sizeof(WORD)))\r
1117         {\r
1118                 goto DONE_ERROR;\r
1119         }\r
1120 \r
1121         if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_ACCELERATOR, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))\r
1122         {\r
1123                 goto DONE_ERROR;\r
1124         }\r
1125 \r
1126         LocalFree(lpaccelNew);\r
1127         return TRUE;\r
1128 \r
1129 DONE_ERROR:\r
1130         LocalFree(lpaccelNew);\r
1131         MYERROR;\r
1132 }\r
1133 \r
1134 BOOL CResModule::ExtractDialog(UINT nID)\r
1135 {\r
1136         const WORD*     lpDlg;\r
1137         const WORD*     lpDlgItem;\r
1138         DIALOGINFO      dlg;\r
1139         DLGITEMINFO     dlgItem;\r
1140         WORD            bNumControls;\r
1141         HRSRC           hrsrc;\r
1142         HGLOBAL         hGlblDlgTemplate;\r
1143 \r
1144         hrsrc = FindResource(m_hResDll, MAKEINTRESOURCE(nID), RT_DIALOG);\r
1145 \r
1146         if (hrsrc == NULL)\r
1147                 MYERROR;\r
1148 \r
1149         hGlblDlgTemplate = LoadResource(m_hResDll, hrsrc);\r
1150         if (hGlblDlgTemplate == NULL)\r
1151                 MYERROR;\r
1152 \r
1153         lpDlg = (const WORD*) LockResource(hGlblDlgTemplate);\r
1154 \r
1155         if (lpDlg == NULL)\r
1156                 MYERROR;\r
1157 \r
1158         lpDlgItem = (const WORD*) GetDialogInfo(lpDlg, &dlg);\r
1159         bNumControls = dlg.nbItems;\r
1160 \r
1161         if (dlg.caption)\r
1162         {\r
1163                 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];\r
1164                 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));\r
1165                 _tcscpy(pBuf, dlg.caption);\r
1166                 CUtils::StringExtend(pBuf);\r
1167 \r
1168                 std::wstring wstr = std::wstring(pBuf);\r
1169                 RESOURCEENTRY entry = m_StringEntries[wstr];\r
1170                 entry.resourceIDs.insert(nID);\r
1171 \r
1172                 m_StringEntries[wstr] = entry;\r
1173                 delete [] pBuf;\r
1174         }\r
1175 \r
1176         while (bNumControls-- != 0)\r
1177         {\r
1178                 TCHAR szTitle[500];\r
1179                 SecureZeroMemory(szTitle, sizeof(szTitle));\r
1180                 BOOL  bCode;\r
1181 \r
1182                 lpDlgItem = GetControlInfo((WORD *) lpDlgItem, &dlgItem, dlg.dialogEx, &bCode);\r
1183 \r
1184                 if (bCode == FALSE)\r
1185                         _tcscpy(szTitle, dlgItem.windowName);\r
1186 \r
1187                 if (_tcslen(szTitle) > 0)\r
1188                 {\r
1189                         CUtils::StringExtend(szTitle);\r
1190 \r
1191                         std::wstring wstr = std::wstring(szTitle);\r
1192                         RESOURCEENTRY entry = m_StringEntries[wstr];\r
1193                         entry.resourceIDs.insert(dlgItem.id);\r
1194 \r
1195                         m_StringEntries[wstr] = entry;\r
1196                 }\r
1197         }\r
1198 \r
1199         UnlockResource(hGlblDlgTemplate);\r
1200         FreeResource(hGlblDlgTemplate);\r
1201         return (TRUE);\r
1202 }\r
1203 \r
1204 BOOL CResModule::ReplaceDialog(UINT nID, WORD wLanguage)\r
1205 {\r
1206         const WORD*     lpDlg;\r
1207         HRSRC           hrsrc;\r
1208         HGLOBAL         hGlblDlgTemplate;\r
1209 \r
1210         hrsrc = FindResourceEx(m_hResDll, RT_DIALOG, MAKEINTRESOURCE(nID), wLanguage);\r
1211 \r
1212         if (hrsrc == NULL)\r
1213                 MYERROR;\r
1214 \r
1215         hGlblDlgTemplate = LoadResource(m_hResDll, hrsrc);\r
1216 \r
1217         if (hGlblDlgTemplate == NULL)\r
1218                 MYERROR;\r
1219 \r
1220         lpDlg = (WORD *) LockResource(hGlblDlgTemplate);\r
1221 \r
1222         if (lpDlg == NULL)\r
1223                 MYERROR;\r
1224 \r
1225         size_t nMem = 0;\r
1226         const WORD * p = lpDlg;\r
1227         if (!CountMemReplaceDialogResource(p, &nMem, NULL))\r
1228                 goto DONE_ERROR;\r
1229         WORD * newDialog = new WORD[nMem + (nMem % 2)];\r
1230         SecureZeroMemory(newDialog, (nMem + (nMem % 2))*2);\r
1231 \r
1232         size_t index = 0;\r
1233         if (!CountMemReplaceDialogResource(lpDlg, &index, newDialog))\r
1234         {\r
1235                 delete [] newDialog;\r
1236                 goto DONE_ERROR;\r
1237         }\r
1238         \r
1239         if (!UpdateResource(m_hUpdateRes, RT_DIALOG, MAKEINTRESOURCE(nID), (m_wTargetLang ? m_wTargetLang : wLanguage), newDialog, (DWORD)(nMem + (nMem % 2))*2))\r
1240         {\r
1241                 delete [] newDialog;\r
1242                 goto DONE_ERROR;\r
1243         }\r
1244         \r
1245         if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_DIALOG, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))\r
1246         {\r
1247                 delete [] newDialog;\r
1248                 goto DONE_ERROR;\r
1249         }\r
1250 \r
1251         delete [] newDialog;\r
1252         UnlockResource(hGlblDlgTemplate);\r
1253         FreeResource(hGlblDlgTemplate);\r
1254         return TRUE;\r
1255 \r
1256 DONE_ERROR:\r
1257         UnlockResource(hGlblDlgTemplate);\r
1258         FreeResource(hGlblDlgTemplate);\r
1259         MYERROR;\r
1260 }\r
1261 \r
1262 const WORD* CResModule::GetDialogInfo(const WORD * pTemplate, LPDIALOGINFO lpDlgInfo)\r
1263 {\r
1264         const WORD* p = (const WORD *)pTemplate;\r
1265 \r
1266         lpDlgInfo->style = GET_DWORD(p);\r
1267         p += 2;\r
1268 \r
1269         if (lpDlgInfo->style == 0xffff0001)     // DIALOGEX resource\r
1270         {\r
1271                 lpDlgInfo->dialogEx = TRUE;\r
1272                 lpDlgInfo->helpId   = GET_DWORD(p);\r
1273                 p += 2;\r
1274                 lpDlgInfo->exStyle  = GET_DWORD(p);\r
1275                 p += 2;\r
1276                 lpDlgInfo->style    = GET_DWORD(p);\r
1277                 p += 2;\r
1278         }\r
1279         else\r
1280         {\r
1281                 lpDlgInfo->dialogEx = FALSE;\r
1282                 lpDlgInfo->helpId   = 0;\r
1283                 lpDlgInfo->exStyle  = GET_DWORD(p);\r
1284                 p += 2;\r
1285         }\r
1286 \r
1287         lpDlgInfo->nbItems = GET_WORD(p);\r
1288         p++;\r
1289 \r
1290         lpDlgInfo->x = GET_WORD(p);\r
1291         p++;\r
1292 \r
1293         lpDlgInfo->y = GET_WORD(p);\r
1294         p++;\r
1295 \r
1296         lpDlgInfo->cx = GET_WORD(p);\r
1297         p++;\r
1298 \r
1299         lpDlgInfo->cy = GET_WORD(p);\r
1300         p++;\r
1301 \r
1302         // Get the menu name\r
1303 \r
1304         switch (GET_WORD(p))\r
1305         {\r
1306         case 0x0000:\r
1307                 lpDlgInfo->menuName = NULL;\r
1308                 p++;\r
1309                 break;\r
1310         case 0xffff:\r
1311                 lpDlgInfo->menuName = (LPCTSTR) (WORD) GET_WORD(p + 1);\r
1312                 p += 2;\r
1313                 break;\r
1314         default:\r
1315                 lpDlgInfo->menuName = (LPCTSTR) p;\r
1316                 p += wcslen((LPCWSTR) p) + 1;\r
1317                 break;\r
1318         }\r
1319 \r
1320         // Get the class name\r
1321 \r
1322         switch (GET_WORD(p))\r
1323         {\r
1324         case 0x0000:\r
1325                 lpDlgInfo->className = (LPCTSTR)MAKEINTATOM(32770);\r
1326                 p++;\r
1327                 break;\r
1328         case 0xffff:\r
1329                 lpDlgInfo->className = (LPCTSTR) (WORD) GET_WORD(p + 1);\r
1330                 p += 2;\r
1331                 break;\r
1332         default:\r
1333                 lpDlgInfo->className = (LPCTSTR) p;\r
1334                 p += wcslen((LPCTSTR)p) + 1;\r
1335                 break;\r
1336         }\r
1337 \r
1338         // Get the window caption\r
1339 \r
1340         lpDlgInfo->caption = (LPCTSTR)p;\r
1341         p += wcslen((LPCWSTR) p) + 1;\r
1342 \r
1343         // Get the font name\r
1344 \r
1345         if (lpDlgInfo->style & DS_SETFONT)\r
1346         {\r
1347                 lpDlgInfo->pointSize = GET_WORD(p);\r
1348                 p++;\r
1349 \r
1350                 if (lpDlgInfo->dialogEx)\r
1351                 {\r
1352                         lpDlgInfo->weight = GET_WORD(p);\r
1353                         p++;\r
1354                         lpDlgInfo->italic = LOBYTE(GET_WORD(p));\r
1355                         p++;\r
1356                 }\r
1357                 else\r
1358                 {\r
1359                         lpDlgInfo->weight = FW_DONTCARE;\r
1360                         lpDlgInfo->italic = FALSE;\r
1361                 }\r
1362 \r
1363                 lpDlgInfo->faceName = (LPCTSTR)p;\r
1364                 p += wcslen((LPCWSTR) p) + 1;\r
1365         }\r
1366         // First control is on DWORD boundary\r
1367         return (const WORD *) ((((long)p) + 3) & ~3);\r
1368 }\r
1369 \r
1370 const WORD* CResModule::GetControlInfo(const WORD* p, LPDLGITEMINFO lpDlgItemInfo, BOOL dialogEx, LPBOOL bIsID)\r
1371 {\r
1372         if (dialogEx)\r
1373         {\r
1374                 lpDlgItemInfo->helpId = GET_DWORD(p);\r
1375                 p += 2;\r
1376                 lpDlgItemInfo->exStyle = GET_DWORD(p);\r
1377                 p += 2;\r
1378                 lpDlgItemInfo->style = GET_DWORD(p);\r
1379                 p += 2;\r
1380         }\r
1381         else\r
1382         {\r
1383                 lpDlgItemInfo->helpId = 0;\r
1384                 lpDlgItemInfo->style = GET_DWORD(p);\r
1385                 p += 2;\r
1386                 lpDlgItemInfo->exStyle = GET_DWORD(p);\r
1387                 p += 2;\r
1388         }\r
1389 \r
1390         lpDlgItemInfo->x = GET_WORD(p);\r
1391         p++;\r
1392 \r
1393         lpDlgItemInfo->y = GET_WORD(p);\r
1394         p++;\r
1395 \r
1396         lpDlgItemInfo->cx = GET_WORD(p);\r
1397         p++;\r
1398 \r
1399         lpDlgItemInfo->cy = GET_WORD(p);\r
1400         p++;\r
1401 \r
1402         if (dialogEx)\r
1403         {\r
1404                 // ID is a DWORD for DIALOGEX\r
1405                 lpDlgItemInfo->id = (WORD) GET_DWORD(p);\r
1406                 p += 2;\r
1407         }\r
1408         else\r
1409         {\r
1410                 lpDlgItemInfo->id = GET_WORD(p);\r
1411                 p++;\r
1412         }\r
1413 \r
1414         if (GET_WORD(p) == 0xffff)\r
1415         {\r
1416                 GET_WORD(p + 1);\r
1417 \r
1418                 p += 2;\r
1419         }\r
1420         else\r
1421         {\r
1422                 lpDlgItemInfo->className = (LPCTSTR) p;\r
1423                 p += wcslen((LPCWSTR) p) + 1;\r
1424         }\r
1425 \r
1426         if (GET_WORD(p) == 0xffff)      // an integer ID?\r
1427         {\r
1428                 *bIsID = TRUE;\r
1429                 lpDlgItemInfo->windowName = (LPCTSTR) (DWORD) GET_WORD(p + 1);\r
1430                 p += 2;\r
1431         }\r
1432         else\r
1433         {\r
1434                 *bIsID = FALSE;\r
1435                 lpDlgItemInfo->windowName = (LPCTSTR) p;\r
1436                 p += wcslen((LPCWSTR) p) + 1;\r
1437         }\r
1438 \r
1439         if (GET_WORD(p))\r
1440         {\r
1441                 lpDlgItemInfo->data = (LPVOID) (p + 1);\r
1442                 p += GET_WORD(p) / sizeof(WORD);\r
1443         }\r
1444         else\r
1445                 lpDlgItemInfo->data = NULL;\r
1446 \r
1447         p++;\r
1448         // Next control is on DWORD boundary\r
1449         return (const WORD *)((((long)p) + 3) & ~3);\r
1450 }\r
1451 \r
1452 const WORD * CResModule::CountMemReplaceDialogResource(const WORD * res, size_t * wordcount, WORD * newDialog)\r
1453 {\r
1454         BOOL bEx = FALSE;\r
1455         DWORD style = GET_DWORD(res);\r
1456         if (newDialog)\r
1457         {\r
1458                 newDialog[(*wordcount)++] = GET_WORD(res++);\r
1459                 newDialog[(*wordcount)++] = GET_WORD(res++);\r
1460         }\r
1461         else\r
1462         {\r
1463                 res += 2;\r
1464                 (*wordcount) += 2;\r
1465         }\r
1466 \r
1467         if (style == 0xffff0001)        // DIALOGEX resource\r
1468         {\r
1469                 bEx = TRUE;\r
1470                 if (newDialog)\r
1471                 {\r
1472                         newDialog[(*wordcount)++] = GET_WORD(res++);    //help id\r
1473                         newDialog[(*wordcount)++] = GET_WORD(res++);    //help id\r
1474                         newDialog[(*wordcount)++] = GET_WORD(res++);    //exStyle\r
1475                         newDialog[(*wordcount)++] = GET_WORD(res++);    //exStyle\r
1476                         style = GET_DWORD(res);\r
1477                         newDialog[(*wordcount)++] = GET_WORD(res++);    //style\r
1478                         newDialog[(*wordcount)++] = GET_WORD(res++);    //style\r
1479                 }\r
1480                 else\r
1481                 {\r
1482                         res += 4;\r
1483                         style = GET_DWORD(res);\r
1484                         res += 2;\r
1485                         (*wordcount) += 6;\r
1486                 }\r
1487         }\r
1488         else\r
1489         {\r
1490                 bEx = FALSE;\r
1491                 if (newDialog)\r
1492                 {\r
1493                         newDialog[(*wordcount)++] = GET_WORD(res++);    //exStyle\r
1494                         newDialog[(*wordcount)++] = GET_WORD(res++);    //exStyle\r
1495                         //style = GET_DWORD(res);\r
1496                         //newDialog[(*wordcount)++] = GET_WORD(res++);  //style\r
1497                         //newDialog[(*wordcount)++] = GET_WORD(res++);  //style\r
1498                 }\r
1499                 else\r
1500                 {\r
1501                         res += 2;\r
1502                         (*wordcount) += 2;\r
1503                 }\r
1504         }\r
1505 \r
1506         if (newDialog)\r
1507                 newDialog[(*wordcount)] = GET_WORD(res);\r
1508         WORD nbItems = GET_WORD(res);\r
1509         (*wordcount)++;\r
1510         res++;\r
1511 \r
1512         if (newDialog)\r
1513                 newDialog[(*wordcount)] = GET_WORD(res); //x\r
1514         (*wordcount)++;\r
1515         res++;\r
1516 \r
1517         if (newDialog)\r
1518                 newDialog[(*wordcount)] = GET_WORD(res); //y\r
1519         (*wordcount)++;\r
1520         res++;\r
1521 \r
1522         if (newDialog)\r
1523                 newDialog[(*wordcount)] = GET_WORD(res); //cx\r
1524         (*wordcount)++;\r
1525         res++;\r
1526 \r
1527         if (newDialog)\r
1528                 newDialog[(*wordcount)] = GET_WORD(res); //cy\r
1529         (*wordcount)++;\r
1530         res++;\r
1531 \r
1532         // Get the menu name\r
1533 \r
1534         switch (GET_WORD(res))\r
1535         {\r
1536         case 0x0000:\r
1537                 if (newDialog)\r
1538                         newDialog[(*wordcount)] = GET_WORD(res);\r
1539                 (*wordcount)++;\r
1540                 res++;\r
1541                 break;\r
1542         case 0xffff:\r
1543                 if (newDialog)\r
1544                 {\r
1545                         newDialog[(*wordcount)++] = GET_WORD(res++);\r
1546                         newDialog[(*wordcount)++] = GET_WORD(res++);\r
1547                 }\r
1548                 else\r
1549                 {\r
1550                         (*wordcount) += 2;\r
1551                         res += 2;\r
1552                 }\r
1553                 break;\r
1554         default:\r
1555                 if (newDialog)\r
1556                 {\r
1557                         wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);\r
1558                 }\r
1559                 (*wordcount) += wcslen((LPCWSTR) res) + 1;\r
1560                 res += wcslen((LPCWSTR) res) + 1;\r
1561                 break;\r
1562         }\r
1563 \r
1564         // Get the class name\r
1565 \r
1566         switch (GET_WORD(res))\r
1567         {\r
1568         case 0x0000:\r
1569                 if (newDialog)\r
1570                         newDialog[(*wordcount)] = GET_WORD(res);\r
1571                 (*wordcount)++;\r
1572                 res++;\r
1573                 break;\r
1574         case 0xffff:\r
1575                 if (newDialog)\r
1576                 {\r
1577                         newDialog[(*wordcount)++] = GET_WORD(res++);\r
1578                         newDialog[(*wordcount)++] = GET_WORD(res++);\r
1579                 }\r
1580                 else\r
1581                 {\r
1582                         (*wordcount) += 2;\r
1583                         res += 2;\r
1584                 }\r
1585                 break;\r
1586         default:\r
1587                 if (newDialog)\r
1588                 {\r
1589                         wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);\r
1590                 }\r
1591                 (*wordcount) += wcslen((LPCWSTR) res) + 1;\r
1592                 res += wcslen((LPCWSTR) res) + 1;\r
1593                 break;\r
1594         }\r
1595 \r
1596         // Get the window caption\r
1597 \r
1598         ReplaceStr((LPCWSTR)res, newDialog, wordcount, &m_bTranslatedDialogStrings, &m_bDefaultDialogStrings);\r
1599         res += wcslen((LPCWSTR)res) + 1;\r
1600 \r
1601         // Get the font name\r
1602 \r
1603         if (style & DS_SETFONT)\r
1604         {\r
1605                 if (newDialog)\r
1606                         newDialog[(*wordcount)] = GET_WORD(res);\r
1607                 res++;\r
1608                 (*wordcount)++;\r
1609 \r
1610                 if (bEx)\r
1611                 {\r
1612                         if (newDialog)\r
1613                         {\r
1614                                 newDialog[(*wordcount)++] = GET_WORD(res++);\r
1615                                 newDialog[(*wordcount)++] = GET_WORD(res++);\r
1616                         }\r
1617                         else\r
1618                         {\r
1619                                 res += 2;\r
1620                                 (*wordcount) += 2;\r
1621                         }\r
1622                 }\r
1623 \r
1624                 if (newDialog)\r
1625                         wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);\r
1626                 (*wordcount) += wcslen((LPCWSTR)res) + 1;\r
1627                 res += wcslen((LPCWSTR)res) + 1;\r
1628         }\r
1629         // First control is on DWORD boundary\r
1630         while ((*wordcount)%2)\r
1631                 (*wordcount)++;\r
1632         while ((ULONG)res % 4)\r
1633                 res++;\r
1634 \r
1635         while (nbItems--)\r
1636         {\r
1637                 res = ReplaceControlInfo(res, wordcount, newDialog, bEx);\r
1638         }\r
1639         return res;\r
1640 }\r
1641 \r
1642 const WORD* CResModule::ReplaceControlInfo(const WORD * res, size_t * wordcount, WORD * newDialog, BOOL bEx)\r
1643 {\r
1644         if (bEx)\r
1645         {\r
1646                 if (newDialog)\r
1647                 {\r
1648                         newDialog[(*wordcount)++] = GET_WORD(res++);    //helpid\r
1649                         newDialog[(*wordcount)++] = GET_WORD(res++);    //helpid\r
1650                 }\r
1651                 else\r
1652                 {\r
1653                         res += 2;\r
1654                         (*wordcount) += 2;\r
1655                 }\r
1656         }\r
1657         if (newDialog)\r
1658         {\r
1659                 LONG * exStyle = (LONG*)&newDialog[(*wordcount)];\r
1660                 newDialog[(*wordcount)++] = GET_WORD(res++);    //exStyle\r
1661                 newDialog[(*wordcount)++] = GET_WORD(res++);    //exStyle\r
1662                 if (m_bRTL)\r
1663                         *exStyle |= WS_EX_RTLREADING;\r
1664         }\r
1665         else\r
1666         {\r
1667                 res += 2;\r
1668                 (*wordcount) += 2;\r
1669         }\r
1670 \r
1671         if (newDialog)\r
1672         {\r
1673                 newDialog[(*wordcount)++] = GET_WORD(res++);    //style\r
1674                 newDialog[(*wordcount)++] = GET_WORD(res++);    //style\r
1675         }\r
1676         else\r
1677         {\r
1678                 res += 2;\r
1679                 (*wordcount) += 2;\r
1680         }\r
1681 \r
1682         if (newDialog)\r
1683                 newDialog[(*wordcount)] = GET_WORD(res);        //x\r
1684         res++;\r
1685         (*wordcount)++;\r
1686 \r
1687         if (newDialog)\r
1688                 newDialog[(*wordcount)] = GET_WORD(res);        //y\r
1689         res++;\r
1690         (*wordcount)++;\r
1691 \r
1692         if (newDialog)\r
1693                 newDialog[(*wordcount)] = GET_WORD(res);        //cx\r
1694         res++;\r
1695         (*wordcount)++;\r
1696 \r
1697         if (newDialog)\r
1698                 newDialog[(*wordcount)] = GET_WORD(res);        //cy\r
1699         res++;\r
1700         (*wordcount)++;\r
1701 \r
1702         if (bEx)\r
1703         {\r
1704                 // ID is a DWORD for DIALOGEX\r
1705                 if (newDialog)\r
1706                 {\r
1707                         newDialog[(*wordcount)++] = GET_WORD(res++);\r
1708                         newDialog[(*wordcount)++] = GET_WORD(res++);\r
1709                 }\r
1710                 else\r
1711                 {\r
1712                         res += 2;\r
1713                         (*wordcount) += 2;\r
1714                 }\r
1715         }\r
1716         else\r
1717         {\r
1718                 if (newDialog)\r
1719                         newDialog[(*wordcount)] = GET_WORD(res);\r
1720                 res++;\r
1721                 (*wordcount)++;\r
1722         }\r
1723 \r
1724         if (GET_WORD(res) == 0xffff)    //classID\r
1725         {\r
1726                 if (newDialog)\r
1727                 {\r
1728                         newDialog[(*wordcount)++] = GET_WORD(res++);\r
1729                         newDialog[(*wordcount)++] = GET_WORD(res++);\r
1730                 }\r
1731                 else\r
1732                 {\r
1733                         res += 2;\r
1734                         (*wordcount) += 2;\r
1735                 }\r
1736         }\r
1737         else\r
1738         {\r
1739                 if (newDialog)\r
1740                         wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);\r
1741                 (*wordcount) += wcslen((LPCWSTR) res) + 1;\r
1742                 res += wcslen((LPCWSTR) res) + 1;\r
1743         }\r
1744 \r
1745         if (GET_WORD(res) == 0xffff)    // an integer ID?\r
1746         {\r
1747                 if (newDialog)\r
1748                 {\r
1749                         newDialog[(*wordcount)++] = GET_WORD(res++);\r
1750                         newDialog[(*wordcount)++] = GET_WORD(res++);\r
1751                 }\r
1752                 else\r
1753                 {\r
1754                         res += 2;\r
1755                         (*wordcount) += 2;\r
1756                 }\r
1757         }\r
1758         else\r
1759         {\r
1760                 ReplaceStr((LPCWSTR)res, newDialog, wordcount, &m_bTranslatedDialogStrings, &m_bDefaultDialogStrings);\r
1761                 res += wcslen((LPCWSTR)res) + 1;\r
1762         }\r
1763 \r
1764         if (newDialog)\r
1765                 memcpy(&newDialog[(*wordcount)], res, (GET_WORD(res)+1)*sizeof(WORD));\r
1766         (*wordcount) += (GET_WORD(res)+1);\r
1767         res += (GET_WORD(res)+1);\r
1768         // Next control is on DWORD boundary\r
1769         while ((*wordcount) % 2)\r
1770                 (*wordcount)++;\r
1771         return (const WORD *)((((long)res) + 3) & ~3);\r
1772 }\r
1773 \r
1774 BOOL CALLBACK CResModule::EnumResNameCallback(HMODULE /*hModule*/, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)\r
1775 {\r
1776         CResModule* lpResModule = (CResModule*)lParam;\r
1777 \r
1778         if (lpszType == RT_STRING)\r
1779         {\r
1780                 if (IS_INTRESOURCE(lpszName))\r
1781                 {\r
1782                         if (!lpResModule->ExtractString(LOWORD(lpszName)))\r
1783                                 return FALSE;\r
1784                 }\r
1785         } \r
1786         else if (lpszType == RT_MENU)\r
1787         {\r
1788                 if (IS_INTRESOURCE(lpszName))\r
1789                 {\r
1790                         if (!lpResModule->ExtractMenu(LOWORD(lpszName)))\r
1791                                 return FALSE;\r
1792                 }\r
1793         }\r
1794         else if (lpszType == RT_DIALOG)\r
1795         {\r
1796                 if (IS_INTRESOURCE(lpszName))\r
1797                 {\r
1798                         if (!lpResModule->ExtractDialog(LOWORD(lpszName)))\r
1799                                 return FALSE;\r
1800                 }\r
1801         }\r
1802         else if (lpszType == RT_ACCELERATOR)\r
1803         {\r
1804                 if (IS_INTRESOURCE(lpszName))\r
1805                 {\r
1806                         if (!lpResModule->ExtractAccelerator(LOWORD(lpszName)))\r
1807                                 return FALSE;\r
1808                 }\r
1809         }\r
1810 \r
1811         return TRUE;\r
1812 }\r
1813 \r
1814 #pragma warning(push)\r
1815 #pragma warning(disable: 4189)\r
1816 BOOL CALLBACK CResModule::EnumResNameWriteCallback(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)\r
1817 {\r
1818         CResModule* lpResModule = (CResModule*)lParam;\r
1819         return EnumResourceLanguages(hModule, lpszType, lpszName, (ENUMRESLANGPROC)&lpResModule->EnumResWriteLangCallback, lParam);\r
1820 }\r
1821 #pragma warning(pop)\r
1822 \r
1823 BOOL CALLBACK CResModule::EnumResWriteLangCallback(HMODULE /*hModule*/, LPCTSTR lpszType, LPTSTR lpszName, WORD wLanguage, LONG_PTR lParam)\r
1824 {\r
1825         BOOL bRes = FALSE;\r
1826         CResModule* lpResModule = (CResModule*)lParam;\r
1827 \r
1828 \r
1829         int count = 0;\r
1830         do \r
1831         {\r
1832                 lpResModule->m_hUpdateRes = BeginUpdateResource(lpResModule->sDestFile.c_str(), FALSE);\r
1833                 if (lpResModule->m_hUpdateRes == NULL)\r
1834                         Sleep(100);\r
1835                 count++;\r
1836         } while ((lpResModule->m_hUpdateRes == NULL)&&(count < 5));\r
1837 \r
1838         if (lpszType == RT_STRING)\r
1839         {\r
1840                 if (IS_INTRESOURCE(lpszName))\r
1841                 {\r
1842                         bRes = lpResModule->ReplaceString(LOWORD(lpszName), wLanguage);\r
1843                 }\r
1844         } \r
1845         else if (lpszType == RT_MENU)\r
1846         {\r
1847                 if (IS_INTRESOURCE(lpszName))\r
1848                 {\r
1849                         bRes = lpResModule->ReplaceMenu(LOWORD(lpszName), wLanguage);\r
1850                 }\r
1851         }\r
1852         else if (lpszType == RT_DIALOG)\r
1853         {\r
1854                 if (IS_INTRESOURCE(lpszName))\r
1855                 {\r
1856                         bRes = lpResModule->ReplaceDialog(LOWORD(lpszName), wLanguage);\r
1857                 }\r
1858         }\r
1859         else if (lpszType == RT_ACCELERATOR)\r
1860         {\r
1861                 if (IS_INTRESOURCE(lpszName))\r
1862                 {\r
1863                         bRes = lpResModule->ReplaceAccelerator(LOWORD(lpszName), wLanguage);\r
1864                 }\r
1865         }\r
1866 \r
1867         if (!EndUpdateResource(lpResModule->m_hUpdateRes, !bRes))\r
1868                 MYERROR;\r
1869         return bRes;\r
1870 \r
1871 }\r
1872 \r
1873 void CResModule::ReplaceStr(LPCWSTR src, WORD * dest, size_t * count, int * translated, int * def)\r
1874 {\r
1875         TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];\r
1876         SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));\r
1877         wcscpy(pBuf, src);\r
1878         CUtils::StringExtend(pBuf);\r
1879 \r
1880         std::wstring wstr = std::wstring(pBuf);\r
1881         RESOURCEENTRY entry = m_StringEntries[wstr];\r
1882         if (entry.msgstr.size())\r
1883         {\r
1884                 wcscpy(pBuf, entry.msgstr.c_str());\r
1885                 CUtils::StringCollapse(pBuf);\r
1886                 if (dest)\r
1887                         wcscpy((wchar_t *)&dest[(*count)], pBuf);\r
1888                 (*count) += wcslen(pBuf)+1;\r
1889                 (*translated)++;\r
1890         }\r
1891         else\r
1892         {\r
1893                 if (dest)\r
1894                         wcscpy((wchar_t *)&dest[(*count)], src);\r
1895                 (*count) += wcslen(src) + 1;\r
1896                 if (wcslen(src))\r
1897                         (*def)++;\r
1898         }\r
1899         delete [] pBuf;\r
1900 }\r