diff options
| author | Rob Mensching <rob@firegiant.com> | 2017-09-03 11:22:38 -0700 |
|---|---|---|
| committer | Rob Mensching <rob@firegiant.com> | 2017-09-03 13:33:33 -0700 |
| commit | 5d8375007754101ff2889d0e79486c8f9b7cf5ab (patch) | |
| tree | a76d6fb6a38dd9f04a93ffcfd9d64e76779b3414 /src/dutil/resrutil.cpp | |
| parent | 8e8da6dbc051ec884b5d439bb4f44dc027d05bbf (diff) | |
| download | wix-5d8375007754101ff2889d0e79486c8f9b7cf5ab.tar.gz wix-5d8375007754101ff2889d0e79486c8f9b7cf5ab.tar.bz2 wix-5d8375007754101ff2889d0e79486c8f9b7cf5ab.zip | |
Initial commit
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 | } | ||
