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