VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxScreen.cpp@ 34440

Last change on this file since 34440 was 33540, checked in by vboxsync, 14 years ago

*: spelling fixes, thanks Timeless!

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.1 KB
Line 
1/** @file
2 *
3 * VBoxVideo Display D3D User mode dll
4 *
5 * Copyright (C) 2010 Oracle Corporation
6 *
7 * This file is part of VirtualBox Open Source Edition (OSE), as
8 * available from http://www.virtualbox.org. This file is free software;
9 * you can redistribute it and/or modify it under the terms of the GNU
10 * General Public License (GPL) as published by the Free Software
11 * Foundation, in version 2 as it comes in the "COPYING" file of the
12 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
13 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
14 */
15#include "VBoxScreen.h"
16
17#include <iprt/log.h>
18
19
20typedef struct VBOXSCREENMONENUM
21{
22 PVBOXSCREENMON pMon;
23 UINT iCur;
24 HRESULT hr;
25 BOOL bChanged;
26} VBOXSCREENMONENUM, *PVBOXSCREENMONENUM;
27
28static VBOXSCREENMON g_VBoxScreenMon;
29
30
31#define VBOX_E_INSUFFICIENT_BUFFER HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)
32#define VBOX_E_NOT_SUPPORTED HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED)
33
34typedef DECLCALLBACK(BOOLEAN) FNVBOXSCREENMON_ADAPTEROP(PVBOXSCREENMON pMon, D3DKMT_HANDLE hAdapter, LPCWSTR pDevName, PVOID pContext);
35typedef FNVBOXSCREENMON_ADAPTEROP *PFNVBOXSCREENMON_ADAPTEROP;
36static HRESULT vboxScreenMonWDDMAdapterOp(PVBOXSCREENMON pMon, LPCWSTR pDevName, PFNVBOXSCREENMON_ADAPTEROP pfnOp, PVOID pContext)
37{
38 D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME OpenAdapterData = {0};
39 wcsncpy(OpenAdapterData.DeviceName, pDevName, RT_ELEMENTS(OpenAdapterData.DeviceName) - 1 /* the last one is always \0 */);
40 HRESULT hr = S_OK;
41 NTSTATUS Status = pMon->pfnD3DKMTOpenAdapterFromGdiDisplayName(&OpenAdapterData);
42 Assert(!Status);
43 if (!Status)
44 {
45 BOOLEAN bCloseAdapter = pfnOp(pMon, OpenAdapterData.hAdapter, OpenAdapterData.DeviceName, pContext);
46
47 if (bCloseAdapter)
48 {
49 D3DKMT_CLOSEADAPTER ClosaAdapterData = {0};
50 ClosaAdapterData.hAdapter = OpenAdapterData.hAdapter;
51 Status = pMon->pfnD3DKMTCloseAdapter(&ClosaAdapterData);
52 if (Status)
53 {
54 Log((__FUNCTION__": pfnD3DKMTCloseAdapter failed, Status (0x%x)\n", Status));
55 /* ignore */
56 Status = 0;
57 }
58 }
59 }
60 else
61 {
62 Log((__FUNCTION__": pfnD3DKMTOpenAdapterFromGdiDisplayName failed, Status (0x%x)\n", Status));
63 hr = E_FAIL;
64 }
65
66 return hr;
67}
68
69typedef struct
70{
71 NTSTATUS Status;
72 PVBOXDISPIFESCAPE pEscape;
73 int cbData;
74} VBOXDISPIFWDDM_ESCAPEOP_CONTEXT, *PVBOXDISPIFWDDM_ESCAPEOP_CONTEXT;
75
76DECLCALLBACK(BOOLEAN) vboxScreenMonEscapeOp(PVBOXSCREENMON pMon, D3DKMT_HANDLE hAdapter, LPCWSTR pDevName, PVOID pContext)
77{
78 PVBOXDISPIFWDDM_ESCAPEOP_CONTEXT pCtx = (PVBOXDISPIFWDDM_ESCAPEOP_CONTEXT)pContext;
79
80 D3DKMT_ESCAPE EscapeData = {0};
81 EscapeData.hAdapter = hAdapter;
82 //EscapeData.hDevice = NULL;
83 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
84 EscapeData.Flags.HardwareAccess = 1;
85 EscapeData.pPrivateDriverData = pCtx->pEscape;
86 EscapeData.PrivateDriverDataSize = VBOXDISPIFESCAPE_SIZE(pCtx->cbData);
87 //EscapeData.hContext = NULL;
88
89 pCtx->Status = pMon->pfnD3DKMTEscape(&EscapeData);
90
91 return TRUE;
92}
93
94static HRESULT vboxScreenMonEscape(PVBOXSCREENMON pMon, PVBOXDISPIFESCAPE pEscape, int cbData)
95{
96 VBOXDISPIFWDDM_ESCAPEOP_CONTEXT Ctx = {0};
97 Ctx.pEscape = pEscape;
98 Ctx.cbData = cbData;
99 HRESULT hr = vboxScreenMonWDDMAdapterOp(pMon, L"\\\\.\\DISPLAY1", vboxScreenMonEscapeOp, &Ctx);
100 Assert(hr == S_OK);
101 if (hr == S_OK)
102 {
103 Assert(!Ctx.Status);
104 if (Ctx.Status)
105 {
106 if (Ctx.Status == 0xC00000BBL) /* not supported */
107 hr = VBOX_E_NOT_SUPPORTED;
108 else
109 hr = E_FAIL;
110 Log((__FUNCTION__": pfnD3DKMTEscape failed, Status (0x%x)\n", Ctx.Status));
111 }
112 }
113 else
114 Log((__FUNCTION__": vboxScreenMRunnerWDDMAdapterOp failed, hr (0x%x)\n", hr));
115
116 return hr;
117}
118
119static BOOL CALLBACK vboxScreenMonEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
120{
121 PVBOXSCREENMONENUM pEnum = (PVBOXSCREENMONENUM)dwData;
122 PVBOXSCREENMON pMon = pEnum->pMon;
123 UINT cbRequired = RT_OFFSETOF(VBOXSCREENLAYOUT, aScreens[pEnum->iCur]);
124 if (pEnum->hr == S_OK)
125 {
126 Assert(pEnum->iCur < VBOX_VIDEO_MAX_SCREENS);
127 if (pEnum->iCur < VBOX_VIDEO_MAX_SCREENS)
128 {
129 MONITORINFOEX minfo;
130 minfo.cbSize = sizeof (minfo);
131 if (GetMonitorInfo(hMonitor, (LPMONITORINFO)&minfo))
132 {
133 D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME OpenAdapterData = {0};
134 wcsncpy(OpenAdapterData.DeviceName, minfo.szDevice, RT_ELEMENTS(OpenAdapterData.DeviceName) - 1 /* the last one is always \0 */);
135 NTSTATUS Status = pMon->pfnD3DKMTOpenAdapterFromGdiDisplayName(&OpenAdapterData);
136 Assert(!Status);
137 if (!Status)
138 {
139 if (pMon->LoData.ScreenLayout.ScreenLayout.cScreens <= pEnum->iCur
140 || pMon->LoData.ScreenLayout.ScreenLayout.aScreens[pEnum->iCur].VidPnSourceId != OpenAdapterData.VidPnSourceId
141 || pMon->LoData.ScreenLayout.ScreenLayout.aScreens[pEnum->iCur].pos.x != lprcMonitor->left
142 || pMon->LoData.ScreenLayout.ScreenLayout.aScreens[pEnum->iCur].pos.y != lprcMonitor->top)
143 {
144 pMon->LoData.ScreenLayout.ScreenLayout.aScreens[pEnum->iCur].VidPnSourceId = OpenAdapterData.VidPnSourceId;
145 pMon->LoData.ScreenLayout.ScreenLayout.aScreens[pEnum->iCur].pos.x = lprcMonitor->left;
146 pMon->LoData.ScreenLayout.ScreenLayout.aScreens[pEnum->iCur].pos.y = lprcMonitor->top;
147 pEnum->bChanged = true;
148 }
149
150 D3DKMT_CLOSEADAPTER ClosaAdapterData = {0};
151 ClosaAdapterData.hAdapter = OpenAdapterData.hAdapter;
152 HRESULT tmpHr = pMon->pfnD3DKMTCloseAdapter(&ClosaAdapterData);
153 Assert(tmpHr == S_OK);
154 }
155 else
156 {
157 pEnum->hr = E_FAIL;
158 }
159 }
160 else
161 {
162 DWORD winEr = GetLastError();
163 HRESULT hr = HRESULT_FROM_WIN32(winEr);
164 Assert(0);
165 Assert(hr != S_OK);
166 Assert(hr != S_FALSE);
167 if (hr == S_OK || hr == S_FALSE)
168 hr = E_FAIL;
169 pEnum->hr = hr;
170 }
171
172// D3DKMT_OPENADAPTERFROMHDC Oa;
173// memset(&Oa, 0, sizeof (D3DKMT_OPENADAPTERFROMHDC));
174// Oa.hDc = hdcMonitor;
175// HRESULT hr = pMon->pfnD3DKMTOpenAdapterFromHdc(&Oa);
176// Assert(hr == S_OK);
177// if (hr == S_OK)
178// {
179// if (pEnum->pScreenInfo->cScreens <= pEnum->iCur
180// || pEnum->pScreenInfo->aScreens[pEnum->iCur].VidPnSourceId != Oa.VidPnSourceId
181// || pEnum->pScreenInfo->aScreens[pEnum->iCur].pos.x != lprcMonitor->left
182// || pEnum->pScreenInfo->aScreens[pEnum->iCur].pos.y == lprcMonitor->top)
183// {
184// pEnum->pScreenInfo->aScreens[pEnum->iCur].VidPnSourceId = Oa.VidPnSourceId;
185// pEnum->pScreenInfo->aScreens[pEnum->iCur].pos.x = lprcMonitor->left;
186// pEnum->pScreenInfo->aScreens[pEnum->iCur].pos.y = lprcMonitor->top;
187// pEnum->bChanged = true;
188// }
189//
190// D3DKMT_CLOSEADAPTER ClosaAdapterData = {0};
191// ClosaAdapterData.hAdapter = Oa.hAdapter;
192// HRESULT tmpHr = pMon->pfnD3DKMTCloseAdapter(&ClosaAdapterData);
193// Assert(tmpHr == S_OK);
194// pEnum->hr = hr;
195// }
196 }
197 else
198 {
199 pEnum->hr = VBOX_E_INSUFFICIENT_BUFFER;
200 }
201 }
202
203 ++pEnum->iCur;
204
205 return TRUE;
206}
207
208
209//static HRESULT vboxScreenMonCheckUpdateChange(PVBOXSCREENMON pMon)
210static HRESULT vboxScreenMonCheckUpdateChange()
211{
212 PVBOXSCREENMON pMon = &g_VBoxScreenMon;
213 VBOXSCREENMONENUM monEnum = {0};
214 monEnum.pMon = pMon;
215
216 BOOL bResult = EnumDisplayMonitors(NULL, NULL, vboxScreenMonEnumProc, (LPARAM)&monEnum);
217 if (bResult)
218 {
219 Assert(monEnum.hr == S_OK);
220 if (monEnum.hr == S_OK && monEnum.bChanged)
221 {
222 Assert(monEnum.iCur);
223 pMon->LoData.ScreenLayout.ScreenLayout.cScreens = monEnum.iCur;
224
225 UINT cbSize = RT_OFFSETOF(VBOXSCREENLAYOUT, aScreens[pMon->LoData.ScreenLayout.ScreenLayout.cScreens]);
226 HRESULT hr = vboxScreenMonEscape(pMon, &pMon->LoData.ScreenLayout.EscapeHdr, cbSize);
227 Assert(hr == S_OK);
228 return hr;
229 }
230 return monEnum.hr;
231 }
232
233 DWORD winEr = GetLastError();
234 HRESULT hr = HRESULT_FROM_WIN32(winEr);
235 Assert(0);
236 Assert(hr != S_OK);
237 Assert(hr != S_FALSE);
238 if (hr == S_OK || hr == S_FALSE)
239 hr = E_FAIL;
240 return hr;
241}
242
243static LRESULT CALLBACK vboxScreenMonWndProc(HWND hwnd,
244 UINT uMsg,
245 WPARAM wParam,
246 LPARAM lParam
247)
248{
249 switch(uMsg)
250 {
251 case WM_DISPLAYCHANGE:
252 {
253 HRESULT hr = vboxScreenMonCheckUpdateChange();
254 Assert(hr == S_OK);
255 }
256 case WM_CLOSE:
257 Log((__FUNCTION__": got WM_CLOSE for hwnd(0x%x)", hwnd));
258 return 0;
259 case WM_DESTROY:
260 Log((__FUNCTION__": got WM_DESTROY for hwnd(0x%x)", hwnd));
261 return 0;
262 case WM_NCHITTEST:
263 Log((__FUNCTION__": got WM_NCHITTEST for hwnd(0x%x)\n", hwnd));
264 return HTNOWHERE;
265 }
266
267 return DefWindowProc(hwnd, uMsg, wParam, lParam);
268}
269
270#define VBOXSCREENMONWND_NAME L"VboxScreenMonWnd"
271
272HRESULT vboxScreenMonWndCreate(HWND *phWnd)
273{
274 HRESULT hr = S_OK;
275 HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);
276 /* Register the Window Class. */
277 WNDCLASS wc;
278 if (!GetClassInfo(hInstance, VBOXSCREENMONWND_NAME, &wc))
279 {
280 wc.style = CS_OWNDC;
281 wc.lpfnWndProc = vboxScreenMonWndProc;
282 wc.cbClsExtra = 0;
283 wc.cbWndExtra = 0;
284 wc.hInstance = hInstance;
285 wc.hIcon = NULL;
286 wc.hCursor = NULL;
287 wc.hbrBackground = NULL;
288 wc.lpszMenuName = NULL;
289 wc.lpszClassName = VBOXSCREENMONWND_NAME;
290 if (!RegisterClass(&wc))
291 {
292 DWORD winErr = GetLastError();
293 Log((__FUNCTION__": RegisterClass failed, winErr(%d)\n", winErr));
294 hr = E_FAIL;
295 }
296 }
297
298 if (hr == S_OK)
299 {
300 HWND hWnd = CreateWindowEx (WS_EX_TOOLWINDOW,
301 VBOXSCREENMONWND_NAME, VBOXSCREENMONWND_NAME,
302 WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED,
303 -100, -100,
304 10, 10,
305 NULL, //GetDesktopWindow() /* hWndParent */,
306 NULL /* hMenu */,
307 hInstance,
308 NULL /* lpParam */);
309 Assert(hWnd);
310 if (hWnd)
311 {
312 *phWnd = hWnd;
313 }
314 else
315 {
316 DWORD winErr = GetLastError();
317 Log((__FUNCTION__": CreateWindowEx failed, winErr(%d)\n", winErr));
318 hr = E_FAIL;
319 }
320 }
321
322 return hr;
323}
324
325static HRESULT vboxScreenMonWndDestroy(HWND hWnd)
326{
327 BOOL bResult = DestroyWindow(hWnd);
328 if (bResult)
329 return S_OK;
330
331 DWORD winErr = GetLastError();
332 Log((__FUNCTION__": DestroyWindow failed, winErr(%d) for hWnd(0x%x)\n", winErr, hWnd));
333 Assert(0);
334
335 return HRESULT_FROM_WIN32(winErr);
336}
337
338//HRESULT vboxScreenMonInit(PVBOXSCREENMON pMon)
339HRESULT vboxScreenMonInit()
340{
341 PVBOXSCREENMON pMon = &g_VBoxScreenMon;
342 HRESULT hr = S_OK;
343
344 memset(pMon, 0, sizeof (VBOXSCREENMON));
345
346 pMon->LoData.ScreenLayout.EscapeHdr.escapeCode = VBOXESC_SCREENLAYOUT;
347
348 pMon->hGdi32 = LoadLibraryW(L"gdi32.dll");
349 if (pMon->hGdi32 != NULL)
350 {
351 bool bSupported = true;
352 pMon->pfnD3DKMTOpenAdapterFromHdc = (PFND3DKMT_OPENADAPTERFROMHDC)GetProcAddress(pMon->hGdi32, "D3DKMTOpenAdapterFromHdc");
353 Log((__FUNCTION__"pfnD3DKMTOpenAdapterFromHdc = %p\n", pMon->pfnD3DKMTOpenAdapterFromHdc));
354 bSupported &= !!(pMon->pfnD3DKMTOpenAdapterFromHdc);
355
356 pMon->pfnD3DKMTOpenAdapterFromGdiDisplayName = (PFND3DKMT_OPENADAPTERFROMGDIDISPLAYNAME)GetProcAddress(pMon->hGdi32, "D3DKMTOpenAdapterFromGdiDisplayName");
357 Log((__FUNCTION__": pfnD3DKMTOpenAdapterFromGdiDisplayName = %p\n", pMon->pfnD3DKMTOpenAdapterFromGdiDisplayName));
358 bSupported &= !!(pMon->pfnD3DKMTOpenAdapterFromGdiDisplayName);
359
360 pMon->pfnD3DKMTCloseAdapter = (PFND3DKMT_CLOSEADAPTER)GetProcAddress(pMon->hGdi32, "D3DKMTCloseAdapter");
361 Log((__FUNCTION__": pfnD3DKMTCloseAdapter = %p\n", pMon->pfnD3DKMTCloseAdapter));
362 bSupported &= !!(pMon->pfnD3DKMTCloseAdapter);
363
364 pMon->pfnD3DKMTEscape = (PFND3DKMT_ESCAPE)GetProcAddress(pMon->hGdi32, "D3DKMTEscape");
365 Log((__FUNCTION__": pfnD3DKMTEscape = %p\n", pMon->pfnD3DKMTEscape));
366 bSupported &= !!(pMon->pfnD3DKMTEscape);
367
368 Assert(bSupported);
369 if (bSupported)
370 {
371 hr = vboxScreenMonWndCreate(&pMon->hWnd);
372 Assert(hr == S_OK);
373 if (hr == S_OK)
374 return S_OK;
375 }
376 else
377 {
378 Log((__FUNCTION__": one of pfnD3DKMT function pointers failed to initialize\n"));
379 hr = VBOX_E_NOT_SUPPORTED;
380 }
381
382 FreeLibrary(pMon->hGdi32);
383 }
384 else
385 {
386 DWORD winEr = GetLastError();
387 hr = HRESULT_FROM_WIN32(winEr);
388 Assert(0);
389 Assert(hr != S_OK);
390 Assert(hr != S_FALSE);
391 if (hr == S_OK || hr == S_FALSE)
392 hr = E_FAIL;
393 }
394
395 return hr;
396}
397
398//HRESULT vboxScreenMonTerm(PVBOXSCREENMON pMon)
399HRESULT vboxScreenMonTerm()
400{
401 PVBOXSCREENMON pMon = &g_VBoxScreenMon;
402 HRESULT tmpHr = vboxScreenMonWndDestroy(pMon->hWnd);
403 Assert(tmpHr == S_OK);
404
405 FreeLibrary(pMon->hGdi32);
406
407 pMon->bInited = FALSE;
408 return S_OK;
409}
410
411HRESULT vboxScreenMonRun()
412{
413 PVBOXSCREENMON pMon = &g_VBoxScreenMon;
414 MSG Msg;
415
416 HRESULT hr = S_FALSE;
417
418 if (!pMon->bInited)
419 {
420 PeekMessage(&Msg,
421 NULL /* HWND hWnd */,
422 WM_USER /* UINT wMsgFilterMin */,
423 WM_USER /* UINT wMsgFilterMax */,
424 PM_NOREMOVE);
425
426 pMon->bInited = TRUE;
427 }
428
429 BOOL bCheck = TRUE;
430 do
431 {
432 if (bCheck)
433 {
434 hr = vboxScreenMonCheckUpdateChange();
435 Assert(hr == S_OK);
436
437 bCheck = FALSE;
438 }
439
440 BOOL bResult = GetMessage(&Msg,
441 0 /*HWND hWnd*/,
442 0 /*UINT wMsgFilterMin*/,
443 0 /*UINT wMsgFilterMax*/
444 );
445
446 if(!bResult) /* WM_QUIT was posted */
447 {
448 hr = S_FALSE;
449 break;
450 }
451
452 if(bResult == -1) /* error occurred */
453 {
454 DWORD winEr = GetLastError();
455 hr = HRESULT_FROM_WIN32(winEr);
456 Assert(0);
457 /* just ensure we never return success in this case */
458 Assert(hr != S_OK);
459 Assert(hr != S_FALSE);
460 if (hr == S_OK || hr == S_FALSE)
461 hr = E_FAIL;
462 break;
463 }
464
465 switch (Msg.message)
466 {
467 case WM_DISPLAYCHANGE:
468 bCheck = TRUE;
469 default:
470 TranslateMessage(&Msg);
471 DispatchMessage(&Msg);
472 break;
473 }
474 } while (1);
475 return 0;
476}
477
478static DWORD WINAPI vboxScreenMRunnerThread(void *pvUser)
479{
480 PVBOXSCREENMONRUNNER pRunner = (PVBOXSCREENMONRUNNER)pvUser;
481 Assert(0);
482
483 BOOL bRc = SetEvent(pRunner->hEvent);
484 if (!bRc)
485 {
486 DWORD winErr = GetLastError();
487 Log((__FUNCTION__": SetEvent failed, winErr = (%d)", winErr));
488 HRESULT tmpHr = HRESULT_FROM_WIN32(winErr);
489 Assert(0);
490 Assert(tmpHr != S_OK);
491 }
492
493 HRESULT hr = vboxScreenMonInit();
494 Assert(hr == S_OK);
495 if (hr == S_OK)
496 {
497 hr = vboxScreenMonRun();
498 Assert(hr == S_OK);
499
500 vboxScreenMonTerm();
501 }
502 return 0;
503}
504
505HRESULT VBoxScreenMRunnerStart(PVBOXSCREENMONRUNNER pMon)
506{
507 HRESULT hr = E_FAIL;
508 memset(pMon, 0, sizeof (VBOXSCREENMONRUNNER));
509
510 pMon->hEvent = CreateEvent(NULL, /* LPSECURITY_ATTRIBUTES lpEventAttributes*/
511 FALSE, /* BOOL bManualReset*/
512 FALSE, /* BOOL bInitialState */
513 NULL /* LPCTSTR lpName */
514 );
515 if (pMon->hEvent)
516 {
517 pMon->hThread = CreateThread(NULL /* LPSECURITY_ATTRIBUTES lpThreadAttributes */,
518 0 /* SIZE_T dwStackSize */,
519 vboxScreenMRunnerThread,
520 pMon,
521 0 /* DWORD dwCreationFlags */,
522 &pMon->idThread);
523 if (pMon->hThread)
524 {
525 Assert(0);
526 return S_OK;
527 }
528 else
529 {
530 DWORD winErr = GetLastError();
531 Log((__FUNCTION__": CreateThread failed, winErr = (%d)", winErr));
532 hr = HRESULT_FROM_WIN32(winErr);
533 Assert(0);
534 Assert(hr != S_OK);
535 }
536 CloseHandle(pMon->hEvent);
537 }
538 else
539 {
540 DWORD winErr = GetLastError();
541 Log((__FUNCTION__": CreateEvent failed, winErr = (%d)", winErr));
542 hr = HRESULT_FROM_WIN32(winErr);
543 Assert(0);
544 Assert(hr != S_OK);
545 }
546
547 return hr;
548}
549
550HRESULT VBoxScreenMRunnerStop(PVBOXSCREENMONRUNNER pMon)
551{
552 if (!pMon->hThread)
553 return S_OK;
554
555 Assert(0);
556
557 HANDLE ahHandles[2];
558 ahHandles[0] = pMon->hThread;
559 ahHandles[1] = pMon->hEvent;
560 DWORD dwResult = WaitForMultipleObjects(2, ahHandles,
561 FALSE, /* BOOL bWaitAll */
562 INFINITE /* DWORD dwMilliseconds */
563 );
564 HRESULT hr = E_FAIL;
565 if (dwResult == WAIT_OBJECT_0 + 1) /* Event is signaled */
566 {
567 BOOL bResult = PostThreadMessage(pMon->idThread, WM_QUIT, 0, 0);
568 if (bResult)
569 {
570 DWORD dwErr = WaitForSingleObject(pMon->hThread, INFINITE);
571 if (dwErr == WAIT_OBJECT_0)
572 {
573 hr = S_OK;
574 }
575 else
576 {
577 DWORD winErr = GetLastError();
578 hr = HRESULT_FROM_WIN32(winErr);
579 Assert(0);
580 }
581 }
582 else
583 {
584 DWORD winErr = GetLastError();
585 Assert(winErr != ERROR_SUCCESS);
586 if (winErr == ERROR_INVALID_THREAD_ID)
587 {
588 hr = S_OK;
589 }
590 else
591 {
592 hr = HRESULT_FROM_WIN32(winErr);
593 Assert(0);
594 }
595 }
596 }
597 else if (dwResult == WAIT_OBJECT_0)
598 {
599 /* thread has terminated already */
600 hr = S_OK;
601 }
602 else
603 {
604 Assert(0);
605 }
606
607 if (hr == S_OK)
608 {
609 CloseHandle(pMon->hThread);
610 pMon->hThread = 0;
611 CloseHandle(pMon->hEvent);
612 pMon->hThread = 0;
613 }
614
615 return hr;
616}
617
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette