Fixed issue #1571: Warn author not set when editing notes
[TortoiseGit.git] / src / ResText / ResModule.cpp
blobe5762355c36b5b60b7aacf8f97d950f217936104
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(LPCTSTR lpszType)
237 HRSRC hrsrc = FindResource(m_hResDll, lpszType, 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((DWORD)lpszType);
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(LPCTSTR lpszType, WORD wLanguage)
292 HRSRC hrsrc = FindResourceEx(m_hResDll, RT_STRING, lpszType, 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, lpszType, (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, lpszType, 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(LPCTSTR lpszType)
403 HRSRC hrsrc = FindResource(m_hResDll, lpszType, RT_MENU);
404 HGLOBAL hglMenuTemplate;
405 WORD version, offset;
406 const WORD *p, *p0;
408 if (!hrsrc)
409 MYERROR;
411 hglMenuTemplate = LoadResource(m_hResDll, hrsrc);
413 if (!hglMenuTemplate)
414 MYERROR;
416 p = (const WORD*)LockResource(hglMenuTemplate);
418 if (p == NULL)
419 MYERROR;
421 // Standard MENU resource
422 //struct MenuHeader {
423 // WORD wVersion; // Currently zero
424 // WORD cbHeaderSize; // Also zero
425 //};
427 // MENUEX resource
428 //struct MenuExHeader {
429 // WORD wVersion; // One
430 // WORD wOffset;
431 // DWORD dwHelpId;
432 //};
433 p0 = p;
434 version = GET_WORD(p);
436 p++;
438 switch (version)
440 case 0:
442 offset = GET_WORD(p);
443 p += offset;
444 p++;
445 if (!ParseMenuResource(p))
446 goto DONE_ERROR;
448 break;
449 case 1:
451 offset = GET_WORD(p);
452 p++;
453 //dwHelpId = GET_DWORD(p);
454 if (!ParseMenuExResource(p0 + offset))
455 goto DONE_ERROR;
457 break;
458 default:
459 goto DONE_ERROR;
462 UnlockResource(hglMenuTemplate);
463 FreeResource(hglMenuTemplate);
464 return TRUE;
466 DONE_ERROR:
467 UnlockResource(hglMenuTemplate);
468 FreeResource(hglMenuTemplate);
469 MYERROR;
472 BOOL CResModule::ReplaceMenu(LPCTSTR lpszType, WORD wLanguage)
474 HRSRC hrsrc = FindResourceEx(m_hResDll, RT_MENU, lpszType, wLanguage);
475 HGLOBAL hglMenuTemplate;
476 WORD version, offset;
477 LPWSTR p;
478 WORD *p0;
480 if (!hrsrc)
481 MYERROR; //just the language wasn't found
483 hglMenuTemplate = LoadResource(m_hResDll, hrsrc);
485 if (!hglMenuTemplate)
486 MYERROR;
488 p = (LPWSTR)LockResource(hglMenuTemplate);
490 if (p == NULL)
491 MYERROR;
493 //struct MenuHeader {
494 // WORD wVersion; // Currently zero
495 // WORD cbHeaderSize; // Also zero
496 //};
498 // MENUEX resource
499 //struct MenuExHeader {
500 // WORD wVersion; // One
501 // WORD wOffset;
502 // DWORD dwHelpId;
503 //};
504 p0 = (WORD *)p;
505 version = GET_WORD(p);
507 p++;
509 switch (version)
511 case 0:
513 offset = GET_WORD(p);
514 p += offset;
515 p++;
516 size_t nMem = 0;
517 if (!CountMemReplaceMenuResource((WORD *)p, &nMem, NULL))
518 goto DONE_ERROR;
519 WORD * newMenu = new WORD[nMem + (nMem % 2)+2];
520 SecureZeroMemory(newMenu, (nMem + (nMem % 2)+2)*2);
521 size_t index = 2; // MenuHeader has 2 WORDs zero
522 if (!CountMemReplaceMenuResource((WORD *)p, &index, newMenu))
524 delete [] newMenu;
525 goto DONE_ERROR;
528 if (!UpdateResource(m_hUpdateRes, RT_MENU, lpszType, (m_wTargetLang ? m_wTargetLang : wLanguage), newMenu, (DWORD)(nMem + (nMem % 2)+2)*2))
530 delete [] newMenu;
531 goto DONE_ERROR;
534 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_MENU, lpszType, wLanguage, NULL, 0)))
536 delete [] newMenu;
537 goto DONE_ERROR;
539 delete [] newMenu;
541 break;
542 case 1:
544 offset = GET_WORD(p);
545 p++;
546 //dwHelpId = GET_DWORD(p);
547 size_t nMem = 0;
548 if (!CountMemReplaceMenuExResource((WORD *)(p0 + offset), &nMem, NULL))
549 goto DONE_ERROR;
550 WORD * newMenu = new WORD[nMem + (nMem % 2) + 4];
551 SecureZeroMemory(newMenu, (nMem + (nMem % 2) + 4) * 2);
552 CopyMemory(newMenu, p0, 2 * sizeof(WORD) + sizeof(DWORD));
553 size_t index = 4; // MenuExHeader has 2 x WORD + 1 x DWORD
554 if (!CountMemReplaceMenuExResource((WORD *)(p0 + offset), &index, newMenu))
556 delete [] newMenu;
557 goto DONE_ERROR;
560 if (!UpdateResource(m_hUpdateRes, RT_MENU, lpszType, (m_wTargetLang ? m_wTargetLang : wLanguage), newMenu, (DWORD)(nMem + (nMem % 2) + 4) * 2))
562 delete [] newMenu;
563 goto DONE_ERROR;
566 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_MENU, lpszType, wLanguage, NULL, 0)))
568 delete [] newMenu;
569 goto DONE_ERROR;
571 delete [] newMenu;
573 break;
574 default:
575 goto DONE_ERROR;
578 UnlockResource(hglMenuTemplate);
579 FreeResource(hglMenuTemplate);
580 return TRUE;
582 DONE_ERROR:
583 UnlockResource(hglMenuTemplate);
584 FreeResource(hglMenuTemplate);
585 MYERROR;
588 const WORD* CResModule::ParseMenuResource(const WORD * res)
590 WORD flags;
591 WORD id = 0;
592 LPCWSTR str;
594 //struct PopupMenuItem {
595 // WORD fItemFlags;
596 // WCHAR szItemText[];
597 //};
598 //struct NormalMenuItem {
599 // WORD fItemFlags;
600 // WORD wMenuID;
601 // WCHAR szItemText[];
602 //};
606 flags = GET_WORD(res);
607 res++;
608 if (!(flags & MF_POPUP))
610 id = GET_WORD(res); //normal menu item
611 res++;
613 else
614 id = (WORD)-1; //popup menu item
616 str = (LPCWSTR)res;
617 size_t l = wcslen(str)+1;
618 res += l;
620 if (flags & MF_POPUP)
622 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
623 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
624 _tcscpy(pBuf, str);
625 CUtils::StringExtend(pBuf);
627 std::wstring wstr = std::wstring(pBuf);
628 RESOURCEENTRY entry = m_StringEntries[wstr];
629 if (id)
630 entry.resourceIDs.insert(id);
632 m_StringEntries[wstr] = entry;
633 delete [] pBuf;
635 if ((res = ParseMenuResource(res))==0)
636 return NULL;
638 else if (id != 0)
640 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
641 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
642 _tcscpy(pBuf, str);
643 CUtils::StringExtend(pBuf);
645 std::wstring wstr = std::wstring(pBuf);
646 RESOURCEENTRY entry = m_StringEntries[wstr];
647 entry.resourceIDs.insert(id);
649 TCHAR szTempBuf[1024];
650 _stprintf(szTempBuf, _T("#: MenuEntry; ID:%d"), id);
651 MENUENTRY menu_entry;
652 menu_entry.wID = id;
653 menu_entry.reference = szTempBuf;
654 menu_entry.msgstr = wstr;
656 m_StringEntries[wstr] = entry;
657 m_MenuEntries[id] = menu_entry;
658 delete [] pBuf;
660 } while (!(flags & MF_END));
661 return res;
664 const WORD* CResModule::CountMemReplaceMenuResource(const WORD * res, size_t * wordcount, WORD * newMenu)
666 WORD flags;
667 WORD id = 0;
669 //struct PopupMenuItem {
670 // WORD fItemFlags;
671 // WCHAR szItemText[];
672 //};
673 //struct NormalMenuItem {
674 // WORD fItemFlags;
675 // WORD wMenuID;
676 // WCHAR szItemText[];
677 //};
681 flags = GET_WORD(res);
682 res++;
683 if (newMenu == NULL)
684 (*wordcount)++;
685 else
686 newMenu[(*wordcount)++] = flags;
687 if (!(flags & MF_POPUP))
689 id = GET_WORD(res); //normal menu item
690 res++;
691 if (newMenu == NULL)
692 (*wordcount)++;
693 else
694 newMenu[(*wordcount)++] = id;
696 else
697 id = (WORD)-1; //popup menu item
699 if (flags & MF_POPUP)
701 ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);
702 res += wcslen((LPCWSTR)res) + 1;
704 if ((res = CountMemReplaceMenuResource(res, wordcount, newMenu))==0)
705 return NULL;
707 else if (id != 0)
709 ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);
710 res += wcslen((LPCWSTR)res) + 1;
712 else
714 if (newMenu)
715 wcscpy((wchar_t *)&newMenu[(*wordcount)], (LPCWSTR)res);
716 (*wordcount) += wcslen((LPCWSTR)res) + 1;
717 res += wcslen((LPCWSTR)res) + 1;
719 } while (!(flags & MF_END));
720 return res;
723 const WORD* CResModule::ParseMenuExResource(const WORD * res)
725 DWORD dwType, menuId;
726 WORD bResInfo;
727 LPCWSTR str;
729 //struct MenuExItem {
730 // DWORD dwType;
731 // DWORD dwState;
732 // DWORD menuId;
733 // WORD bResInfo;
734 // WCHAR szText[];
735 // DWORD dwHelpId; - Popup menu only
736 //};
740 dwType = GET_DWORD(res);
741 res += 2;
742 //dwState = GET_DWORD(res);
743 res += 2;
744 menuId = GET_DWORD(res);
745 res += 2;
746 bResInfo = GET_WORD(res);
747 res++;
749 str = (LPCWSTR)res;
750 size_t l = wcslen(str)+1;
751 res += l;
752 // Align to DWORD boundary
753 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);
755 if (dwType & MFT_SEPARATOR)
756 continue;
758 if (bResInfo & 0x01)
760 // Popup menu - note this can also have a non-zero ID
761 if (menuId == 0)
762 menuId = (WORD)-1;
763 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
764 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
765 _tcscpy(pBuf, str);
766 CUtils::StringExtend(pBuf);
768 std::wstring wstr = std::wstring(pBuf);
769 RESOURCEENTRY entry = m_StringEntries[wstr];
770 // Popup has a DWORD help entry on a DWORD boundary - skip over it
771 res += 2;
773 entry.resourceIDs.insert(menuId);
774 TCHAR szTempBuf[1024];
775 _stprintf(szTempBuf, _T("#: MenuExPopupEntry; ID:%d"), menuId);
776 MENUENTRY menu_entry;
777 menu_entry.wID = (WORD)menuId;
778 menu_entry.reference = szTempBuf;
779 menu_entry.msgstr = wstr;
780 m_StringEntries[wstr] = entry;
781 m_MenuEntries[(WORD)menuId] = menu_entry;
782 delete [] pBuf;
784 if ((res = ParseMenuExResource(res)) == 0)
785 return NULL;
786 } else if (menuId != 0)
788 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
789 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
790 _tcscpy(pBuf, str);
791 CUtils::StringExtend(pBuf);
793 std::wstring wstr = std::wstring(pBuf);
794 RESOURCEENTRY entry = m_StringEntries[wstr];
795 entry.resourceIDs.insert(menuId);
797 TCHAR szTempBuf[1024];
798 _stprintf(szTempBuf, _T("#: MenuExEntry; ID:%d"), menuId);
799 MENUENTRY menu_entry;
800 menu_entry.wID = (WORD)menuId;
801 menu_entry.reference = szTempBuf;
802 menu_entry.msgstr = wstr;
803 m_StringEntries[wstr] = entry;
804 m_MenuEntries[(WORD)menuId] = menu_entry;
805 delete [] pBuf;
807 } while (!(bResInfo & 0x80));
808 return res;
811 const WORD* CResModule::CountMemReplaceMenuExResource(const WORD * res, size_t * wordcount, WORD * newMenu)
813 DWORD dwType, menuId;
814 WORD bResInfo;
815 WORD *p0;
817 //struct MenuExItem {
818 // DWORD dwType;
819 // DWORD dwState;
820 // DWORD menuId;
821 // WORD bResInfo;
822 // WCHAR szText[];
823 // DWORD dwHelpId; - Popup menu only
824 //};
828 p0 = (WORD *)res;
829 dwType = GET_DWORD(res);
830 res += 2;
831 //dwState = GET_DWORD(res);
832 res += 2;
833 menuId = GET_DWORD(res);
834 res += 2;
835 bResInfo = GET_WORD(res);
836 res++;
838 if (newMenu != NULL) {
839 CopyMemory(&newMenu[*wordcount], p0, 7 * sizeof(WORD));
841 (*wordcount) += 7;
843 if (dwType & MFT_SEPARATOR) {
844 // Align to DWORD
845 (*wordcount)++;
846 res++;
847 continue;
850 if (bResInfo & 0x01)
852 ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);
853 res += wcslen((LPCWSTR)res) + 1;
854 // Align to DWORD
855 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);
856 if ((*wordcount) & 0x01)
857 (*wordcount)++;
859 if (newMenu != NULL)
860 CopyMemory(&newMenu[*wordcount], res, sizeof(DWORD)); // Copy Help ID
862 res += 2;
863 (*wordcount) += 2;
865 if ((res = CountMemReplaceMenuExResource(res, wordcount, newMenu)) == 0)
866 return NULL;
868 else if (menuId != 0)
870 ReplaceStr((LPCWSTR)res, newMenu, wordcount, &m_bTranslatedMenuStrings, &m_bDefaultMenuStrings);
871 res += wcslen((LPCWSTR)res) + 1;
873 else
875 if (newMenu)
876 wcscpy((wchar_t *)&newMenu[(*wordcount)], (LPCWSTR)res);
877 (*wordcount) += wcslen((LPCWSTR)res) + 1;
878 res += wcslen((LPCWSTR)res) + 1;
880 // Align to DWORD
881 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);
882 if ((*wordcount) & 0x01)
883 (*wordcount)++;
884 } while (!(bResInfo & 0x80));
885 return res;
888 BOOL CResModule::ExtractAccelerator(LPCTSTR lpszType)
890 HRSRC hrsrc = FindResource(m_hResDll, lpszType, RT_ACCELERATOR);
891 HGLOBAL hglAccTable;
892 WORD fFlags, wAnsi, wID;
893 const WORD* p;
894 bool bEnd(false);
896 if (!hrsrc)
897 MYERROR;
899 hglAccTable = LoadResource(m_hResDll, hrsrc);
901 if (!hglAccTable)
902 goto DONE_ERROR;
904 p = (const WORD*)LockResource(hglAccTable);
906 if (p == NULL)
907 MYERROR;
910 struct ACCELTABLEENTRY
912 WORD fFlags; FVIRTKEY, FSHIFT, FCONTROL, FALT, 0x80 - Last in a table
913 WORD wAnsi; ANSI character
914 WORD wId; Keyboard accelerator passed to windows
915 WORD padding; # bytes added to ensure aligned to DWORD boundary
921 fFlags = GET_WORD(p);
922 p++;
923 wAnsi = GET_WORD(p);
924 p++;
925 wID = GET_WORD(p);
926 p++;
927 p++; // Skip over padding
929 if ((fFlags & 0x80) == 0x80)
930 { // 0x80
931 bEnd = true;
934 if ((wAnsi < 0x30) ||
935 (wAnsi > 0x5A) ||
936 (wAnsi >= 0x3A && wAnsi <= 0x40))
937 continue;
939 TCHAR * pBuf = new TCHAR[1024];
940 SecureZeroMemory(pBuf, 1024 * sizeof(TCHAR));
942 // include the menu ID in the msgid to make sure that 'duplicate'
943 // accelerator keys are listed in the po-file.
944 // without this, we would get entries like this:
945 //#. Accelerator Entry for Menu ID:32809; '&Filter'
946 //#. Accelerator Entry for Menu ID:57636; '&Find'
947 //#: Corresponding Menu ID:32771; '&Find'
948 //msgid "V C +F"
949 //msgstr ""
951 // Since "filter" and "find" are most likely translated to words starting
952 // with different letters, we need to have a separate accelerator entry
953 // for each of those
954 _stprintf(pBuf, _T("ID:%d:"), wID);
956 // EXACTLY 5 characters long "ACS+X"
957 // V = Virtual key (or blank if not used)
958 // A = Alt key (or blank if not used)
959 // C = Ctrl key (or blank if not used)
960 // S = Shift key (or blank if not used)
961 // X = upper case character
962 // e.g. "V CS+Q" == Ctrl + Shift + 'Q'
963 if ((fFlags & FVIRTKEY) == FVIRTKEY) // 0x01
964 _tcscat(pBuf, _T("V"));
965 else
966 _tcscat(pBuf, _T(" "));
968 if ((fFlags & FALT) == FALT) // 0x10
969 _tcscat(pBuf, _T("A"));
970 else
971 _tcscat(pBuf, _T(" "));
973 if ((fFlags & FCONTROL) == FCONTROL) // 0x08
974 _tcscat(pBuf, _T("C"));
975 else
976 _tcscat(pBuf, _T(" "));
978 if ((fFlags & FSHIFT) == FSHIFT) // 0x04
979 _tcscat(pBuf, _T("S"));
980 else
981 _tcscat(pBuf, _T(" "));
983 _stprintf(pBuf, _T("%s+%c"), pBuf, wAnsi);
985 std::wstring wstr = std::wstring(pBuf);
986 RESOURCEENTRY AKey_entry = m_StringEntries[wstr];
988 TCHAR szTempBuf[1024];
989 SecureZeroMemory(szTempBuf, sizeof (szTempBuf));
990 std::wstring wmenu = _T("");
991 pME_iter = m_MenuEntries.find(wID);
992 if (pME_iter != m_MenuEntries.end())
994 wmenu = pME_iter->second.msgstr;
996 _stprintf(szTempBuf, _T("#. Accelerator Entry for Menu ID:%d; '%s'"), wID, wmenu.c_str());
997 AKey_entry.automaticcomments.push_back(std::wstring(szTempBuf));
999 m_StringEntries[wstr] = AKey_entry;
1000 delete [] pBuf;
1001 } while (!bEnd);
1003 UnlockResource(hglAccTable);
1004 FreeResource(hglAccTable);
1005 return TRUE;
1007 DONE_ERROR:
1008 UnlockResource(hglAccTable);
1009 FreeResource(hglAccTable);
1010 MYERROR;
1013 BOOL CResModule::ReplaceAccelerator(LPCTSTR lpszType, WORD wLanguage)
1015 LPACCEL lpaccelNew; // pointer to new accelerator table
1016 HACCEL haccelOld; // handle to old accelerator table
1017 int cAccelerators; // number of accelerators in table
1018 HGLOBAL hglAccTableNew;
1019 const WORD* p;
1020 int i;
1022 haccelOld = LoadAccelerators(m_hResDll, lpszType);
1024 if (haccelOld == NULL)
1025 MYERROR;
1027 cAccelerators = CopyAcceleratorTable(haccelOld, NULL, 0);
1029 lpaccelNew = (LPACCEL) LocalAlloc(LPTR, cAccelerators * sizeof(ACCEL));
1031 if (lpaccelNew == NULL)
1032 MYERROR;
1034 CopyAcceleratorTable(haccelOld, lpaccelNew, cAccelerators);
1036 // Find the accelerator that the user modified
1037 // and change its flags and virtual-key code
1038 // as appropriate.
1040 BYTE xfVirt;
1041 WORD xkey;
1042 static const size_t BufferSize = 1024;
1043 TCHAR * pBuf = new TCHAR[BufferSize];
1044 for (i = 0; i < cAccelerators; i++)
1046 if ((lpaccelNew[i].key < 0x30) ||
1047 (lpaccelNew[i].key > 0x5A) ||
1048 (lpaccelNew[i].key >= 0x3A && lpaccelNew[i].key <= 0x40))
1049 continue;
1051 SecureZeroMemory(pBuf, BufferSize * sizeof(TCHAR));
1053 _stprintf(pBuf, _T("ID:%d:"), lpaccelNew[i].cmd);
1055 // get original key combination
1056 if ((lpaccelNew[i].fVirt & FVIRTKEY) == FVIRTKEY) // 0x01
1057 _tcscat(pBuf, _T("V"));
1058 else
1059 _tcscat(pBuf, _T(" "));
1061 if ((lpaccelNew[i].fVirt & FALT) == FALT) // 0x10
1062 _tcscat(pBuf, _T("A"));
1063 else
1064 _tcscat(pBuf, _T(" "));
1066 if ((lpaccelNew[i].fVirt & FCONTROL) == FCONTROL) // 0x08
1067 _tcscat(pBuf, _T("C"));
1068 else
1069 _tcscat(pBuf, _T(" "));
1071 if ((lpaccelNew[i].fVirt & FSHIFT) == FSHIFT) // 0x04
1072 _tcscat(pBuf, _T("S"));
1073 else
1074 _tcscat(pBuf, _T(" "));
1076 _stprintf(pBuf, _T("%s+%c"), pBuf, lpaccelNew[i].key);
1078 // Is it there?
1079 std::map<std::wstring, RESOURCEENTRY>::iterator pAK_iter = m_StringEntries.find(pBuf);
1080 if (pAK_iter != m_StringEntries.end())
1082 m_bTranslatedAcceleratorStrings++;
1083 xfVirt = 0;
1084 xkey = 0;
1085 std::wstring wtemp = pAK_iter->second.msgstr;
1086 wtemp = wtemp.substr(wtemp.find_last_of(':')+1);
1087 if (wtemp.size() != 6)
1088 continue;
1089 if (wtemp.compare(0, 1, _T("V")) == 0)
1090 xfVirt |= FVIRTKEY;
1091 else if (wtemp.compare(0, 1, _T(" ")) != 0)
1092 continue; // not a space - user must have made a mistake when translating
1093 if (wtemp.compare(1, 1, _T("A")) == 0)
1094 xfVirt |= FALT;
1095 else if (wtemp.compare(1, 1, _T(" ")) != 0)
1096 continue; // not a space - user must have made a mistake when translating
1097 if (wtemp.compare(2, 1, _T("C")) == 0)
1098 xfVirt |= FCONTROL;
1099 else if (wtemp.compare(2, 1, _T(" ")) != 0)
1100 continue; // not a space - user must have made a mistake when translating
1101 if (wtemp.compare(3, 1, _T("S")) == 0)
1102 xfVirt |= FSHIFT;
1103 else if (wtemp.compare(3, 1, _T(" ")) != 0)
1104 continue; // not a space - user must have made a mistake when translating
1105 if (wtemp.compare(4, 1, _T("+")) == 0)
1107 _stscanf(wtemp.substr(5, 1).c_str(), _T("%c"), &xkey);
1108 lpaccelNew[i].fVirt = xfVirt;
1109 lpaccelNew[i].key = xkey;
1112 else
1113 m_bDefaultAcceleratorStrings++;
1116 delete [] pBuf;
1118 // Create the new accelerator table
1119 hglAccTableNew = LocalAlloc(LPTR, cAccelerators * 4 * sizeof(WORD));
1120 p = (WORD *)hglAccTableNew;
1121 lpaccelNew[cAccelerators-1].fVirt |= 0x80;
1122 for (i = 0; i < cAccelerators; i++)
1124 memcpy((void *)p, &lpaccelNew[i].fVirt, 1);
1125 p++;
1126 memcpy((void *)p, &lpaccelNew[i].key, sizeof(WORD));
1127 p++;
1128 memcpy((void *)p, &lpaccelNew[i].cmd, sizeof(WORD));
1129 p++;
1130 p++;
1133 if (!UpdateResource(m_hUpdateRes, RT_ACCELERATOR, lpszType,
1134 (m_wTargetLang ? m_wTargetLang : wLanguage), hglAccTableNew /* haccelNew*/, cAccelerators * 4 * sizeof(WORD)))
1136 goto DONE_ERROR;
1139 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_ACCELERATOR, lpszType, wLanguage, NULL, 0)))
1141 goto DONE_ERROR;
1144 LocalFree(hglAccTableNew);
1145 LocalFree(lpaccelNew);
1146 return TRUE;
1148 DONE_ERROR:
1149 LocalFree(hglAccTableNew);
1150 LocalFree(lpaccelNew);
1151 MYERROR;
1154 BOOL CResModule::ExtractDialog(LPCTSTR lpszType)
1156 const WORD* lpDlg;
1157 const WORD* lpDlgItem;
1158 DIALOGINFO dlg;
1159 DLGITEMINFO dlgItem;
1160 WORD bNumControls;
1161 HRSRC hrsrc;
1162 HGLOBAL hGlblDlgTemplate;
1164 hrsrc = FindResource(m_hResDll, lpszType, RT_DIALOG);
1166 if (hrsrc == NULL)
1167 MYERROR;
1169 hGlblDlgTemplate = LoadResource(m_hResDll, hrsrc);
1170 if (hGlblDlgTemplate == NULL)
1171 MYERROR;
1173 lpDlg = (const WORD*) LockResource(hGlblDlgTemplate);
1175 if (lpDlg == NULL)
1176 MYERROR;
1178 lpDlgItem = (const WORD*) GetDialogInfo(lpDlg, &dlg);
1179 bNumControls = dlg.nbItems;
1181 if (dlg.caption)
1183 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
1184 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
1185 _tcscpy(pBuf, dlg.caption);
1186 CUtils::StringExtend(pBuf);
1188 std::wstring wstr = std::wstring(pBuf);
1189 RESOURCEENTRY entry = m_StringEntries[wstr];
1190 entry.resourceIDs.insert((DWORD)lpszType);
1192 m_StringEntries[wstr] = entry;
1193 delete [] pBuf;
1196 while (bNumControls-- != 0)
1198 TCHAR szTitle[500];
1199 SecureZeroMemory(szTitle, sizeof(szTitle));
1200 BOOL bCode;
1202 lpDlgItem = GetControlInfo((WORD *) lpDlgItem, &dlgItem, dlg.dialogEx, &bCode);
1204 if (bCode == FALSE)
1205 _tcscpy(szTitle, dlgItem.windowName);
1207 if (_tcslen(szTitle) > 0)
1209 CUtils::StringExtend(szTitle);
1211 std::wstring wstr = std::wstring(szTitle);
1212 RESOURCEENTRY entry = m_StringEntries[wstr];
1213 entry.resourceIDs.insert(dlgItem.id);
1215 m_StringEntries[wstr] = entry;
1219 UnlockResource(hGlblDlgTemplate);
1220 FreeResource(hGlblDlgTemplate);
1221 return (TRUE);
1224 BOOL CResModule::ReplaceDialog(LPCTSTR lpszType, WORD wLanguage)
1226 const WORD* lpDlg;
1227 HRSRC hrsrc;
1228 HGLOBAL hGlblDlgTemplate;
1230 hrsrc = FindResourceEx(m_hResDll, RT_DIALOG, lpszType, wLanguage);
1232 if (hrsrc == NULL)
1233 MYERROR;
1235 hGlblDlgTemplate = LoadResource(m_hResDll, hrsrc);
1237 if (hGlblDlgTemplate == NULL)
1238 MYERROR;
1240 lpDlg = (WORD *) LockResource(hGlblDlgTemplate);
1242 if (lpDlg == NULL)
1243 MYERROR;
1245 size_t nMem = 0;
1246 const WORD * p = lpDlg;
1247 if (!CountMemReplaceDialogResource(p, &nMem, NULL))
1248 goto DONE_ERROR;
1249 WORD * newDialog = new WORD[nMem + (nMem % 2)];
1250 SecureZeroMemory(newDialog, (nMem + (nMem % 2))*2);
1252 size_t index = 0;
1253 if (!CountMemReplaceDialogResource(lpDlg, &index, newDialog))
1255 delete [] newDialog;
1256 goto DONE_ERROR;
1259 if (!UpdateResource(m_hUpdateRes, RT_DIALOG, lpszType, (m_wTargetLang ? m_wTargetLang : wLanguage), newDialog, (DWORD)(nMem + (nMem % 2))*2))
1261 delete [] newDialog;
1262 goto DONE_ERROR;
1265 if ((m_wTargetLang)&&(!UpdateResource(m_hUpdateRes, RT_DIALOG, lpszType, wLanguage, NULL, 0)))
1267 delete [] newDialog;
1268 goto DONE_ERROR;
1271 delete [] newDialog;
1272 UnlockResource(hGlblDlgTemplate);
1273 FreeResource(hGlblDlgTemplate);
1274 return TRUE;
1276 DONE_ERROR:
1277 UnlockResource(hGlblDlgTemplate);
1278 FreeResource(hGlblDlgTemplate);
1279 MYERROR;
1282 const WORD* CResModule::GetDialogInfo(const WORD * pTemplate, LPDIALOGINFO lpDlgInfo)
1284 const WORD* p = (const WORD *)pTemplate;
1286 lpDlgInfo->style = GET_DWORD(p);
1287 p += 2;
1289 if (lpDlgInfo->style == 0xffff0001) // DIALOGEX resource
1291 lpDlgInfo->dialogEx = TRUE;
1292 lpDlgInfo->helpId = GET_DWORD(p);
1293 p += 2;
1294 lpDlgInfo->exStyle = GET_DWORD(p);
1295 p += 2;
1296 lpDlgInfo->style = GET_DWORD(p);
1297 p += 2;
1299 else
1301 lpDlgInfo->dialogEx = FALSE;
1302 lpDlgInfo->helpId = 0;
1303 lpDlgInfo->exStyle = GET_DWORD(p);
1304 p += 2;
1307 lpDlgInfo->nbItems = GET_WORD(p);
1308 p++;
1310 lpDlgInfo->x = GET_WORD(p);
1311 p++;
1313 lpDlgInfo->y = GET_WORD(p);
1314 p++;
1316 lpDlgInfo->cx = GET_WORD(p);
1317 p++;
1319 lpDlgInfo->cy = GET_WORD(p);
1320 p++;
1322 // Get the menu name
1324 switch (GET_WORD(p))
1326 case 0x0000:
1327 lpDlgInfo->menuName = NULL;
1328 p++;
1329 break;
1330 case 0xffff:
1331 lpDlgInfo->menuName = (LPCTSTR) (WORD) GET_WORD(p + 1);
1332 p += 2;
1333 break;
1334 default:
1335 lpDlgInfo->menuName = (LPCTSTR) p;
1336 p += wcslen((LPCWSTR) p) + 1;
1337 break;
1340 // Get the class name
1342 switch (GET_WORD(p))
1344 case 0x0000:
1345 lpDlgInfo->className = (LPCTSTR)MAKEINTATOM(32770);
1346 p++;
1347 break;
1348 case 0xffff:
1349 lpDlgInfo->className = (LPCTSTR) (WORD) GET_WORD(p + 1);
1350 p += 2;
1351 break;
1352 default:
1353 lpDlgInfo->className = (LPCTSTR) p;
1354 p += wcslen((LPCTSTR)p) + 1;
1355 break;
1358 // Get the window caption
1360 lpDlgInfo->caption = (LPCTSTR)p;
1361 p += wcslen((LPCWSTR) p) + 1;
1363 // Get the font name
1365 if (lpDlgInfo->style & DS_SETFONT)
1367 lpDlgInfo->pointSize = GET_WORD(p);
1368 p++;
1370 if (lpDlgInfo->dialogEx)
1372 lpDlgInfo->weight = GET_WORD(p);
1373 p++;
1374 lpDlgInfo->italic = LOBYTE(GET_WORD(p));
1375 p++;
1377 else
1379 lpDlgInfo->weight = FW_DONTCARE;
1380 lpDlgInfo->italic = FALSE;
1383 lpDlgInfo->faceName = (LPCTSTR)p;
1384 p += wcslen((LPCWSTR) p) + 1;
1386 // First control is on DWORD boundary
1387 p += ((((WORD)p + 3) & ~3) - (WORD)p)/sizeof(WORD);
1389 return p;
1392 const WORD* CResModule::GetControlInfo(const WORD* p, LPDLGITEMINFO lpDlgItemInfo, BOOL dialogEx, LPBOOL bIsID)
1394 if (dialogEx)
1396 lpDlgItemInfo->helpId = GET_DWORD(p);
1397 p += 2;
1398 lpDlgItemInfo->exStyle = GET_DWORD(p);
1399 p += 2;
1400 lpDlgItemInfo->style = GET_DWORD(p);
1401 p += 2;
1403 else
1405 lpDlgItemInfo->helpId = 0;
1406 lpDlgItemInfo->style = GET_DWORD(p);
1407 p += 2;
1408 lpDlgItemInfo->exStyle = GET_DWORD(p);
1409 p += 2;
1412 lpDlgItemInfo->x = GET_WORD(p);
1413 p++;
1415 lpDlgItemInfo->y = GET_WORD(p);
1416 p++;
1418 lpDlgItemInfo->cx = GET_WORD(p);
1419 p++;
1421 lpDlgItemInfo->cy = GET_WORD(p);
1422 p++;
1424 if (dialogEx)
1426 // ID is a DWORD for DIALOGEX
1427 lpDlgItemInfo->id = (WORD) GET_DWORD(p);
1428 p += 2;
1430 else
1432 lpDlgItemInfo->id = GET_WORD(p);
1433 p++;
1436 if (GET_WORD(p) == 0xffff)
1438 GET_WORD(p + 1);
1440 p += 2;
1442 else
1444 lpDlgItemInfo->className = (LPCTSTR) p;
1445 p += wcslen((LPCWSTR) p) + 1;
1448 if (GET_WORD(p) == 0xffff) // an integer ID?
1450 *bIsID = TRUE;
1451 lpDlgItemInfo->windowName = (LPCTSTR) (DWORD) GET_WORD(p + 1);
1452 p += 2;
1454 else
1456 *bIsID = FALSE;
1457 lpDlgItemInfo->windowName = (LPCTSTR) p;
1458 p += wcslen((LPCWSTR) p) + 1;
1461 if (GET_WORD(p))
1463 lpDlgItemInfo->data = (LPVOID) (p + 1);
1464 p += GET_WORD(p) / sizeof(WORD);
1466 else
1467 lpDlgItemInfo->data = NULL;
1469 p++;
1470 // Next control is on DWORD boundary
1471 p += ((((WORD)p + 3) & ~3) - (WORD)p)/sizeof(WORD);
1472 return p;
1475 const WORD * CResModule::CountMemReplaceDialogResource(const WORD * res, size_t * wordcount, WORD * newDialog)
1477 BOOL bEx = FALSE;
1478 DWORD style = GET_DWORD(res);
1479 if (newDialog)
1481 newDialog[(*wordcount)++] = GET_WORD(res++);
1482 newDialog[(*wordcount)++] = GET_WORD(res++);
1484 else
1486 res += 2;
1487 (*wordcount) += 2;
1490 if (style == 0xffff0001) // DIALOGEX resource
1492 bEx = TRUE;
1493 if (newDialog)
1495 newDialog[(*wordcount)++] = GET_WORD(res++); //help id
1496 newDialog[(*wordcount)++] = GET_WORD(res++); //help id
1497 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1498 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1499 style = GET_DWORD(res);
1500 newDialog[(*wordcount)++] = GET_WORD(res++); //style
1501 newDialog[(*wordcount)++] = GET_WORD(res++); //style
1503 else
1505 res += 4;
1506 style = GET_DWORD(res);
1507 res += 2;
1508 (*wordcount) += 6;
1511 else
1513 bEx = FALSE;
1514 if (newDialog)
1516 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1517 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1518 //style = GET_DWORD(res);
1519 //newDialog[(*wordcount)++] = GET_WORD(res++); //style
1520 //newDialog[(*wordcount)++] = GET_WORD(res++); //style
1522 else
1524 res += 2;
1525 (*wordcount) += 2;
1529 if (newDialog)
1530 newDialog[(*wordcount)] = GET_WORD(res);
1531 WORD nbItems = GET_WORD(res);
1532 (*wordcount)++;
1533 res++;
1535 if (newDialog)
1536 newDialog[(*wordcount)] = GET_WORD(res); //x
1537 (*wordcount)++;
1538 res++;
1540 if (newDialog)
1541 newDialog[(*wordcount)] = GET_WORD(res); //y
1542 (*wordcount)++;
1543 res++;
1545 if (newDialog)
1546 newDialog[(*wordcount)] = GET_WORD(res); //cx
1547 (*wordcount)++;
1548 res++;
1550 if (newDialog)
1551 newDialog[(*wordcount)] = GET_WORD(res); //cy
1552 (*wordcount)++;
1553 res++;
1555 // Get the menu name
1557 switch (GET_WORD(res))
1559 case 0x0000:
1560 if (newDialog)
1561 newDialog[(*wordcount)] = GET_WORD(res);
1562 (*wordcount)++;
1563 res++;
1564 break;
1565 case 0xffff:
1566 if (newDialog)
1568 newDialog[(*wordcount)++] = GET_WORD(res++);
1569 newDialog[(*wordcount)++] = GET_WORD(res++);
1571 else
1573 (*wordcount) += 2;
1574 res += 2;
1576 break;
1577 default:
1578 if (newDialog)
1580 wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);
1582 (*wordcount) += wcslen((LPCWSTR) res) + 1;
1583 res += wcslen((LPCWSTR) res) + 1;
1584 break;
1587 // Get the class name
1589 switch (GET_WORD(res))
1591 case 0x0000:
1592 if (newDialog)
1593 newDialog[(*wordcount)] = GET_WORD(res);
1594 (*wordcount)++;
1595 res++;
1596 break;
1597 case 0xffff:
1598 if (newDialog)
1600 newDialog[(*wordcount)++] = GET_WORD(res++);
1601 newDialog[(*wordcount)++] = GET_WORD(res++);
1603 else
1605 (*wordcount) += 2;
1606 res += 2;
1608 break;
1609 default:
1610 if (newDialog)
1612 wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);
1614 (*wordcount) += wcslen((LPCWSTR) res) + 1;
1615 res += wcslen((LPCWSTR) res) + 1;
1616 break;
1619 // Get the window caption
1621 ReplaceStr((LPCWSTR)res, newDialog, wordcount, &m_bTranslatedDialogStrings, &m_bDefaultDialogStrings);
1622 res += wcslen((LPCWSTR)res) + 1;
1624 // Get the font name
1626 if (style & DS_SETFONT)
1628 if (newDialog)
1629 newDialog[(*wordcount)] = GET_WORD(res);
1630 res++;
1631 (*wordcount)++;
1633 if (bEx)
1635 if (newDialog)
1637 newDialog[(*wordcount)++] = GET_WORD(res++);
1638 newDialog[(*wordcount)++] = GET_WORD(res++);
1640 else
1642 res += 2;
1643 (*wordcount) += 2;
1647 if (newDialog)
1648 wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);
1649 (*wordcount) += wcslen((LPCWSTR)res) + 1;
1650 res += wcslen((LPCWSTR)res) + 1;
1652 // First control is on DWORD boundary
1653 while ((*wordcount)%2)
1654 (*wordcount)++;
1655 while ((ULONG)res % 4)
1656 res++;
1658 while (nbItems--)
1660 res = ReplaceControlInfo(res, wordcount, newDialog, bEx);
1662 return res;
1665 const WORD* CResModule::ReplaceControlInfo(const WORD * res, size_t * wordcount, WORD * newDialog, BOOL bEx)
1667 if (bEx)
1669 if (newDialog)
1671 newDialog[(*wordcount)++] = GET_WORD(res++); //helpid
1672 newDialog[(*wordcount)++] = GET_WORD(res++); //helpid
1674 else
1676 res += 2;
1677 (*wordcount) += 2;
1680 if (newDialog)
1682 LONG * exStyle = (LONG*)&newDialog[(*wordcount)];
1683 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1684 newDialog[(*wordcount)++] = GET_WORD(res++); //exStyle
1685 if (m_bRTL)
1686 *exStyle |= WS_EX_RTLREADING;
1688 else
1690 res += 2;
1691 (*wordcount) += 2;
1694 if (newDialog)
1696 newDialog[(*wordcount)++] = GET_WORD(res++); //style
1697 newDialog[(*wordcount)++] = GET_WORD(res++); //style
1699 else
1701 res += 2;
1702 (*wordcount) += 2;
1705 if (newDialog)
1706 newDialog[(*wordcount)] = GET_WORD(res); //x
1707 res++;
1708 (*wordcount)++;
1710 if (newDialog)
1711 newDialog[(*wordcount)] = GET_WORD(res); //y
1712 res++;
1713 (*wordcount)++;
1715 if (newDialog)
1716 newDialog[(*wordcount)] = GET_WORD(res); //cx
1717 res++;
1718 (*wordcount)++;
1720 if (newDialog)
1721 newDialog[(*wordcount)] = GET_WORD(res); //cy
1722 res++;
1723 (*wordcount)++;
1725 if (bEx)
1727 // ID is a DWORD for DIALOGEX
1728 if (newDialog)
1730 newDialog[(*wordcount)++] = GET_WORD(res++);
1731 newDialog[(*wordcount)++] = GET_WORD(res++);
1733 else
1735 res += 2;
1736 (*wordcount) += 2;
1739 else
1741 if (newDialog)
1742 newDialog[(*wordcount)] = GET_WORD(res);
1743 res++;
1744 (*wordcount)++;
1747 if (GET_WORD(res) == 0xffff) //classID
1749 if (newDialog)
1751 newDialog[(*wordcount)++] = GET_WORD(res++);
1752 newDialog[(*wordcount)++] = GET_WORD(res++);
1754 else
1756 res += 2;
1757 (*wordcount) += 2;
1760 else
1762 if (newDialog)
1763 wcscpy((LPWSTR)&newDialog[(*wordcount)], (LPCWSTR)res);
1764 (*wordcount) += wcslen((LPCWSTR) res) + 1;
1765 res += wcslen((LPCWSTR) res) + 1;
1768 if (GET_WORD(res) == 0xffff) // an integer ID?
1770 if (newDialog)
1772 newDialog[(*wordcount)++] = GET_WORD(res++);
1773 newDialog[(*wordcount)++] = GET_WORD(res++);
1775 else
1777 res += 2;
1778 (*wordcount) += 2;
1781 else
1783 ReplaceStr((LPCWSTR)res, newDialog, wordcount, &m_bTranslatedDialogStrings, &m_bDefaultDialogStrings);
1784 res += wcslen((LPCWSTR)res) + 1;
1787 if (newDialog)
1788 memcpy(&newDialog[(*wordcount)], res, (GET_WORD(res)+1)*sizeof(WORD));
1789 (*wordcount) += (GET_WORD(res)+1);
1790 res += (GET_WORD(res)+1);
1791 // Next control is on DWORD boundary
1792 while ((*wordcount) % 2)
1793 (*wordcount)++;
1794 res += ((((WORD)res + 3) & ~3) - (WORD)res)/sizeof(WORD);
1796 return res;
1799 BOOL CALLBACK CResModule::EnumResNameCallback(HMODULE /*hModule*/, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)
1801 CResModule* lpResModule = (CResModule*)lParam;
1803 if (lpszType == RT_STRING)
1805 if (IS_INTRESOURCE(lpszName))
1807 if (!lpResModule->ExtractString(lpszName))
1808 return FALSE;
1811 else if (lpszType == RT_MENU)
1813 if (IS_INTRESOURCE(lpszName))
1815 if (!lpResModule->ExtractMenu(lpszName))
1816 return FALSE;
1819 else if (lpszType == RT_DIALOG)
1821 if (IS_INTRESOURCE(lpszName))
1823 if (!lpResModule->ExtractDialog(lpszName))
1824 return FALSE;
1827 else if (lpszType == RT_ACCELERATOR)
1829 if (IS_INTRESOURCE(lpszName))
1831 if (!lpResModule->ExtractAccelerator(lpszName))
1832 return FALSE;
1836 return TRUE;
1839 #pragma warning(push)
1840 #pragma warning(disable: 4189)
1841 BOOL CALLBACK CResModule::EnumResNameWriteCallback(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)
1843 CResModule* lpResModule = (CResModule*)lParam;
1844 return EnumResourceLanguages(hModule, lpszType, lpszName, (ENUMRESLANGPROC)&lpResModule->EnumResWriteLangCallback, lParam);
1846 #pragma warning(pop)
1848 BOOL CALLBACK CResModule::EnumResWriteLangCallback(HMODULE /*hModule*/, LPCTSTR lpszType, LPTSTR lpszName, WORD wLanguage, LONG_PTR lParam)
1850 BOOL bRes = FALSE;
1851 CResModule* lpResModule = (CResModule*)lParam;
1853 if (lpszType == RT_STRING)
1855 bRes = lpResModule->ReplaceString(lpszName, wLanguage);
1857 else if (lpszType == RT_MENU)
1859 bRes = lpResModule->ReplaceMenu(lpszName, wLanguage);
1861 else if (lpszType == RT_DIALOG)
1863 bRes = lpResModule->ReplaceDialog(lpszName, wLanguage);
1865 else if (lpszType == RT_ACCELERATOR)
1867 bRes = lpResModule->ReplaceAccelerator(lpszName, wLanguage);
1870 return bRes;
1874 void CResModule::ReplaceStr(LPCWSTR src, WORD * dest, size_t * count, int * translated, int * def)
1876 TCHAR * pBuf = new TCHAR[MAX_STRING_LENGTH];
1877 SecureZeroMemory(pBuf, MAX_STRING_LENGTH * sizeof(TCHAR));
1878 wcscpy(pBuf, src);
1879 CUtils::StringExtend(pBuf);
1881 std::wstring wstr = std::wstring(pBuf);
1882 RESOURCEENTRY entry = m_StringEntries[wstr];
1883 if (!entry.msgstr.empty())
1885 wcscpy(pBuf, entry.msgstr.c_str());
1886 CUtils::StringCollapse(pBuf);
1887 if (dest)
1888 wcscpy((wchar_t *)&dest[(*count)], pBuf);
1889 (*count) += wcslen(pBuf)+1;
1890 (*translated)++;
1892 else
1894 if (dest)
1895 wcscpy((wchar_t *)&dest[(*count)], src);
1896 (*count) += wcslen(src) + 1;
1897 if (wcslen(src))
1898 (*def)++;
1900 delete [] pBuf;