aboutsummaryrefslogtreecommitdiff
path: root/src/libs/dutil/WixToolset.DUtil/wndutil.cpp
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2021-10-31 14:20:44 -0500
committerSean Hall <r.sean.hall@gmail.com>2021-11-01 16:34:09 -0500
commit7e60078d4a7fe748a39c135def9e84a2421ab474 (patch)
tree51dbe5067ca9596f99107719734c4946e4c080b4 /src/libs/dutil/WixToolset.DUtil/wndutil.cpp
parentc092722a147940532b08f62403e182ef279f2c74 (diff)
downloadwix-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.cpp206
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
23struct MEMBUFFER_FOR_RICHEDIT
24{
25 BYTE* rgbData;
26 DWORD cbData;
27
28 DWORD iData;
29};
30
31const DWORD GROW_WINDOW_TEXT = 250;
32
33
34// prototypes
35static DWORD CALLBACK RichEditStreamFromFileHandleCallback(
36 __in DWORD_PTR dwCookie,
37 __in_bcount(cb) LPBYTE pbBuff,
38 __in LONG cb,
39 __in LONG *pcb
40 );
41static 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
49DAPI_(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
85LExit:
86 ReleaseStr(sczFile);
87 ReleaseFile(hFile);
88
89 return hr;
90}
91
92DAPI_(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
112LExit:
113 return hr;
114}
115
116
117DAPI_(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
159LExit:
160 return hr;
161}
162
163
164static 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
179LExit:
180 return hr;
181}
182
183
184static 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}