diff options
Diffstat (limited to 'src/ext/Util/ca/scaperfexec.cpp')
-rw-r--r-- | src/ext/Util/ca/scaperfexec.cpp | 423 |
1 files changed, 423 insertions, 0 deletions
diff --git a/src/ext/Util/ca/scaperfexec.cpp b/src/ext/Util/ca/scaperfexec.cpp new file mode 100644 index 00000000..c5425754 --- /dev/null +++ b/src/ext/Util/ca/scaperfexec.cpp | |||
@@ -0,0 +1,423 @@ | |||
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 | typedef DWORD (STDAPICALLTYPE *PFNPERFCOUNTERTEXTSTRINGS)(LPWSTR lpCommandLine, BOOL bQuietModeArg); | ||
6 | |||
7 | static HRESULT ExecutePerfCounterData( | ||
8 | __in MSIHANDLE hInstall, | ||
9 | __in BOOL fInstall | ||
10 | ); | ||
11 | static HRESULT CreateDataFile( | ||
12 | __in LPCWSTR wzTempFolder, | ||
13 | __in LPCWSTR wzData, | ||
14 | __in BOOL fIniData, | ||
15 | __out HANDLE *phFile, | ||
16 | __out_opt LPWSTR *ppwzFile | ||
17 | ); | ||
18 | |||
19 | |||
20 | /******************************************************************** | ||
21 | RegisterPerfCounterData - CUSTOM ACTION ENTRY POINT for registering | ||
22 | performance counters | ||
23 | |||
24 | Input: deferred CustomActionData: wzName\twzIniData\twzConstantData\twzName\twzIniData\twzConstantData\t... | ||
25 | *******************************************************************/ | ||
26 | extern "C" UINT __stdcall RegisterPerfCounterData( | ||
27 | __in MSIHANDLE hInstall | ||
28 | ) | ||
29 | { | ||
30 | // AssertSz(FALSE, "debug RegisterPerfCounterData()"); | ||
31 | HRESULT hr = S_OK; | ||
32 | DWORD er = ERROR_SUCCESS; | ||
33 | |||
34 | hr = WcaInitialize(hInstall, "RegisterPerfCounterData"); | ||
35 | ExitOnFailure(hr, "Failed to initialize RegisterPerfCounterData."); | ||
36 | |||
37 | hr = ExecutePerfCounterData(hInstall, TRUE); | ||
38 | MessageExitOnFailure(hr, msierrInstallPerfCounterData, "Failed to execute Wix4PerformanceCategory table."); | ||
39 | |||
40 | LExit: | ||
41 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
42 | return WcaFinalize(er); | ||
43 | } | ||
44 | |||
45 | |||
46 | /******************************************************************** | ||
47 | UnregisterPerfCounterData - CUSTOM ACTION ENTRY POINT for registering | ||
48 | performance counters | ||
49 | |||
50 | Input: deferred CustomActionData: wzName\twzIniData\twzConstantData\twzName\twzIniData\twzConstantData\t... | ||
51 | *******************************************************************/ | ||
52 | extern "C" UINT __stdcall UnregisterPerfCounterData( | ||
53 | __in MSIHANDLE hInstall | ||
54 | ) | ||
55 | { | ||
56 | // AssertSz(FALSE, "debug UnregisterPerfCounterData()"); | ||
57 | HRESULT hr = S_OK; | ||
58 | DWORD er = ERROR_SUCCESS; | ||
59 | |||
60 | hr = WcaInitialize(hInstall, "UnregisterPerfCounterData"); | ||
61 | ExitOnFailure(hr, "Failed to initialize UnregisterPerfCounterData."); | ||
62 | |||
63 | hr = ExecutePerfCounterData(hInstall, FALSE); | ||
64 | MessageExitOnFailure(hr, msierrUninstallPerfCounterData, "Failed to execute Wix4PerformanceCategory table."); | ||
65 | |||
66 | LExit: | ||
67 | er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
68 | return WcaFinalize(er); | ||
69 | } | ||
70 | |||
71 | |||
72 | /******************************************************************** | ||
73 | RegisterPerfmon - CUSTOM ACTION ENTRY POINT for registering | ||
74 | counters | ||
75 | |||
76 | Input: deferred CustomActionData - | ||
77 | wzFile or wzName | ||
78 | *******************************************************************/ | ||
79 | extern "C" UINT __stdcall RegisterPerfmon( | ||
80 | __in MSIHANDLE hInstall | ||
81 | ) | ||
82 | { | ||
83 | // Assert(FALSE); | ||
84 | UINT er = ERROR_SUCCESS; | ||
85 | HRESULT hr = S_OK; | ||
86 | LPWSTR pwzData = NULL; | ||
87 | |||
88 | HMODULE hMod = NULL; | ||
89 | PFNPERFCOUNTERTEXTSTRINGS pfnPerfCounterTextString; | ||
90 | DWORD dwRet; | ||
91 | LPWSTR pwzShortPath = NULL; | ||
92 | DWORD cchShortPath = MAX_PATH; | ||
93 | DWORD cchShortPathLength = 0; | ||
94 | |||
95 | LPWSTR pwzCommand = NULL; | ||
96 | |||
97 | hr = WcaInitialize(hInstall, "RegisterPerfmon"); | ||
98 | ExitOnFailure(hr, "failed to initialize"); | ||
99 | |||
100 | hr = WcaGetProperty(L"CustomActionData", &pwzData); | ||
101 | ExitOnFailure(hr, "failed to get CustomActionData"); | ||
102 | |||
103 | WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); | ||
104 | |||
105 | // do the perfmon registration | ||
106 | if (NULL == hMod) | ||
107 | { | ||
108 | hr = LoadSystemLibrary(L"loadperf.dll", &hMod); | ||
109 | } | ||
110 | ExitOnFailure(hr, "failed to load DLL for PerfMon"); | ||
111 | |||
112 | pfnPerfCounterTextString = (PFNPERFCOUNTERTEXTSTRINGS)::GetProcAddress(hMod, "LoadPerfCounterTextStringsW"); | ||
113 | ExitOnNullWithLastError(pfnPerfCounterTextString, hr, "failed to get DLL function for PerfMon"); | ||
114 | |||
115 | hr = StrAlloc(&pwzShortPath, cchShortPath); | ||
116 | ExitOnFailure(hr, "failed to allocate string"); | ||
117 | |||
118 | WcaLog(LOGMSG_VERBOSE, "Converting DLL path to short format: %ls", pwzData); | ||
119 | cchShortPathLength = ::GetShortPathNameW(pwzData, pwzShortPath, cchShortPath); | ||
120 | if (cchShortPathLength > cchShortPath) | ||
121 | { | ||
122 | cchShortPath = cchShortPathLength + 1; | ||
123 | hr = StrAlloc(&pwzShortPath, cchShortPath); | ||
124 | ExitOnFailure(hr, "failed to allocate string"); | ||
125 | |||
126 | cchShortPathLength = ::GetShortPathNameW(pwzData, pwzShortPath, cchShortPath); | ||
127 | } | ||
128 | |||
129 | if (0 == cchShortPathLength) | ||
130 | { | ||
131 | ExitOnLastError(hr, "failed to get short path format of path: %ls", pwzData); | ||
132 | } | ||
133 | |||
134 | hr = StrAllocFormatted(&pwzCommand, L"lodctr \"%s\"", pwzShortPath); | ||
135 | ExitOnFailure(hr, "failed to format lodctr string"); | ||
136 | |||
137 | WcaLog(LOGMSG_VERBOSE, "RegisterPerfmon running command: '%ls'", pwzCommand); | ||
138 | dwRet = (*pfnPerfCounterTextString)(pwzCommand, TRUE); | ||
139 | if (dwRet != ERROR_SUCCESS && dwRet != ERROR_ALREADY_EXISTS) | ||
140 | { | ||
141 | hr = HRESULT_FROM_WIN32(dwRet); | ||
142 | MessageExitOnFailure(hr, msierrPERFMONFailedRegisterDLL, "failed to register with PerfMon, DLL: %ls", pwzData); | ||
143 | } | ||
144 | |||
145 | hr = S_OK; | ||
146 | LExit: | ||
147 | ReleaseStr(pwzData); | ||
148 | |||
149 | if (FAILED(hr)) | ||
150 | er = ERROR_INSTALL_FAILURE; | ||
151 | return WcaFinalize(er); | ||
152 | } | ||
153 | |||
154 | |||
155 | extern "C" UINT __stdcall UnregisterPerfmon( | ||
156 | __in MSIHANDLE hInstall | ||
157 | ) | ||
158 | { | ||
159 | // Assert(FALSE); | ||
160 | UINT er = ERROR_SUCCESS; | ||
161 | HRESULT hr = S_OK; | ||
162 | LPWSTR pwzData = NULL; | ||
163 | |||
164 | HMODULE hMod = NULL; | ||
165 | PFNPERFCOUNTERTEXTSTRINGS pfnPerfCounterTextString; | ||
166 | DWORD dwRet; | ||
167 | WCHAR wz[255]; | ||
168 | |||
169 | hr = WcaInitialize(hInstall, "UnregisterPerfmon"); | ||
170 | ExitOnFailure(hr, "failed to initialize"); | ||
171 | |||
172 | hr = WcaGetProperty(L"CustomActionData", &pwzData); | ||
173 | ExitOnFailure(hr, "failed to get CustomActionData"); | ||
174 | |||
175 | WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); | ||
176 | |||
177 | // do the perfmon unregistration | ||
178 | hr = E_FAIL; | ||
179 | if (hMod == NULL) | ||
180 | { | ||
181 | hr = LoadSystemLibrary(L"loadperf.dll", &hMod); | ||
182 | } | ||
183 | ExitOnFailure(hr, "failed to load DLL for PerfMon"); | ||
184 | |||
185 | pfnPerfCounterTextString = (PFNPERFCOUNTERTEXTSTRINGS)::GetProcAddress(hMod, "UnloadPerfCounterTextStringsW"); | ||
186 | ExitOnNullWithLastError(pfnPerfCounterTextString, hr, "failed to get DLL function for PerfMon"); | ||
187 | |||
188 | hr = ::StringCchPrintfW(wz, countof(wz), L"unlodctr \"%s\"", pwzData); | ||
189 | ExitOnFailure(hr, "Failed to format unlodctr string with: %ls", pwzData); | ||
190 | WcaLog(LOGMSG_VERBOSE, "UnregisterPerfmon running command: '%ls'", wz); | ||
191 | dwRet = (*pfnPerfCounterTextString)(wz, TRUE); | ||
192 | // if the counters aren't registered, then OK to continue | ||
193 | if (dwRet != ERROR_SUCCESS && dwRet != ERROR_FILE_NOT_FOUND && dwRet != ERROR_BADKEY) | ||
194 | { | ||
195 | hr = HRESULT_FROM_WIN32(dwRet); | ||
196 | MessageExitOnFailure(hr, msierrPERFMONFailedUnregisterDLL, "failed to unregsister with PerfMon, DLL: %ls", pwzData); | ||
197 | } | ||
198 | |||
199 | hr = S_OK; | ||
200 | LExit: | ||
201 | ReleaseStr(pwzData); | ||
202 | |||
203 | if (FAILED(hr)) | ||
204 | er = ERROR_INSTALL_FAILURE; | ||
205 | return WcaFinalize(er); | ||
206 | } | ||
207 | |||
208 | |||
209 | static HRESULT ExecutePerfCounterData( | ||
210 | __in MSIHANDLE /*hInstall*/, | ||
211 | __in BOOL fInstall | ||
212 | ) | ||
213 | { | ||
214 | HRESULT hr = S_OK; | ||
215 | DWORD er = ERROR_SUCCESS; | ||
216 | |||
217 | HMODULE hModule = NULL; | ||
218 | PFNPERFCOUNTERTEXTSTRINGS pfnPerfCounterTextString = NULL; | ||
219 | LPCWSTR wzPrefix = NULL; | ||
220 | |||
221 | LPWSTR pwzCustomActionData = NULL; | ||
222 | LPWSTR pwz = NULL; | ||
223 | |||
224 | LPWSTR pwzName = NULL; | ||
225 | LPWSTR pwzIniData = NULL; | ||
226 | LPWSTR pwzConstantData = NULL; | ||
227 | LPWSTR pwzTempFolder = NULL; | ||
228 | LPWSTR pwzIniFile = NULL; | ||
229 | LPWSTR pwzExecute = NULL; | ||
230 | |||
231 | HANDLE hIniData = INVALID_HANDLE_VALUE; | ||
232 | HANDLE hConstantData = INVALID_HANDLE_VALUE; | ||
233 | |||
234 | // Load the system performance counter helper DLL then get the appropriate | ||
235 | // entrypoint out of it. Fortunately, they have the same signature so we | ||
236 | // can use one function pointer to point to both. | ||
237 | hr = LoadSystemLibrary(L"loadperf.dll", &hModule); | ||
238 | ExitOnFailure(hr, "failed to load DLL for PerfMon"); | ||
239 | |||
240 | if (fInstall) | ||
241 | { | ||
242 | wzPrefix = L"lodctr"; | ||
243 | pfnPerfCounterTextString = (PFNPERFCOUNTERTEXTSTRINGS)::GetProcAddress(hModule, "LoadPerfCounterTextStringsW"); | ||
244 | } | ||
245 | else | ||
246 | { | ||
247 | wzPrefix = L"unlodctr"; | ||
248 | pfnPerfCounterTextString = (PFNPERFCOUNTERTEXTSTRINGS)::GetProcAddress(hModule, "UnloadPerfCounterTextStringsW"); | ||
249 | } | ||
250 | ExitOnNullWithLastError(pfnPerfCounterTextString, hr, "Failed to get DLL function for PerfMon"); | ||
251 | |||
252 | // Now get the CustomActionData and execute it. | ||
253 | hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData); | ||
254 | ExitOnFailure(hr, "Failed to get CustomActionData."); | ||
255 | |||
256 | WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData); | ||
257 | |||
258 | pwz = pwzCustomActionData; | ||
259 | |||
260 | while (S_OK == (hr = WcaReadStringFromCaData(&pwz, &pwzName))) | ||
261 | { | ||
262 | hr = WcaReadStringFromCaData(&pwz, &pwzIniData); | ||
263 | ExitOnFailure(hr, "Failed to read IniData from custom action data."); | ||
264 | |||
265 | hr = WcaReadStringFromCaData(&pwz, &pwzConstantData); | ||
266 | ExitOnFailure(hr, "Failed to read ConstantData from custom action data."); | ||
267 | |||
268 | if (fInstall) | ||
269 | { | ||
270 | hr = PathCreateTempDirectory(NULL, L"WIXPF%03x", 999, &pwzTempFolder); | ||
271 | ExitOnFailure(hr, "Failed to create temp directory."); | ||
272 | |||
273 | hr = CreateDataFile(pwzTempFolder, pwzIniData, TRUE, &hIniData, &pwzIniFile); | ||
274 | ExitOnFailure(hr, "Failed to create .ini file for performance counter category: %ls", pwzName); | ||
275 | |||
276 | hr = CreateDataFile(pwzTempFolder, pwzConstantData, FALSE, &hConstantData, NULL); | ||
277 | ExitOnFailure(hr, "Failed to create .h file for performance counter category: %ls", pwzName); | ||
278 | |||
279 | hr = StrAllocFormatted(&pwzExecute, L"%s \"%s\"", wzPrefix, pwzIniFile); | ||
280 | ExitOnFailure(hr, "Failed to allocate string to execute."); | ||
281 | |||
282 | // Execute the install. | ||
283 | er = (*pfnPerfCounterTextString)(pwzExecute, TRUE); | ||
284 | hr = HRESULT_FROM_WIN32(er); | ||
285 | ExitOnFailure(hr, "Failed to execute install of performance counter category: %ls", pwzName); | ||
286 | |||
287 | if (INVALID_HANDLE_VALUE != hIniData) | ||
288 | { | ||
289 | ::CloseHandle(hIniData); | ||
290 | hIniData = INVALID_HANDLE_VALUE; | ||
291 | } | ||
292 | |||
293 | if (INVALID_HANDLE_VALUE != hConstantData) | ||
294 | { | ||
295 | ::CloseHandle(hConstantData); | ||
296 | hConstantData = INVALID_HANDLE_VALUE; | ||
297 | } | ||
298 | |||
299 | DirEnsureDelete(pwzTempFolder, TRUE, TRUE); | ||
300 | } | ||
301 | else | ||
302 | { | ||
303 | hr = StrAllocFormatted(&pwzExecute, L"%s \"%s\"", wzPrefix, pwzName); | ||
304 | ExitOnFailure(hr, "Failed to allocate string to execute."); | ||
305 | |||
306 | // Execute the uninstall and if the counter isn't registered then ignore | ||
307 | // the error since it won't hurt anything. | ||
308 | er = (*pfnPerfCounterTextString)(pwzExecute, TRUE); | ||
309 | if (ERROR_FILE_NOT_FOUND == er || ERROR_BADKEY == er) | ||
310 | { | ||
311 | er = ERROR_SUCCESS; | ||
312 | } | ||
313 | hr = HRESULT_FROM_WIN32(er); | ||
314 | ExitOnFailure(hr, "Failed to execute uninstall of performance counter category: %ls", pwzName); | ||
315 | } | ||
316 | } | ||
317 | |||
318 | if (E_NOMOREITEMS == hr) // If there are no more items, all is well | ||
319 | { | ||
320 | hr = S_OK; | ||
321 | } | ||
322 | ExitOnFailure(hr, "Failed to execute all perf counter data."); | ||
323 | |||
324 | hr = S_OK; | ||
325 | |||
326 | LExit: | ||
327 | if (INVALID_HANDLE_VALUE != hIniData) | ||
328 | { | ||
329 | ::CloseHandle(hIniData); | ||
330 | } | ||
331 | |||
332 | if (INVALID_HANDLE_VALUE != hConstantData) | ||
333 | { | ||
334 | ::CloseHandle(hConstantData); | ||
335 | } | ||
336 | |||
337 | ReleaseStr(pwzExecute); | ||
338 | ReleaseStr(pwzIniFile); | ||
339 | ReleaseStr(pwzTempFolder); | ||
340 | ReleaseStr(pwzConstantData); | ||
341 | ReleaseStr(pwzIniData); | ||
342 | ReleaseStr(pwzName); | ||
343 | ReleaseStr(pwzCustomActionData); | ||
344 | |||
345 | if (hModule) | ||
346 | { | ||
347 | ::FreeLibrary(hModule); | ||
348 | } | ||
349 | |||
350 | return hr; | ||
351 | } | ||
352 | |||
353 | |||
354 | static HRESULT CreateDataFile( | ||
355 | __in LPCWSTR wzTempFolder, | ||
356 | __in LPCWSTR wzData, | ||
357 | __in BOOL fIniData, | ||
358 | __out HANDLE *phFile, | ||
359 | __out_opt LPWSTR *ppwzFile | ||
360 | ) | ||
361 | { | ||
362 | HRESULT hr = S_OK; | ||
363 | HANDLE hFile = INVALID_HANDLE_VALUE; | ||
364 | LPWSTR pwzFile = NULL; | ||
365 | LPSTR pszData = NULL; | ||
366 | DWORD cbData = 0; | ||
367 | DWORD cbWritten = 0; | ||
368 | |||
369 | // Convert the data to UTF-8 because lodctr/unloctr | ||
370 | // doesn't like unicode. | ||
371 | hr = StrAnsiAllocString(&pszData, wzData, 0, CP_UTF8); | ||
372 | ExitOnFailure(hr, "Failed to covert data to ANSI."); | ||
373 | |||
374 | cbData = lstrlenA(pszData); | ||
375 | |||
376 | // Concatenate the paths together, open the file data file | ||
377 | // and dump the data in there. | ||
378 | hr = StrAllocString(&pwzFile, wzTempFolder, 0); | ||
379 | ExitOnFailure(hr, "Failed to copy temp directory name."); | ||
380 | |||
381 | hr = StrAllocConcat(&pwzFile, L"wixperf", 0); | ||
382 | ExitOnFailure(hr, "Failed to add name of file."); | ||
383 | |||
384 | hr = StrAllocConcat(&pwzFile, fIniData ? L".ini" : L".h", 0); | ||
385 | ExitOnFailure(hr, "Failed to add extension of file."); | ||
386 | |||
387 | hFile = ::CreateFileW(pwzFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); | ||
388 | if (INVALID_HANDLE_VALUE == hFile) | ||
389 | { | ||
390 | ExitWithLastError(hr, "Failed to open new temp file: %ls", pwzFile); | ||
391 | } | ||
392 | |||
393 | if (!::WriteFile(hFile, pszData, cbData, &cbWritten, NULL)) | ||
394 | { | ||
395 | ExitWithLastError(hr, "Failed to write data to new temp file: %ls", pwzFile); | ||
396 | } | ||
397 | |||
398 | if (INVALID_HANDLE_VALUE != hFile) | ||
399 | { | ||
400 | ::CloseHandle(hFile); | ||
401 | hFile = INVALID_HANDLE_VALUE; | ||
402 | } | ||
403 | |||
404 | // Return the requested values. | ||
405 | *phFile = hFile; | ||
406 | hFile = INVALID_HANDLE_VALUE; | ||
407 | |||
408 | if (ppwzFile) | ||
409 | { | ||
410 | *ppwzFile = pwzFile; | ||
411 | pwzFile = NULL; | ||
412 | } | ||
413 | |||
414 | LExit: | ||
415 | if (INVALID_HANDLE_VALUE != hFile) | ||
416 | { | ||
417 | ::CloseHandle(hFile); | ||
418 | } | ||
419 | ReleaseStr(pszData); | ||
420 | ReleaseStr(pwzFile); | ||
421 | |||
422 | return hr; | ||
423 | } | ||