Fixed issue #1220: ext/CrashServer/CommonLibs/Zlib/Zlib.vcproj immediate dir Win32...
[TortoiseGit.git] / src / ResText / ResModule.cpp
blob1add1662492162b55d18b59bbc2790ff9aa3b35b
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2008, 2010-2012 - TortoiseSVN
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 #include "StdAfx.h"
19 #include "Utils.h"
20 #include ".\resmodule.h"
21 #include <memory>
23 #define MYERROR {CUtils::Error(); return FALSE;}
25 CResModule::CResModule(void)
26 : m_bTranslatedStrings(0)
27 , m_bDefaultStrings(0)
28 , m_bTranslatedDialogStrings(0)
29 , m_bDefaultDialogStrings(0)
30 , m_bTranslatedMenuStrings(0)
31 , m_bDefaultMenuStrings(0)
32 , m_bTranslatedAcceleratorStrings(0)
33 , m_bDefaultAcceleratorStrings(0)
34 , m_wTargetLang(0)
35 , m_hResDll(NULL)
36 , m_hUpdateRes(NULL)
37 , m_bQuiet(false)
38 , m_bRTL(false)
39 , m_bAdjustEOLs(false)
43 CResModule::~CResModule(void)
47 BOOL CResModule::ExtractResources(std::vector<std::wstring> filelist, LPCTSTR lpszPOFilePath, BOOL bNoUpdate, LPCTSTR lpszHeaderFile)
49 for (std::vector<std::wstring>::iterator I = filelist.begin(); I != filelist.end(); ++I)
51 m_hResDll = LoadLibraryEx(I->c_str(), NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE|LOAD_LIBRARY_AS_DATAFILE);
52 if (m_hResDll == NULL)
53 MYERROR;
55 size_t nEntries = m_StringEntries.size();
56 // fill in the std::map with all translatable entries
58 if (!m_bQuiet)
59 _ftprintf(stdout, _T("Extracting StringTable...."));
60 EnumResourceNames(m_hResDll, RT_STRING, EnumResNameCallback, (LONG_PTR)this);
61 if (!m_bQuiet)
62 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
63 nEntries = m_StringEntries.size();
65 if (!m_bQuiet)
66 _ftprintf(stdout, _T("Extracting Dialogs........"));
67 EnumResourceNames(m_hResDll, RT_DIALOG, EnumResNameCallback, (LONG_PTR)this);
68 if (!m_bQuiet)
69 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
70 nEntries = m_StringEntries.size();
72 if (!m_bQuiet)
73 _ftprintf(stdout, _T("Extracting Menus.........."));
74 EnumResourceNames(m_hResDll, RT_MENU, EnumResNameCallback, (LONG_PTR)this);
75 if (!m_bQuiet)
76 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
77 nEntries = m_StringEntries.size();
78 if (!m_bQuiet)
79 _ftprintf(stdout, _T("Extracting Accelerators..."));
80 EnumResourceNames(m_hResDll, RT_ACCELERATOR, EnumResNameCallback, (LONG_PTR)this);
81 if (!m_bQuiet)
82 _ftprintf(stdout, _T("%4d Accelerators\n"), m_StringEntries.size()-nEntries);
83 nEntries = m_StringEntries.size();
85 // parse a probably existing file and update the translations which are
86 // already done
87 m_StringEntries.ParseFile(lpszPOFilePath, !bNoUpdate, m_bAdjustEOLs);
89 FreeLibrary(m_hResDll);
92 // at last, save the new file
93 return m_StringEntries.SaveFile(lpszPOFilePath, lpszHeaderFile);
96 BOOL CResModule::ExtractResources(LPCTSTR lpszSrcLangDllPath, LPCTSTR lpszPoFilePath, BOOL bNoUpdate, LPCTSTR lpszHeaderFile)
98 m_hResDll = LoadLibraryEx(lpszSrcLangDllPath, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE|LOAD_LIBRARY_AS_DATAFILE);
99 if (m_hResDll == NULL)
100 MYERROR;
102 size_t nEntries = 0;
103 // fill in the std::map with all translatable entries
105 if (!m_bQuiet)
106 _ftprintf(stdout, _T("Extracting StringTable...."));
107 EnumResourceNames(m_hResDll, RT_STRING, EnumResNameCallback, (LONG_PTR)this);
108 if (!m_bQuiet)
109 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size());
110 nEntries = m_StringEntries.size();
112 if (!m_bQuiet)
113 _ftprintf(stdout, _T("Extracting Dialogs........"));
114 EnumResourceNames(m_hResDll, RT_DIALOG, EnumResNameCallback, (LONG_PTR)this);
115 if (!m_bQuiet)
116 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
117 nEntries = m_StringEntries.size();
119 if (!m_bQuiet)
120 _ftprintf(stdout, _T("Extracting Menus.........."));
121 EnumResourceNames(m_hResDll, RT_MENU, EnumResNameCallback, (LONG_PTR)this);
122 if (!m_bQuiet)
123 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
124 nEntries = m_StringEntries.size();
126 if (!m_bQuiet)
127 _ftprintf(stdout, _T("Extracting Accelerators..."));
128 EnumResourceNames(m_hResDll, RT_ACCELERATOR, EnumResNameCallback, (LONG_PTR)this);
129 if (!m_bQuiet)
130 _ftprintf(stdout, _T("%4d Accelerators\n"), m_StringEntries.size()-nEntries);
131 nEntries = m_StringEntries.size();
133 // parse a probably existing file and update the translations which are
134 // already done
135 m_StringEntries.ParseFile(lpszPoFilePath, !bNoUpdate, m_bAdjustEOLs);
137 // at last, save the new file
138 if (!m_StringEntries.SaveFile(lpszPoFilePath, lpszHeaderFile))
139 goto DONE_ERROR;
141 FreeLibrary(m_hResDll);
142 return TRUE;
144 DONE_ERROR:
145 if (m_hResDll)
146 FreeLibrary(m_hResDll);
147 return FALSE;
150 BOOL CResModule::CreateTranslatedResources(LPCTSTR lpszSrcLangDllPath, LPCTSTR lpszDestLangDllPath, LPCTSTR lpszPOFilePath)
152 if (!CopyFile(lpszSrcLangDllPath, lpszDestLangDllPath, FALSE))
153 MYERROR;
155 int count = 0;
158 m_hResDll = LoadLibraryEx (lpszSrcLangDllPath, NULL, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE|LOAD_LIBRARY_AS_IMAGE_RESOURCE|LOAD_IGNORE_CODE_AUTHZ_LEVEL);
159 if (m_hResDll == NULL)
160 Sleep(100);
161 count++;
162 } while ((m_hResDll == NULL)&&(count < 10));
164 if (m_hResDll == NULL)
165 MYERROR;
167 sDestFile = std::wstring(lpszDestLangDllPath);
169 // get all translated strings
170 if (!m_StringEntries.ParseFile(lpszPOFilePath, FALSE, m_bAdjustEOLs))
171 goto DONE_ERROR;
172 m_bTranslatedStrings = 0;
173 m_bDefaultStrings = 0;
174 m_bTranslatedDialogStrings = 0;
175 m_bDefaultDialogStrings = 0;
176 m_bTranslatedMenuStrings = 0;
177 m_bDefaultMenuStrings = 0;
178 m_bTranslatedAcceleratorStrings = 0;
179 m_bDefaultAcceleratorStrings = 0;
181 BOOL bRes = FALSE;
182 count = 0;
185 m_hUpdateRes = BeginUpdateResource(sDestFile.c_str(), FALSE);
186 if (m_hUpdateRes == NULL)
187 Sleep(100);
188 count++;
189 } while ((m_hUpdateRes == NULL)&&(count < 10));
191 if (m_hUpdateRes == NULL)
192 MYERROR;
195 if (!m_bQuiet)
196 _ftprintf(stdout, _T("Translating StringTable..."));
197 bRes = EnumResourceNames(m_hResDll, RT_STRING, EnumResNameWriteCallback, (LONG_PTR)this);
198 if (!m_bQuiet)
199 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedStrings, m_bDefaultStrings);
201 if (!m_bQuiet)
202 _ftprintf(stdout, _T("Translating Dialogs......."));
203 bRes = EnumResourceNames(m_hResDll, RT_DIALOG, EnumResNameWriteCallback, (LONG_PTR)this);
204 if (!m_bQuiet)
205 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedDialogStrings, m_bDefaultDialogStrings);
207 if (!m_bQuiet)
208 _ftprintf(stdout, _T("Translating Menus........."));
209 bRes = EnumResourceNames(m_hResDll, RT_MENU, EnumResNameWriteCallback, (LONG_PTR)this);
210 if (!m_bQuiet)
211 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedMenuStrings, m_bDefaultMenuStrings);
213 if (!m_bQuiet)
214 _ftprintf(stdout, _T("Translating Accelerators.."));
215 bRes = EnumResourceNames(m_hResDll, RT_ACCELERATOR, EnumResNameWriteCallback, (LONG_PTR)this);
216 if (!m_bQuiet)
217 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedAcceleratorStrings, m_bDefaultAcceleratorStrings);
219 bRes = TRUE;
220 if (!EndUpdateResource(m_hUpdateRes, !bRes))
221 MYERROR;
223 FreeLibrary(m_hResDll);
224 return TRUE;
225 DONE_ERROR:
226 if (m_hResDll)
227 FreeLibrary(m_hResDll);
228 return FALSE;
231 BOOL CResModule::ExtractString(UINT nID)
233 HRSRC hrsrc = FindResource(m_hResDll, MAKEINTRESOURCE(nID), RT_STRING);
234 HGLOBAL hglStringTable;
235 LPWSTR p;
237 if (!hrsrc)
238 MYERROR;
239 hglStringTable = LoadResource(m_hResDll, hrsrc);
241 if (!hglStringTable)
242 goto DONE_ERROR;
243 p = (LPWSTR)LockResource(hglStringTable);
245 if (p == NULL)
246 goto DONE_ERROR;
247 /* [Block of 16 strings. The strings are Pascal style with a WORD
248 length preceding the string. 16 strings are always written, even
249 if not all slots are full. Any slots in the block with no string
250 have a zero WORD for the length.]
253 //first check how much memory we need
254 LPWSTR pp = p;
255 for (int i=0; i<16; ++i)
257 int len = GET_WORD(pp);
258 pp++;
259 std::wstring msgid = std::wstring(pp, len);
260 WCHAR * pBuf = new WCHAR[MAX_STRING_LENGTH*2];
261 SecureZeroMemory(pBuf, MAX_STRING_LENGTH*2*sizeof(WCHAR));
262 wcscpy(pBuf, msgid.c_str());
263 CUtils::StringExtend(pBuf);
265 if (wcslen(pBuf))
267 std::wstring str = std::wstring(pBuf);
268 RESOURCEENTRY entry = m_StringEntries[str];
269 entry.resourceIDs.insert(nID);
270 if (wcschr(str.c_str(), '%'))
271 entry.flag = _T("#, c-format");
272 m_StringEntries[str] = entry;
274 delete [] pBuf;
275 pp += len;
277 UnlockResource(hglStringTable);
278 FreeResource(hglStringTable);
279 return TRUE;
280 DONE_ERROR:
281 UnlockResource(hglStringTable);
282 FreeResource(hglStringTable);
283 MYERROR;
286 BOOL CResModule::ReplaceString(UINT nID, WORD wLanguage)
288 HRSRC hrsrc = FindResourceEx(m_hResDll, RT_STRING, MAKEINTRESOURCE(nID), wLanguage);
289 HGLOBAL hglStringTable;
290 LPWSTR p;
292 if (!hrsrc)
293 MYERROR;
294 hglStringTable = LoadResource(m_hResDll, hrsrc);
296 if (!hglStringTable)
297 goto DONE_ERROR;
298 p = (LPWSTR)LockResource(hglStringTable);
300 if (p == NULL)
301 goto DONE_ERROR;
302 /* [Block of 16 strings. The strings are Pascal style with a WORD
303 length preceding the string. 16 strings are always written, even
304 if not all slots are full. Any slots in the block with no string
305 have a zero WORD for the length.]
308 //first check how much memory we need
309 size_t nMem = 0;
310 LPWSTR pp = p;
311 for (int i=0; i<16; ++i)
313 nMem++;
314 size_t len = GET_WORD(pp);
315 pp++;
316 std::wstring msgid = std::wstring(pp, len);
317 WCHAR * pBuf = new WCHAR[MAX_STRING_LENGTH*2];
318 SecureZeroMemory(pBuf, MAX_STRING_LENGTH*2*sizeof(WCHAR));
319 wcscpy(pBuf, msgid.c_str());
320 CUtils::StringExtend(pBuf);
321 msgid = std::wstring(pBuf);
323 RESOURCEENTRY resEntry;
324 resEntry = m_StringEntries[msgid];
325 wcscpy(pBuf, resEntry.msgstr.c_str());
326 CUtils::StringCollapse(pBuf);
327 size_t newlen = wcslen(pBuf);
328 if (newlen)
329 nMem += newlen;
330 else
331 nMem += len;
332 pp += len;
333 delete [] pBuf;
336 WORD * newTable = new WORD[nMem + (nMem % 2)];
337 SecureZeroMemory(newTable, (nMem + (nMem % 2))*2);
339 size_t index = 0;
340 for (int i=0; i<16; ++i)
342 int len = GET_WORD(p);
343 p++;
344 std::wstring msgid = std::wstring(p, len);
345 WCHAR * pBuf = new WCHAR[MAX_STRING_LENGTH*2];
346 SecureZeroMemory(pBuf, MAX_STRING_LENGTH*2*sizeof(WCHAR));
347 wcscpy(pBuf, msgid.c_str());
348 CUtils::StringExtend(pBuf);
349 msgid = std::wstring(pBuf);
351 RESOURCEENTRY resEntry;
352 resEntry = m_StringEntries[msgid];
353 wcscpy(pBuf, resEntry.msgstr.c_str());
354 CUtils::StringCollapse(pBuf);
355 size_t newlen = wcslen(pBuf);
356 if (newlen)
358 newTable[index++] = (WORD)newlen;
359 wcsncpy((wchar_t *)&newTable[index], pBuf, newlen);
360 index += newlen;
361 m_bTranslatedStrings++;
363 else
365 newTable[index++] = (WORD)len;
366 if (len)
367 wcsncpy((wchar_t *)&newTable[index], p, len);
368 index += len;
369 if (len)
370 m_bDefaultStrings++;
372 p += len;
373 delete [] pBuf;
376 if (!UpdateResource(m_hUpdateRes, RT_STRING, MAKEINTRESOURCE(nID), (m_wTargetLang ? m_wTargetLang : wLanguage), newTable, (DWORD)(nMem + (nMem % 2))*2))
378 delete [] newTable;
379 goto DONE_ERROR;
382 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_STRING, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))
384 delete [] newTable;
385 goto DONE_ERROR;
387 delete [] newTable;
388 UnlockResource(hglStringTable);
389 FreeResource(hglStringTable);
390 return TRUE;
391 DONE_ERROR:
392 UnlockResource(hglStringTable);
393 FreeResource(hglStringTable);
394 MYERROR;
397 BOOL CResModule::ExtractMenu(UINT nID)
399 HRSRC hrsrc = FindResource(m_hResDll, MAKEINTRESOURCE(nID), RT_MENU);
400 HGLOBAL hglMenuTemplate;
401 WORD version, offset;
402 DWORD dwHelpId;
403 const WORD *p, *p0;
405 if (!hrsrc)
406 MYERROR;
408 hglMenuTemplate = LoadResource(m_hResDll, hrsrc);
410 if (!hglMenuTemplate)
411 MYERROR;
413 p = (const WORD*)LockResource(hglMenuTemplate);
415 if (p == NULL)
416 MYERROR;
418 // Standard MENU resource
419 //struct MenuHeader {
420 // WORD wVersion; // Currently zero
421 // WORD cbHeaderSize; // Also zero
422 //};
424 // MENUEX resource
425 //struct MenuExHeader {
426 // WORD wVersion; // One
427 // WORD wOffset;
428 // DWORD dwHelpId;
429 //};
430 p0 = p;
431 version = GET_WORD(p);
433 p++;
435 switch (version)
437 case 0:
439 offset = GET_WORD(p);
440 p += offset;
441 p++;
442 if (!ParseMenuResource(p))
443 goto DONE_ERROR;
445 break;
446 case 1:
448 offset = GET_WORD(p);
449 p++;
450 dwHelpId = GET_DWORD(p);
451 if (!ParseMenuExResource(p0 + offset))
452 goto DONE_ERROR;
454 break;
455 default:
456 goto DONE_ERROR;
459 UnlockResource(hglMenuTemplate);
460 FreeResource(hglMenuTemplate);
461 return TRUE;
463 DONE_ERROR:
464 UnlockResource(hglMenuTemplate);
465 FreeResource(hglMenuTemplate);
466 MYERROR;
469 BOOL CResModule::ReplaceMenu(UINT nID, WORD wLanguage)
471 HRSRC hrsrc = FindResourceEx(m_hResDll, RT_MENU, MAKEINTRESOURCE(nID), wLanguage);
472 HGLOBAL hglMenuTemplate;
473 WORD version, offset;
474 LPWSTR p;
475 WORD *p0;
476 DWORD dwHelpId;
478 if (!hrsrc)
479 MYERROR; //just the language wasn't found
481 hglMenuTemplate = LoadResource(m_hResDll, hrsrc);
483 if (!hglMenuTemplate)
484 MYERROR;
486 p = (LPWSTR)LockResource(hglMenuTemplate);
488 if (p == NULL)
489 MYERROR;
491 //struct MenuHeader {
492 // WORD wVersion; // Currently zero
493 // WORD cbHeaderSize; // Also zero
494 //};
496 // MENUEX resource
497 //struct MenuExHeader {
498 // WORD wVersion; // One
499 // WORD wOffset;
500 // DWORD dwHelpId;
501 //};
502 p0 = (WORD *)p;
503 version = GET_WORD(p);
505 p++;
507 switch (version)
509 case 0:
511 offset = GET_WORD(p);
512 p += offset;
513 p++;
514 size_t nMem = 0;
515 if (!CountMemReplaceMenuResource((WORD *)p, &nMem, NULL))
516 goto DONE_ERROR;
517 WORD * newMenu = new WORD[nMem + (nMem % 2)+2];
518 SecureZeroMemory(newMenu, (nMem + (nMem % 2)+2)*2);
519 size_t index = 2; // MenuHeader has 2 WORDs zero
520 if (!CountMemReplaceMenuResource((WORD *)p, &index, newMenu))
522 delete [] newMenu;
523 goto DONE_ERROR;
526 if (!UpdateResource(m_hUpdateRes, RT_MENU, MAKEINTRESOURCE(nID), (m_wTargetLang ? m_wTargetLang : wLanguage), newMenu, (DWORD)(nMem + (nMem % 2)+2)*2))
528 delete [] newMenu;
529 goto DONE_ERROR;
532 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_MENU, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))
534 delete [] newMenu;
535 goto DONE_ERROR;
537 delete [] newMenu;
539 break;
540 case 1:
542 offset = GET_WORD(p);
543 p++;
544 dwHelpId = GET_DWORD(p);
545 size_t nMem = 0;
546 if (!CountMemReplaceMenuExResource((WORD *)(p0 + offset), &nMem, NULL))
547 goto DONE_ERROR;
548 WORD * newMenu = new WORD[nMem + (nMem % 2) + 4];
549 SecureZeroMemory(newMenu, (nMem + (nMem % 2) + 4) * 2);
550 CopyMemory(newMenu, p0, 2 * sizeof(WORD) + sizeof(DWORD));
551 size_t index = 4; // MenuExHeader has 2 x WORD + 1 x DWORD
552 if (!CountMemReplaceMenuExResource((WORD *)(p0 + offset), &index, newMenu))
554 delete [] newMenu;
555 goto DONE_ERROR;
558 if (!UpdateResource(m_hUpdateRes, RT_MENU, MAKEINTRESOURCE(nID), (m_wTargetLang ? m_wTargetLang : wLanguage), newMenu, (DWORD)(nMem + (nMem % 2) + 4) * 2))
560 delete [] newMenu;
561 goto DONE_ERROR;
564 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_MENU, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))
566 delete [] newMenu;
567 goto DONE_ERROR;
569 delete [] newMenu;
571 break;
572 default:
573 goto DONE_ERROR;
576 UnlockResource(hglMenuTemplate);
577 FreeResource(hglMenuTemplate);
578 return TRUE;
580 DONE_ERROR:
581 UnlockResource(hglMenuTemplate);
582 FreeResource(hglMenuTemplate);
583 MYERROR;
586 const WORD* CResModule::ParseMenuResource(const WORD * res)
588 WORD flags;
589 WORD id = 0;
590 LPCWSTR str;
592 //struct PopupMenuItem {
593 // WORD fItemFlags;
594 // WCHAR szItemText[];
595 //};
596 //struct NormalMenuItem {
597 // WORD fItemFlags;
598 // WORD wMenuID;
599 // WCHAR szItemText[];
600 //};
604 flags = GET_WORD(res);
605 res++;
606 if (!(flags & MF_POPUP))
608 id = GET_WORD(res); //normal menu item
609 res++;
611 else
612 id = (WORD)-1; //popup menu item
614 str = (LPCWSTR)res;
615 size_t l = wcslen(str)+1;
616 res += l;
618 if (flags & MF_POPUP)
620 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
621 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
622 _tcscpy(pBuf, str);
623 CUtils::StringExtend(pBuf);
625 std::wstring wstr = std::wstring(pBuf);
626 RESOURCEENTRY entry = m_StringEntries[wstr];
627 if (id)
628 entry.resourceIDs.insert(id);
630 m_StringEntries[wstr] = entry;
631 delete [] pBuf;
633 if ((res = ParseMenuResource(res))==0)
634 return NULL;
636 else if (id != 0)
638 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
639 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
640 _tcscpy(pBuf, str);
641 CUtils::StringExtend(pBuf);
643 std::wstring wstr = std::wstring(pBuf);
644 RESOURCEENTRY entry = m_StringEntries[wstr];
645 entry.resourceIDs.insert(id);
647 TCHAR szTempBuf[1024];
648 _stprintf(szTempBuf, _T("#: MenuEntry; ID:%d"), id);
649 MENUENTRY menu_entry;
650 menu_entry.wID = id;
651 menu_entry.reference = szTempBuf;
652 menu_entry.msgstr = wstr;
654 m_StringEntries[wstr] = entry;
655 m_MenuEntries[id] = menu_entry;
656 delete [] pBuf;
658 } while (!(flags & MF_END));
659 return res;
662 const WORD* CResModule::CountMemReplaceMenuResource(const WORD * res, size_t * wordcount, WORD * newMenu)
664 WORD flags;
665 WORD id = 0;
667 //struct PopupMenuItem {
668 // WORD fItemFlags;
669 // WCHAR szItemText[];
670 //};
671 //struct NormalMenuItem {
672 // WORD fItemFlags;
673 // WORD wMenuID;
674 // WCHAR szItemText[];
675 //};
679 flags = GET_WORD(res);
680 res++;
681 if (newMenu == NULL)
682 (*wordcount)++;
683 else
684 newMenu[(*wordcount)++] = flags;
685 if (!(flags & MF_POPUP))
687 id = GET_WORD(res); //normal menu item
688 res++;
689 if (newMenu == NULL)
690 (*wordcount)++;
691 else
692 newMenu[(*wordcount)++] = id;
694 else
695 id = (WORD)-1; //popup menu item
697 if (flags & MF_POPUP)
699 ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);
700 res += wcslen((LPCWSTR)res) + 1;
702 if ((res = CountMemReplaceMenuResource(res, wordcount, newMenu))==0)
703 return NULL;
705 else if (id != 0)
707 ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);
708 res += wcslen((LPCWSTR)res) + 1;
710 else
712 if (newMenu)
713 wcscpy((wchar_t *)&newMenu[(*wordcount)], (LPCWSTR)res);
714 (*wordcount) += wcslen((LPCWSTR)res) + 1;
715 res += wcslen((LPCWSTR)res) + 1;
717 } while (!(flags & MF_END));
718 return res;
721 const WORD* CResModule::ParseMenuExResource(const WORD * res)
723 DWORD dwType, dwState, menuId;
724 WORD bResInfo;
725 LPCWSTR str;
727 //struct MenuExItem {
728 // DWORD dwType;
729 // DWORD dwState;
730 // DWORD menuId;
731 // WORD bResInfo;
732 // WCHAR szText[];
733 // DWORD dwHelpId; - Popup menu only
734 //};
738 dwType = GET_DWORD(res);
739 res += 2;
740 dwState = GET_DWORD(res);
741 res += 2;
742 menuId = GET_DWORD(res);
743 res += 2;
744 bResInfo = GET_WORD(res);
745 res++;
747 str = (LPCWSTR)res;
748 size_t l = wcslen(str)+1;
749 res += l;
750 // Align to DWORD boundary
751 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);
753 if (dwType & MFT_SEPARATOR)
754 continue;
756 if (bResInfo & 0x01)
758 // Popup menu - note this can also have a non-zero ID
759 if (menuId == 0)
760 menuId = (WORD)-1;
761 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
762 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
763 _tcscpy(pBuf, str);
764 CUtils::StringExtend(pBuf);
766 std::wstring wstr = std::wstring(pBuf);
767 RESOURCEENTRY entry = m_StringEntries[wstr];
768 // Popup has a DWORD help entry on a DWORD boundary - skip over it
769 res += 2;
771 entry.resourceIDs.insert(menuId);
772 TCHAR szTempBuf[1024];
773 _stprintf(szTempBuf, _T("#: MenuExPopupEntry; ID:%d"), menuId);
774 MENUENTRY menu_entry;
775 menu_entry.wID = (WORD)menuId;
776 menu_entry.reference = szTempBuf;
777 menu_entry.msgstr = wstr;
778 m_StringEntries[wstr] = entry;
779 m_MenuEntries[(WORD)menuId] = menu_entry;
780 delete [] pBuf;
782 if ((res = ParseMenuExResource(res)) == 0)
783 return NULL;
784 } else if (menuId != 0)
786 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
787 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
788 _tcscpy(pBuf, str);
789 CUtils::StringExtend(pBuf);
791 std::wstring wstr = std::wstring(pBuf);
792 RESOURCEENTRY entry = m_StringEntries[wstr];
793 entry.resourceIDs.insert(menuId);
795 TCHAR szTempBuf[1024];
796 _stprintf(szTempBuf, _T("#: MenuExEntry; ID:%d"), menuId);
797 MENUENTRY menu_entry;
798 menu_entry.wID = (WORD)menuId;
799 menu_entry.reference = szTempBuf;
800 menu_entry.msgstr = wstr;
801 m_StringEntries[wstr] = entry;
802 m_MenuEntries[(WORD)menuId] = menu_entry;
803 delete [] pBuf;
805 } while (!(bResInfo & 0x80));
806 return res;
809 const WORD* CResModule::CountMemReplaceMenuExResource(const WORD * res, size_t * wordcount, WORD * newMenu)
811 DWORD dwType, dwState, menuId;
812 WORD bResInfo;
813 WORD *p0;
815 //struct MenuExItem {
816 // DWORD dwType;
817 // DWORD dwState;
818 // DWORD menuId;
819 // WORD bResInfo;
820 // WCHAR szText[];
821 // DWORD dwHelpId; - Popup menu only
822 //};
826 p0 = (WORD *)res;
827 dwType = GET_DWORD(res);
828 res += 2;
829 dwState = GET_DWORD(res);
830 res += 2;
831 menuId = GET_DWORD(res);
832 res += 2;
833 bResInfo = GET_WORD(res);
834 res++;
836 if (newMenu != NULL) {
837 CopyMemory(&newMenu[*wordcount], p0, 7 * sizeof(WORD));
839 (*wordcount) += 7;
841 if (dwType & MFT_SEPARATOR) {
842 // Align to DWORD
843 (*wordcount)++;
844 res++;
845 continue;
848 if (bResInfo & 0x01)
850 ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);
851 res += wcslen((LPCWSTR)res) + 1;
852 // Align to DWORD
853 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);
854 if ((*wordcount) & 0x01)
855 (*wordcount)++;
857 if (newMenu != NULL)
858 CopyMemory(&newMenu[*wordcount], res, sizeof(DWORD)); // Copy Help ID
860 res += 2;
861 (*wordcount) += 2;
863 if ((res = CountMemReplaceMenuExResource(res, wordcount, newMenu)) == 0)
864 return NULL;
866 else if (menuId != 0)
868 ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);
869 res += wcslen((LPCWSTR)res) + 1;
871 else
873 if (newMenu)
874 wcscpy((wchar_t *)&newMenu[(*wordcount)], (LPCWSTR)res);
875 (*wordcount) += wcslen((LPCWSTR)res) + 1;
876 res += wcslen((LPCWSTR)res) + 1;
878 // Align to DWORD
879 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);
880 if ((*wordcount) & 0x01)
881 (*wordcount)++;
882 } while (!(bResInfo & 0x80));
883 return res;
886 BOOL CResModule::ExtractAccelerator(UINT nID)
888 HRSRC hrsrc = FindResource(m_hResDll, MAKEINTRESOURCE(nID), RT_ACCELERATOR);
889 HGLOBAL hglAccTable;
890 WORD fFlags, wAnsi, wID;
891 const WORD* p;
892 bool bEnd(false);
894 if (!hrsrc)
895 MYERROR;
897 hglAccTable = LoadResource(m_hResDll, hrsrc);
899 if (!hglAccTable)
900 goto DONE_ERROR;
902 p = (const WORD*)LockResource(hglAccTable);
904 if (p == NULL)
905 MYERROR;
908 struct ACCELTABLEENTRY
910 WORD fFlags; FVIRTKEY, FSHIFT, FCONTROL, FALT, 0x80 - Last in a table
911 WORD wAnsi; ANSI character
912 WORD wId; Keyboard accelerator passed to windows
913 WORD padding; # bytes added to ensure aligned to DWORD boundary
919 fFlags = GET_WORD(p);
920 p++;
921 wAnsi = GET_WORD(p);
922 p++;
923 wID = GET_WORD(p);
924 p++;
925 p++; // Skip over padding
927 if ((fFlags & 0x80) == 0x80)
928 { // 0x80
929 bEnd = true;
932 if ((wAnsi < 0x30) ||
933 (wAnsi > 0x5A) ||
934 (wAnsi >= 0x3A && wAnsi <= 0x40))
935 continue;
937 TCHAR * pBuf = new TCHAR[1024];
938 SecureZeroMemory(pBuf, 1024 * sizeof(TCHAR));
940 // include the menu ID in the msgid to make sure that 'duplicate'
941 // accelerator keys are listed in the po-file.
942 // without this, we would get entries like this:
943 //#. Accelerator Entry for Menu ID:32809; '&Filter'
944 //#. Accelerator Entry for Menu ID:57636; '&Find'
945 //#: Corresponding Menu ID:32771; '&Find'
946 //msgid "V C +F"
947 //msgstr ""
949 // Since "filter" and "find" are most likely translated to words starting
950 // with different letters, we need to have a separate accelerator entry
951 // for each of those
952 _stprintf(pBuf, _T("ID:%d:"), wID);
954 // EXACTLY 5 characters long "ACS+X"
955 // V = Virtual key (or blank if not used)
956 // A = Alt key (or blank if not used)
957 // C = Ctrl key (or blank if not used)
958 // S = Shift key (or blank if not used)
959 // X = upper case character
960 // e.g. "V CS+Q" == Ctrl + Shift + 'Q'
961 if ((fFlags & FVIRTKEY) == FVIRTKEY) // 0x01
962 _tcscat(pBuf, _T("V"));
963 else
964 _tcscat(pBuf, _T(" "));
966 if ((fFlags & FALT) == FALT) // 0x10
967 _tcscat(pBuf, _T("A"));
968 else
969 _tcscat(pBuf, _T(" "));
971 if ((fFlags & FCONTROL) == FCONTROL) // 0x08
972 _tcscat(pBuf, _T("C"));
973 else
974 _tcscat(pBuf, _T(" "));
976 if ((fFlags & FSHIFT) == FSHIFT) // 0x04
977 _tcscat(pBuf, _T("S"));
978 else
979 _tcscat(pBuf, _T(" "));
981 _stprintf(pBuf, _T("%s+%c"), pBuf, wAnsi);
983 std::wstring wstr = std::wstring(pBuf);
984 RESOURCEENTRY AKey_entry = m_StringEntries[wstr];
986 TCHAR szTempBuf[1024];
987 SecureZeroMemory(szTempBuf, sizeof (szTempBuf));
988 std::wstring wmenu = _T("");
989 pME_iter = m_MenuEntries.find(wID);
990 if (pME_iter != m_MenuEntries.end())
992 wmenu = pME_iter->second.msgstr;
994 _stprintf(szTempBuf, _T("#. Accelerator Entry for Menu ID:%d; '%s'"), wID, wmenu.c_str());
995 AKey_entry.automaticcomments.push_back(std::wstring(szTempBuf));
997 m_StringEntries[wstr] = AKey_entry;
998 delete [] pBuf;
999 } while (!bEnd);
1001 UnlockResource(hglAccTable);
1002 FreeResource(hglAccTable);
1003 return TRUE;
1005 DONE_ERROR:
1006 UnlockResource(hglAccTable);
1007 FreeResource(hglAccTable);
1008 MYERROR;
1011 BOOL CResModule::ReplaceAccelerator(UINT nID, WORD wLanguage)
1013 LPACCEL lpaccelNew; // pointer to new accelerator table
1014 HACCEL haccelOld; // handle to old accelerator table
1015 int cAccelerators; // number of accelerators in table
1016 HGLOBAL hglAccTableNew;
1017 const WORD* p;
1018 int i;
1020 haccelOld = LoadAccelerators(m_hResDll, MAKEINTRESOURCE(nID));
1022 if (haccelOld == NULL)
1023 MYERROR;
1025 cAccelerators = CopyAcceleratorTable(haccelOld, NULL, 0);
1027 lpaccelNew = (LPACCEL) LocalAlloc(LPTR, cAccelerators * sizeof(ACCEL));
1029 if (lpaccelNew == NULL)
1030 MYERROR;
1032 CopyAcceleratorTable(haccelOld, lpaccelNew, cAccelerators);
1034 // Find the accelerator that the user modified
1035 // and change its flags and virtual-key code
1036 // as appropriate.
1038 BYTE xfVirt;
1039 WORD xkey;
1040 static const size_t BufferSize = 1024;
1041 TCHAR * pBuf = new TCHAR[BufferSize];
1042 for (i = 0; i < cAccelerators; i++)
1044 if ((lpaccelNew[i].key < 0x30) ||
1045 (lpaccelNew[i].key > 0x5A) ||
1046 (lpaccelNew[i].key >= 0x3A && lpaccelNew[i].key <= 0x40))
1047 continue;
1049 SecureZeroMemory(pBuf, BufferSize * sizeof(TCHAR));
1051 _stprintf(pBuf, _T("ID:%d:"), lpaccelNew[i].cmd);
1053 // get original key combination
1054 if ((lpaccelNew[i].fVirt & FVIRTKEY) == FVIRTKEY) // 0x01
1055 _tcscat(pBuf, _T("V"));
1056 else
1057 _tcscat(pBuf, _T(" "));
1059 if ((lpaccelNew[i].fVirt & FALT) == FALT) // 0x10
1060 _tcscat(pBuf, _T("A"));
1061 else
1062 _tcscat(pBuf, _T(" "));
1064 if ((lpaccelNew[i].fVirt & FCONTROL) == FCONTROL) // 0x08
1065 _tcscat(pBuf, _T("C"));
1066 else
1067 _tcscat(pBuf, _T(" "));
1069 if ((lpaccelNew[i].fVirt & FSHIFT) == FSHIFT) // 0x04
1070 _tcscat(pBuf, _T("S"));
1071 else
1072 _tcscat(pBuf, _T(" "));
1074 _stprintf(pBuf, _T("%s+%c"), pBuf, lpaccelNew[i].key);
1076 // Is it there?
1077 std::map<std::wstring, RESOURCEENTRY>::iterator pAK_iter = m_StringEntries.find(pBuf);
1078 if (pAK_iter != m_StringEntries.end())
1080 m_bTranslatedAcceleratorStrings++;
1081 xfVirt = 0;
1082 xkey = 0;
1083 std::wstring wtemp = pAK_iter->second.msgstr;
1084 wtemp = wtemp.substr(wtemp.find_last_of(':')+1);
1085 if (wtemp.size() != 6)
1086 continue;
1087 if (wtemp.compare(0, 1, _T("V")) == 0)
1088 xfVirt |= FVIRTKEY;
1089 else if (wtemp.compare(0, 1, _T(" ")) != 0)
1090 continue; // not a space - user must have made a mistake when translating
1091 if (wtemp.compare(1, 1, _T("A")) == 0)
1092 xfVirt |= FALT;
1093 else if (wtemp.compare(1, 1, _T(" ")) != 0)
1094 continue; // not a space - user must have made a mistake when translating
1095 if (wtemp.compare(2, 1, _T("C")) == 0)
1096 xfVirt |= FCONTROL;
1097 else if (wtemp.compare(2, 1, _T(" ")) != 0)
1098 continue; // not a space - user must have made a mistake when translating
1099 if (wtemp.compare(3, 1, _T("S")) == 0)
1100 xfVirt |= FSHIFT;
1101 else if (wtemp.compare(3, 1, _T(" ")) != 0)
1102 continue; // not a space - user must have made a mistake when translating
1103 if (wtemp.compare(4, 1, _T("+")) == 0)
1105 _stscanf(wtemp.substr(5, 1).c_str(), _T("%c"), &xkey);
1106 lpaccelNew[i].fVirt = xfVirt;
1107 lpaccelNew[i].key = xkey;
1110 else
1111 m_bDefaultAcceleratorStrings++;
1114 delete [] pBuf;
1116 // Create the new accelerator table
1117 hglAccTableNew = LocalAlloc(LPTR, cAccelerators * 4 * sizeof(WORD));
1118 p = (WORD *)hglAccTableNew;
1119 lpaccelNew[cAccelerators-1].fVirt |= 0x80;
1120 for (i = 0; i < cAccelerators; i++)
1122 memcpy((void *)p, &lpaccelNew[i].fVirt, 1);
1123 p++;
1124 memcpy((void *)p, &lpaccelNew[i].key, sizeof(WORD));
1125 p++;
1126 memcpy((void *)p, &lpaccelNew[i].cmd, sizeof(WORD));
1127 p++;
1128 p++;
1131 if (!UpdateResource(m_hUpdateRes, RT_ACCELERATOR, MAKEINTRESOURCE(nID),
1132 (m_wTargetLang ? m_wTargetLang : wLanguage), hglAccTableNew /* haccelNew*/, cAccelerators * 4 * sizeof(WORD)))
1134 goto DONE_ERROR;
1137 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_ACCELERATOR, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))
1139 goto DONE_ERROR;
1142 LocalFree(hglAccTableNew);
1143 LocalFree(lpaccelNew);
1144 return TRUE;
1146 DONE_ERROR:
1147 LocalFree(hglAccTableNew);
1148 LocalFree(lpaccelNew);
1149 MYERROR;
1152 BOOL CResModule::ExtractDialog(UINT nID)
1154 const WORD* lpDlg;
1155 const WORD* lpDlgItem;
1156 DIALOGINFO dlg;
1157 DLGITEMINFO dlgItem;
1158 WORD bNumControls;
1159 HRSRC hrsrc;
1160 HGLOBAL hGlblDlgTemplate;
1162 hrsrc = FindResource(m_hResDll, MAKEINTRESOURCE(nID), RT_DIALOG);
1164 if (hrsrc == NULL)
1165 MYERROR;
1167 hGlblDlgTemplate = LoadResource(m_hResDll, hrsrc);
1168 if (hGlblDlgTemplate == NULL)
1169 MYERROR;
1171 lpDlg = (const WORD*) LockResource(hGlblDlgTemplate);
1173 if (lpDlg == NULL)
1174 MYERROR;
1176 lpDlgItem = (const WORD*) GetDialogInfo(lpDlg, &dlg);
1177 bNumControls = dlg.nbItems;
1179 if (dlg.caption)
1181 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
1182 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
1183 _tcscpy(pBuf, dlg.caption);
1184 CUtils::StringExtend(pBuf);
1186 std::wstring wstr = std::wstring(pBuf);
1187 RESOURCEENTRY entry = m_StringEntries[wstr];
1188 entry.resourceIDs.insert(nID);
1190 m_StringEntries[wstr] = entry;
1191 delete [] pBuf;
1194 while (bNumControls-- != 0)
1196 TCHAR szTitle[500];
1197 SecureZeroMemory(szTitle, sizeof(szTitle));
1198 BOOL bCode;
1200 lpDlgItem = GetControlInfo((WORD *) lpDlgItem, &dlgItem, dlg.dialogEx, &bCode);
1202 if (bCode == FALSE)
1203 _tcscpy(szTitle, dlgItem.windowName);
1205 if (_tcslen(szTitle) > 0)
1207 CUtils::StringExtend(szTitle);
1209 std::wstring wstr = std::wstring(szTitle);
1210 RESOURCEENTRY entry = m_StringEntries[wstr];
1211 entry.resourceIDs.insert(dlgItem.id);
1213 m_StringEntries[wstr] = entry;
1217 UnlockResource(hGlblDlgTemplate);
1218 FreeResource(hGlblDlgTemplate);
1219 return (TRUE);
1222 BOOL CResModule::ReplaceDialog(UINT nID, WORD wLanguage)
1224 const WORD* lpDlg;
1225 HRSRC hrsrc;
1226 HGLOBAL hGlblDlgTemplate;
1228 hrsrc = FindResourceEx(m_hResDll, RT_DIALOG, MAKEINTRESOURCE(nID), wLanguage);
1230 if (hrsrc == NULL)
1231 MYERROR;
1233 hGlblDlgTemplate = LoadResource(m_hResDll, hrsrc);
1235 if (hGlblDlgTemplate == NULL)
1236 MYERROR;
1238 lpDlg = (WORD *) LockResource(hGlblDlgTemplate);
1240 if (lpDlg == NULL)
1241 MYERROR;
1243 size_t nMem = 0;
1244 const WORD * p = lpDlg;
1245 if (!CountMemReplaceDialogResource(p, &nMem, NULL))
1246 goto DONE_ERROR;
1247 WORD * newDialog = new WORD[nMem + (nMem % 2)];
1248 SecureZeroMemory(newDialog, (nMem + (nMem % 2))*2);
1250 size_t index = 0;
1251 if (!CountMemReplaceDialogResource(lpDlg, &index, newDialog))
1253 delete [] newDialog;
1254 goto DONE_ERROR;
1257 if (!UpdateResource(m_hUpdateRes, RT_DIALOG, MAKEINTRESOURCE(nID), (m_wTargetLang ? m_wTargetLang : wLanguage), newDialog, (DWORD)(nMem + (nMem % 2))*2))
1259 delete [] newDialog;
1260 goto DONE_ERROR;
1263 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_DIALOG, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))
1265 delete [] newDialog;
1266 goto DONE_ERROR;
1269 delete [] newDialog;
1270 UnlockResource(hGlblDlgTemplate);
1271 FreeResource(hGlblDlgTemplate);
1272 return TRUE;
1274 DONE_ERROR:
1275 UnlockResource(hGlblDlgTemplate);
1276 FreeResource(hGlblDlgTemplate);
1277 MYERROR;
1280 const WORD* CResModule::GetDialogInfo(const WORD * pTemplate, LPDIALOGINFO lpDlgInfo)
1282 const WORD* p = (const WORD *)pTemplate;
1284 lpDlgInfo->style = GET_DWORD(p);
1285 p += 2;
1287 if (lpDlgInfo->style == 0xffff0001) // DIALOGEX resource
1289 lpDlgInfo->dialogEx = TRUE;
1290 lpDlgInfo->helpId = GET_DWORD(p);
1291 p += 2;
1292 lpDlgInfo->exStyle = GET_DWORD(p);
1293 p += 2;
1294 lpDlgInfo->style = GET_DWORD(p);
1295 p += 2;
1297 else
1299 lpDlgInfo->dialogEx = FALSE;
1300 lpDlgInfo->helpId = 0;
1301 lpDlgInfo->exStyle = GET_DWORD(p);
1302 p += 2;
1305 lpDlgInfo->nbItems = GET_WORD(p);
1306 p++;
1308 lpDlgInfo->x = GET_WORD(p);
1309 p++;
1311 lpDlgInfo->y = GET_WORD(p);
1312 p++;
1314 lpDlgInfo->cx = GET_WORD(p);
1315 p++;
1317 lpDlgInfo->cy = GET_WORD(p);
1318 p++;
1320 // Get the menu name
1322 switch (GET_WORD(p))
1324 case 0x0000:
1325 lpDlgInfo->menuName = NULL;
1326 p++;
1327 break;
1328 case 0xffff:
1329 lpDlgInfo->menuName = (LPCTSTR) (WORD) GET_WORD(p + 1);
1330 p += 2;
1331 break;
1332 default:
1333 lpDlgInfo->menuName = (LPCTSTR) p;
1334 p += wcslen((LPCWSTR) p) + 1;
1335 break;
1338 // Get the class name
1340 switch (GET_WORD(p))
1342 case 0x0000:
1343 lpDlgInfo->className = (LPCTSTR)MAKEINTATOM(32770);
1344 p++;
1345 break;
1346 case 0xffff:
1347 lpDlgInfo->className = (LPCTSTR) (WORD) GET_WORD(p + 1);
1348 p += 2;
1349 break;
1350 default:
1351 lpDlgInfo->className = (LPCTSTR) p;
1352 p += wcslen((LPCTSTR)p) + 1;
1353 break;
1356 // Get the window caption
1358 lpDlgInfo->caption = (LPCTSTR)p;
1359 p += wcslen((LPCWSTR) p) + 1;
1361 // Get the font name
1363 if (lpDlgInfo->style & DS_SETFONT)
1365 lpDlgInfo->pointSize = GET_WORD(p);
1366 p++;
1368 if (lpDlgInfo->dialogEx)
1370 lpDlgInfo->weight = GET_WORD(p);
1371 p++;
1372 lpDlgInfo->italic = LOBYTE(GET_WORD(p));
1373 p++;
1375 else
1377 lpDlgInfo->weight = FW_DONTCARE;
1378 lpDlgInfo->italic = FALSE;
1381 lpDlgInfo->faceName = (LPCTSTR)p;
1382 p += wcslen((LPCWSTR) p) + 1;
1384 // First control is on DWORD boundary
1385 p += ((((WORD)p + 3) & ~3) - (WORD)p)/sizeof(WORD);
1387 return p;
1390 const WORD* CResModule::GetControlInfo(const WORD* p, LPDLGITEMINFO lpDlgItemInfo, BOOL dialogEx, LPBOOL bIsID)
1392 if (dialogEx)
1394 lpDlgItemInfo->helpId = GET_DWORD(p);
1395 p += 2;
1396 lpDlgItemInfo->exStyle = GET_DWORD(p);
1397 p += 2;
1398 lpDlgItemInfo->style = GET_DWORD(p);
1399 p += 2;
1401 else
1403 lpDlgItemInfo->helpId = 0;
1404 lpDlgItemInfo->style = GET_DWORD(p);
1405 p += 2;
1406 lpDlgItemInfo->exStyle = GET_DWORD(p);
1407 p += 2;
1410 lpDlgItemInfo->x = GET_WORD(p);
1411 p++;
1413 lpDlgItemInfo->y = GET_WORD(p);
1414 p++;
1416 lpDlgItemInfo->cx = GET_WORD(p);
1417 p++;
1419 lpDlgItemInfo->cy = GET_WORD(p);
1420 p++;
1422 if (dialogEx)
1424 // ID is a DWORD for DIALOGEX
1425 lpDlgItemInfo->id = (WORD) GET_DWORD(p);
1426 p += 2;
1428 else
1430 lpDlgItemInfo->id = GET_WORD(p);
1431 p++;
1434 if (GET_WORD(p) == 0xffff)
1436 GET_WORD(p + 1);
1438 p += 2;
1440 else
1442 lpDlgItemInfo->className = (LPCTSTR) p;
1443 p += wcslen((LPCWSTR) p) + 1;
1446 if (GET_WORD(p) == 0xffff) // an integer ID?
1448 *bIsID = TRUE;
1449 lpDlgItemInfo->windowName = (LPCTSTR) (DWORD) GET_WORD(p + 1);
1450 p += 2;
1452 else
1454 *bIsID = FALSE;
1455 lpDlgItemInfo->windowName = (LPCTSTR) p;
1456 p += wcslen((LPCWSTR) p) + 1;
1459 if (GET_WORD(p))
1461 lpDlgItemInfo->data = (LPVOID) (p + 1);
1462 p += GET_WORD(p) / sizeof(WORD);
1464 else
1465 lpDlgItemInfo->data = NULL;
1467 p++;
1468 // Next control is on DWORD boundary
1469 p += ((((WORD)p + 3) & ~3) - (WORD)p)/sizeof(WORD);
1470 return p;
1473 const WORD * CResModule::CountMemReplaceDialogResource(const WORD * res, size_t * wordcount, WORD * newDialog)
1475 BOOL bEx = FALSE;
1476 DWORD style = GET_DWORD(res);
1477 if (newDialog)
1479 newDialog[(*wordcount)++] = GET_WORD(res++);
1480 newDialog[(*wordcount)++] = GET_WORD(res++);
1482 else
1484 res += 2;
1485 (*wordcount) += 2;
1488 if (style == 0xffff0001) // DIALOGEX resource
1490 bEx = TRUE;
1491 if (newDialog)
1493 newDialog[(*wordcount)++] = GET_WORD(res++); //help id
1494 newDialog[(*wordcount)++] = GET_WORD(res++); //help id
1495 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1496 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1497 style = GET_DWORD(res);
1498 newDialog[(*wordcount)++] = GET_WORD(res++); //style
1499 newDialog[(*wordcount)++] = GET_WORD(res++); //style
1501 else
1503 res += 4;
1504 style = GET_DWORD(res);
1505 res += 2;
1506 (*wordcount) += 6;
1509 else
1511 bEx = FALSE;
1512 if (newDialog)
1514 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1515 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1516 //style = GET_DWORD(res);
1517 //newDialog[(*wordcount)++] = GET_WORD(res++); //style
1518 //newDialog[(*wordcount)++] = GET_WORD(res++); //style
1520 else
1522 res += 2;
1523 (*wordcount) += 2;
1527 if (newDialog)
1528 newDialog[(*wordcount)] = GET_WORD(res);
1529 WORD nbItems = GET_WORD(res);
1530 (*wordcount)++;
1531 res++;
1533 if (newDialog)
1534 newDialog[(*wordcount)] = GET_WORD(res); //x
1535 (*wordcount)++;
1536 res++;
1538 if (newDialog)
1539 newDialog[(*wordcount)] = GET_WORD(res); //y
1540 (*wordcount)++;
1541 res++;
1543 if (newDialog)
1544 newDialog[(*wordcount)] = GET_WORD(res); //cx
1545 (*wordcount)++;
1546 res++;
1548 if (newDialog)
1549 newDialog[(*wordcount)] = GET_WORD(res); //cy
1550 (*wordcount)++;
1551 res++;
1553 // Get the menu name
1555 switch (GET_WORD(res))
1557 case 0x0000:
1558 if (newDialog)
1559 newDialog[(*wordcount)] = GET_WORD(res);
1560 (*wordcount)++;
1561 res++;
1562 break;
1563 case 0xffff:
1564 if (newDialog)
1566 newDialog[(*wordcount)++] = GET_WORD(res++);
1567 newDialog[(*wordcount)++] = GET_WORD(res++);
1569 else
1571 (*wordcount) += 2;
1572 res += 2;
1574 break;
1575 default:
1576 if (newDialog)
1578 wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);
1580 (*wordcount) += wcslen((LPCWSTR) res) + 1;
1581 res += wcslen((LPCWSTR) res) + 1;
1582 break;
1585 // Get the class name
1587 switch (GET_WORD(res))
1589 case 0x0000:
1590 if (newDialog)
1591 newDialog[(*wordcount)] = GET_WORD(res);
1592 (*wordcount)++;
1593 res++;
1594 break;
1595 case 0xffff:
1596 if (newDialog)
1598 newDialog[(*wordcount)++] = GET_WORD(res++);
1599 newDialog[(*wordcount)++] = GET_WORD(res++);
1601 else
1603 (*wordcount) += 2;
1604 res += 2;
1606 break;
1607 default:
1608 if (newDialog)
1610 wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);
1612 (*wordcount) += wcslen((LPCWSTR) res) + 1;
1613 res += wcslen((LPCWSTR) res) + 1;
1614 break;
1617 // Get the window caption
1619 ReplaceStr((LPCWSTR)res, newDialog, wordcount, &m_bTranslatedDialogStrings, &m_bDefaultDialogStrings);
1620 res += wcslen((LPCWSTR)res) + 1;
1622 // Get the font name
1624 if (style & DS_SETFONT)
1626 if (newDialog)
1627 newDialog[(*wordcount)] = GET_WORD(res);
1628 res++;
1629 (*wordcount)++;
1631 if (bEx)
1633 if (newDialog)
1635 newDialog[(*wordcount)++] = GET_WORD(res++);
1636 newDialog[(*wordcount)++] = GET_WORD(res++);
1638 else
1640 res += 2;
1641 (*wordcount) += 2;
1645 if (newDialog)
1646 wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);
1647 (*wordcount) += wcslen((LPCWSTR)res) + 1;
1648 res += wcslen((LPCWSTR)res) + 1;
1650 // First control is on DWORD boundary
1651 while ((*wordcount)%2)
1652 (*wordcount)++;
1653 while ((ULONG)res % 4)
1654 res++;
1656 while (nbItems--)
1658 res = ReplaceControlInfo(res, wordcount, newDialog, bEx);
1660 return res;
1663 const WORD* CResModule::ReplaceControlInfo(const WORD * res, size_t * wordcount, WORD * newDialog, BOOL bEx)
1665 if (bEx)
1667 if (newDialog)
1669 newDialog[(*wordcount)++] = GET_WORD(res++); //helpid
1670 newDialog[(*wordcount)++] = GET_WORD(res++); //helpid
1672 else
1674 res += 2;
1675 (*wordcount) += 2;
1678 if (newDialog)
1680 LONG * exStyle = (LONG*)&newDialog[(*wordcount)];
1681 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1682 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1683 if (m_bRTL)
1684 *exStyle |= WS_EX_RTLREADING;
1686 else
1688 res += 2;
1689 (*wordcount) += 2;
1692 if (newDialog)
1694 newDialog[(*wordcount)++] = GET_WORD(res++); //style
1695 newDialog[(*wordcount)++] = GET_WORD(res++); //style
1697 else
1699 res += 2;
1700 (*wordcount) += 2;
1703 if (newDialog)
1704 newDialog[(*wordcount)] = GET_WORD(res); //x
1705 res++;
1706 (*wordcount)++;
1708 if (newDialog)
1709 newDialog[(*wordcount)] = GET_WORD(res); //y
1710 res++;
1711 (*wordcount)++;
1713 if (newDialog)
1714 newDialog[(*wordcount)] = GET_WORD(res); //cx
1715 res++;
1716 (*wordcount)++;
1718 if (newDialog)
1719 newDialog[(*wordcount)] = GET_WORD(res); //cy
1720 res++;
1721 (*wordcount)++;
1723 if (bEx)
1725 // ID is a DWORD for DIALOGEX
1726 if (newDialog)
1728 newDialog[(*wordcount)++] = GET_WORD(res++);
1729 newDialog[(*wordcount)++] = GET_WORD(res++);
1731 else
1733 res += 2;
1734 (*wordcount) += 2;
1737 else
1739 if (newDialog)
1740 newDialog[(*wordcount)] = GET_WORD(res);
1741 res++;
1742 (*wordcount)++;
1745 if (GET_WORD(res) == 0xffff) //classID
1747 if (newDialog)
1749 newDialog[(*wordcount)++] = GET_WORD(res++);
1750 newDialog[(*wordcount)++] = GET_WORD(res++);
1752 else
1754 res += 2;
1755 (*wordcount) += 2;
1758 else
1760 if (newDialog)
1761 wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);
1762 (*wordcount) += wcslen((LPCWSTR) res) + 1;
1763 res += wcslen((LPCWSTR) res) + 1;
1766 if (GET_WORD(res) == 0xffff) // an integer ID?
1768 if (newDialog)
1770 newDialog[(*wordcount)++] = GET_WORD(res++);
1771 newDialog[(*wordcount)++] = GET_WORD(res++);
1773 else
1775 res += 2;
1776 (*wordcount) += 2;
1779 else
1781 ReplaceStr((LPCWSTR)res, newDialog, wordcount, &m_bTranslatedDialogStrings, &m_bDefaultDialogStrings);
1782 res += wcslen((LPCWSTR)res) + 1;
1785 if (newDialog)
1786 memcpy(&newDialog[(*wordcount)], res, (GET_WORD(res)+1)*sizeof(WORD));
1787 (*wordcount) += (GET_WORD(res)+1);
1788 res += (GET_WORD(res)+1);
1789 // Next control is on DWORD boundary
1790 while ((*wordcount) % 2)
1791 (*wordcount)++;
1792 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);
1794 return res;
1797 BOOL CALLBACK CResModule::EnumResNameCallback(HMODULE /*hModule*/, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)
1799 CResModule* lpResModule = (CResModule*)lParam;
1801 if (lpszType == RT_STRING)
1803 if (IS_INTRESOURCE(lpszName))
1805 if (!lpResModule->ExtractString(LOWORD(lpszName)))
1806 return FALSE;
1809 else if (lpszType == RT_MENU)
1811 if (IS_INTRESOURCE(lpszName))
1813 if (!lpResModule->ExtractMenu(LOWORD(lpszName)))
1814 return FALSE;
1817 else if (lpszType == RT_DIALOG)
1819 if (IS_INTRESOURCE(lpszName))
1821 if (!lpResModule->ExtractDialog(LOWORD(lpszName)))
1822 return FALSE;
1825 else if (lpszType == RT_ACCELERATOR)
1827 if (IS_INTRESOURCE(lpszName))
1829 if (!lpResModule->ExtractAccelerator(LOWORD(lpszName)))
1830 return FALSE;
1834 return TRUE;
1837 #pragma warning(push)
1838 #pragma warning(disable: 4189)
1839 BOOL CALLBACK CResModule::EnumResNameWriteCallback(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)
1841 CResModule* lpResModule = (CResModule*)lParam;
1842 return EnumResourceLanguages(hModule, lpszType, lpszName, (ENUMRESLANGPROC)&lpResModule->EnumResWriteLangCallback, lParam);
1844 #pragma warning(pop)
1846 BOOL CALLBACK CResModule::EnumResWriteLangCallback(HMODULE /*hModule*/, LPCTSTR lpszType, LPTSTR lpszName, WORD wLanguage, LONG_PTR lParam)
1848 BOOL bRes = FALSE;
1849 CResModule* lpResModule = (CResModule*)lParam;
1851 if (lpszType == RT_STRING)
1853 if (IS_INTRESOURCE(lpszName))
1855 bRes = lpResModule->ReplaceString(LOWORD(lpszName), wLanguage);
1858 else if (lpszType == RT_MENU)
1860 if (IS_INTRESOURCE(lpszName))
1862 bRes = lpResModule->ReplaceMenu(LOWORD(lpszName), wLanguage);
1865 else if (lpszType == RT_DIALOG)
1867 if (IS_INTRESOURCE(lpszName))
1869 bRes = lpResModule->ReplaceDialog(LOWORD(lpszName), wLanguage);
1872 else if (lpszType == RT_ACCELERATOR)
1874 if (IS_INTRESOURCE(lpszName))
1876 bRes = lpResModule->ReplaceAccelerator(LOWORD(lpszName), wLanguage);
1880 return bRes;
1884 void CResModule::ReplaceStr(LPCWSTR src, WORD * dest, size_t * count, int * translated, int * def)
1886 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
1887 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
1888 wcscpy(pBuf, src);
1889 CUtils::StringExtend(pBuf);
1891 std::wstring wstr = std::wstring(pBuf);
1892 RESOURCEENTRY entry = m_StringEntries[wstr];
1893 if (entry.msgstr.size())
1895 wcscpy(pBuf, entry.msgstr.c_str());
1896 CUtils::StringCollapse(pBuf);
1897 if (dest)
1898 wcscpy((wchar_t *)&dest[(*count)], pBuf);
1899 (*count) += wcslen(pBuf)+1;
1900 (*translated)++;
1902 else
1904 if (dest)
1905 wcscpy((wchar_t *)&dest[(*count)], src);
1906 (*count) += wcslen(src) + 1;
1907 if (wcslen(src))
1908 (*def)++;
1910 delete [] pBuf;