Fixed issue #1372: Support git pull --no-tags
[TortoiseGit.git] / src / ResText / ResModule.cpp
blob677539880d6cc794124be183c85b5769eac9aa02
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>
22 #include "..\Utils\SysInfo.h"
24 #define MYERROR {CUtils::Error(); return FALSE;}
26 CResModule::CResModule(void)
27 : m_bTranslatedStrings(0)
28 , m_bDefaultStrings(0)
29 , m_bTranslatedDialogStrings(0)
30 , m_bDefaultDialogStrings(0)
31 , m_bTranslatedMenuStrings(0)
32 , m_bDefaultMenuStrings(0)
33 , m_bTranslatedAcceleratorStrings(0)
34 , m_bDefaultAcceleratorStrings(0)
35 , m_wTargetLang(0)
36 , m_hResDll(NULL)
37 , m_hUpdateRes(NULL)
38 , m_bQuiet(false)
39 , m_bRTL(false)
40 , m_bAdjustEOLs(false)
44 CResModule::~CResModule(void)
48 BOOL CResModule::ExtractResources(std::vector<std::wstring> filelist, LPCTSTR lpszPOFilePath, BOOL bNoUpdate, LPCTSTR lpszHeaderFile)
50 for (std::vector<std::wstring>::iterator I = filelist.begin(); I != filelist.end(); ++I)
52 m_hResDll = LoadLibraryEx(I->c_str(), NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE|LOAD_LIBRARY_AS_DATAFILE);
53 if (m_hResDll == NULL)
54 MYERROR;
56 size_t nEntries = m_StringEntries.size();
57 // fill in the std::map with all translatable entries
59 if (!m_bQuiet)
60 _ftprintf(stdout, _T("Extracting StringTable...."));
61 EnumResourceNames(m_hResDll, RT_STRING, EnumResNameCallback, (LONG_PTR)this);
62 if (!m_bQuiet)
63 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
64 nEntries = m_StringEntries.size();
66 if (!m_bQuiet)
67 _ftprintf(stdout, _T("Extracting Dialogs........"));
68 EnumResourceNames(m_hResDll, RT_DIALOG, EnumResNameCallback, (LONG_PTR)this);
69 if (!m_bQuiet)
70 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
71 nEntries = m_StringEntries.size();
73 if (!m_bQuiet)
74 _ftprintf(stdout, _T("Extracting Menus.........."));
75 EnumResourceNames(m_hResDll, RT_MENU, EnumResNameCallback, (LONG_PTR)this);
76 if (!m_bQuiet)
77 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
78 nEntries = m_StringEntries.size();
79 if (!m_bQuiet)
80 _ftprintf(stdout, _T("Extracting Accelerators..."));
81 EnumResourceNames(m_hResDll, RT_ACCELERATOR, EnumResNameCallback, (LONG_PTR)this);
82 if (!m_bQuiet)
83 _ftprintf(stdout, _T("%4d Accelerators\n"), m_StringEntries.size()-nEntries);
84 nEntries = m_StringEntries.size();
86 // parse a probably existing file and update the translations which are
87 // already done
88 m_StringEntries.ParseFile(lpszPOFilePath, !bNoUpdate, m_bAdjustEOLs);
90 FreeLibrary(m_hResDll);
93 // at last, save the new file
94 return m_StringEntries.SaveFile(lpszPOFilePath, lpszHeaderFile);
97 BOOL CResModule::ExtractResources(LPCTSTR lpszSrcLangDllPath, LPCTSTR lpszPoFilePath, BOOL bNoUpdate, LPCTSTR lpszHeaderFile)
99 m_hResDll = LoadLibraryEx(lpszSrcLangDllPath, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE|LOAD_LIBRARY_AS_DATAFILE);
100 if (m_hResDll == NULL)
101 MYERROR;
103 size_t nEntries = 0;
104 // fill in the std::map with all translatable entries
106 if (!m_bQuiet)
107 _ftprintf(stdout, _T("Extracting StringTable...."));
108 EnumResourceNames(m_hResDll, RT_STRING, EnumResNameCallback, (LONG_PTR)this);
109 if (!m_bQuiet)
110 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size());
111 nEntries = m_StringEntries.size();
113 if (!m_bQuiet)
114 _ftprintf(stdout, _T("Extracting Dialogs........"));
115 EnumResourceNames(m_hResDll, RT_DIALOG, EnumResNameCallback, (LONG_PTR)this);
116 if (!m_bQuiet)
117 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
118 nEntries = m_StringEntries.size();
120 if (!m_bQuiet)
121 _ftprintf(stdout, _T("Extracting Menus.........."));
122 EnumResourceNames(m_hResDll, RT_MENU, EnumResNameCallback, (LONG_PTR)this);
123 if (!m_bQuiet)
124 _ftprintf(stdout, _T("%4d Strings\n"), m_StringEntries.size()-nEntries);
125 nEntries = m_StringEntries.size();
127 if (!m_bQuiet)
128 _ftprintf(stdout, _T("Extracting Accelerators..."));
129 EnumResourceNames(m_hResDll, RT_ACCELERATOR, EnumResNameCallback, (LONG_PTR)this);
130 if (!m_bQuiet)
131 _ftprintf(stdout, _T("%4d Accelerators\n"), m_StringEntries.size()-nEntries);
132 nEntries = m_StringEntries.size();
134 // parse a probably existing file and update the translations which are
135 // already done
136 m_StringEntries.ParseFile(lpszPoFilePath, !bNoUpdate, m_bAdjustEOLs);
138 // at last, save the new file
139 if (!m_StringEntries.SaveFile(lpszPoFilePath, lpszHeaderFile))
140 goto DONE_ERROR;
142 FreeLibrary(m_hResDll);
143 return TRUE;
145 DONE_ERROR:
146 if (m_hResDll)
147 FreeLibrary(m_hResDll);
148 return FALSE;
151 BOOL CResModule::CreateTranslatedResources(LPCTSTR lpszSrcLangDllPath, LPCTSTR lpszDestLangDllPath, LPCTSTR lpszPOFilePath)
153 if (!CopyFile(lpszSrcLangDllPath, lpszDestLangDllPath, FALSE))
154 MYERROR;
156 int count = 0;
159 if (SysInfo::Instance().IsVistaOrLater())
160 m_hResDll = LoadLibraryEx (lpszSrcLangDllPath, NULL, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE|LOAD_LIBRARY_AS_IMAGE_RESOURCE|LOAD_IGNORE_CODE_AUTHZ_LEVEL);
161 else
162 m_hResDll = LoadLibraryEx (lpszSrcLangDllPath, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE|LOAD_IGNORE_CODE_AUTHZ_LEVEL);
163 if (m_hResDll == NULL)
164 Sleep(100);
165 count++;
166 } while ((m_hResDll == NULL)&&(count < 10));
168 if (m_hResDll == NULL)
169 MYERROR;
171 sDestFile = std::wstring(lpszDestLangDllPath);
173 // get all translated strings
174 if (!m_StringEntries.ParseFile(lpszPOFilePath, FALSE, m_bAdjustEOLs))
175 goto DONE_ERROR;
176 m_bTranslatedStrings = 0;
177 m_bDefaultStrings = 0;
178 m_bTranslatedDialogStrings = 0;
179 m_bDefaultDialogStrings = 0;
180 m_bTranslatedMenuStrings = 0;
181 m_bDefaultMenuStrings = 0;
182 m_bTranslatedAcceleratorStrings = 0;
183 m_bDefaultAcceleratorStrings = 0;
185 BOOL bRes = FALSE;
186 count = 0;
189 m_hUpdateRes = BeginUpdateResource(sDestFile.c_str(), FALSE);
190 if (m_hUpdateRes == NULL)
191 Sleep(100);
192 count++;
193 } while ((m_hUpdateRes == NULL)&&(count < 10));
195 if (m_hUpdateRes == NULL)
196 MYERROR;
199 if (!m_bQuiet)
200 _ftprintf(stdout, _T("Translating StringTable..."));
201 bRes = EnumResourceNames(m_hResDll, RT_STRING, EnumResNameWriteCallback, (LONG_PTR)this);
202 if (!m_bQuiet)
203 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedStrings, m_bDefaultStrings);
205 if (!m_bQuiet)
206 _ftprintf(stdout, _T("Translating Dialogs......."));
207 bRes = EnumResourceNames(m_hResDll, RT_DIALOG, EnumResNameWriteCallback, (LONG_PTR)this);
208 if (!m_bQuiet)
209 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedDialogStrings, m_bDefaultDialogStrings);
211 if (!m_bQuiet)
212 _ftprintf(stdout, _T("Translating Menus........."));
213 bRes = EnumResourceNames(m_hResDll, RT_MENU, EnumResNameWriteCallback, (LONG_PTR)this);
214 if (!m_bQuiet)
215 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedMenuStrings, m_bDefaultMenuStrings);
217 if (!m_bQuiet)
218 _ftprintf(stdout, _T("Translating Accelerators.."));
219 bRes = EnumResourceNames(m_hResDll, RT_ACCELERATOR, EnumResNameWriteCallback, (LONG_PTR)this);
220 if (!m_bQuiet)
221 _ftprintf(stdout, _T("%4d translated, %4d not translated\n"), m_bTranslatedAcceleratorStrings, m_bDefaultAcceleratorStrings);
223 bRes = TRUE;
224 if (!EndUpdateResource(m_hUpdateRes, !bRes))
225 MYERROR;
227 FreeLibrary(m_hResDll);
228 return TRUE;
229 DONE_ERROR:
230 if (m_hResDll)
231 FreeLibrary(m_hResDll);
232 return FALSE;
235 BOOL CResModule::ExtractString(UINT nID)
237 HRSRC hrsrc = FindResource(m_hResDll, MAKEINTRESOURCE(nID), RT_STRING);
238 HGLOBAL hglStringTable;
239 LPWSTR p;
241 if (!hrsrc)
242 MYERROR;
243 hglStringTable = LoadResource(m_hResDll, hrsrc);
245 if (!hglStringTable)
246 goto DONE_ERROR;
247 p = (LPWSTR)LockResource(hglStringTable);
249 if (p == NULL)
250 goto DONE_ERROR;
251 /* [Block of 16 strings. The strings are Pascal style with a WORD
252 length preceding the string. 16 strings are always written, even
253 if not all slots are full. Any slots in the block with no string
254 have a zero WORD for the length.]
257 //first check how much memory we need
258 LPWSTR pp = p;
259 for (int i=0; i<16; ++i)
261 int len = GET_WORD(pp);
262 pp++;
263 std::wstring msgid = std::wstring(pp, len);
264 WCHAR * pBuf = new WCHAR[MAX_STRING_LENGTH*2];
265 SecureZeroMemory(pBuf, MAX_STRING_LENGTH*2*sizeof(WCHAR));
266 wcscpy(pBuf, msgid.c_str());
267 CUtils::StringExtend(pBuf);
269 if (wcslen(pBuf))
271 std::wstring str = std::wstring(pBuf);
272 RESOURCEENTRY entry = m_StringEntries[str];
273 entry.resourceIDs.insert(nID);
274 if (wcschr(str.c_str(), '%'))
275 entry.flag = _T("#, c-format");
276 m_StringEntries[str] = entry;
278 delete [] pBuf;
279 pp += len;
281 UnlockResource(hglStringTable);
282 FreeResource(hglStringTable);
283 return TRUE;
284 DONE_ERROR:
285 UnlockResource(hglStringTable);
286 FreeResource(hglStringTable);
287 MYERROR;
290 BOOL CResModule::ReplaceString(UINT nID, WORD wLanguage)
292 HRSRC hrsrc = FindResourceEx(m_hResDll, RT_STRING, MAKEINTRESOURCE(nID), wLanguage);
293 HGLOBAL hglStringTable;
294 LPWSTR p;
296 if (!hrsrc)
297 MYERROR;
298 hglStringTable = LoadResource(m_hResDll, hrsrc);
300 if (!hglStringTable)
301 goto DONE_ERROR;
302 p = (LPWSTR)LockResource(hglStringTable);
304 if (p == NULL)
305 goto DONE_ERROR;
306 /* [Block of 16 strings. The strings are Pascal style with a WORD
307 length preceding the string. 16 strings are always written, even
308 if not all slots are full. Any slots in the block with no string
309 have a zero WORD for the length.]
312 //first check how much memory we need
313 size_t nMem = 0;
314 LPWSTR pp = p;
315 for (int i=0; i<16; ++i)
317 nMem++;
318 size_t len = GET_WORD(pp);
319 pp++;
320 std::wstring msgid = std::wstring(pp, len);
321 WCHAR * pBuf = new WCHAR[MAX_STRING_LENGTH*2];
322 SecureZeroMemory(pBuf, MAX_STRING_LENGTH*2*sizeof(WCHAR));
323 wcscpy(pBuf, msgid.c_str());
324 CUtils::StringExtend(pBuf);
325 msgid = std::wstring(pBuf);
327 RESOURCEENTRY resEntry;
328 resEntry = m_StringEntries[msgid];
329 wcscpy(pBuf, resEntry.msgstr.c_str());
330 CUtils::StringCollapse(pBuf);
331 size_t newlen = wcslen(pBuf);
332 if (newlen)
333 nMem += newlen;
334 else
335 nMem += len;
336 pp += len;
337 delete [] pBuf;
340 WORD * newTable = new WORD[nMem + (nMem % 2)];
341 SecureZeroMemory(newTable, (nMem + (nMem % 2))*2);
343 size_t index = 0;
344 for (int i=0; i<16; ++i)
346 int len = GET_WORD(p);
347 p++;
348 std::wstring msgid = std::wstring(p, len);
349 WCHAR * pBuf = new WCHAR[MAX_STRING_LENGTH*2];
350 SecureZeroMemory(pBuf, MAX_STRING_LENGTH*2*sizeof(WCHAR));
351 wcscpy(pBuf, msgid.c_str());
352 CUtils::StringExtend(pBuf);
353 msgid = std::wstring(pBuf);
355 RESOURCEENTRY resEntry;
356 resEntry = m_StringEntries[msgid];
357 wcscpy(pBuf, resEntry.msgstr.c_str());
358 CUtils::StringCollapse(pBuf);
359 size_t newlen = wcslen(pBuf);
360 if (newlen)
362 newTable[index++] = (WORD)newlen;
363 wcsncpy((wchar_t *)&newTable[index], pBuf, newlen);
364 index += newlen;
365 m_bTranslatedStrings++;
367 else
369 newTable[index++] = (WORD)len;
370 if (len)
371 wcsncpy((wchar_t *)&newTable[index], p, len);
372 index += len;
373 if (len)
374 m_bDefaultStrings++;
376 p += len;
377 delete [] pBuf;
380 if (!UpdateResource(m_hUpdateRes, RT_STRING, MAKEINTRESOURCE(nID), (m_wTargetLang ? m_wTargetLang : wLanguage), newTable, (DWORD)(nMem + (nMem % 2))*2))
382 delete [] newTable;
383 goto DONE_ERROR;
386 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_STRING, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))
388 delete [] newTable;
389 goto DONE_ERROR;
391 delete [] newTable;
392 UnlockResource(hglStringTable);
393 FreeResource(hglStringTable);
394 return TRUE;
395 DONE_ERROR:
396 UnlockResource(hglStringTable);
397 FreeResource(hglStringTable);
398 MYERROR;
401 BOOL CResModule::ExtractMenu(UINT nID)
403 HRSRC hrsrc = FindResource(m_hResDll, MAKEINTRESOURCE(nID), RT_MENU);
404 HGLOBAL hglMenuTemplate;
405 WORD version, offset;
406 DWORD dwHelpId;
407 const WORD *p, *p0;
409 if (!hrsrc)
410 MYERROR;
412 hglMenuTemplate = LoadResource(m_hResDll, hrsrc);
414 if (!hglMenuTemplate)
415 MYERROR;
417 p = (const WORD*)LockResource(hglMenuTemplate);
419 if (p == NULL)
420 MYERROR;
422 // Standard MENU resource
423 //struct MenuHeader {
424 // WORD wVersion; // Currently zero
425 // WORD cbHeaderSize; // Also zero
426 //};
428 // MENUEX resource
429 //struct MenuExHeader {
430 // WORD wVersion; // One
431 // WORD wOffset;
432 // DWORD dwHelpId;
433 //};
434 p0 = p;
435 version = GET_WORD(p);
437 p++;
439 switch (version)
441 case 0:
443 offset = GET_WORD(p);
444 p += offset;
445 p++;
446 if (!ParseMenuResource(p))
447 goto DONE_ERROR;
449 break;
450 case 1:
452 offset = GET_WORD(p);
453 p++;
454 dwHelpId = GET_DWORD(p);
455 if (!ParseMenuExResource(p0 + offset))
456 goto DONE_ERROR;
458 break;
459 default:
460 goto DONE_ERROR;
463 UnlockResource(hglMenuTemplate);
464 FreeResource(hglMenuTemplate);
465 return TRUE;
467 DONE_ERROR:
468 UnlockResource(hglMenuTemplate);
469 FreeResource(hglMenuTemplate);
470 MYERROR;
473 BOOL CResModule::ReplaceMenu(UINT nID, WORD wLanguage)
475 HRSRC hrsrc = FindResourceEx(m_hResDll, RT_MENU, MAKEINTRESOURCE(nID), wLanguage);
476 HGLOBAL hglMenuTemplate;
477 WORD version, offset;
478 LPWSTR p;
479 WORD *p0;
480 DWORD dwHelpId;
482 if (!hrsrc)
483 MYERROR; //just the language wasn't found
485 hglMenuTemplate = LoadResource(m_hResDll, hrsrc);
487 if (!hglMenuTemplate)
488 MYERROR;
490 p = (LPWSTR)LockResource(hglMenuTemplate);
492 if (p == NULL)
493 MYERROR;
495 //struct MenuHeader {
496 // WORD wVersion; // Currently zero
497 // WORD cbHeaderSize; // Also zero
498 //};
500 // MENUEX resource
501 //struct MenuExHeader {
502 // WORD wVersion; // One
503 // WORD wOffset;
504 // DWORD dwHelpId;
505 //};
506 p0 = (WORD *)p;
507 version = GET_WORD(p);
509 p++;
511 switch (version)
513 case 0:
515 offset = GET_WORD(p);
516 p += offset;
517 p++;
518 size_t nMem = 0;
519 if (!CountMemReplaceMenuResource((WORD *)p, &nMem, NULL))
520 goto DONE_ERROR;
521 WORD * newMenu = new WORD[nMem + (nMem % 2)+2];
522 SecureZeroMemory(newMenu, (nMem + (nMem % 2)+2)*2);
523 size_t index = 2; // MenuHeader has 2 WORDs zero
524 if (!CountMemReplaceMenuResource((WORD *)p, &index, newMenu))
526 delete [] newMenu;
527 goto DONE_ERROR;
530 if (!UpdateResource(m_hUpdateRes, RT_MENU, MAKEINTRESOURCE(nID), (m_wTargetLang ? m_wTargetLang : wLanguage), newMenu, (DWORD)(nMem + (nMem % 2)+2)*2))
532 delete [] newMenu;
533 goto DONE_ERROR;
536 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_MENU, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))
538 delete [] newMenu;
539 goto DONE_ERROR;
541 delete [] newMenu;
543 break;
544 case 1:
546 offset = GET_WORD(p);
547 p++;
548 dwHelpId = GET_DWORD(p);
549 size_t nMem = 0;
550 if (!CountMemReplaceMenuExResource((WORD *)(p0 + offset), &nMem, NULL))
551 goto DONE_ERROR;
552 WORD * newMenu = new WORD[nMem + (nMem % 2) + 4];
553 SecureZeroMemory(newMenu, (nMem + (nMem % 2) + 4) * 2);
554 CopyMemory(newMenu, p0, 2 * sizeof(WORD) + sizeof(DWORD));
555 size_t index = 4; // MenuExHeader has 2 x WORD + 1 x DWORD
556 if (!CountMemReplaceMenuExResource((WORD *)(p0 + offset), &index, newMenu))
558 delete [] newMenu;
559 goto DONE_ERROR;
562 if (!UpdateResource(m_hUpdateRes, RT_MENU, MAKEINTRESOURCE(nID), (m_wTargetLang ? m_wTargetLang : wLanguage), newMenu, (DWORD)(nMem + (nMem % 2) + 4) * 2))
564 delete [] newMenu;
565 goto DONE_ERROR;
568 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_MENU, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))
570 delete [] newMenu;
571 goto DONE_ERROR;
573 delete [] newMenu;
575 break;
576 default:
577 goto DONE_ERROR;
580 UnlockResource(hglMenuTemplate);
581 FreeResource(hglMenuTemplate);
582 return TRUE;
584 DONE_ERROR:
585 UnlockResource(hglMenuTemplate);
586 FreeResource(hglMenuTemplate);
587 MYERROR;
590 const WORD* CResModule::ParseMenuResource(const WORD * res)
592 WORD flags;
593 WORD id = 0;
594 LPCWSTR str;
596 //struct PopupMenuItem {
597 // WORD fItemFlags;
598 // WCHAR szItemText[];
599 //};
600 //struct NormalMenuItem {
601 // WORD fItemFlags;
602 // WORD wMenuID;
603 // WCHAR szItemText[];
604 //};
608 flags = GET_WORD(res);
609 res++;
610 if (!(flags & MF_POPUP))
612 id = GET_WORD(res); //normal menu item
613 res++;
615 else
616 id = (WORD)-1; //popup menu item
618 str = (LPCWSTR)res;
619 size_t l = wcslen(str)+1;
620 res += l;
622 if (flags & MF_POPUP)
624 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
625 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
626 _tcscpy(pBuf, str);
627 CUtils::StringExtend(pBuf);
629 std::wstring wstr = std::wstring(pBuf);
630 RESOURCEENTRY entry = m_StringEntries[wstr];
631 if (id)
632 entry.resourceIDs.insert(id);
634 m_StringEntries[wstr] = entry;
635 delete [] pBuf;
637 if ((res = ParseMenuResource(res))==0)
638 return NULL;
640 else if (id != 0)
642 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
643 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
644 _tcscpy(pBuf, str);
645 CUtils::StringExtend(pBuf);
647 std::wstring wstr = std::wstring(pBuf);
648 RESOURCEENTRY entry = m_StringEntries[wstr];
649 entry.resourceIDs.insert(id);
651 TCHAR szTempBuf[1024];
652 _stprintf(szTempBuf, _T("#: MenuEntry; ID:%d"), id);
653 MENUENTRY menu_entry;
654 menu_entry.wID = id;
655 menu_entry.reference = szTempBuf;
656 menu_entry.msgstr = wstr;
658 m_StringEntries[wstr] = entry;
659 m_MenuEntries[id] = menu_entry;
660 delete [] pBuf;
662 } while (!(flags & MF_END));
663 return res;
666 const WORD* CResModule::CountMemReplaceMenuResource(const WORD * res, size_t * wordcount, WORD * newMenu)
668 WORD flags;
669 WORD id = 0;
671 //struct PopupMenuItem {
672 // WORD fItemFlags;
673 // WCHAR szItemText[];
674 //};
675 //struct NormalMenuItem {
676 // WORD fItemFlags;
677 // WORD wMenuID;
678 // WCHAR szItemText[];
679 //};
683 flags = GET_WORD(res);
684 res++;
685 if (newMenu == NULL)
686 (*wordcount)++;
687 else
688 newMenu[(*wordcount)++] = flags;
689 if (!(flags & MF_POPUP))
691 id = GET_WORD(res); //normal menu item
692 res++;
693 if (newMenu == NULL)
694 (*wordcount)++;
695 else
696 newMenu[(*wordcount)++] = id;
698 else
699 id = (WORD)-1; //popup menu item
701 if (flags & MF_POPUP)
703 ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);
704 res += wcslen((LPCWSTR)res) + 1;
706 if ((res = CountMemReplaceMenuResource(res, wordcount, newMenu))==0)
707 return NULL;
709 else if (id != 0)
711 ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);
712 res += wcslen((LPCWSTR)res) + 1;
714 else
716 if (newMenu)
717 wcscpy((wchar_t *)&newMenu[(*wordcount)], (LPCWSTR)res);
718 (*wordcount) += wcslen((LPCWSTR)res) + 1;
719 res += wcslen((LPCWSTR)res) + 1;
721 } while (!(flags & MF_END));
722 return res;
725 const WORD* CResModule::ParseMenuExResource(const WORD * res)
727 DWORD dwType, dwState, menuId;
728 WORD bResInfo;
729 LPCWSTR str;
731 //struct MenuExItem {
732 // DWORD dwType;
733 // DWORD dwState;
734 // DWORD menuId;
735 // WORD bResInfo;
736 // WCHAR szText[];
737 // DWORD dwHelpId; - Popup menu only
738 //};
742 dwType = GET_DWORD(res);
743 res += 2;
744 dwState = GET_DWORD(res);
745 res += 2;
746 menuId = GET_DWORD(res);
747 res += 2;
748 bResInfo = GET_WORD(res);
749 res++;
751 str = (LPCWSTR)res;
752 size_t l = wcslen(str)+1;
753 res += l;
754 // Align to DWORD boundary
755 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);
757 if (dwType & MFT_SEPARATOR)
758 continue;
760 if (bResInfo & 0x01)
762 // Popup menu - note this can also have a non-zero ID
763 if (menuId == 0)
764 menuId = (WORD)-1;
765 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
766 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
767 _tcscpy(pBuf, str);
768 CUtils::StringExtend(pBuf);
770 std::wstring wstr = std::wstring(pBuf);
771 RESOURCEENTRY entry = m_StringEntries[wstr];
772 // Popup has a DWORD help entry on a DWORD boundary - skip over it
773 res += 2;
775 entry.resourceIDs.insert(menuId);
776 TCHAR szTempBuf[1024];
777 _stprintf(szTempBuf, _T("#: MenuExPopupEntry; ID:%d"), menuId);
778 MENUENTRY menu_entry;
779 menu_entry.wID = (WORD)menuId;
780 menu_entry.reference = szTempBuf;
781 menu_entry.msgstr = wstr;
782 m_StringEntries[wstr] = entry;
783 m_MenuEntries[(WORD)menuId] = menu_entry;
784 delete [] pBuf;
786 if ((res = ParseMenuExResource(res)) == 0)
787 return NULL;
788 } else if (menuId != 0)
790 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
791 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
792 _tcscpy(pBuf, str);
793 CUtils::StringExtend(pBuf);
795 std::wstring wstr = std::wstring(pBuf);
796 RESOURCEENTRY entry = m_StringEntries[wstr];
797 entry.resourceIDs.insert(menuId);
799 TCHAR szTempBuf[1024];
800 _stprintf(szTempBuf, _T("#: MenuExEntry; ID:%d"), menuId);
801 MENUENTRY menu_entry;
802 menu_entry.wID = (WORD)menuId;
803 menu_entry.reference = szTempBuf;
804 menu_entry.msgstr = wstr;
805 m_StringEntries[wstr] = entry;
806 m_MenuEntries[(WORD)menuId] = menu_entry;
807 delete [] pBuf;
809 } while (!(bResInfo & 0x80));
810 return res;
813 const WORD* CResModule::CountMemReplaceMenuExResource(const WORD * res, size_t * wordcount, WORD * newMenu)
815 DWORD dwType, dwState, menuId;
816 WORD bResInfo;
817 WORD *p0;
819 //struct MenuExItem {
820 // DWORD dwType;
821 // DWORD dwState;
822 // DWORD menuId;
823 // WORD bResInfo;
824 // WCHAR szText[];
825 // DWORD dwHelpId; - Popup menu only
826 //};
830 p0 = (WORD *)res;
831 dwType = GET_DWORD(res);
832 res += 2;
833 dwState = GET_DWORD(res);
834 res += 2;
835 menuId = GET_DWORD(res);
836 res += 2;
837 bResInfo = GET_WORD(res);
838 res++;
840 if (newMenu != NULL) {
841 CopyMemory(&newMenu[*wordcount], p0, 7 * sizeof(WORD));
843 (*wordcount) += 7;
845 if (dwType & MFT_SEPARATOR) {
846 // Align to DWORD
847 (*wordcount)++;
848 res++;
849 continue;
852 if (bResInfo & 0x01)
854 ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);
855 res += wcslen((LPCWSTR)res) + 1;
856 // Align to DWORD
857 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);
858 if ((*wordcount) & 0x01)
859 (*wordcount)++;
861 if (newMenu != NULL)
862 CopyMemory(&newMenu[*wordcount], res, sizeof(DWORD)); // Copy Help ID
864 res += 2;
865 (*wordcount) += 2;
867 if ((res = CountMemReplaceMenuExResource(res, wordcount, newMenu)) == 0)
868 return NULL;
870 else if (menuId != 0)
872 ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);
873 res += wcslen((LPCWSTR)res) + 1;
875 else
877 if (newMenu)
878 wcscpy((wchar_t *)&newMenu[(*wordcount)], (LPCWSTR)res);
879 (*wordcount) += wcslen((LPCWSTR)res) + 1;
880 res += wcslen((LPCWSTR)res) + 1;
882 // Align to DWORD
883 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);
884 if ((*wordcount) & 0x01)
885 (*wordcount)++;
886 } while (!(bResInfo & 0x80));
887 return res;
890 BOOL CResModule::ExtractAccelerator(UINT nID)
892 HRSRC hrsrc = FindResource(m_hResDll, MAKEINTRESOURCE(nID), RT_ACCELERATOR);
893 HGLOBAL hglAccTable;
894 WORD fFlags, wAnsi, wID;
895 const WORD* p;
896 bool bEnd(false);
898 if (!hrsrc)
899 MYERROR;
901 hglAccTable = LoadResource(m_hResDll, hrsrc);
903 if (!hglAccTable)
904 goto DONE_ERROR;
906 p = (const WORD*)LockResource(hglAccTable);
908 if (p == NULL)
909 MYERROR;
912 struct ACCELTABLEENTRY
914 WORD fFlags; FVIRTKEY, FSHIFT, FCONTROL, FALT, 0x80 - Last in a table
915 WORD wAnsi; ANSI character
916 WORD wId; Keyboard accelerator passed to windows
917 WORD padding; # bytes added to ensure aligned to DWORD boundary
923 fFlags = GET_WORD(p);
924 p++;
925 wAnsi = GET_WORD(p);
926 p++;
927 wID = GET_WORD(p);
928 p++;
929 p++; // Skip over padding
931 if ((fFlags & 0x80) == 0x80)
932 { // 0x80
933 bEnd = true;
936 if ((wAnsi < 0x30) ||
937 (wAnsi > 0x5A) ||
938 (wAnsi >= 0x3A && wAnsi <= 0x40))
939 continue;
941 TCHAR * pBuf = new TCHAR[1024];
942 SecureZeroMemory(pBuf, 1024 * sizeof(TCHAR));
944 // include the menu ID in the msgid to make sure that 'duplicate'
945 // accelerator keys are listed in the po-file.
946 // without this, we would get entries like this:
947 //#. Accelerator Entry for Menu ID:32809; '&Filter'
948 //#. Accelerator Entry for Menu ID:57636; '&Find'
949 //#: Corresponding Menu ID:32771; '&Find'
950 //msgid "V C +F"
951 //msgstr ""
953 // Since "filter" and "find" are most likely translated to words starting
954 // with different letters, we need to have a separate accelerator entry
955 // for each of those
956 _stprintf(pBuf, _T("ID:%d:"), wID);
958 // EXACTLY 5 characters long "ACS+X"
959 // V = Virtual key (or blank if not used)
960 // A = Alt key (or blank if not used)
961 // C = Ctrl key (or blank if not used)
962 // S = Shift key (or blank if not used)
963 // X = upper case character
964 // e.g. "V CS+Q" == Ctrl + Shift + 'Q'
965 if ((fFlags & FVIRTKEY) == FVIRTKEY) // 0x01
966 _tcscat(pBuf, _T("V"));
967 else
968 _tcscat(pBuf, _T(" "));
970 if ((fFlags & FALT) == FALT) // 0x10
971 _tcscat(pBuf, _T("A"));
972 else
973 _tcscat(pBuf, _T(" "));
975 if ((fFlags & FCONTROL) == FCONTROL) // 0x08
976 _tcscat(pBuf, _T("C"));
977 else
978 _tcscat(pBuf, _T(" "));
980 if ((fFlags & FSHIFT) == FSHIFT) // 0x04
981 _tcscat(pBuf, _T("S"));
982 else
983 _tcscat(pBuf, _T(" "));
985 _stprintf(pBuf, _T("%s+%c"), pBuf, wAnsi);
987 std::wstring wstr = std::wstring(pBuf);
988 RESOURCEENTRY AKey_entry = m_StringEntries[wstr];
990 TCHAR szTempBuf[1024];
991 SecureZeroMemory(szTempBuf, sizeof (szTempBuf));
992 std::wstring wmenu = _T("");
993 pME_iter = m_MenuEntries.find(wID);
994 if (pME_iter != m_MenuEntries.end())
996 wmenu = pME_iter->second.msgstr;
998 _stprintf(szTempBuf, _T("#. Accelerator Entry for Menu ID:%d; '%s'"), wID, wmenu.c_str());
999 AKey_entry.automaticcomments.push_back(std::wstring(szTempBuf));
1001 m_StringEntries[wstr] = AKey_entry;
1002 delete [] pBuf;
1003 } while (!bEnd);
1005 UnlockResource(hglAccTable);
1006 FreeResource(hglAccTable);
1007 return TRUE;
1009 DONE_ERROR:
1010 UnlockResource(hglAccTable);
1011 FreeResource(hglAccTable);
1012 MYERROR;
1015 BOOL CResModule::ReplaceAccelerator(UINT nID, WORD wLanguage)
1017 LPACCEL lpaccelNew; // pointer to new accelerator table
1018 HACCEL haccelOld; // handle to old accelerator table
1019 int cAccelerators; // number of accelerators in table
1020 HGLOBAL hglAccTableNew;
1021 const WORD* p;
1022 int i;
1024 haccelOld = LoadAccelerators(m_hResDll, MAKEINTRESOURCE(nID));
1026 if (haccelOld == NULL)
1027 MYERROR;
1029 cAccelerators = CopyAcceleratorTable(haccelOld, NULL, 0);
1031 lpaccelNew = (LPACCEL) LocalAlloc(LPTR, cAccelerators * sizeof(ACCEL));
1033 if (lpaccelNew == NULL)
1034 MYERROR;
1036 CopyAcceleratorTable(haccelOld, lpaccelNew, cAccelerators);
1038 // Find the accelerator that the user modified
1039 // and change its flags and virtual-key code
1040 // as appropriate.
1042 BYTE xfVirt;
1043 WORD xkey;
1044 static const size_t BufferSize = 1024;
1045 TCHAR * pBuf = new TCHAR[BufferSize];
1046 for (i = 0; i < cAccelerators; i++)
1048 if ((lpaccelNew[i].key < 0x30) ||
1049 (lpaccelNew[i].key > 0x5A) ||
1050 (lpaccelNew[i].key >= 0x3A && lpaccelNew[i].key <= 0x40))
1051 continue;
1053 SecureZeroMemory(pBuf, BufferSize * sizeof(TCHAR));
1055 _stprintf(pBuf, _T("ID:%d:"), lpaccelNew[i].cmd);
1057 // get original key combination
1058 if ((lpaccelNew[i].fVirt & FVIRTKEY) == FVIRTKEY) // 0x01
1059 _tcscat(pBuf, _T("V"));
1060 else
1061 _tcscat(pBuf, _T(" "));
1063 if ((lpaccelNew[i].fVirt & FALT) == FALT) // 0x10
1064 _tcscat(pBuf, _T("A"));
1065 else
1066 _tcscat(pBuf, _T(" "));
1068 if ((lpaccelNew[i].fVirt & FCONTROL) == FCONTROL) // 0x08
1069 _tcscat(pBuf, _T("C"));
1070 else
1071 _tcscat(pBuf, _T(" "));
1073 if ((lpaccelNew[i].fVirt & FSHIFT) == FSHIFT) // 0x04
1074 _tcscat(pBuf, _T("S"));
1075 else
1076 _tcscat(pBuf, _T(" "));
1078 _stprintf(pBuf, _T("%s+%c"), pBuf, lpaccelNew[i].key);
1080 // Is it there?
1081 std::map<std::wstring, RESOURCEENTRY>::iterator pAK_iter = m_StringEntries.find(pBuf);
1082 if (pAK_iter != m_StringEntries.end())
1084 m_bTranslatedAcceleratorStrings++;
1085 xfVirt = 0;
1086 xkey = 0;
1087 std::wstring wtemp = pAK_iter->second.msgstr;
1088 wtemp = wtemp.substr(wtemp.find_last_of(':')+1);
1089 if (wtemp.size() != 6)
1090 continue;
1091 if (wtemp.compare(0, 1, _T("V")) == 0)
1092 xfVirt |= FVIRTKEY;
1093 else if (wtemp.compare(0, 1, _T(" ")) != 0)
1094 continue; // not a space - user must have made a mistake when translating
1095 if (wtemp.compare(1, 1, _T("A")) == 0)
1096 xfVirt |= FALT;
1097 else if (wtemp.compare(1, 1, _T(" ")) != 0)
1098 continue; // not a space - user must have made a mistake when translating
1099 if (wtemp.compare(2, 1, _T("C")) == 0)
1100 xfVirt |= FCONTROL;
1101 else if (wtemp.compare(2, 1, _T(" ")) != 0)
1102 continue; // not a space - user must have made a mistake when translating
1103 if (wtemp.compare(3, 1, _T("S")) == 0)
1104 xfVirt |= FSHIFT;
1105 else if (wtemp.compare(3, 1, _T(" ")) != 0)
1106 continue; // not a space - user must have made a mistake when translating
1107 if (wtemp.compare(4, 1, _T("+")) == 0)
1109 _stscanf(wtemp.substr(5, 1).c_str(), _T("%c"), &xkey);
1110 lpaccelNew[i].fVirt = xfVirt;
1111 lpaccelNew[i].key = xkey;
1114 else
1115 m_bDefaultAcceleratorStrings++;
1118 delete [] pBuf;
1120 // Create the new accelerator table
1121 hglAccTableNew = LocalAlloc(LPTR, cAccelerators * 4 * sizeof(WORD));
1122 p = (WORD *)hglAccTableNew;
1123 lpaccelNew[cAccelerators-1].fVirt |= 0x80;
1124 for (i = 0; i < cAccelerators; i++)
1126 memcpy((void *)p, &lpaccelNew[i].fVirt, 1);
1127 p++;
1128 memcpy((void *)p, &lpaccelNew[i].key, sizeof(WORD));
1129 p++;
1130 memcpy((void *)p, &lpaccelNew[i].cmd, sizeof(WORD));
1131 p++;
1132 p++;
1135 if (!UpdateResource(m_hUpdateRes, RT_ACCELERATOR, MAKEINTRESOURCE(nID),
1136 (m_wTargetLang ? m_wTargetLang : wLanguage), hglAccTableNew /* haccelNew*/, cAccelerators * 4 * sizeof(WORD)))
1138 goto DONE_ERROR;
1141 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_ACCELERATOR, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))
1143 goto DONE_ERROR;
1146 LocalFree(hglAccTableNew);
1147 LocalFree(lpaccelNew);
1148 return TRUE;
1150 DONE_ERROR:
1151 LocalFree(hglAccTableNew);
1152 LocalFree(lpaccelNew);
1153 MYERROR;
1156 BOOL CResModule::ExtractDialog(UINT nID)
1158 const WORD* lpDlg;
1159 const WORD* lpDlgItem;
1160 DIALOGINFO dlg;
1161 DLGITEMINFO dlgItem;
1162 WORD bNumControls;
1163 HRSRC hrsrc;
1164 HGLOBAL hGlblDlgTemplate;
1166 hrsrc = FindResource(m_hResDll, MAKEINTRESOURCE(nID), RT_DIALOG);
1168 if (hrsrc == NULL)
1169 MYERROR;
1171 hGlblDlgTemplate = LoadResource(m_hResDll, hrsrc);
1172 if (hGlblDlgTemplate == NULL)
1173 MYERROR;
1175 lpDlg = (const WORD*) LockResource(hGlblDlgTemplate);
1177 if (lpDlg == NULL)
1178 MYERROR;
1180 lpDlgItem = (const WORD*) GetDialogInfo(lpDlg, &dlg);
1181 bNumControls = dlg.nbItems;
1183 if (dlg.caption)
1185 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
1186 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
1187 _tcscpy(pBuf, dlg.caption);
1188 CUtils::StringExtend(pBuf);
1190 std::wstring wstr = std::wstring(pBuf);
1191 RESOURCEENTRY entry = m_StringEntries[wstr];
1192 entry.resourceIDs.insert(nID);
1194 m_StringEntries[wstr] = entry;
1195 delete [] pBuf;
1198 while (bNumControls-- != 0)
1200 TCHAR szTitle[500];
1201 SecureZeroMemory(szTitle, sizeof(szTitle));
1202 BOOL bCode;
1204 lpDlgItem = GetControlInfo((WORD *) lpDlgItem, &dlgItem, dlg.dialogEx, &bCode);
1206 if (bCode == FALSE)
1207 _tcscpy(szTitle, dlgItem.windowName);
1209 if (_tcslen(szTitle) > 0)
1211 CUtils::StringExtend(szTitle);
1213 std::wstring wstr = std::wstring(szTitle);
1214 RESOURCEENTRY entry = m_StringEntries[wstr];
1215 entry.resourceIDs.insert(dlgItem.id);
1217 m_StringEntries[wstr] = entry;
1221 UnlockResource(hGlblDlgTemplate);
1222 FreeResource(hGlblDlgTemplate);
1223 return (TRUE);
1226 BOOL CResModule::ReplaceDialog(UINT nID, WORD wLanguage)
1228 const WORD* lpDlg;
1229 HRSRC hrsrc;
1230 HGLOBAL hGlblDlgTemplate;
1232 hrsrc = FindResourceEx(m_hResDll, RT_DIALOG, MAKEINTRESOURCE(nID), wLanguage);
1234 if (hrsrc == NULL)
1235 MYERROR;
1237 hGlblDlgTemplate = LoadResource(m_hResDll, hrsrc);
1239 if (hGlblDlgTemplate == NULL)
1240 MYERROR;
1242 lpDlg = (WORD *) LockResource(hGlblDlgTemplate);
1244 if (lpDlg == NULL)
1245 MYERROR;
1247 size_t nMem = 0;
1248 const WORD * p = lpDlg;
1249 if (!CountMemReplaceDialogResource(p, &nMem, NULL))
1250 goto DONE_ERROR;
1251 WORD * newDialog = new WORD[nMem + (nMem % 2)];
1252 SecureZeroMemory(newDialog, (nMem + (nMem % 2))*2);
1254 size_t index = 0;
1255 if (!CountMemReplaceDialogResource(lpDlg, &index, newDialog))
1257 delete [] newDialog;
1258 goto DONE_ERROR;
1261 if (!UpdateResource(m_hUpdateRes, RT_DIALOG, MAKEINTRESOURCE(nID), (m_wTargetLang ? m_wTargetLang : wLanguage), newDialog, (DWORD)(nMem + (nMem % 2))*2))
1263 delete [] newDialog;
1264 goto DONE_ERROR;
1267 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_DIALOG, MAKEINTRESOURCE(nID), wLanguage, NULL, 0)))
1269 delete [] newDialog;
1270 goto DONE_ERROR;
1273 delete [] newDialog;
1274 UnlockResource(hGlblDlgTemplate);
1275 FreeResource(hGlblDlgTemplate);
1276 return TRUE;
1278 DONE_ERROR:
1279 UnlockResource(hGlblDlgTemplate);
1280 FreeResource(hGlblDlgTemplate);
1281 MYERROR;
1284 const WORD* CResModule::GetDialogInfo(const WORD * pTemplate, LPDIALOGINFO lpDlgInfo)
1286 const WORD* p = (const WORD *)pTemplate;
1288 lpDlgInfo->style = GET_DWORD(p);
1289 p += 2;
1291 if (lpDlgInfo->style == 0xffff0001) // DIALOGEX resource
1293 lpDlgInfo->dialogEx = TRUE;
1294 lpDlgInfo->helpId = GET_DWORD(p);
1295 p += 2;
1296 lpDlgInfo->exStyle = GET_DWORD(p);
1297 p += 2;
1298 lpDlgInfo->style = GET_DWORD(p);
1299 p += 2;
1301 else
1303 lpDlgInfo->dialogEx = FALSE;
1304 lpDlgInfo->helpId = 0;
1305 lpDlgInfo->exStyle = GET_DWORD(p);
1306 p += 2;
1309 lpDlgInfo->nbItems = GET_WORD(p);
1310 p++;
1312 lpDlgInfo->x = GET_WORD(p);
1313 p++;
1315 lpDlgInfo->y = GET_WORD(p);
1316 p++;
1318 lpDlgInfo->cx = GET_WORD(p);
1319 p++;
1321 lpDlgInfo->cy = GET_WORD(p);
1322 p++;
1324 // Get the menu name
1326 switch (GET_WORD(p))
1328 case 0x0000:
1329 lpDlgInfo->menuName = NULL;
1330 p++;
1331 break;
1332 case 0xffff:
1333 lpDlgInfo->menuName = (LPCTSTR) (WORD) GET_WORD(p + 1);
1334 p += 2;
1335 break;
1336 default:
1337 lpDlgInfo->menuName = (LPCTSTR) p;
1338 p += wcslen((LPCWSTR) p) + 1;
1339 break;
1342 // Get the class name
1344 switch (GET_WORD(p))
1346 case 0x0000:
1347 lpDlgInfo->className = (LPCTSTR)MAKEINTATOM(32770);
1348 p++;
1349 break;
1350 case 0xffff:
1351 lpDlgInfo->className = (LPCTSTR) (WORD) GET_WORD(p + 1);
1352 p += 2;
1353 break;
1354 default:
1355 lpDlgInfo->className = (LPCTSTR) p;
1356 p += wcslen((LPCTSTR)p) + 1;
1357 break;
1360 // Get the window caption
1362 lpDlgInfo->caption = (LPCTSTR)p;
1363 p += wcslen((LPCWSTR) p) + 1;
1365 // Get the font name
1367 if (lpDlgInfo->style & DS_SETFONT)
1369 lpDlgInfo->pointSize = GET_WORD(p);
1370 p++;
1372 if (lpDlgInfo->dialogEx)
1374 lpDlgInfo->weight = GET_WORD(p);
1375 p++;
1376 lpDlgInfo->italic = LOBYTE(GET_WORD(p));
1377 p++;
1379 else
1381 lpDlgInfo->weight = FW_DONTCARE;
1382 lpDlgInfo->italic = FALSE;
1385 lpDlgInfo->faceName = (LPCTSTR)p;
1386 p += wcslen((LPCWSTR) p) + 1;
1388 // First control is on DWORD boundary
1389 p += ((((WORD)p + 3) & ~3) - (WORD)p)/sizeof(WORD);
1391 return p;
1394 const WORD* CResModule::GetControlInfo(const WORD* p, LPDLGITEMINFO lpDlgItemInfo, BOOL dialogEx, LPBOOL bIsID)
1396 if (dialogEx)
1398 lpDlgItemInfo->helpId = GET_DWORD(p);
1399 p += 2;
1400 lpDlgItemInfo->exStyle = GET_DWORD(p);
1401 p += 2;
1402 lpDlgItemInfo->style = GET_DWORD(p);
1403 p += 2;
1405 else
1407 lpDlgItemInfo->helpId = 0;
1408 lpDlgItemInfo->style = GET_DWORD(p);
1409 p += 2;
1410 lpDlgItemInfo->exStyle = GET_DWORD(p);
1411 p += 2;
1414 lpDlgItemInfo->x = GET_WORD(p);
1415 p++;
1417 lpDlgItemInfo->y = GET_WORD(p);
1418 p++;
1420 lpDlgItemInfo->cx = GET_WORD(p);
1421 p++;
1423 lpDlgItemInfo->cy = GET_WORD(p);
1424 p++;
1426 if (dialogEx)
1428 // ID is a DWORD for DIALOGEX
1429 lpDlgItemInfo->id = (WORD) GET_DWORD(p);
1430 p += 2;
1432 else
1434 lpDlgItemInfo->id = GET_WORD(p);
1435 p++;
1438 if (GET_WORD(p) == 0xffff)
1440 GET_WORD(p + 1);
1442 p += 2;
1444 else
1446 lpDlgItemInfo->className = (LPCTSTR) p;
1447 p += wcslen((LPCWSTR) p) + 1;
1450 if (GET_WORD(p) == 0xffff) // an integer ID?
1452 *bIsID = TRUE;
1453 lpDlgItemInfo->windowName = (LPCTSTR) (DWORD) GET_WORD(p + 1);
1454 p += 2;
1456 else
1458 *bIsID = FALSE;
1459 lpDlgItemInfo->windowName = (LPCTSTR) p;
1460 p += wcslen((LPCWSTR) p) + 1;
1463 if (GET_WORD(p))
1465 lpDlgItemInfo->data = (LPVOID) (p + 1);
1466 p += GET_WORD(p) / sizeof(WORD);
1468 else
1469 lpDlgItemInfo->data = NULL;
1471 p++;
1472 // Next control is on DWORD boundary
1473 p += ((((WORD)p + 3) & ~3) - (WORD)p)/sizeof(WORD);
1474 return p;
1477 const WORD * CResModule::CountMemReplaceDialogResource(const WORD * res, size_t * wordcount, WORD * newDialog)
1479 BOOL bEx = FALSE;
1480 DWORD style = GET_DWORD(res);
1481 if (newDialog)
1483 newDialog[(*wordcount)++] = GET_WORD(res++);
1484 newDialog[(*wordcount)++] = GET_WORD(res++);
1486 else
1488 res += 2;
1489 (*wordcount) += 2;
1492 if (style == 0xffff0001) // DIALOGEX resource
1494 bEx = TRUE;
1495 if (newDialog)
1497 newDialog[(*wordcount)++] = GET_WORD(res++); //help id
1498 newDialog[(*wordcount)++] = GET_WORD(res++); //help id
1499 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1500 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1501 style = GET_DWORD(res);
1502 newDialog[(*wordcount)++] = GET_WORD(res++); //style
1503 newDialog[(*wordcount)++] = GET_WORD(res++); //style
1505 else
1507 res += 4;
1508 style = GET_DWORD(res);
1509 res += 2;
1510 (*wordcount) += 6;
1513 else
1515 bEx = FALSE;
1516 if (newDialog)
1518 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1519 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1520 //style = GET_DWORD(res);
1521 //newDialog[(*wordcount)++] = GET_WORD(res++); //style
1522 //newDialog[(*wordcount)++] = GET_WORD(res++); //style
1524 else
1526 res += 2;
1527 (*wordcount) += 2;
1531 if (newDialog)
1532 newDialog[(*wordcount)] = GET_WORD(res);
1533 WORD nbItems = GET_WORD(res);
1534 (*wordcount)++;
1535 res++;
1537 if (newDialog)
1538 newDialog[(*wordcount)] = GET_WORD(res); //x
1539 (*wordcount)++;
1540 res++;
1542 if (newDialog)
1543 newDialog[(*wordcount)] = GET_WORD(res); //y
1544 (*wordcount)++;
1545 res++;
1547 if (newDialog)
1548 newDialog[(*wordcount)] = GET_WORD(res); //cx
1549 (*wordcount)++;
1550 res++;
1552 if (newDialog)
1553 newDialog[(*wordcount)] = GET_WORD(res); //cy
1554 (*wordcount)++;
1555 res++;
1557 // Get the menu name
1559 switch (GET_WORD(res))
1561 case 0x0000:
1562 if (newDialog)
1563 newDialog[(*wordcount)] = GET_WORD(res);
1564 (*wordcount)++;
1565 res++;
1566 break;
1567 case 0xffff:
1568 if (newDialog)
1570 newDialog[(*wordcount)++] = GET_WORD(res++);
1571 newDialog[(*wordcount)++] = GET_WORD(res++);
1573 else
1575 (*wordcount) += 2;
1576 res += 2;
1578 break;
1579 default:
1580 if (newDialog)
1582 wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);
1584 (*wordcount) += wcslen((LPCWSTR) res) + 1;
1585 res += wcslen((LPCWSTR) res) + 1;
1586 break;
1589 // Get the class name
1591 switch (GET_WORD(res))
1593 case 0x0000:
1594 if (newDialog)
1595 newDialog[(*wordcount)] = GET_WORD(res);
1596 (*wordcount)++;
1597 res++;
1598 break;
1599 case 0xffff:
1600 if (newDialog)
1602 newDialog[(*wordcount)++] = GET_WORD(res++);
1603 newDialog[(*wordcount)++] = GET_WORD(res++);
1605 else
1607 (*wordcount) += 2;
1608 res += 2;
1610 break;
1611 default:
1612 if (newDialog)
1614 wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);
1616 (*wordcount) += wcslen((LPCWSTR) res) + 1;
1617 res += wcslen((LPCWSTR) res) + 1;
1618 break;
1621 // Get the window caption
1623 ReplaceStr((LPCWSTR)res, newDialog, wordcount, &m_bTranslatedDialogStrings, &m_bDefaultDialogStrings);
1624 res += wcslen((LPCWSTR)res) + 1;
1626 // Get the font name
1628 if (style & DS_SETFONT)
1630 if (newDialog)
1631 newDialog[(*wordcount)] = GET_WORD(res);
1632 res++;
1633 (*wordcount)++;
1635 if (bEx)
1637 if (newDialog)
1639 newDialog[(*wordcount)++] = GET_WORD(res++);
1640 newDialog[(*wordcount)++] = GET_WORD(res++);
1642 else
1644 res += 2;
1645 (*wordcount) += 2;
1649 if (newDialog)
1650 wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);
1651 (*wordcount) += wcslen((LPCWSTR)res) + 1;
1652 res += wcslen((LPCWSTR)res) + 1;
1654 // First control is on DWORD boundary
1655 while ((*wordcount)%2)
1656 (*wordcount)++;
1657 while ((ULONG)res % 4)
1658 res++;
1660 while (nbItems--)
1662 res = ReplaceControlInfo(res, wordcount, newDialog, bEx);
1664 return res;
1667 const WORD* CResModule::ReplaceControlInfo(const WORD * res, size_t * wordcount, WORD * newDialog, BOOL bEx)
1669 if (bEx)
1671 if (newDialog)
1673 newDialog[(*wordcount)++] = GET_WORD(res++); //helpid
1674 newDialog[(*wordcount)++] = GET_WORD(res++); //helpid
1676 else
1678 res += 2;
1679 (*wordcount) += 2;
1682 if (newDialog)
1684 LONG * exStyle = (LONG*)&newDialog[(*wordcount)];
1685 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1686 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1687 if (m_bRTL)
1688 *exStyle |= WS_EX_RTLREADING;
1690 else
1692 res += 2;
1693 (*wordcount) += 2;
1696 if (newDialog)
1698 newDialog[(*wordcount)++] = GET_WORD(res++); //style
1699 newDialog[(*wordcount)++] = GET_WORD(res++); //style
1701 else
1703 res += 2;
1704 (*wordcount) += 2;
1707 if (newDialog)
1708 newDialog[(*wordcount)] = GET_WORD(res); //x
1709 res++;
1710 (*wordcount)++;
1712 if (newDialog)
1713 newDialog[(*wordcount)] = GET_WORD(res); //y
1714 res++;
1715 (*wordcount)++;
1717 if (newDialog)
1718 newDialog[(*wordcount)] = GET_WORD(res); //cx
1719 res++;
1720 (*wordcount)++;
1722 if (newDialog)
1723 newDialog[(*wordcount)] = GET_WORD(res); //cy
1724 res++;
1725 (*wordcount)++;
1727 if (bEx)
1729 // ID is a DWORD for DIALOGEX
1730 if (newDialog)
1732 newDialog[(*wordcount)++] = GET_WORD(res++);
1733 newDialog[(*wordcount)++] = GET_WORD(res++);
1735 else
1737 res += 2;
1738 (*wordcount) += 2;
1741 else
1743 if (newDialog)
1744 newDialog[(*wordcount)] = GET_WORD(res);
1745 res++;
1746 (*wordcount)++;
1749 if (GET_WORD(res) == 0xffff) //classID
1751 if (newDialog)
1753 newDialog[(*wordcount)++] = GET_WORD(res++);
1754 newDialog[(*wordcount)++] = GET_WORD(res++);
1756 else
1758 res += 2;
1759 (*wordcount) += 2;
1762 else
1764 if (newDialog)
1765 wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);
1766 (*wordcount) += wcslen((LPCWSTR) res) + 1;
1767 res += wcslen((LPCWSTR) res) + 1;
1770 if (GET_WORD(res) == 0xffff) // an integer ID?
1772 if (newDialog)
1774 newDialog[(*wordcount)++] = GET_WORD(res++);
1775 newDialog[(*wordcount)++] = GET_WORD(res++);
1777 else
1779 res += 2;
1780 (*wordcount) += 2;
1783 else
1785 ReplaceStr((LPCWSTR)res, newDialog, wordcount, &m_bTranslatedDialogStrings, &m_bDefaultDialogStrings);
1786 res += wcslen((LPCWSTR)res) + 1;
1789 if (newDialog)
1790 memcpy(&newDialog[(*wordcount)], res, (GET_WORD(res)+1)*sizeof(WORD));
1791 (*wordcount) += (GET_WORD(res)+1);
1792 res += (GET_WORD(res)+1);
1793 // Next control is on DWORD boundary
1794 while ((*wordcount) % 2)
1795 (*wordcount)++;
1796 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);
1798 return res;
1801 BOOL CALLBACK CResModule::EnumResNameCallback(HMODULE /*hModule*/, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)
1803 CResModule* lpResModule = (CResModule*)lParam;
1805 if (lpszType == RT_STRING)
1807 if (IS_INTRESOURCE(lpszName))
1809 if (!lpResModule->ExtractString(LOWORD(lpszName)))
1810 return FALSE;
1813 else if (lpszType == RT_MENU)
1815 if (IS_INTRESOURCE(lpszName))
1817 if (!lpResModule->ExtractMenu(LOWORD(lpszName)))
1818 return FALSE;
1821 else if (lpszType == RT_DIALOG)
1823 if (IS_INTRESOURCE(lpszName))
1825 if (!lpResModule->ExtractDialog(LOWORD(lpszName)))
1826 return FALSE;
1829 else if (lpszType == RT_ACCELERATOR)
1831 if (IS_INTRESOURCE(lpszName))
1833 if (!lpResModule->ExtractAccelerator(LOWORD(lpszName)))
1834 return FALSE;
1838 return TRUE;
1841 #pragma warning(push)
1842 #pragma warning(disable: 4189)
1843 BOOL CALLBACK CResModule::EnumResNameWriteCallback(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)
1845 CResModule* lpResModule = (CResModule*)lParam;
1846 return EnumResourceLanguages(hModule, lpszType, lpszName, (ENUMRESLANGPROC)&lpResModule->EnumResWriteLangCallback, lParam);
1848 #pragma warning(pop)
1850 BOOL CALLBACK CResModule::EnumResWriteLangCallback(HMODULE /*hModule*/, LPCTSTR lpszType, LPTSTR lpszName, WORD wLanguage, LONG_PTR lParam)
1852 BOOL bRes = FALSE;
1853 CResModule* lpResModule = (CResModule*)lParam;
1855 if (lpszType == RT_STRING)
1857 if (IS_INTRESOURCE(lpszName))
1859 bRes = lpResModule->ReplaceString(LOWORD(lpszName), wLanguage);
1862 else if (lpszType == RT_MENU)
1864 if (IS_INTRESOURCE(lpszName))
1866 bRes = lpResModule->ReplaceMenu(LOWORD(lpszName), wLanguage);
1869 else if (lpszType == RT_DIALOG)
1871 if (IS_INTRESOURCE(lpszName))
1873 bRes = lpResModule->ReplaceDialog(LOWORD(lpszName), wLanguage);
1876 else if (lpszType == RT_ACCELERATOR)
1878 if (IS_INTRESOURCE(lpszName))
1880 bRes = lpResModule->ReplaceAccelerator(LOWORD(lpszName), wLanguage);
1884 return bRes;
1888 void CResModule::ReplaceStr(LPCWSTR src, WORD * dest, size_t * count, int * translated, int * def)
1890 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
1891 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
1892 wcscpy(pBuf, src);
1893 CUtils::StringExtend(pBuf);
1895 std::wstring wstr = std::wstring(pBuf);
1896 RESOURCEENTRY entry = m_StringEntries[wstr];
1897 if (!entry.msgstr.empty())
1899 wcscpy(pBuf, entry.msgstr.c_str());
1900 CUtils::StringCollapse(pBuf);
1901 if (dest)
1902 wcscpy((wchar_t *)&dest[(*count)], pBuf);
1903 (*count) += wcslen(pBuf)+1;
1904 (*translated)++;
1906 else
1908 if (dest)
1909 wcscpy((wchar_t *)&dest[(*count)], src);
1910 (*count) += wcslen(src) + 1;
1911 if (wcslen(src))
1912 (*def)++;
1914 delete [] pBuf;