diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2021-10-31 14:20:44 -0500 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2021-11-01 16:34:09 -0500 |
commit | 7e60078d4a7fe748a39c135def9e84a2421ab474 (patch) | |
tree | 51dbe5067ca9596f99107719734c4946e4c080b4 /src/libs/dutil/WixToolset.DUtil/wndutil.cpp | |
parent | c092722a147940532b08f62403e182ef279f2c74 (diff) | |
download | wix-7e60078d4a7fe748a39c135def9e84a2421ab474.tar.gz wix-7e60078d4a7fe748a39c135def9e84a2421ab474.tar.bz2 wix-7e60078d4a7fe748a39c135def9e84a2421ab474.zip |
Avoid using control ids inside of thmutil.
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/wndutil.cpp')
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/wndutil.cpp | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/wndutil.cpp b/src/libs/dutil/WixToolset.DUtil/wndutil.cpp new file mode 100644 index 00000000..b75b0491 --- /dev/null +++ b/src/libs/dutil/WixToolset.DUtil/wndutil.cpp | |||
@@ -0,0 +1,206 @@ | |||
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 WnduExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_WNDUTIL, x, s, __VA_ARGS__) | ||
8 | #define WnduExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_WNDUTIL, x, s, __VA_ARGS__) | ||
9 | #define WnduExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_WNDUTIL, x, s, __VA_ARGS__) | ||
10 | #define WnduExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_WNDUTIL, x, s, __VA_ARGS__) | ||
11 | #define WnduExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_WNDUTIL, x, s, __VA_ARGS__) | ||
12 | #define WnduExitWithRootFailure(x, e, s, ...) ExitWithRootFailureSource(DUTIL_SOURCE_WNDUTIL, x, e, s, __VA_ARGS__) | ||
13 | #define WnduExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_WNDUTIL, x, s, __VA_ARGS__) | ||
14 | #define WnduExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_WNDUTIL, p, x, e, s, __VA_ARGS__) | ||
15 | #define WnduExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_WNDUTIL, p, x, s, __VA_ARGS__) | ||
16 | #define WnduExitOnNullDebugTrace(p, x, e, s, ...) ExitOnNullDebugTraceSource(DUTIL_SOURCE_WNDUTIL, p, x, e, s, __VA_ARGS__) | ||
17 | #define WnduExitOnInvalidHandleWithLastError(p, x, s, ...) ExitOnInvalidHandleWithLastErrorSource(DUTIL_SOURCE_WNDUTIL, p, x, s, __VA_ARGS__) | ||
18 | #define WnduExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_WNDUTIL, e, x, s, __VA_ARGS__) | ||
19 | #define WnduExitOnOptionalXmlQueryFailure(x, b, s, ...) ExitOnOptionalXmlQueryFailureSource(DUTIL_SOURCE_WNDUTIL, x, b, s, __VA_ARGS__) | ||
20 | #define WnduExitOnRequiredXmlQueryFailure(x, s, ...) ExitOnRequiredXmlQueryFailureSource(DUTIL_SOURCE_WNDUTIL, x, s, __VA_ARGS__) | ||
21 | #define WnduExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_WNDUTIL, g, x, s, __VA_ARGS__) | ||
22 | |||
23 | struct MEMBUFFER_FOR_RICHEDIT | ||
24 | { | ||
25 | BYTE* rgbData; | ||
26 | DWORD cbData; | ||
27 | |||
28 | DWORD iData; | ||
29 | }; | ||
30 | |||
31 | const DWORD GROW_WINDOW_TEXT = 250; | ||
32 | |||
33 | |||
34 | // prototypes | ||
35 | static DWORD CALLBACK RichEditStreamFromFileHandleCallback( | ||
36 | __in DWORD_PTR dwCookie, | ||
37 | __in_bcount(cb) LPBYTE pbBuff, | ||
38 | __in LONG cb, | ||
39 | __in LONG *pcb | ||
40 | ); | ||
41 | static DWORD CALLBACK RichEditStreamFromMemoryCallback( | ||
42 | __in DWORD_PTR dwCookie, | ||
43 | __in_bcount(cb) LPBYTE pbBuff, | ||
44 | __in LONG cb, | ||
45 | __in LONG *pcb | ||
46 | ); | ||
47 | |||
48 | |||
49 | DAPI_(HRESULT) WnduLoadRichEditFromFile( | ||
50 | __in HWND hWnd, | ||
51 | __in_z LPCWSTR wzFileName, | ||
52 | __in HMODULE hModule | ||
53 | ) | ||
54 | { | ||
55 | HRESULT hr = S_OK; | ||
56 | LPWSTR sczFile = NULL; | ||
57 | HANDLE hFile = INVALID_HANDLE_VALUE; | ||
58 | |||
59 | hr = PathRelativeToModule(&sczFile, wzFileName, hModule); | ||
60 | WnduExitOnFailure(hr, "Failed to read resource data."); | ||
61 | |||
62 | hFile = ::CreateFileW(sczFile, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); | ||
63 | if (INVALID_HANDLE_VALUE == hFile) | ||
64 | { | ||
65 | WnduExitWithLastError(hr, "Failed to open RTF file."); | ||
66 | } | ||
67 | else | ||
68 | { | ||
69 | LONGLONG llRtfSize; | ||
70 | hr = FileSizeByHandle(hFile, &llRtfSize); | ||
71 | if (SUCCEEDED(hr)) | ||
72 | { | ||
73 | ::SendMessageW(hWnd, EM_EXLIMITTEXT, 0, static_cast<LPARAM>(llRtfSize)); | ||
74 | } | ||
75 | |||
76 | EDITSTREAM es = { }; | ||
77 | es.pfnCallback = RichEditStreamFromFileHandleCallback; | ||
78 | es.dwCookie = reinterpret_cast<DWORD_PTR>(hFile); | ||
79 | |||
80 | ::SendMessageW(hWnd, EM_STREAMIN, SF_RTF, reinterpret_cast<LPARAM>(&es)); | ||
81 | hr = es.dwError; | ||
82 | WnduExitOnFailure(hr, "Failed to update RTF stream."); | ||
83 | } | ||
84 | |||
85 | LExit: | ||
86 | ReleaseStr(sczFile); | ||
87 | ReleaseFile(hFile); | ||
88 | |||
89 | return hr; | ||
90 | } | ||
91 | |||
92 | DAPI_(HRESULT) WnduLoadRichEditFromResource( | ||
93 | __in HWND hWnd, | ||
94 | __in_z LPCSTR szResourceName, | ||
95 | __in HMODULE hModule | ||
96 | ) | ||
97 | { | ||
98 | HRESULT hr = S_OK; | ||
99 | MEMBUFFER_FOR_RICHEDIT buffer = { }; | ||
100 | EDITSTREAM es = { }; | ||
101 | |||
102 | hr = ResReadData(hModule, szResourceName, reinterpret_cast<LPVOID*>(&buffer.rgbData), &buffer.cbData); | ||
103 | WnduExitOnFailure(hr, "Failed to read resource data."); | ||
104 | |||
105 | es.pfnCallback = RichEditStreamFromMemoryCallback; | ||
106 | es.dwCookie = reinterpret_cast<DWORD_PTR>(&buffer); | ||
107 | |||
108 | ::SendMessageW(hWnd, EM_STREAMIN, SF_RTF, reinterpret_cast<LPARAM>(&es)); | ||
109 | hr = es.dwError; | ||
110 | WnduExitOnFailure(hr, "Failed to update RTF stream."); | ||
111 | |||
112 | LExit: | ||
113 | return hr; | ||
114 | } | ||
115 | |||
116 | |||
117 | DAPI_(HRESULT) WnduGetControlText( | ||
118 | __in HWND hWnd, | ||
119 | __inout_z LPWSTR* psczText | ||
120 | ) | ||
121 | { | ||
122 | HRESULT hr = S_OK; | ||
123 | SIZE_T cbSize = 0; | ||
124 | DWORD cchText = 0; | ||
125 | DWORD cchTextRead = 0; | ||
126 | |||
127 | // Ensure the string has room for at least one character. | ||
128 | hr = StrMaxLength(*psczText, &cbSize); | ||
129 | WnduExitOnFailure(hr, "Failed to get text buffer length."); | ||
130 | |||
131 | cchText = (DWORD)min(DWORD_MAX, cbSize); | ||
132 | |||
133 | if (!cchText) | ||
134 | { | ||
135 | cchText = GROW_WINDOW_TEXT; | ||
136 | |||
137 | hr = StrAlloc(psczText, cchText); | ||
138 | WnduExitOnFailure(hr, "Failed to grow text buffer."); | ||
139 | } | ||
140 | |||
141 | // Read (and keep growing buffer) until we finally read less than there | ||
142 | // is room in the buffer. | ||
143 | for (;;) | ||
144 | { | ||
145 | cchTextRead = ::GetWindowTextW(hWnd, *psczText, cchText); | ||
146 | if (cchTextRead + 1 < cchText) | ||
147 | { | ||
148 | break; | ||
149 | } | ||
150 | else | ||
151 | { | ||
152 | cchText = cchTextRead + GROW_WINDOW_TEXT; | ||
153 | |||
154 | hr = StrAlloc(psczText, cchText); | ||
155 | WnduExitOnFailure(hr, "Failed to grow text buffer again."); | ||
156 | } | ||
157 | } | ||
158 | |||
159 | LExit: | ||
160 | return hr; | ||
161 | } | ||
162 | |||
163 | |||
164 | static DWORD CALLBACK RichEditStreamFromFileHandleCallback( | ||
165 | __in DWORD_PTR dwCookie, | ||
166 | __in_bcount(cb) LPBYTE pbBuff, | ||
167 | __in LONG cb, | ||
168 | __in LONG* pcb | ||
169 | ) | ||
170 | { | ||
171 | HRESULT hr = S_OK; | ||
172 | HANDLE hFile = reinterpret_cast<HANDLE>(dwCookie); | ||
173 | |||
174 | if (!::ReadFile(hFile, pbBuff, cb, reinterpret_cast<DWORD*>(pcb), NULL)) | ||
175 | { | ||
176 | WnduExitWithLastError(hr, "Failed to read file"); | ||
177 | } | ||
178 | |||
179 | LExit: | ||
180 | return hr; | ||
181 | } | ||
182 | |||
183 | |||
184 | static DWORD CALLBACK RichEditStreamFromMemoryCallback( | ||
185 | __in DWORD_PTR dwCookie, | ||
186 | __in_bcount(cb) LPBYTE pbBuff, | ||
187 | __in LONG cb, | ||
188 | __in LONG* pcb | ||
189 | ) | ||
190 | { | ||
191 | HRESULT hr = S_OK; | ||
192 | MEMBUFFER_FOR_RICHEDIT* pBuffer = reinterpret_cast<MEMBUFFER_FOR_RICHEDIT*>(dwCookie); | ||
193 | DWORD cbCopy = 0; | ||
194 | |||
195 | if (pBuffer->iData < pBuffer->cbData) | ||
196 | { | ||
197 | cbCopy = min(static_cast<DWORD>(cb), pBuffer->cbData - pBuffer->iData); | ||
198 | memcpy(pbBuff, pBuffer->rgbData + pBuffer->iData, cbCopy); | ||
199 | |||
200 | pBuffer->iData += cbCopy; | ||
201 | Assert(pBuffer->iData <= pBuffer->cbData); | ||
202 | } | ||
203 | |||
204 | *pcb = cbCopy; | ||
205 | return hr; | ||
206 | } | ||