aboutsummaryrefslogtreecommitdiff
path: root/src/dutil/resrutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dutil/resrutil.cpp')
-rw-r--r--src/dutil/resrutil.cpp251
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
8BOOL 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/********************************************************************
17ResGetStringLangId - get the language id for a string in the string table.
18
19********************************************************************/
20extern "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
49LExit:
50 if (hModule)
51 {
52 ::FreeLibrary(hModule);
53 }
54
55 return hr;
56}
57
58
59/********************************************************************
60ResReadString
61
62NOTE: ppwzString should be freed with StrFree()
63********************************************************************/
64extern "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
97LExit:
98 return hr;
99}
100
101
102/********************************************************************
103 ResReadStringAnsi
104
105 NOTE: ppszString should be freed with StrFree()
106********************************************************************/
107extern "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
143LExit:
144 return hr;
145}
146
147
148/********************************************************************
149ResReadData - returns a pointer to the specified resource data
150
151NOTE: there is no "free" function for this call
152********************************************************************/
153extern "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
187LExit:
188 return hr;
189}
190
191
192/********************************************************************
193ResExportDataToFile - extracts the resource data to the specified target file
194
195********************************************************************/
196extern "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
224LExit:
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
239BOOL 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}