diff options
Diffstat (limited to 'src/dutil/resrutil.cpp')
-rw-r--r-- | src/dutil/resrutil.cpp | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/src/dutil/resrutil.cpp b/src/dutil/resrutil.cpp new file mode 100644 index 00000000..1da03ed9 --- /dev/null +++ b/src/dutil/resrutil.cpp | |||
@@ -0,0 +1,251 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | #include "precomp.h" | ||
4 | |||
5 | #define RES_STRINGS_PER_BLOCK 16 | ||
6 | |||
7 | |||
8 | BOOL CALLBACK EnumLangIdProc( | ||
9 | __in_opt HMODULE hModule, | ||
10 | __in_z LPCSTR lpType, | ||
11 | __in_z LPCSTR lpName, | ||
12 | __in WORD wLanguage, | ||
13 | __in LONG_PTR lParam | ||
14 | ); | ||
15 | |||
16 | /******************************************************************** | ||
17 | ResGetStringLangId - get the language id for a string in the string table. | ||
18 | |||
19 | ********************************************************************/ | ||
20 | extern "C" HRESULT DAPI ResGetStringLangId( | ||
21 | __in_opt LPCWSTR wzPath, | ||
22 | __in UINT uID, | ||
23 | __out WORD *pwLangId | ||
24 | ) | ||
25 | { | ||
26 | Assert(pwLangId); | ||
27 | |||
28 | HRESULT hr = S_OK; | ||
29 | HINSTANCE hModule = NULL; | ||
30 | DWORD dwBlockId = (uID / RES_STRINGS_PER_BLOCK) + 1; | ||
31 | WORD wFoundLangId = 0; | ||
32 | |||
33 | if (wzPath && *wzPath) | ||
34 | { | ||
35 | hModule = LoadLibraryExW(wzPath, NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE); | ||
36 | ExitOnNullWithLastError(hModule, hr, "Failed to open resource file: %ls", wzPath); | ||
37 | } | ||
38 | |||
39 | #pragma prefast(push) | ||
40 | #pragma prefast(disable:25068) | ||
41 | if (!::EnumResourceLanguagesA(hModule, RT_STRING, MAKEINTRESOURCE(dwBlockId), static_cast<ENUMRESLANGPROC>(EnumLangIdProc), reinterpret_cast<LONG_PTR>(&wFoundLangId))) | ||
42 | #pragma prefast(pop) | ||
43 | { | ||
44 | ExitWithLastError(hr, "Failed to find string language identifier."); | ||
45 | } | ||
46 | |||
47 | *pwLangId = wFoundLangId; | ||
48 | |||
49 | LExit: | ||
50 | if (hModule) | ||
51 | { | ||
52 | ::FreeLibrary(hModule); | ||
53 | } | ||
54 | |||
55 | return hr; | ||
56 | } | ||
57 | |||
58 | |||
59 | /******************************************************************** | ||
60 | ResReadString | ||
61 | |||
62 | NOTE: ppwzString should be freed with StrFree() | ||
63 | ********************************************************************/ | ||
64 | extern "C" HRESULT DAPI ResReadString( | ||
65 | __in HINSTANCE hinst, | ||
66 | __in UINT uID, | ||
67 | __deref_out_z LPWSTR* ppwzString | ||
68 | ) | ||
69 | { | ||
70 | Assert(hinst && ppwzString); | ||
71 | |||
72 | HRESULT hr = S_OK; | ||
73 | DWORD cch = 64; // first guess | ||
74 | DWORD cchReturned = 0; | ||
75 | |||
76 | do | ||
77 | { | ||
78 | hr = StrAlloc(ppwzString, cch); | ||
79 | ExitOnFailureDebugTrace(hr, "Failed to allocate string for resource id: %d", uID); | ||
80 | |||
81 | cchReturned = ::LoadStringW(hinst, uID, *ppwzString, cch); | ||
82 | if (0 == cchReturned) | ||
83 | { | ||
84 | ExitWithLastError(hr, "Failed to load string resource id: %d", uID); | ||
85 | } | ||
86 | |||
87 | // if the returned string count is one character too small, it's likely we have | ||
88 | // more data to read | ||
89 | if (cchReturned + 1 == cch) | ||
90 | { | ||
91 | cch *= 2; | ||
92 | hr = S_FALSE; | ||
93 | } | ||
94 | } while (S_FALSE == hr); | ||
95 | ExitOnFailure(hr, "Failed to load string resource id: %d", uID); | ||
96 | |||
97 | LExit: | ||
98 | return hr; | ||
99 | } | ||
100 | |||
101 | |||
102 | /******************************************************************** | ||
103 | ResReadStringAnsi | ||
104 | |||
105 | NOTE: ppszString should be freed with StrFree() | ||
106 | ********************************************************************/ | ||
107 | extern "C" HRESULT DAPI ResReadStringAnsi( | ||
108 | __in HINSTANCE hinst, | ||
109 | __in UINT uID, | ||
110 | __deref_out_z LPSTR* ppszString | ||
111 | ) | ||
112 | { | ||
113 | Assert(hinst && ppszString); | ||
114 | |||
115 | HRESULT hr = S_OK; | ||
116 | DWORD cch = 64; // first guess | ||
117 | DWORD cchReturned = 0; | ||
118 | |||
119 | do | ||
120 | { | ||
121 | hr = StrAnsiAlloc(ppszString, cch); | ||
122 | ExitOnFailureDebugTrace(hr, "Failed to allocate string for resource id: %d", uID); | ||
123 | |||
124 | #pragma prefast(push) | ||
125 | #pragma prefast(disable:25068) | ||
126 | cchReturned = ::LoadStringA(hinst, uID, *ppszString, cch); | ||
127 | #pragma prefast(pop) | ||
128 | if (0 == cchReturned) | ||
129 | { | ||
130 | ExitWithLastError(hr, "Failed to load string resource id: %d", uID); | ||
131 | } | ||
132 | |||
133 | // if the returned string count is one character too small, it's likely we have | ||
134 | // more data to read | ||
135 | if (cchReturned + 1 == cch) | ||
136 | { | ||
137 | cch *= 2; | ||
138 | hr = S_FALSE; | ||
139 | } | ||
140 | } while (S_FALSE == hr); | ||
141 | ExitOnFailure(hr, "failed to load string resource id: %d", uID); | ||
142 | |||
143 | LExit: | ||
144 | return hr; | ||
145 | } | ||
146 | |||
147 | |||
148 | /******************************************************************** | ||
149 | ResReadData - returns a pointer to the specified resource data | ||
150 | |||
151 | NOTE: there is no "free" function for this call | ||
152 | ********************************************************************/ | ||
153 | extern "C" HRESULT DAPI ResReadData( | ||
154 | __in_opt HINSTANCE hinst, | ||
155 | __in_z LPCSTR szDataName, | ||
156 | __deref_out_bcount(*pcb) PVOID *ppv, | ||
157 | __out DWORD *pcb | ||
158 | ) | ||
159 | { | ||
160 | Assert(szDataName); | ||
161 | Assert(ppv); | ||
162 | |||
163 | HRESULT hr = S_OK; | ||
164 | HRSRC hRsrc = NULL; | ||
165 | HGLOBAL hData = NULL; | ||
166 | DWORD cbData = 0; | ||
167 | |||
168 | #pragma prefast(push) | ||
169 | #pragma prefast(disable:25068) | ||
170 | hRsrc = ::FindResourceExA(hinst, RT_RCDATA, szDataName, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)); | ||
171 | #pragma prefast(pop) | ||
172 | ExitOnNullWithLastError(hRsrc, hr, "Failed to find resource."); | ||
173 | |||
174 | hData = ::LoadResource(hinst, hRsrc); | ||
175 | ExitOnNullWithLastError(hData, hr, "Failed to load resource."); | ||
176 | |||
177 | cbData = ::SizeofResource(hinst, hRsrc); | ||
178 | if (!cbData) | ||
179 | { | ||
180 | ExitWithLastError(hr, "Failed to get size of resource."); | ||
181 | } | ||
182 | |||
183 | *ppv = ::LockResource(hData); | ||
184 | ExitOnNullWithLastError(*ppv, hr, "Failed to lock data resource."); | ||
185 | *pcb = cbData; | ||
186 | |||
187 | LExit: | ||
188 | return hr; | ||
189 | } | ||
190 | |||
191 | |||
192 | /******************************************************************** | ||
193 | ResExportDataToFile - extracts the resource data to the specified target file | ||
194 | |||
195 | ********************************************************************/ | ||
196 | extern "C" HRESULT DAPI ResExportDataToFile( | ||
197 | __in_z LPCSTR szDataName, | ||
198 | __in_z LPCWSTR wzTargetFile, | ||
199 | __in DWORD dwCreationDisposition | ||
200 | ) | ||
201 | { | ||
202 | HRESULT hr = S_OK; | ||
203 | PVOID pData = NULL; | ||
204 | DWORD cbData = 0; | ||
205 | DWORD cbWritten = 0; | ||
206 | HANDLE hFile = INVALID_HANDLE_VALUE; | ||
207 | BOOL bCreatedFile = FALSE; | ||
208 | |||
209 | hr = ResReadData(NULL, szDataName, &pData, &cbData); | ||
210 | ExitOnFailure(hr, "Failed to GetData from %s.", szDataName); | ||
211 | |||
212 | hFile = ::CreateFileW(wzTargetFile, GENERIC_WRITE, 0, NULL, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL); | ||
213 | if (INVALID_HANDLE_VALUE == hFile) | ||
214 | { | ||
215 | ExitWithLastError(hr, "Failed to CreateFileW for %ls.", wzTargetFile); | ||
216 | } | ||
217 | bCreatedFile = TRUE; | ||
218 | |||
219 | if (!::WriteFile(hFile, pData, cbData, &cbWritten, NULL)) | ||
220 | { | ||
221 | ExitWithLastError(hr, "Failed to ::WriteFile for %ls.", wzTargetFile); | ||
222 | } | ||
223 | |||
224 | LExit: | ||
225 | ReleaseFile(hFile); | ||
226 | |||
227 | if (FAILED(hr)) | ||
228 | { | ||
229 | if (bCreatedFile) | ||
230 | { | ||
231 | ::DeleteFileW(wzTargetFile); | ||
232 | } | ||
233 | } | ||
234 | |||
235 | return hr; | ||
236 | } | ||
237 | |||
238 | |||
239 | BOOL CALLBACK EnumLangIdProc( | ||
240 | __in_opt HMODULE /* hModule */, | ||
241 | __in_z LPCSTR /* lpType */, | ||
242 | __in_z LPCSTR /* lpName */, | ||
243 | __in WORD wLanguage, | ||
244 | __in LONG_PTR lParam | ||
245 | ) | ||
246 | { | ||
247 | WORD *pwLangId = reinterpret_cast<WORD*>(lParam); | ||
248 | |||
249 | *pwLangId = wLanguage; | ||
250 | return TRUE; | ||
251 | } | ||