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.
20 #include ".\resmodule.h"
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)
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
)
56 size_t nEntries
= m_StringEntries
.size();
57 // fill in the std::map with all translatable entries
60 _ftprintf(stdout
, _T("Extracting StringTable...."));
61 EnumResourceNames(m_hResDll
, RT_STRING
, EnumResNameCallback
, (LONG_PTR
)this);
63 _ftprintf(stdout
, _T("%4d Strings\n"), m_StringEntries
.size()-nEntries
);
64 nEntries
= m_StringEntries
.size();
67 _ftprintf(stdout
, _T("Extracting Dialogs........"));
68 EnumResourceNames(m_hResDll
, RT_DIALOG
, EnumResNameCallback
, (LONG_PTR
)this);
70 _ftprintf(stdout
, _T("%4d Strings\n"), m_StringEntries
.size()-nEntries
);
71 nEntries
= m_StringEntries
.size();
74 _ftprintf(stdout
, _T("Extracting Menus.........."));
75 EnumResourceNames(m_hResDll
, RT_MENU
, EnumResNameCallback
, (LONG_PTR
)this);
77 _ftprintf(stdout
, _T("%4d Strings\n"), m_StringEntries
.size()-nEntries
);
78 nEntries
= m_StringEntries
.size();
80 _ftprintf(stdout
, _T("Extracting Accelerators..."));
81 EnumResourceNames(m_hResDll
, RT_ACCELERATOR
, EnumResNameCallback
, (LONG_PTR
)this);
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
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
)
104 // fill in the std::map with all translatable entries
107 _ftprintf(stdout
, _T("Extracting StringTable...."));
108 EnumResourceNames(m_hResDll
, RT_STRING
, EnumResNameCallback
, (LONG_PTR
)this);
110 _ftprintf(stdout
, _T("%4d Strings\n"), m_StringEntries
.size());
111 nEntries
= m_StringEntries
.size();
114 _ftprintf(stdout
, _T("Extracting Dialogs........"));
115 EnumResourceNames(m_hResDll
, RT_DIALOG
, EnumResNameCallback
, (LONG_PTR
)this);
117 _ftprintf(stdout
, _T("%4d Strings\n"), m_StringEntries
.size()-nEntries
);
118 nEntries
= m_StringEntries
.size();
121 _ftprintf(stdout
, _T("Extracting Menus.........."));
122 EnumResourceNames(m_hResDll
, RT_MENU
, EnumResNameCallback
, (LONG_PTR
)this);
124 _ftprintf(stdout
, _T("%4d Strings\n"), m_StringEntries
.size()-nEntries
);
125 nEntries
= m_StringEntries
.size();
128 _ftprintf(stdout
, _T("Extracting Accelerators..."));
129 EnumResourceNames(m_hResDll
, RT_ACCELERATOR
, EnumResNameCallback
, (LONG_PTR
)this);
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
136 m_StringEntries
.ParseFile(lpszPoFilePath
, !bNoUpdate
, m_bAdjustEOLs
);
138 // at last, save the new file
139 if (!m_StringEntries
.SaveFile(lpszPoFilePath
, lpszHeaderFile
))
142 FreeLibrary(m_hResDll
);
147 FreeLibrary(m_hResDll
);
151 BOOL
CResModule::CreateTranslatedResources(LPCTSTR lpszSrcLangDllPath
, LPCTSTR lpszDestLangDllPath
, LPCTSTR lpszPOFilePath
)
153 if (!CopyFile(lpszSrcLangDllPath
, lpszDestLangDllPath
, FALSE
))
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
);
162 m_hResDll
= LoadLibraryEx (lpszSrcLangDllPath
, NULL
, LOAD_LIBRARY_AS_IMAGE_RESOURCE
|LOAD_IGNORE_CODE_AUTHZ_LEVEL
);
163 if (m_hResDll
== NULL
)
166 } while ((m_hResDll
== NULL
)&&(count
< 10));
168 if (m_hResDll
== NULL
)
171 sDestFile
= std::wstring(lpszDestLangDllPath
);
173 // get all translated strings
174 if (!m_StringEntries
.ParseFile(lpszPOFilePath
, FALSE
, m_bAdjustEOLs
))
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;
189 m_hUpdateRes
= BeginUpdateResource(sDestFile
.c_str(), FALSE
);
190 if (m_hUpdateRes
== NULL
)
193 } while ((m_hUpdateRes
== NULL
)&&(count
< 10));
195 if (m_hUpdateRes
== NULL
)
200 _ftprintf(stdout
, _T("Translating StringTable..."));
201 bRes
= EnumResourceNames(m_hResDll
, RT_STRING
, EnumResNameWriteCallback
, (LONG_PTR
)this);
203 _ftprintf(stdout
, _T("%4d translated, %4d not translated\n"), m_bTranslatedStrings
, m_bDefaultStrings
);
206 _ftprintf(stdout
, _T("Translating Dialogs......."));
207 bRes
= EnumResourceNames(m_hResDll
, RT_DIALOG
, EnumResNameWriteCallback
, (LONG_PTR
)this);
209 _ftprintf(stdout
, _T("%4d translated, %4d not translated\n"), m_bTranslatedDialogStrings
, m_bDefaultDialogStrings
);
212 _ftprintf(stdout
, _T("Translating Menus........."));
213 bRes
= EnumResourceNames(m_hResDll
, RT_MENU
, EnumResNameWriteCallback
, (LONG_PTR
)this);
215 _ftprintf(stdout
, _T("%4d translated, %4d not translated\n"), m_bTranslatedMenuStrings
, m_bDefaultMenuStrings
);
218 _ftprintf(stdout
, _T("Translating Accelerators.."));
219 bRes
= EnumResourceNames(m_hResDll
, RT_ACCELERATOR
, EnumResNameWriteCallback
, (LONG_PTR
)this);
221 _ftprintf(stdout
, _T("%4d translated, %4d not translated\n"), m_bTranslatedAcceleratorStrings
, m_bDefaultAcceleratorStrings
);
224 if (!EndUpdateResource(m_hUpdateRes
, !bRes
))
227 FreeLibrary(m_hResDll
);
231 FreeLibrary(m_hResDll
);
235 BOOL
CResModule::ExtractString(UINT nID
)
237 HRSRC hrsrc
= FindResource(m_hResDll
, MAKEINTRESOURCE(nID
), RT_STRING
);
238 HGLOBAL hglStringTable
;
243 hglStringTable
= LoadResource(m_hResDll
, hrsrc
);
247 p
= (LPWSTR
)LockResource(hglStringTable
);
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
259 for (int i
=0; i
<16; ++i
)
261 int len
= GET_WORD(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
);
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
;
281 UnlockResource(hglStringTable
);
282 FreeResource(hglStringTable
);
285 UnlockResource(hglStringTable
);
286 FreeResource(hglStringTable
);
290 BOOL
CResModule::ReplaceString(UINT nID
, WORD wLanguage
)
292 HRSRC hrsrc
= FindResourceEx(m_hResDll
, RT_STRING
, MAKEINTRESOURCE(nID
), wLanguage
);
293 HGLOBAL hglStringTable
;
298 hglStringTable
= LoadResource(m_hResDll
, hrsrc
);
302 p
= (LPWSTR
)LockResource(hglStringTable
);
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
315 for (int i
=0; i
<16; ++i
)
318 size_t len
= GET_WORD(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
);
340 WORD
* newTable
= new WORD
[nMem
+ (nMem
% 2)];
341 SecureZeroMemory(newTable
, (nMem
+ (nMem
% 2))*2);
344 for (int i
=0; i
<16; ++i
)
346 int len
= GET_WORD(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
);
362 newTable
[index
++] = (WORD
)newlen
;
363 wcsncpy((wchar_t *)&newTable
[index
], pBuf
, newlen
);
365 m_bTranslatedStrings
++;
369 newTable
[index
++] = (WORD
)len
;
371 wcsncpy((wchar_t *)&newTable
[index
], p
, len
);
380 if (!UpdateResource(m_hUpdateRes
, RT_STRING
, MAKEINTRESOURCE(nID
), (m_wTargetLang
? m_wTargetLang
: wLanguage
), newTable
, (DWORD
)(nMem
+ (nMem
% 2))*2))
386 if ((m_wTargetLang
)&&(!UpdateResource(m_hUpdateRes
, RT_STRING
, MAKEINTRESOURCE(nID
), wLanguage
, NULL
, 0)))
392 UnlockResource(hglStringTable
);
393 FreeResource(hglStringTable
);
396 UnlockResource(hglStringTable
);
397 FreeResource(hglStringTable
);
401 BOOL
CResModule::ExtractMenu(UINT nID
)
403 HRSRC hrsrc
= FindResource(m_hResDll
, MAKEINTRESOURCE(nID
), RT_MENU
);
404 HGLOBAL hglMenuTemplate
;
405 WORD version
, offset
;
412 hglMenuTemplate
= LoadResource(m_hResDll
, hrsrc
);
414 if (!hglMenuTemplate
)
417 p
= (const WORD
*)LockResource(hglMenuTemplate
);
422 // Standard MENU resource
423 //struct MenuHeader {
424 // WORD wVersion; // Currently zero
425 // WORD cbHeaderSize; // Also zero
429 //struct MenuExHeader {
430 // WORD wVersion; // One
435 version
= GET_WORD(p
);
443 offset
= GET_WORD(p
);
446 if (!ParseMenuResource(p
))
452 offset
= GET_WORD(p
);
454 dwHelpId
= GET_DWORD(p
);
455 if (!ParseMenuExResource(p0
+ offset
))
463 UnlockResource(hglMenuTemplate
);
464 FreeResource(hglMenuTemplate
);
468 UnlockResource(hglMenuTemplate
);
469 FreeResource(hglMenuTemplate
);
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
;
483 MYERROR
; //just the language wasn't found
485 hglMenuTemplate
= LoadResource(m_hResDll
, hrsrc
);
487 if (!hglMenuTemplate
)
490 p
= (LPWSTR
)LockResource(hglMenuTemplate
);
495 //struct MenuHeader {
496 // WORD wVersion; // Currently zero
497 // WORD cbHeaderSize; // Also zero
501 //struct MenuExHeader {
502 // WORD wVersion; // One
507 version
= GET_WORD(p
);
515 offset
= GET_WORD(p
);
519 if (!CountMemReplaceMenuResource((WORD
*)p
, &nMem
, NULL
))
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
))
530 if (!UpdateResource(m_hUpdateRes
, RT_MENU
, MAKEINTRESOURCE(nID
), (m_wTargetLang
? m_wTargetLang
: wLanguage
), newMenu
, (DWORD
)(nMem
+ (nMem
% 2)+2)*2))
536 if ((m_wTargetLang
)&&(!UpdateResource(m_hUpdateRes
, RT_MENU
, MAKEINTRESOURCE(nID
), wLanguage
, NULL
, 0)))
546 offset
= GET_WORD(p
);
548 dwHelpId
= GET_DWORD(p
);
550 if (!CountMemReplaceMenuExResource((WORD
*)(p0
+ offset
), &nMem
, NULL
))
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
))
562 if (!UpdateResource(m_hUpdateRes
, RT_MENU
, MAKEINTRESOURCE(nID
), (m_wTargetLang
? m_wTargetLang
: wLanguage
), newMenu
, (DWORD
)(nMem
+ (nMem
% 2) + 4) * 2))
568 if ((m_wTargetLang
)&&(!UpdateResource(m_hUpdateRes
, RT_MENU
, MAKEINTRESOURCE(nID
), wLanguage
, NULL
, 0)))
580 UnlockResource(hglMenuTemplate
);
581 FreeResource(hglMenuTemplate
);
585 UnlockResource(hglMenuTemplate
);
586 FreeResource(hglMenuTemplate
);
590 const WORD
* CResModule::ParseMenuResource(const WORD
* res
)
596 //struct PopupMenuItem {
598 // WCHAR szItemText[];
600 //struct NormalMenuItem {
603 // WCHAR szItemText[];
608 flags
= GET_WORD(res
);
610 if (!(flags
& MF_POPUP
))
612 id
= GET_WORD(res
); //normal menu item
616 id
= (WORD
)-1; //popup menu item
619 size_t l
= wcslen(str
)+1;
622 if (flags
& MF_POPUP
)
624 TCHAR
* pBuf
= new TCHAR
[MAX_STRING_LENGTH
];
625 SecureZeroMemory(pBuf
, MAX_STRING_LENGTH
* sizeof(TCHAR
));
627 CUtils::StringExtend(pBuf
);
629 std::wstring wstr
= std::wstring(pBuf
);
630 RESOURCEENTRY entry
= m_StringEntries
[wstr
];
632 entry
.resourceIDs
.insert(id
);
634 m_StringEntries
[wstr
] = entry
;
637 if ((res
= ParseMenuResource(res
))==0)
642 TCHAR
* pBuf
= new TCHAR
[MAX_STRING_LENGTH
];
643 SecureZeroMemory(pBuf
, MAX_STRING_LENGTH
* sizeof(TCHAR
));
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
;
655 menu_entry
.reference
= szTempBuf
;
656 menu_entry
.msgstr
= wstr
;
658 m_StringEntries
[wstr
] = entry
;
659 m_MenuEntries
[id
] = menu_entry
;
662 } while (!(flags
& MF_END
));
666 const WORD
* CResModule::CountMemReplaceMenuResource(const WORD
* res
, size_t * wordcount
, WORD
* newMenu
)
671 //struct PopupMenuItem {
673 // WCHAR szItemText[];
675 //struct NormalMenuItem {
678 // WCHAR szItemText[];
683 flags
= GET_WORD(res
);
688 newMenu
[(*wordcount
)++] = flags
;
689 if (!(flags
& MF_POPUP
))
691 id
= GET_WORD(res
); //normal menu item
696 newMenu
[(*wordcount
)++] = id
;
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)
711 ReplaceStr((LPCWSTR
)res
, newMenu
, wordcount
, &m_bTranslatedMenuStrings
, &m_bDefaultMenuStrings
);
712 res
+= wcslen((LPCWSTR
)res
) + 1;
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
));
725 const WORD
* CResModule::ParseMenuExResource(const WORD
* res
)
727 DWORD dwType
, dwState
, menuId
;
731 //struct MenuExItem {
737 // DWORD dwHelpId; - Popup menu only
742 dwType
= GET_DWORD(res
);
744 dwState
= GET_DWORD(res
);
746 menuId
= GET_DWORD(res
);
748 bResInfo
= GET_WORD(res
);
752 size_t l
= wcslen(str
)+1;
754 // Align to DWORD boundary
755 res
+= ((((WORD
)res
+ 3) & ~3) - (WORD
)res
)/sizeof(WORD
);
757 if (dwType
& MFT_SEPARATOR
)
762 // Popup menu - note this can also have a non-zero ID
765 TCHAR
* pBuf
= new TCHAR
[MAX_STRING_LENGTH
];
766 SecureZeroMemory(pBuf
, MAX_STRING_LENGTH
* sizeof(TCHAR
));
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
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
;
786 if ((res
= ParseMenuExResource(res
)) == 0)
788 } else if (menuId
!= 0)
790 TCHAR
* pBuf
= new TCHAR
[MAX_STRING_LENGTH
];
791 SecureZeroMemory(pBuf
, MAX_STRING_LENGTH
* sizeof(TCHAR
));
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
;
809 } while (!(bResInfo
& 0x80));
813 const WORD
* CResModule::CountMemReplaceMenuExResource(const WORD
* res
, size_t * wordcount
, WORD
* newMenu
)
815 DWORD dwType
, dwState
, menuId
;
819 //struct MenuExItem {
825 // DWORD dwHelpId; - Popup menu only
831 dwType
= GET_DWORD(res
);
833 dwState
= GET_DWORD(res
);
835 menuId
= GET_DWORD(res
);
837 bResInfo
= GET_WORD(res
);
840 if (newMenu
!= NULL
) {
841 CopyMemory(&newMenu
[*wordcount
], p0
, 7 * sizeof(WORD
));
845 if (dwType
& MFT_SEPARATOR
) {
854 ReplaceStr((LPCWSTR
)res
, newMenu
, wordcount
, &m_bTranslatedMenuStrings
, &m_bDefaultMenuStrings
);
855 res
+= wcslen((LPCWSTR
)res
) + 1;
857 res
+= ((((WORD
)res
+ 3) & ~3) - (WORD
)res
)/sizeof(WORD
);
858 if ((*wordcount
) & 0x01)
862 CopyMemory(&newMenu
[*wordcount
], res
, sizeof(DWORD
)); // Copy Help ID
867 if ((res
= CountMemReplaceMenuExResource(res
, wordcount
, newMenu
)) == 0)
870 else if (menuId
!= 0)
872 ReplaceStr((LPCWSTR
)res
, newMenu
, wordcount
, &m_bTranslatedMenuStrings
, &m_bDefaultMenuStrings
);
873 res
+= wcslen((LPCWSTR
)res
) + 1;
878 wcscpy((wchar_t *)&newMenu
[(*wordcount
)], (LPCWSTR
)res
);
879 (*wordcount
) += wcslen((LPCWSTR
)res
) + 1;
880 res
+= wcslen((LPCWSTR
)res
) + 1;
883 res
+= ((((WORD
)res
+ 3) & ~3) - (WORD
)res
)/sizeof(WORD
);
884 if ((*wordcount
) & 0x01)
886 } while (!(bResInfo
& 0x80));
890 BOOL
CResModule::ExtractAccelerator(UINT nID
)
892 HRSRC hrsrc
= FindResource(m_hResDll
, MAKEINTRESOURCE(nID
), RT_ACCELERATOR
);
894 WORD fFlags
, wAnsi
, wID
;
901 hglAccTable
= LoadResource(m_hResDll
, hrsrc
);
906 p
= (const WORD
*)LockResource(hglAccTable
);
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
);
929 p
++; // Skip over padding
931 if ((fFlags
& 0x80) == 0x80)
936 if ((wAnsi
< 0x30) ||
938 (wAnsi
>= 0x3A && wAnsi
<= 0x40))
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'
953 // Since "filter" and "find" are most likely translated to words starting
954 // with different letters, we need to have a separate accelerator entry
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"));
968 _tcscat(pBuf
, _T(" "));
970 if ((fFlags
& FALT
) == FALT
) // 0x10
971 _tcscat(pBuf
, _T("A"));
973 _tcscat(pBuf
, _T(" "));
975 if ((fFlags
& FCONTROL
) == FCONTROL
) // 0x08
976 _tcscat(pBuf
, _T("C"));
978 _tcscat(pBuf
, _T(" "));
980 if ((fFlags
& FSHIFT
) == FSHIFT
) // 0x04
981 _tcscat(pBuf
, _T("S"));
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
;
1005 UnlockResource(hglAccTable
);
1006 FreeResource(hglAccTable
);
1010 UnlockResource(hglAccTable
);
1011 FreeResource(hglAccTable
);
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
;
1024 haccelOld
= LoadAccelerators(m_hResDll
, MAKEINTRESOURCE(nID
));
1026 if (haccelOld
== NULL
)
1029 cAccelerators
= CopyAcceleratorTable(haccelOld
, NULL
, 0);
1031 lpaccelNew
= (LPACCEL
) LocalAlloc(LPTR
, cAccelerators
* sizeof(ACCEL
));
1033 if (lpaccelNew
== NULL
)
1036 CopyAcceleratorTable(haccelOld
, lpaccelNew
, cAccelerators
);
1038 // Find the accelerator that the user modified
1039 // and change its flags and virtual-key code
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))
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"));
1061 _tcscat(pBuf
, _T(" "));
1063 if ((lpaccelNew
[i
].fVirt
& FALT
) == FALT
) // 0x10
1064 _tcscat(pBuf
, _T("A"));
1066 _tcscat(pBuf
, _T(" "));
1068 if ((lpaccelNew
[i
].fVirt
& FCONTROL
) == FCONTROL
) // 0x08
1069 _tcscat(pBuf
, _T("C"));
1071 _tcscat(pBuf
, _T(" "));
1073 if ((lpaccelNew
[i
].fVirt
& FSHIFT
) == FSHIFT
) // 0x04
1074 _tcscat(pBuf
, _T("S"));
1076 _tcscat(pBuf
, _T(" "));
1078 _stprintf(pBuf
, _T("%s+%c"), pBuf
, lpaccelNew
[i
].key
);
1081 std::map
<std::wstring
, RESOURCEENTRY
>::iterator pAK_iter
= m_StringEntries
.find(pBuf
);
1082 if (pAK_iter
!= m_StringEntries
.end())
1084 m_bTranslatedAcceleratorStrings
++;
1087 std::wstring wtemp
= pAK_iter
->second
.msgstr
;
1088 wtemp
= wtemp
.substr(wtemp
.find_last_of(':')+1);
1089 if (wtemp
.size() != 6)
1091 if (wtemp
.compare(0, 1, _T("V")) == 0)
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)
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)
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)
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
;
1115 m_bDefaultAcceleratorStrings
++;
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);
1128 memcpy((void *)p
, &lpaccelNew
[i
].key
, sizeof(WORD
));
1130 memcpy((void *)p
, &lpaccelNew
[i
].cmd
, sizeof(WORD
));
1135 if (!UpdateResource(m_hUpdateRes
, RT_ACCELERATOR
, MAKEINTRESOURCE(nID
),
1136 (m_wTargetLang
? m_wTargetLang
: wLanguage
), hglAccTableNew
/* haccelNew*/, cAccelerators
* 4 * sizeof(WORD
)))
1141 if ((m_wTargetLang
)&&(!UpdateResource(m_hUpdateRes
, RT_ACCELERATOR
, MAKEINTRESOURCE(nID
), wLanguage
, NULL
, 0)))
1146 LocalFree(hglAccTableNew
);
1147 LocalFree(lpaccelNew
);
1151 LocalFree(hglAccTableNew
);
1152 LocalFree(lpaccelNew
);
1156 BOOL
CResModule::ExtractDialog(UINT nID
)
1159 const WORD
* lpDlgItem
;
1161 DLGITEMINFO dlgItem
;
1164 HGLOBAL hGlblDlgTemplate
;
1166 hrsrc
= FindResource(m_hResDll
, MAKEINTRESOURCE(nID
), RT_DIALOG
);
1171 hGlblDlgTemplate
= LoadResource(m_hResDll
, hrsrc
);
1172 if (hGlblDlgTemplate
== NULL
)
1175 lpDlg
= (const WORD
*) LockResource(hGlblDlgTemplate
);
1180 lpDlgItem
= (const WORD
*) GetDialogInfo(lpDlg
, &dlg
);
1181 bNumControls
= dlg
.nbItems
;
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
;
1198 while (bNumControls
-- != 0)
1201 SecureZeroMemory(szTitle
, sizeof(szTitle
));
1204 lpDlgItem
= GetControlInfo((WORD
*) lpDlgItem
, &dlgItem
, dlg
.dialogEx
, &bCode
);
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
);
1226 BOOL
CResModule::ReplaceDialog(UINT nID
, WORD wLanguage
)
1230 HGLOBAL hGlblDlgTemplate
;
1232 hrsrc
= FindResourceEx(m_hResDll
, RT_DIALOG
, MAKEINTRESOURCE(nID
), wLanguage
);
1237 hGlblDlgTemplate
= LoadResource(m_hResDll
, hrsrc
);
1239 if (hGlblDlgTemplate
== NULL
)
1242 lpDlg
= (WORD
*) LockResource(hGlblDlgTemplate
);
1248 const WORD
* p
= lpDlg
;
1249 if (!CountMemReplaceDialogResource(p
, &nMem
, NULL
))
1251 WORD
* newDialog
= new WORD
[nMem
+ (nMem
% 2)];
1252 SecureZeroMemory(newDialog
, (nMem
+ (nMem
% 2))*2);
1255 if (!CountMemReplaceDialogResource(lpDlg
, &index
, newDialog
))
1257 delete [] newDialog
;
1261 if (!UpdateResource(m_hUpdateRes
, RT_DIALOG
, MAKEINTRESOURCE(nID
), (m_wTargetLang
? m_wTargetLang
: wLanguage
), newDialog
, (DWORD
)(nMem
+ (nMem
% 2))*2))
1263 delete [] newDialog
;
1267 if ((m_wTargetLang
)&&(!UpdateResource(m_hUpdateRes
, RT_DIALOG
, MAKEINTRESOURCE(nID
), wLanguage
, NULL
, 0)))
1269 delete [] newDialog
;
1273 delete [] newDialog
;
1274 UnlockResource(hGlblDlgTemplate
);
1275 FreeResource(hGlblDlgTemplate
);
1279 UnlockResource(hGlblDlgTemplate
);
1280 FreeResource(hGlblDlgTemplate
);
1284 const WORD
* CResModule::GetDialogInfo(const WORD
* pTemplate
, LPDIALOGINFO lpDlgInfo
)
1286 const WORD
* p
= (const WORD
*)pTemplate
;
1288 lpDlgInfo
->style
= GET_DWORD(p
);
1291 if (lpDlgInfo
->style
== 0xffff0001) // DIALOGEX resource
1293 lpDlgInfo
->dialogEx
= TRUE
;
1294 lpDlgInfo
->helpId
= GET_DWORD(p
);
1296 lpDlgInfo
->exStyle
= GET_DWORD(p
);
1298 lpDlgInfo
->style
= GET_DWORD(p
);
1303 lpDlgInfo
->dialogEx
= FALSE
;
1304 lpDlgInfo
->helpId
= 0;
1305 lpDlgInfo
->exStyle
= GET_DWORD(p
);
1309 lpDlgInfo
->nbItems
= GET_WORD(p
);
1312 lpDlgInfo
->x
= GET_WORD(p
);
1315 lpDlgInfo
->y
= GET_WORD(p
);
1318 lpDlgInfo
->cx
= GET_WORD(p
);
1321 lpDlgInfo
->cy
= GET_WORD(p
);
1324 // Get the menu name
1326 switch (GET_WORD(p
))
1329 lpDlgInfo
->menuName
= NULL
;
1333 lpDlgInfo
->menuName
= (LPCTSTR
) (WORD
) GET_WORD(p
+ 1);
1337 lpDlgInfo
->menuName
= (LPCTSTR
) p
;
1338 p
+= wcslen((LPCWSTR
) p
) + 1;
1342 // Get the class name
1344 switch (GET_WORD(p
))
1347 lpDlgInfo
->className
= (LPCTSTR
)MAKEINTATOM(32770);
1351 lpDlgInfo
->className
= (LPCTSTR
) (WORD
) GET_WORD(p
+ 1);
1355 lpDlgInfo
->className
= (LPCTSTR
) p
;
1356 p
+= wcslen((LPCTSTR
)p
) + 1;
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
);
1372 if (lpDlgInfo
->dialogEx
)
1374 lpDlgInfo
->weight
= GET_WORD(p
);
1376 lpDlgInfo
->italic
= LOBYTE(GET_WORD(p
));
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
);
1394 const WORD
* CResModule::GetControlInfo(const WORD
* p
, LPDLGITEMINFO lpDlgItemInfo
, BOOL dialogEx
, LPBOOL bIsID
)
1398 lpDlgItemInfo
->helpId
= GET_DWORD(p
);
1400 lpDlgItemInfo
->exStyle
= GET_DWORD(p
);
1402 lpDlgItemInfo
->style
= GET_DWORD(p
);
1407 lpDlgItemInfo
->helpId
= 0;
1408 lpDlgItemInfo
->style
= GET_DWORD(p
);
1410 lpDlgItemInfo
->exStyle
= GET_DWORD(p
);
1414 lpDlgItemInfo
->x
= GET_WORD(p
);
1417 lpDlgItemInfo
->y
= GET_WORD(p
);
1420 lpDlgItemInfo
->cx
= GET_WORD(p
);
1423 lpDlgItemInfo
->cy
= GET_WORD(p
);
1428 // ID is a DWORD for DIALOGEX
1429 lpDlgItemInfo
->id
= (WORD
) GET_DWORD(p
);
1434 lpDlgItemInfo
->id
= GET_WORD(p
);
1438 if (GET_WORD(p
) == 0xffff)
1446 lpDlgItemInfo
->className
= (LPCTSTR
) p
;
1447 p
+= wcslen((LPCWSTR
) p
) + 1;
1450 if (GET_WORD(p
) == 0xffff) // an integer ID?
1453 lpDlgItemInfo
->windowName
= (LPCTSTR
) (DWORD
) GET_WORD(p
+ 1);
1459 lpDlgItemInfo
->windowName
= (LPCTSTR
) p
;
1460 p
+= wcslen((LPCWSTR
) p
) + 1;
1465 lpDlgItemInfo
->data
= (LPVOID
) (p
+ 1);
1466 p
+= GET_WORD(p
) / sizeof(WORD
);
1469 lpDlgItemInfo
->data
= NULL
;
1472 // Next control is on DWORD boundary
1473 p
+= ((((WORD
)p
+ 3) & ~3) - (WORD
)p
)/sizeof(WORD
);
1477 const WORD
* CResModule::CountMemReplaceDialogResource(const WORD
* res
, size_t * wordcount
, WORD
* newDialog
)
1480 DWORD style
= GET_DWORD(res
);
1483 newDialog
[(*wordcount
)++] = GET_WORD(res
++);
1484 newDialog
[(*wordcount
)++] = GET_WORD(res
++);
1492 if (style
== 0xffff0001) // DIALOGEX resource
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
1508 style
= GET_DWORD(res
);
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
1532 newDialog
[(*wordcount
)] = GET_WORD(res
);
1533 WORD nbItems
= GET_WORD(res
);
1538 newDialog
[(*wordcount
)] = GET_WORD(res
); //x
1543 newDialog
[(*wordcount
)] = GET_WORD(res
); //y
1548 newDialog
[(*wordcount
)] = GET_WORD(res
); //cx
1553 newDialog
[(*wordcount
)] = GET_WORD(res
); //cy
1557 // Get the menu name
1559 switch (GET_WORD(res
))
1563 newDialog
[(*wordcount
)] = GET_WORD(res
);
1570 newDialog
[(*wordcount
)++] = GET_WORD(res
++);
1571 newDialog
[(*wordcount
)++] = GET_WORD(res
++);
1582 wcscpy((LPWSTR
)&newDialog
[(*wordcount
)], (LPCWSTR
)res
);
1584 (*wordcount
) += wcslen((LPCWSTR
) res
) + 1;
1585 res
+= wcslen((LPCWSTR
) res
) + 1;
1589 // Get the class name
1591 switch (GET_WORD(res
))
1595 newDialog
[(*wordcount
)] = GET_WORD(res
);
1602 newDialog
[(*wordcount
)++] = GET_WORD(res
++);
1603 newDialog
[(*wordcount
)++] = GET_WORD(res
++);
1614 wcscpy((LPWSTR
)&newDialog
[(*wordcount
)], (LPCWSTR
)res
);
1616 (*wordcount
) += wcslen((LPCWSTR
) res
) + 1;
1617 res
+= wcslen((LPCWSTR
) res
) + 1;
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
)
1631 newDialog
[(*wordcount
)] = GET_WORD(res
);
1639 newDialog
[(*wordcount
)++] = GET_WORD(res
++);
1640 newDialog
[(*wordcount
)++] = GET_WORD(res
++);
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)
1657 while ((ULONG
)res
% 4)
1662 res
= ReplaceControlInfo(res
, wordcount
, newDialog
, bEx
);
1667 const WORD
* CResModule::ReplaceControlInfo(const WORD
* res
, size_t * wordcount
, WORD
* newDialog
, BOOL bEx
)
1673 newDialog
[(*wordcount
)++] = GET_WORD(res
++); //helpid
1674 newDialog
[(*wordcount
)++] = GET_WORD(res
++); //helpid
1684 LONG
* exStyle
= (LONG
*)&newDialog
[(*wordcount
)];
1685 newDialog
[(*wordcount
)++] = GET_WORD(res
++); //exStyle
1686 newDialog
[(*wordcount
)++] = GET_WORD(res
++); //exStyle
1688 *exStyle
|= WS_EX_RTLREADING
;
1698 newDialog
[(*wordcount
)++] = GET_WORD(res
++); //style
1699 newDialog
[(*wordcount
)++] = GET_WORD(res
++); //style
1708 newDialog
[(*wordcount
)] = GET_WORD(res
); //x
1713 newDialog
[(*wordcount
)] = GET_WORD(res
); //y
1718 newDialog
[(*wordcount
)] = GET_WORD(res
); //cx
1723 newDialog
[(*wordcount
)] = GET_WORD(res
); //cy
1729 // ID is a DWORD for DIALOGEX
1732 newDialog
[(*wordcount
)++] = GET_WORD(res
++);
1733 newDialog
[(*wordcount
)++] = GET_WORD(res
++);
1744 newDialog
[(*wordcount
)] = GET_WORD(res
);
1749 if (GET_WORD(res
) == 0xffff) //classID
1753 newDialog
[(*wordcount
)++] = GET_WORD(res
++);
1754 newDialog
[(*wordcount
)++] = GET_WORD(res
++);
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?
1774 newDialog
[(*wordcount
)++] = GET_WORD(res
++);
1775 newDialog
[(*wordcount
)++] = GET_WORD(res
++);
1785 ReplaceStr((LPCWSTR
)res
, newDialog
, wordcount
, &m_bTranslatedDialogStrings
, &m_bDefaultDialogStrings
);
1786 res
+= wcslen((LPCWSTR
)res
) + 1;
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)
1796 res
+= ((((WORD
)res
+ 3) & ~3) - (WORD
)res
)/sizeof(WORD
);
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
)))
1813 else if (lpszType
== RT_MENU
)
1815 if (IS_INTRESOURCE(lpszName
))
1817 if (!lpResModule
->ExtractMenu(LOWORD(lpszName
)))
1821 else if (lpszType
== RT_DIALOG
)
1823 if (IS_INTRESOURCE(lpszName
))
1825 if (!lpResModule
->ExtractDialog(LOWORD(lpszName
)))
1829 else if (lpszType
== RT_ACCELERATOR
)
1831 if (IS_INTRESOURCE(lpszName
))
1833 if (!lpResModule
->ExtractAccelerator(LOWORD(lpszName
)))
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
)
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
);
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
));
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
);
1902 wcscpy((wchar_t *)&dest
[(*count
)], pBuf
);
1903 (*count
) += wcslen(pBuf
)+1;
1909 wcscpy((wchar_t *)&dest
[(*count
)], src
);
1910 (*count
) += wcslen(src
) + 1;