diff options
author | Bob Arnson <bob@firegiant.com> | 2021-02-09 21:35:37 -0500 |
---|---|---|
committer | Bob Arnson <bob@firegiant.com> | 2021-02-09 21:50:07 -0500 |
commit | 422d6e48e2f9bdcec62f9a147cb8c2f34bf73a5f (patch) | |
tree | ca44636fb3edeb99f82faae46723ceba789db46d | |
parent | 096784ea5114cb5bf99151cc047d69951035d152 (diff) | |
download | wix-422d6e48e2f9bdcec62f9a147cb8c2f34bf73a5f.tar.gz wix-422d6e48e2f9bdcec62f9a147cb8c2f34bf73a5f.tar.bz2 wix-422d6e48e2f9bdcec62f9a147cb8c2f34bf73a5f.zip |
Remove BITS support. Update DUtil dependency.
-rw-r--r-- | src/engine/apply.cpp | 25 | ||||
-rw-r--r-- | src/engine/bitsengine.cpp | 505 | ||||
-rw-r--r-- | src/engine/bitsengine.h | 23 | ||||
-rw-r--r-- | src/engine/engine.vcxproj | 6 | ||||
-rw-r--r-- | src/engine/packages.config | 2 | ||||
-rw-r--r-- | src/engine/precomp.h | 2 | ||||
-rw-r--r-- | src/stub/packages.config | 2 | ||||
-rw-r--r-- | src/stub/stub.vcxproj | 4 | ||||
-rw-r--r-- | src/test/BurnUnitTest/BurnUnitTest.vcxproj | 4 | ||||
-rw-r--r-- | src/test/BurnUnitTest/packages.config | 2 | ||||
-rw-r--r-- | src/test/BurnUnitTest/precomp.h | 1 |
11 files changed, 15 insertions, 561 deletions
diff --git a/src/engine/apply.cpp b/src/engine/apply.cpp index 7c47ba75..55141ef9 100644 --- a/src/engine/apply.cpp +++ b/src/engine/apply.cpp | |||
@@ -1509,26 +1509,13 @@ static HRESULT DownloadPayload( | |||
1509 | cacheCallback.pfnCancel = NULL; // TODO: set this | 1509 | cacheCallback.pfnCancel = NULL; // TODO: set this |
1510 | cacheCallback.pv = pProgress; | 1510 | cacheCallback.pv = pProgress; |
1511 | 1511 | ||
1512 | // If the protocol is specially marked, "bits" let's use that. | 1512 | authenticationData.pUX = pProgress->pUX; |
1513 | if (L'b' == pDownloadSource->sczUrl[0] && | 1513 | authenticationData.wzPackageOrContainerId = wzPackageOrContainerId; |
1514 | L'i' == pDownloadSource->sczUrl[1] && | 1514 | authenticationData.wzPayloadId = wzPayloadId; |
1515 | L't' == pDownloadSource->sczUrl[2] && | 1515 | authenticationCallback.pv = static_cast<LPVOID>(&authenticationData); |
1516 | L's' == pDownloadSource->sczUrl[3] && | 1516 | authenticationCallback.pfnAuthenticate = &AuthenticationRequired; |
1517 | (L':' == pDownloadSource->sczUrl[4] || (L's' == pDownloadSource->sczUrl[4] && L':' == pDownloadSource->sczUrl[5])) | ||
1518 | ) | ||
1519 | { | ||
1520 | hr = BitsDownloadUrl(&cacheCallback, pDownloadSource, wzDestinationPath); | ||
1521 | } | ||
1522 | else // wininet handles everything else. | ||
1523 | { | ||
1524 | authenticationData.pUX = pProgress->pUX; | ||
1525 | authenticationData.wzPackageOrContainerId = wzPackageOrContainerId; | ||
1526 | authenticationData.wzPayloadId = wzPayloadId; | ||
1527 | authenticationCallback.pv = static_cast<LPVOID>(&authenticationData); | ||
1528 | authenticationCallback.pfnAuthenticate = &AuthenticationRequired; | ||
1529 | 1517 | ||
1530 | hr = DownloadUrl(pDownloadSource, qwDownloadSize, wzDestinationPath, &cacheCallback, &authenticationCallback); | 1518 | hr = DownloadUrl(pDownloadSource, qwDownloadSize, wzDestinationPath, &cacheCallback, &authenticationCallback); |
1531 | } | ||
1532 | ExitOnFailure(hr, "Failed attempt to download URL: '%ls' to: '%ls'", pDownloadSource->sczUrl, wzDestinationPath); | 1519 | ExitOnFailure(hr, "Failed attempt to download URL: '%ls' to: '%ls'", pDownloadSource->sczUrl, wzDestinationPath); |
1533 | 1520 | ||
1534 | LExit: | 1521 | LExit: |
diff --git a/src/engine/bitsengine.cpp b/src/engine/bitsengine.cpp deleted file mode 100644 index b8093b77..00000000 --- a/src/engine/bitsengine.cpp +++ /dev/null | |||
@@ -1,505 +0,0 @@ | |||
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 | // const | ||
6 | |||
7 | const DWORD BITSENGINE_NO_PROGRESS_TIMEOUT = 2 * 60; | ||
8 | const DWORD BITSENGINE_MSG_WAIT_TIMEOUT = 1; | ||
9 | |||
10 | // functions | ||
11 | |||
12 | static HRESULT CreateJob( | ||
13 | __out IBackgroundCopyJob** ppJob | ||
14 | ); | ||
15 | static HRESULT SetCredentials( | ||
16 | __in IBackgroundCopyJob* pJob, | ||
17 | __in_z_opt LPCWSTR wzUser, | ||
18 | __in_z_opt LPCWSTR wzPassword | ||
19 | ); | ||
20 | static void SendError( | ||
21 | __in DOWNLOAD_CACHE_CALLBACK* pCacheCallback, | ||
22 | __in IBackgroundCopyJob* pJob, | ||
23 | __in HRESULT hrError, | ||
24 | __in BG_ERROR_CONTEXT context, | ||
25 | __out_opt BOOL* pfRetry | ||
26 | ); | ||
27 | |||
28 | |||
29 | // class | ||
30 | |||
31 | class CBurnBitsCallback : public IBackgroundCopyCallback | ||
32 | { | ||
33 | public: // IUnknown | ||
34 | virtual STDMETHODIMP QueryInterface( | ||
35 | __in const IID& riid, | ||
36 | __out void** ppvObject | ||
37 | ) | ||
38 | { | ||
39 | HRESULT hr = S_OK; | ||
40 | |||
41 | ExitOnNull(ppvObject, hr, E_INVALIDARG, "Invalid argument ppvObject"); | ||
42 | *ppvObject = NULL; | ||
43 | |||
44 | if (::IsEqualIID(__uuidof(IBackgroundCopyCallback), riid)) | ||
45 | { | ||
46 | *ppvObject = static_cast<IBackgroundCopyCallback*>(this); | ||
47 | } | ||
48 | else if (::IsEqualIID(IID_IUnknown, riid)) | ||
49 | { | ||
50 | *ppvObject = reinterpret_cast<IUnknown*>(this); | ||
51 | } | ||
52 | else // no interface for requested iid | ||
53 | { | ||
54 | ExitFunction1(hr = E_NOINTERFACE); | ||
55 | } | ||
56 | |||
57 | AddRef(); | ||
58 | |||
59 | LExit: | ||
60 | return hr; | ||
61 | } | ||
62 | |||
63 | virtual STDMETHODIMP_(ULONG) AddRef() | ||
64 | { | ||
65 | return ::InterlockedIncrement(&this->m_cReferences); | ||
66 | } | ||
67 | |||
68 | virtual STDMETHODIMP_(ULONG) Release() | ||
69 | { | ||
70 | long l = ::InterlockedDecrement(&this->m_cReferences); | ||
71 | if (0 < l) | ||
72 | { | ||
73 | return l; | ||
74 | } | ||
75 | |||
76 | delete this; | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | public: // IBackgroundCopyCallback | ||
81 | virtual STDMETHODIMP JobTransferred( | ||
82 | __in IBackgroundCopyJob* pJob | ||
83 | ) | ||
84 | { | ||
85 | HRESULT hr = S_OK; | ||
86 | |||
87 | hr = SendProgress(pJob); | ||
88 | ExitOnFailure(hr, "Failure while sending progress during BITS job transferred."); | ||
89 | |||
90 | LExit: | ||
91 | if (FAILED(hr)) | ||
92 | { | ||
93 | ProcessResult(BG_ERROR_CONTEXT_NONE, hr); | ||
94 | } | ||
95 | else | ||
96 | { | ||
97 | ::SetEvent(m_hComplete); | ||
98 | } | ||
99 | |||
100 | return S_OK; // must return S_OK otherwise BITS just keeps calling back. | ||
101 | } | ||
102 | |||
103 | virtual STDMETHODIMP JobError( | ||
104 | __in IBackgroundCopyJob* /*pJob*/, | ||
105 | __in IBackgroundCopyError* pError | ||
106 | ) | ||
107 | { | ||
108 | HRESULT hr = S_OK; | ||
109 | BG_ERROR_CONTEXT context = BG_ERROR_CONTEXT_NONE; | ||
110 | HRESULT hrError = S_OK; | ||
111 | |||
112 | hr = pError->GetError(&context, &hrError); | ||
113 | ExitOnFailure(hr, "Failed to get error context."); | ||
114 | |||
115 | if (SUCCEEDED(hrError)) | ||
116 | { | ||
117 | hr = E_UNEXPECTED; | ||
118 | } | ||
119 | |||
120 | LExit: | ||
121 | ProcessResult(context, FAILED(hrError) ? hrError : hr); | ||
122 | |||
123 | return S_OK; // must return S_OK otherwise BITS just keeps calling back. | ||
124 | } | ||
125 | |||
126 | virtual STDMETHODIMP JobModification( | ||
127 | __in IBackgroundCopyJob* pJob, | ||
128 | __in DWORD /*dwReserved*/ | ||
129 | ) | ||
130 | { | ||
131 | HRESULT hr = S_OK; | ||
132 | BG_JOB_STATE state = BG_JOB_STATE_ERROR; | ||
133 | |||
134 | ::EnterCriticalSection(&m_cs); | ||
135 | |||
136 | hr = pJob->GetState(&state); | ||
137 | ExitOnFailure(hr, "Failed to get state during job modification."); | ||
138 | |||
139 | // If we're actually downloading stuff, let's send progress. | ||
140 | if (BG_JOB_STATE_TRANSFERRING == state) | ||
141 | { | ||
142 | hr = SendProgress(pJob); | ||
143 | ExitOnFailure(hr, "Failure while sending progress during BITS job modification."); | ||
144 | } | ||
145 | |||
146 | LExit: | ||
147 | ::LeaveCriticalSection(&m_cs); | ||
148 | |||
149 | ProcessResult(BG_ERROR_CONTEXT_NONE, hr); | ||
150 | |||
151 | return S_OK; // documentation says to always return S_OK | ||
152 | } | ||
153 | |||
154 | public: | ||
155 | void Reset() | ||
156 | { | ||
157 | m_hrError = S_OK; | ||
158 | m_contextError = BG_ERROR_CONTEXT_NONE; | ||
159 | |||
160 | ::ResetEvent(m_hComplete); | ||
161 | } | ||
162 | |||
163 | HRESULT WaitForCompletion( | ||
164 | __in IBackgroundCopyJob* pJob | ||
165 | ) | ||
166 | { | ||
167 | HRESULT hr = S_OK; | ||
168 | HANDLE rghEvents[1] = { m_hComplete }; | ||
169 | MSG msg = { }; | ||
170 | BOOL fMessageProcessed = FALSE; | ||
171 | |||
172 | do | ||
173 | { | ||
174 | fMessageProcessed = FALSE; | ||
175 | |||
176 | switch (::MsgWaitForMultipleObjects(countof(rghEvents), rghEvents, FALSE, BITSENGINE_MSG_WAIT_TIMEOUT * 1000, QS_ALLINPUT)) | ||
177 | { | ||
178 | case WAIT_OBJECT_0: | ||
179 | break; | ||
180 | |||
181 | case WAIT_OBJECT_0 + 1: | ||
182 | ::PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE); | ||
183 | fMessageProcessed = TRUE; | ||
184 | break; | ||
185 | |||
186 | case WAIT_TIMEOUT: | ||
187 | // Call the progress callback periodically if we are not transferring to ensure that cancelling is responsive | ||
188 | // (progress callback is also handles cancelling). Note that if we are transferring, IBackgroundCopyCallback | ||
189 | // methods handle progress/cancelling. If we are not transferring, the IBackgroundCopyCallback methods may | ||
190 | // not be called until the job times out (minutes for a foreground job, weeks for a background job). | ||
191 | SendProgressIfNotTransferring(pJob); | ||
192 | fMessageProcessed = TRUE; | ||
193 | break; | ||
194 | |||
195 | default: | ||
196 | ExitWithLastError(hr, "Failed while waiting for download."); | ||
197 | } | ||
198 | } while (fMessageProcessed); | ||
199 | |||
200 | LExit: | ||
201 | return hr; | ||
202 | } | ||
203 | |||
204 | void GetError( | ||
205 | __out HRESULT* pHR, | ||
206 | __out BG_ERROR_CONTEXT* pContext | ||
207 | ) | ||
208 | { | ||
209 | *pHR = m_hrError; | ||
210 | *pContext = m_contextError; | ||
211 | } | ||
212 | |||
213 | private: | ||
214 | HRESULT SendProgress( | ||
215 | __in IBackgroundCopyJob* pJob | ||
216 | ) | ||
217 | { | ||
218 | HRESULT hr = S_OK; | ||
219 | BG_JOB_PROGRESS progress = { }; | ||
220 | |||
221 | if (m_pCallback && m_pCallback->pfnProgress) | ||
222 | { | ||
223 | hr = pJob->GetProgress(&progress); | ||
224 | ExitOnFailure(hr, "Failed to get progress when BITS job was transferred."); | ||
225 | |||
226 | hr = CacheSendProgressCallback(m_pCallback, progress.BytesTransferred, progress.BytesTotal, INVALID_HANDLE_VALUE); | ||
227 | ExitOnFailure(hr, "Failed to send progress from BITS job."); | ||
228 | } | ||
229 | |||
230 | LExit: | ||
231 | return hr; | ||
232 | } | ||
233 | |||
234 | void SendProgressIfNotTransferring( | ||
235 | __in IBackgroundCopyJob* pJob | ||
236 | ) | ||
237 | { | ||
238 | HRESULT hr = S_OK; | ||
239 | BG_JOB_STATE state = BG_JOB_STATE_ERROR; | ||
240 | |||
241 | ::EnterCriticalSection(&m_cs); | ||
242 | |||
243 | hr = pJob->GetState(&state); | ||
244 | ExitOnFailure(hr, "Failed to get BITS job state."); | ||
245 | |||
246 | if (BG_JOB_STATE_TRANSFERRING != state) | ||
247 | { | ||
248 | hr = SendProgress(pJob); | ||
249 | ExitOnFailure(hr, "Failure while sending progress."); | ||
250 | } | ||
251 | |||
252 | LExit: | ||
253 | ::LeaveCriticalSection(&m_cs); | ||
254 | |||
255 | ProcessResult(BG_ERROR_CONTEXT_NONE, hr); | ||
256 | } | ||
257 | |||
258 | void ProcessResult( | ||
259 | __in BG_ERROR_CONTEXT context, | ||
260 | __in HRESULT hr | ||
261 | ) | ||
262 | { | ||
263 | if (FAILED(hr)) | ||
264 | { | ||
265 | m_contextError = context; | ||
266 | m_hrError = hr; | ||
267 | |||
268 | ::SetEvent(m_hComplete); | ||
269 | } | ||
270 | } | ||
271 | |||
272 | public: | ||
273 | CBurnBitsCallback( | ||
274 | __in_opt DOWNLOAD_CACHE_CALLBACK* pCallback, | ||
275 | __out HRESULT* pHR | ||
276 | ) | ||
277 | { | ||
278 | HRESULT hr = S_OK; | ||
279 | |||
280 | m_cReferences = 1; | ||
281 | ::InitializeCriticalSection(&m_cs); | ||
282 | |||
283 | m_hComplete = ::CreateEventW(NULL, TRUE, FALSE, NULL); | ||
284 | ExitOnNullWithLastError(m_hComplete, hr, "Failed to create BITS job complete event."); | ||
285 | |||
286 | m_contextError = BG_ERROR_CONTEXT_NONE; | ||
287 | m_hrError = S_OK; | ||
288 | |||
289 | m_pCallback = pCallback; | ||
290 | |||
291 | LExit: | ||
292 | *pHR = hr; | ||
293 | } | ||
294 | |||
295 | ~CBurnBitsCallback() | ||
296 | { | ||
297 | m_pCallback = NULL; | ||
298 | ReleaseHandle(m_hComplete); | ||
299 | ::DeleteCriticalSection(&m_cs); | ||
300 | } | ||
301 | |||
302 | private: | ||
303 | long m_cReferences; | ||
304 | CRITICAL_SECTION m_cs; | ||
305 | BG_ERROR_CONTEXT m_contextError; | ||
306 | HRESULT m_hrError; | ||
307 | |||
308 | HANDLE m_hComplete; | ||
309 | DOWNLOAD_CACHE_CALLBACK* m_pCallback; | ||
310 | }; | ||
311 | |||
312 | |||
313 | extern "C" HRESULT BitsDownloadUrl( | ||
314 | __in DOWNLOAD_CACHE_CALLBACK* pCallback, | ||
315 | __in DOWNLOAD_SOURCE* pDownloadSource, | ||
316 | __in_z LPCWSTR wzDestinationPath | ||
317 | ) | ||
318 | { | ||
319 | HRESULT hr = S_OK; | ||
320 | LPWSTR sczDownloadUrl = NULL; | ||
321 | CBurnBitsCallback* pBitsCallback = NULL; | ||
322 | IBackgroundCopyJob* pJob = NULL; | ||
323 | BOOL fRetry = FALSE; | ||
324 | BG_ERROR_CONTEXT contextError = BG_ERROR_CONTEXT_NONE; | ||
325 | |||
326 | // If the URL isn't at least 8 characters long (e.g.: "bits://X") then it | ||
327 | // isn't going to do us any good. | ||
328 | if (8 > lstrlenW(pDownloadSource->sczUrl)) | ||
329 | { | ||
330 | hr = E_INVALIDARG; | ||
331 | ExitOnRootFailure(hr, "Invalid BITS engine URL: %ls", pDownloadSource->sczUrl); | ||
332 | } | ||
333 | |||
334 | // Fix the URL to be "http" instead of "bits". | ||
335 | hr = StrAllocString(&sczDownloadUrl, pDownloadSource->sczUrl, 0); | ||
336 | ExitOnFailure(hr, "Failed to copy download URL."); | ||
337 | |||
338 | sczDownloadUrl[0] = L'h'; | ||
339 | sczDownloadUrl[1] = L't'; | ||
340 | sczDownloadUrl[2] = L't'; | ||
341 | sczDownloadUrl[3] = L'p'; | ||
342 | |||
343 | // Create and configure the BITS job. | ||
344 | hr = CreateJob(&pJob); | ||
345 | ExitOnFailure(hr, "Failed to create BITS job."); | ||
346 | |||
347 | hr = SetCredentials(pJob, pDownloadSource->sczUser, pDownloadSource->sczPassword); | ||
348 | ExitOnFailure(hr, "Failed to set credentials for BITS job."); | ||
349 | |||
350 | hr = pJob->AddFile(sczDownloadUrl, wzDestinationPath); | ||
351 | ExitOnFailure(hr, "Failed to add file to BITS job."); | ||
352 | |||
353 | // Set the callback into the BITs job. | ||
354 | pBitsCallback = new CBurnBitsCallback(pCallback, &hr); | ||
355 | ExitOnNull(pBitsCallback, hr, E_OUTOFMEMORY, "Failed to create BITS job callback."); | ||
356 | ExitOnFailure(hr, "Failed to initialize BITS job callback."); | ||
357 | |||
358 | hr = pJob->SetNotifyInterface(pBitsCallback); | ||
359 | ExitOnFailure(hr, "Failed to set callback interface for BITS job."); | ||
360 | |||
361 | // Go into our retry download loop. | ||
362 | do | ||
363 | { | ||
364 | fRetry = FALSE; | ||
365 | |||
366 | pBitsCallback->Reset(); // ensure we are ready for the download to start (again?). | ||
367 | |||
368 | hr = pJob->Resume(); | ||
369 | ExitOnFailure(hr, "Falied to start BITS job."); | ||
370 | |||
371 | hr = pBitsCallback->WaitForCompletion(pJob); | ||
372 | ExitOnFailure(hr, "Failed while waiting for BITS download."); | ||
373 | |||
374 | // See if there are any errors. | ||
375 | pBitsCallback->GetError(&hr, &contextError); | ||
376 | if (HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) == hr) | ||
377 | { | ||
378 | ExitFunction(); | ||
379 | } | ||
380 | else if (FAILED(hr)) | ||
381 | { | ||
382 | SendError(pCallback, pJob, hr, contextError, &fRetry); | ||
383 | } | ||
384 | } while (fRetry); | ||
385 | ExitOnFailure(hr, "Failed to download BITS job."); | ||
386 | |||
387 | // After all that, we should have the file downloaded so complete the job to get | ||
388 | // the file copied to the destination. | ||
389 | hr = pJob->Complete(); | ||
390 | ExitOnFailure(hr, "Failed to complete BITS job."); | ||
391 | |||
392 | LExit: | ||
393 | if (pJob) | ||
394 | { | ||
395 | pJob->SetNotifyInterface(NULL); | ||
396 | |||
397 | // If we failed, kill the job. | ||
398 | if (FAILED(hr)) | ||
399 | { | ||
400 | pJob->Cancel(); // TODO: should we cancel if we're going to retry the package? Probably the right thing to do. | ||
401 | } | ||
402 | } | ||
403 | |||
404 | ReleaseObject(pBitsCallback); | ||
405 | ReleaseObject(pJob); | ||
406 | ReleaseStr(sczDownloadUrl); | ||
407 | |||
408 | return hr; | ||
409 | } | ||
410 | |||
411 | static HRESULT CreateJob( | ||
412 | __out IBackgroundCopyJob** ppJob | ||
413 | ) | ||
414 | { | ||
415 | HRESULT hr = S_OK; | ||
416 | IBackgroundCopyManager* pBitsManager = NULL; | ||
417 | IBackgroundCopyJob* pJob = NULL; | ||
418 | GUID guidJob = { }; | ||
419 | |||
420 | hr = ::CoCreateInstance(__uuidof(BackgroundCopyManager), NULL, CLSCTX_ALL, __uuidof(IBackgroundCopyManager), reinterpret_cast<LPVOID*>(&pBitsManager)); | ||
421 | ExitOnFailure(hr, "Failed to create IBackgroundCopyManager."); | ||
422 | |||
423 | hr = pBitsManager->CreateJob(L"WixBurn", BG_JOB_TYPE_DOWNLOAD, &guidJob, &pJob); | ||
424 | ExitOnFailure(hr, "Failed to create BITS job."); | ||
425 | |||
426 | hr = pJob->SetNotifyFlags(BG_NOTIFY_JOB_TRANSFERRED | BG_NOTIFY_JOB_ERROR | BG_NOTIFY_JOB_MODIFICATION); | ||
427 | ExitOnFailure(hr, "Failed to set notification flags for BITS job."); | ||
428 | |||
429 | hr = pJob->SetNoProgressTimeout(BITSENGINE_NO_PROGRESS_TIMEOUT); // use 2 minutes since default is 14 days. | ||
430 | ExitOnFailure(hr, "Failed to set progress timeout."); | ||
431 | |||
432 | hr = pJob->SetPriority(BG_JOB_PRIORITY_FOREGROUND); | ||
433 | ExitOnFailure(hr, "Failed to set BITS job to foreground."); | ||
434 | |||
435 | *ppJob = pJob; | ||
436 | pJob = NULL; | ||
437 | |||
438 | LExit: | ||
439 | ReleaseObject(pJob); | ||
440 | ReleaseObject(pBitsManager); | ||
441 | |||
442 | return hr; | ||
443 | } | ||
444 | |||
445 | static HRESULT SetCredentials( | ||
446 | __in IBackgroundCopyJob* pJob, | ||
447 | __in_z_opt LPCWSTR wzUser, | ||
448 | __in_z_opt LPCWSTR wzPassword | ||
449 | ) | ||
450 | { | ||
451 | HRESULT hr = S_OK; | ||
452 | IBackgroundCopyJob2* pJob2 = NULL; | ||
453 | BG_AUTH_CREDENTIALS ac = { }; | ||
454 | |||
455 | // If IBackgroundCopyJob2::SetCredentials() is supported, set the username/password. | ||
456 | hr = pJob->QueryInterface(IID_PPV_ARGS(&pJob2)); | ||
457 | if (SUCCEEDED(hr)) | ||
458 | { | ||
459 | ac.Target = BG_AUTH_TARGET_PROXY; | ||
460 | ac.Credentials.Basic.UserName = const_cast<LPWSTR>(wzUser); | ||
461 | ac.Credentials.Basic.Password = const_cast<LPWSTR>(wzPassword); | ||
462 | |||
463 | ac.Scheme = BG_AUTH_SCHEME_NTLM; | ||
464 | hr = pJob2->SetCredentials(&ac); | ||
465 | ExitOnFailure(hr, "Failed to set background copy NTLM credentials"); | ||
466 | |||
467 | ac.Scheme = BG_AUTH_SCHEME_NEGOTIATE; | ||
468 | hr = pJob2->SetCredentials(&ac); | ||
469 | ExitOnFailure(hr, "Failed to set background copy negotiate credentials"); | ||
470 | } | ||
471 | |||
472 | hr = S_OK; | ||
473 | |||
474 | LExit: | ||
475 | ReleaseObject(pJob2); | ||
476 | |||
477 | return hr; | ||
478 | } | ||
479 | |||
480 | static void SendError( | ||
481 | __in DOWNLOAD_CACHE_CALLBACK* pCacheCallback, | ||
482 | __in IBackgroundCopyJob* pJob, | ||
483 | __in HRESULT hrError, | ||
484 | __in BG_ERROR_CONTEXT /*context*/, | ||
485 | __out_opt BOOL* pfRetry | ||
486 | ) | ||
487 | { | ||
488 | HRESULT hr = S_OK; | ||
489 | IBackgroundCopyError* pError = NULL; | ||
490 | LPWSTR pszErrorDescription = NULL; | ||
491 | |||
492 | hr = pJob->GetError(&pError); | ||
493 | if (SUCCEEDED(hr)) | ||
494 | { | ||
495 | pError->GetErrorDescription(LANGIDFROMLCID(::GetThreadLocale()), &pszErrorDescription); | ||
496 | } | ||
497 | |||
498 | CacheSendErrorCallback(pCacheCallback, hrError, pszErrorDescription, pfRetry); | ||
499 | |||
500 | if (pszErrorDescription) | ||
501 | { | ||
502 | ::CoTaskMemFree(pszErrorDescription); | ||
503 | } | ||
504 | ReleaseObject(pError); | ||
505 | } | ||
diff --git a/src/engine/bitsengine.h b/src/engine/bitsengine.h deleted file mode 100644 index b1c1d805..00000000 --- a/src/engine/bitsengine.h +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | #pragma once | ||
2 | // 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. | ||
3 | |||
4 | |||
5 | #ifdef __cplusplus | ||
6 | extern "C" { | ||
7 | #endif | ||
8 | |||
9 | // structs | ||
10 | |||
11 | |||
12 | // functions | ||
13 | |||
14 | HRESULT BitsDownloadUrl( | ||
15 | __in DOWNLOAD_CACHE_CALLBACK* pCallback, | ||
16 | __in DOWNLOAD_SOURCE* pDownloadSource, | ||
17 | __in LPCWSTR wzDestinationPath | ||
18 | ); | ||
19 | |||
20 | |||
21 | #ifdef __cplusplus | ||
22 | } | ||
23 | #endif | ||
diff --git a/src/engine/engine.vcxproj b/src/engine/engine.vcxproj index bc724a40..a6ab60df 100644 --- a/src/engine/engine.vcxproj +++ b/src/engine/engine.vcxproj | |||
@@ -1,7 +1,7 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | 1 | <?xml version="1.0" encoding="utf-8"?> |
2 | <!-- 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 | <!-- 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. --> |
3 | <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | 3 | <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
4 | <Import Project="..\..\packages\WixToolset.DUtil.4.0.61\build\WixToolset.DUtil.props" Condition="Exists('..\..\packages\WixToolset.DUtil.4.0.61\build\WixToolset.DUtil.props')" /> | 4 | <Import Project="..\..\packages\WixToolset.DUtil.4.0.62\build\WixToolset.DUtil.props" Condition="Exists('..\..\packages\WixToolset.DUtil.4.0.62\build\WixToolset.DUtil.props')" /> |
5 | <ItemGroup Label="ProjectConfigurations"> | 5 | <ItemGroup Label="ProjectConfigurations"> |
6 | <ProjectConfiguration Include="Debug|Win32"> | 6 | <ProjectConfiguration Include="Debug|Win32"> |
7 | <Configuration>Debug</Configuration> | 7 | <Configuration>Debug</Configuration> |
@@ -45,7 +45,6 @@ | |||
45 | <ItemGroup> | 45 | <ItemGroup> |
46 | <ClCompile Include="apply.cpp" /> | 46 | <ClCompile Include="apply.cpp" /> |
47 | <ClCompile Include="approvedexe.cpp" /> | 47 | <ClCompile Include="approvedexe.cpp" /> |
48 | <ClCompile Include="bitsengine.cpp" /> | ||
49 | <ClCompile Include="burnextension.cpp" /> | 48 | <ClCompile Include="burnextension.cpp" /> |
50 | <ClCompile Include="detect.cpp" /> | 49 | <ClCompile Include="detect.cpp" /> |
51 | <ClCompile Include="embedded.cpp" /> | 50 | <ClCompile Include="embedded.cpp" /> |
@@ -90,7 +89,6 @@ | |||
90 | <ItemGroup> | 89 | <ItemGroup> |
91 | <ClInclude Include="apply.h" /> | 90 | <ClInclude Include="apply.h" /> |
92 | <ClInclude Include="approvedexe.h" /> | 91 | <ClInclude Include="approvedexe.h" /> |
93 | <ClInclude Include="bitsengine.h" /> | ||
94 | <ClInclude Include="..\WixToolset.BootstrapperCore.Native\inc\BootstrapperApplication.h" /> | 92 | <ClInclude Include="..\WixToolset.BootstrapperCore.Native\inc\BootstrapperApplication.h" /> |
95 | <ClInclude Include="..\WixToolset.BootstrapperCore.Native\inc\BootstrapperEngine.h" /> | 93 | <ClInclude Include="..\WixToolset.BootstrapperCore.Native\inc\BootstrapperEngine.h" /> |
96 | <ClInclude Include="..\WixToolset.BootstrapperCore.Native\inc\BundleExtension.h" /> | 94 | <ClInclude Include="..\WixToolset.BootstrapperCore.Native\inc\BundleExtension.h" /> |
@@ -167,7 +165,7 @@ rc.exe -fo "$(OutDir)engine.res" "$(IntDir)engine.messages.rc"</Command> | |||
167 | <PropertyGroup> | 165 | <PropertyGroup> |
168 | <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> | 166 | <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> |
169 | </PropertyGroup> | 167 | </PropertyGroup> |
170 | <Error Condition="!Exists('..\..\packages\WixToolset.DUtil.4.0.61\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.DUtil.4.0.61\build\WixToolset.DUtil.props'))" /> | 168 | <Error Condition="!Exists('..\..\packages\WixToolset.DUtil.4.0.62\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.DUtil.4.0.62\build\WixToolset.DUtil.props'))" /> |
171 | <Error Condition="!Exists('..\..\packages\Nerdbank.GitVersioning.3.3.37\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Nerdbank.GitVersioning.3.3.37\build\Nerdbank.GitVersioning.targets'))" /> | 169 | <Error Condition="!Exists('..\..\packages\Nerdbank.GitVersioning.3.3.37\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Nerdbank.GitVersioning.3.3.37\build\Nerdbank.GitVersioning.targets'))" /> |
172 | </Target> | 170 | </Target> |
173 | </Project> \ No newline at end of file | 171 | </Project> \ No newline at end of file |
diff --git a/src/engine/packages.config b/src/engine/packages.config index 102b8bee..ad6df168 100644 --- a/src/engine/packages.config +++ b/src/engine/packages.config | |||
@@ -1,5 +1,5 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | 1 | <?xml version="1.0" encoding="utf-8"?> |
2 | <packages> | 2 | <packages> |
3 | <package id="Nerdbank.GitVersioning" version="3.3.37" targetFramework="native" developmentDependency="true" /> | 3 | <package id="Nerdbank.GitVersioning" version="3.3.37" targetFramework="native" developmentDependency="true" /> |
4 | <package id="WixToolset.DUtil" version="4.0.61" targetFramework="native" /> | 4 | <package id="WixToolset.DUtil" version="4.0.62" targetFramework="native" /> |
5 | </packages> \ No newline at end of file | 5 | </packages> \ No newline at end of file |
diff --git a/src/engine/precomp.h b/src/engine/precomp.h index 1b3e9bdc..4f8e9d46 100644 --- a/src/engine/precomp.h +++ b/src/engine/precomp.h | |||
@@ -4,7 +4,6 @@ | |||
4 | 4 | ||
5 | #include <windows.h> | 5 | #include <windows.h> |
6 | #include <aclapi.h> | 6 | #include <aclapi.h> |
7 | #include <Bits.h> | ||
8 | 7 | ||
9 | #include <math.h> | 8 | #include <math.h> |
10 | #include <msiquery.h> | 9 | #include <msiquery.h> |
@@ -96,7 +95,6 @@ | |||
96 | #include "manifest.h" | 95 | #include "manifest.h" |
97 | #include "splashscreen.h" | 96 | #include "splashscreen.h" |
98 | #include "uithread.h" | 97 | #include "uithread.h" |
99 | #include "bitsengine.h" | ||
100 | #include "netfxchainer.h" | 98 | #include "netfxchainer.h" |
101 | 99 | ||
102 | #include "externalengine.h" | 100 | #include "externalengine.h" |
diff --git a/src/stub/packages.config b/src/stub/packages.config index 3b161457..1c027b04 100644 --- a/src/stub/packages.config +++ b/src/stub/packages.config | |||
@@ -4,5 +4,5 @@ | |||
4 | <package id="Microsoft.SourceLink.Common" version="1.0.0" targetFramework="native" developmentDependency="true" /> | 4 | <package id="Microsoft.SourceLink.Common" version="1.0.0" targetFramework="native" developmentDependency="true" /> |
5 | <package id="Microsoft.SourceLink.GitHub" version="1.0.0" targetFramework="native" developmentDependency="true" /> | 5 | <package id="Microsoft.SourceLink.GitHub" version="1.0.0" targetFramework="native" developmentDependency="true" /> |
6 | <package id="Nerdbank.GitVersioning" version="3.3.37" targetFramework="native" developmentDependency="true" /> | 6 | <package id="Nerdbank.GitVersioning" version="3.3.37" targetFramework="native" developmentDependency="true" /> |
7 | <package id="WixToolset.DUtil" version="4.0.61" targetFramework="native" /> | 7 | <package id="WixToolset.DUtil" version="4.0.62" targetFramework="native" /> |
8 | </packages> \ No newline at end of file | 8 | </packages> \ No newline at end of file |
diff --git a/src/stub/stub.vcxproj b/src/stub/stub.vcxproj index f4d34d1d..f9a7b5a9 100644 --- a/src/stub/stub.vcxproj +++ b/src/stub/stub.vcxproj | |||
@@ -5,7 +5,7 @@ | |||
5 | <Import Project="..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.props" Condition="Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.props')" /> | 5 | <Import Project="..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.props" Condition="Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.props')" /> |
6 | <Import Project="..\..\packages\Microsoft.SourceLink.Common.1.0.0\build\Microsoft.SourceLink.Common.props" Condition="Exists('..\..\packages\Microsoft.SourceLink.Common.1.0.0\build\Microsoft.SourceLink.Common.props')" /> | 6 | <Import Project="..\..\packages\Microsoft.SourceLink.Common.1.0.0\build\Microsoft.SourceLink.Common.props" Condition="Exists('..\..\packages\Microsoft.SourceLink.Common.1.0.0\build\Microsoft.SourceLink.Common.props')" /> |
7 | <Import Project="..\..\packages\Microsoft.Build.Tasks.Git.1.0.0\build\Microsoft.Build.Tasks.Git.props" Condition="Exists('..\..\packages\Microsoft.Build.Tasks.Git.1.0.0\build\Microsoft.Build.Tasks.Git.props')" /> | 7 | <Import Project="..\..\packages\Microsoft.Build.Tasks.Git.1.0.0\build\Microsoft.Build.Tasks.Git.props" Condition="Exists('..\..\packages\Microsoft.Build.Tasks.Git.1.0.0\build\Microsoft.Build.Tasks.Git.props')" /> |
8 | <Import Project="..\..\packages\WixToolset.DUtil.4.0.61\build\WixToolset.DUtil.props" Condition="Exists('..\..\packages\WixToolset.DUtil.4.0.61\build\WixToolset.DUtil.props')" /> | 8 | <Import Project="..\..\packages\WixToolset.DUtil.4.0.62\build\WixToolset.DUtil.props" Condition="Exists('..\..\packages\WixToolset.DUtil.4.0.62\build\WixToolset.DUtil.props')" /> |
9 | 9 | ||
10 | <ItemGroup Label="ProjectConfigurations"> | 10 | <ItemGroup Label="ProjectConfigurations"> |
11 | <ProjectConfiguration Include="Debug|Win32"> | 11 | <ProjectConfiguration Include="Debug|Win32"> |
@@ -117,6 +117,6 @@ | |||
117 | <Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.props'))" /> | 117 | <Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.props'))" /> |
118 | <Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.targets'))" /> | 118 | <Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.targets'))" /> |
119 | <Error Condition="!Exists('..\..\packages\Nerdbank.GitVersioning.3.3.37\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Nerdbank.GitVersioning.3.3.37\build\Nerdbank.GitVersioning.targets'))" /> | 119 | <Error Condition="!Exists('..\..\packages\Nerdbank.GitVersioning.3.3.37\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Nerdbank.GitVersioning.3.3.37\build\Nerdbank.GitVersioning.targets'))" /> |
120 | <Error Condition="!Exists('..\..\packages\WixToolset.DUtil.4.0.61\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.DUtil.4.0.61\build\WixToolset.DUtil.props'))" /> | 120 | <Error Condition="!Exists('..\..\packages\WixToolset.DUtil.4.0.62\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.DUtil.4.0.62\build\WixToolset.DUtil.props'))" /> |
121 | </Target> | 121 | </Target> |
122 | </Project> \ No newline at end of file | 122 | </Project> \ No newline at end of file |
diff --git a/src/test/BurnUnitTest/BurnUnitTest.vcxproj b/src/test/BurnUnitTest/BurnUnitTest.vcxproj index 62e58942..08dc68e7 100644 --- a/src/test/BurnUnitTest/BurnUnitTest.vcxproj +++ b/src/test/BurnUnitTest/BurnUnitTest.vcxproj | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | 5 | <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
6 | <Import Project="..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.47\build\WixBuildTools.TestSupport.Native.props" Condition="Exists('..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.47\build\WixBuildTools.TestSupport.Native.props')" /> | 6 | <Import Project="..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.47\build\WixBuildTools.TestSupport.Native.props" Condition="Exists('..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.47\build\WixBuildTools.TestSupport.Native.props')" /> |
7 | <Import Project="..\..\..\packages\WixToolset.DUtil.4.0.61\build\WixToolset.DUtil.props" Condition="Exists('..\..\..\packages\WixToolset.DUtil.4.0.61\build\WixToolset.DUtil.props')" /> | 7 | <Import Project="..\..\..\packages\WixToolset.DUtil.4.0.62\build\WixToolset.DUtil.props" Condition="Exists('..\..\..\packages\WixToolset.DUtil.4.0.62\build\WixToolset.DUtil.props')" /> |
8 | <ItemGroup Label="ProjectConfigurations"> | 8 | <ItemGroup Label="ProjectConfigurations"> |
9 | <ProjectConfiguration Include="Debug|ARM64"> | 9 | <ProjectConfiguration Include="Debug|ARM64"> |
10 | <Configuration>Debug</Configuration> | 10 | <Configuration>Debug</Configuration> |
@@ -95,6 +95,6 @@ | |||
95 | </PropertyGroup> | 95 | </PropertyGroup> |
96 | <Error Condition="!Exists('..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.47\build\WixBuildTools.TestSupport.Native.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.47\build\WixBuildTools.TestSupport.Native.props'))" /> | 96 | <Error Condition="!Exists('..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.47\build\WixBuildTools.TestSupport.Native.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.47\build\WixBuildTools.TestSupport.Native.props'))" /> |
97 | <Error Condition="!Exists('..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.47\build\WixBuildTools.TestSupport.Native.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.47\build\WixBuildTools.TestSupport.Native.targets'))" /> | 97 | <Error Condition="!Exists('..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.47\build\WixBuildTools.TestSupport.Native.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\WixBuildTools.TestSupport.Native.4.0.47\build\WixBuildTools.TestSupport.Native.targets'))" /> |
98 | <Error Condition="!Exists('..\..\..\packages\WixToolset.DUtil.4.0.61\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\WixToolset.DUtil.4.0.61\build\WixToolset.DUtil.props'))" /> | 98 | <Error Condition="!Exists('..\..\..\packages\WixToolset.DUtil.4.0.62\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\WixToolset.DUtil.4.0.62\build\WixToolset.DUtil.props'))" /> |
99 | </Target> | 99 | </Target> |
100 | </Project> \ No newline at end of file | 100 | </Project> \ No newline at end of file |
diff --git a/src/test/BurnUnitTest/packages.config b/src/test/BurnUnitTest/packages.config index e3e97259..a35dfe1f 100644 --- a/src/test/BurnUnitTest/packages.config +++ b/src/test/BurnUnitTest/packages.config | |||
@@ -10,5 +10,5 @@ | |||
10 | <package id="xunit.runner.visualstudio" version="2.4.1" /> | 10 | <package id="xunit.runner.visualstudio" version="2.4.1" /> |
11 | <package id="WixBuildTools.TestSupport" version="4.0.47" /> | 11 | <package id="WixBuildTools.TestSupport" version="4.0.47" /> |
12 | <package id="WixBuildTools.TestSupport.Native" version="4.0.47" /> | 12 | <package id="WixBuildTools.TestSupport.Native" version="4.0.47" /> |
13 | <package id="WixToolset.DUtil" version="4.0.61" targetFramework="native" /> | 13 | <package id="WixToolset.DUtil" version="4.0.62" targetFramework="native" /> |
14 | </packages> \ No newline at end of file | 14 | </packages> \ No newline at end of file |
diff --git a/src/test/BurnUnitTest/precomp.h b/src/test/BurnUnitTest/precomp.h index a5db1555..d2b57d61 100644 --- a/src/test/BurnUnitTest/precomp.h +++ b/src/test/BurnUnitTest/precomp.h | |||
@@ -67,7 +67,6 @@ | |||
67 | #include "embedded.h" | 67 | #include "embedded.h" |
68 | #include "manifest.h" | 68 | #include "manifest.h" |
69 | #include "splashscreen.h" | 69 | #include "splashscreen.h" |
70 | #include "bitsengine.h" | ||
71 | #include "detect.h" | 70 | #include "detect.h" |
72 | 71 | ||
73 | #pragma managed | 72 | #pragma managed |