VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Miniport/wddm/VBoxVideoMisc.cpp@ 32766

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

wddm: multi-monitor fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.0 KB
Line 
1/*
2 * Copyright (C) 2010 Oracle Corporation
3 *
4 * This file is part of VirtualBox Open Source Edition (OSE), as
5 * available from http://www.virtualbox.org. This file is free software;
6 * you can redistribute it and/or modify it under the terms of the GNU
7 * General Public License (GPL) as published by the Free Software
8 * Foundation, in version 2 as it comes in the "COPYING" file of the
9 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
10 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
11 */
12
13#include "../VBoxVideo.h"
14#include "../Helper.h"
15
16#include <iprt/asm.h>
17
18#include <stdio.h>
19
20NTSTATUS vboxWddmHTableCreate(PVBOXWDDM_HTABLE pTbl, uint32_t cSize)
21{
22 memset(pTbl, 0, sizeof (*pTbl));
23 pTbl->paData = (PVOID*)vboxWddmMemAllocZero(sizeof (pTbl->paData[0]) * cSize);
24 if (pTbl->paData)
25 {
26 pTbl->cSize = cSize;
27 return STATUS_SUCCESS;
28 }
29 return STATUS_NO_MEMORY;
30}
31
32VOID vboxWddmHTableDestroy(PVBOXWDDM_HTABLE pTbl)
33{
34 vboxWddmMemFree(pTbl->paData);
35}
36
37DECLINLINE(VBOXWDDM_HANDLE) vboxWddmHTableIndex2Handle(uint32_t iIndex)
38{
39 return iIndex+1;
40}
41
42DECLINLINE(uint32_t) vboxWddmHTableHandle2Index(VBOXWDDM_HANDLE hHandle)
43{
44 return hHandle-1;
45}
46
47NTSTATUS vboxWddmHTableRealloc(PVBOXWDDM_HTABLE pTbl, uint32_t cNewSize)
48{
49 Assert(cNewSize > pTbl->cSize);
50 if (cNewSize > pTbl->cSize)
51 {
52 PVOID *pvNewData = (PVOID*)vboxWddmMemAllocZero(sizeof (pTbl->paData[0]) * cNewSize);
53 memcpy(pvNewData, pTbl->paData, sizeof (pTbl->paData[0]) * pTbl->cSize);
54 pTbl->iNext2Search = pTbl->cSize;
55 pTbl->cSize = cNewSize;
56 pTbl->paData = pvNewData;
57 return STATUS_SUCCESS;
58 }
59 else if (cNewSize >= pTbl->cData)
60 return STATUS_NOT_IMPLEMENTED;
61 return STATUS_INVALID_PARAMETER;
62
63}
64VBOXWDDM_HANDLE vboxWddmHTablePut(PVBOXWDDM_HTABLE pTbl, PVOID pvData)
65{
66 if (pTbl->cSize == pTbl->cData)
67 {
68 Assert(0);
69 NTSTATUS Status = vboxWddmHTableRealloc(pTbl, pTbl->cSize + RT_MAX(10, pTbl->cSize/4));
70 Assert(Status == STATUS_SUCCESS);
71 if (Status != STATUS_SUCCESS)
72 return VBOXWDDM_HANDLE_INVALID;
73 }
74 for (UINT i = pTbl->iNext2Search; ; ++i, i %= pTbl->cSize)
75 {
76 Assert(i < pTbl->cSize);
77 if (!pTbl->paData[i])
78 {
79 pTbl->paData[i] = pvData;
80 ++pTbl->cData;
81 Assert(pTbl->cData <= pTbl->cSize);
82 ++pTbl->iNext2Search;
83 pTbl->iNext2Search %= pTbl->cSize;
84 return vboxWddmHTableIndex2Handle(i);
85 }
86 }
87 Assert(0);
88 return VBOXWDDM_HANDLE_INVALID;
89}
90
91PVOID vboxWddmHTableRemove(PVBOXWDDM_HTABLE pTbl, VBOXWDDM_HANDLE hHandle)
92{
93 uint32_t iIndex = vboxWddmHTableHandle2Index(hHandle);
94 Assert(iIndex < pTbl->cSize);
95 if (iIndex < pTbl->cSize)
96 {
97 PVOID pvData = pTbl->paData[iIndex];
98 pTbl->paData[iIndex] = NULL;
99 --pTbl->cData;
100 Assert(pTbl->cData <= pTbl->cSize);
101 pTbl->iNext2Search = iIndex;
102 return pvData;
103 }
104 return NULL;
105}
106
107PVOID vboxWddmHTableGet(PVBOXWDDM_HTABLE pTbl, VBOXWDDM_HANDLE hHandle)
108{
109 uint32_t iIndex = vboxWddmHTableHandle2Index(hHandle);
110 Assert(iIndex < pTbl->cSize);
111 if (iIndex < pTbl->cSize)
112 return pTbl->paData[iIndex];
113 return NULL;
114}
115
116VOID vboxWddmHTableIterInit(PVBOXWDDM_HTABLE pTbl, PVBOXWDDM_HTABLE_ITERATOR pIter)
117{
118 pIter->pTbl = pTbl;
119 pIter->iCur = ~0UL;
120 pIter->cLeft = pTbl->cData;
121}
122
123BOOL vboxWddmHTableIterHasNext(PVBOXWDDM_HTABLE_ITERATOR pIter)
124{
125 return pIter->cLeft;
126}
127
128
129PVOID vboxWddmHTableIterNext(PVBOXWDDM_HTABLE_ITERATOR pIter, VBOXWDDM_HANDLE *phHandle)
130{
131 if (vboxWddmHTableIterHasNext(pIter))
132 {
133 for (uint32_t i = pIter->iCur+1; i < pIter->pTbl->cSize ; ++i)
134 {
135 if (pIter->pTbl->paData[i])
136 {
137 pIter->iCur = i;
138 --pIter->cLeft;
139 VBOXWDDM_HANDLE hHandle = vboxWddmHTableIndex2Handle(i);
140 Assert(hHandle);
141 if (phHandle)
142 *phHandle = hHandle;
143 return pIter->pTbl->paData[i];
144 }
145 }
146 }
147
148 Assert(!vboxWddmHTableIterHasNext(pIter));
149 if (phHandle)
150 *phHandle = VBOXWDDM_HANDLE_INVALID;
151 return NULL;
152}
153
154
155PVOID vboxWddmHTableIterRemoveCur(PVBOXWDDM_HTABLE_ITERATOR pIter)
156{
157 VBOXWDDM_HANDLE hHandle = vboxWddmHTableIndex2Handle(pIter->iCur);
158 Assert(hHandle);
159 if (hHandle)
160 {
161 PVOID pRet = vboxWddmHTableRemove(pIter->pTbl, hHandle);
162 Assert(pRet);
163 return pRet;
164 }
165 return NULL;
166}
167
168PVBOXWDDM_SWAPCHAIN vboxWddmSwapchainCreate()
169{
170 PVBOXWDDM_SWAPCHAIN pSwapchain = (PVBOXWDDM_SWAPCHAIN)vboxWddmMemAllocZero(sizeof (VBOXWDDM_SWAPCHAIN));
171 Assert(pSwapchain);
172 if (pSwapchain)
173 {
174 InitializeListHead(&pSwapchain->AllocList);
175 pSwapchain->enmState = VBOXWDDM_OBJSTATE_TYPE_INITIALIZED;
176 pSwapchain->cRefs = 1;
177 }
178 return pSwapchain;
179}
180
181DECLINLINE(BOOLEAN) vboxWddmSwapchainRetainLocked(PVBOXWDDM_SWAPCHAIN pSwapchain)
182{
183 if (pSwapchain->enmState == VBOXWDDM_OBJSTATE_TYPE_INITIALIZED)
184 {
185 ASMAtomicIncU32(&pSwapchain->cRefs);
186 return TRUE;
187 }
188 return FALSE;
189}
190
191DECLINLINE(BOOLEAN) vboxWddmSwapchainRetain(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain)
192{
193 KIRQL OldIrql;
194 BOOLEAN bRc;
195 KeAcquireSpinLock(&pDevExt->SynchLock, &OldIrql);
196 bRc = vboxWddmSwapchainRetainLocked(pSwapchain);
197 KeReleaseSpinLock(&pDevExt->SynchLock, OldIrql);
198 return bRc;
199}
200
201DECLINLINE(VOID) vboxWddmSwapchainRelease(PVBOXWDDM_SWAPCHAIN pSwapchain)
202{
203 uint32_t cRefs = ASMAtomicDecU32(&pSwapchain->cRefs);
204 Assert(cRefs < UINT32_MAX/2);
205 if (!cRefs)
206 vboxWddmMemFree(pSwapchain);
207}
208
209PVBOXWDDM_SWAPCHAIN vboxWddmSwapchainRetainByAlloc(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_ALLOCATION pAlloc)
210{
211 KIRQL OldIrql;
212 PVBOXWDDM_SWAPCHAIN pSwapchain;
213 KeAcquireSpinLock(&pDevExt->SynchLock, &OldIrql);
214 pSwapchain = pAlloc->pSwapchain;
215 if (pSwapchain && !vboxWddmSwapchainRetainLocked(pSwapchain))
216 pSwapchain = NULL;
217 KeReleaseSpinLock(&pDevExt->SynchLock, OldIrql);
218 return pSwapchain;
219}
220
221VOID vboxWddmSwapchainAllocRemove(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain, PVBOXWDDM_ALLOCATION pAlloc)
222{
223 KIRQL OldIrql;
224 KeAcquireSpinLock(&pDevExt->SynchLock, &OldIrql);
225 Assert(pAlloc->pSwapchain == pSwapchain);
226 pAlloc->pSwapchain = NULL;
227 RemoveEntryList(&pAlloc->SwapchainEntry);
228 KeReleaseSpinLock(&pDevExt->SynchLock, OldIrql);
229 vboxWddmSwapchainRelease(pSwapchain);
230}
231
232BOOLEAN vboxWddmSwapchainAllocAdd(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain, PVBOXWDDM_ALLOCATION pAlloc)
233{
234 KIRQL OldIrql;
235 BOOLEAN bRc;
236 Assert(!pAlloc->pSwapchain);
237 KeAcquireSpinLock(&pDevExt->SynchLock, &OldIrql);
238 bRc = vboxWddmSwapchainRetainLocked(pSwapchain);
239 if (bRc)
240 {
241 if (pAlloc->pSwapchain)
242 {
243 RemoveEntryList(&pAlloc->SwapchainEntry);
244 }
245 InsertTailList(&pSwapchain->AllocList, &pAlloc->SwapchainEntry);
246 pAlloc->pSwapchain = pSwapchain;
247 }
248 KeReleaseSpinLock(&pDevExt->SynchLock, OldIrql);
249 return bRc;
250}
251
252#define VBOXSCENTRY_2_ALLOC(_pE) ((PVBOXWDDM_ALLOCATION)((uint8_t*)(_pE) - RT_OFFSETOF(VBOXWDDM_ALLOCATION, SwapchainEntry)))
253
254static VOID vboxWddmSwapchainAllocRemoveAllInternal(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain, BOOLEAN bOnDestroy)
255{
256 KIRQL OldIrql;
257 UINT cRemoved = 0;
258 KeAcquireSpinLock(&pDevExt->SynchLock, &OldIrql);
259 PLIST_ENTRY pEntry = pSwapchain->AllocList.Flink;
260 do
261 {
262 if (pEntry != &pSwapchain->AllocList)
263 {
264 PVBOXWDDM_ALLOCATION pAlloc = VBOXSCENTRY_2_ALLOC(pEntry);
265 pEntry = pEntry->Flink;
266 Assert(pAlloc->pSwapchain == pSwapchain);
267 pAlloc->pSwapchain = NULL;
268 RemoveEntryList(&pAlloc->SwapchainEntry);
269 ++cRemoved;
270 }
271 else
272 break;
273 } while (1);
274
275 if (bOnDestroy)
276 pSwapchain->enmState = VBOXWDDM_OBJSTATE_TYPE_TERMINATED;
277 KeReleaseSpinLock(&pDevExt->SynchLock, OldIrql);
278
279 for (UINT i = 0; i < cRemoved; ++i)
280 vboxWddmSwapchainRelease(pSwapchain);
281}
282
283VOID vboxWddmSwapchainAllocRemoveAll(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain)
284{
285 vboxWddmSwapchainAllocRemoveAllInternal(pDevExt, pSwapchain, FALSE);
286}
287
288VOID vboxWddmSwapchainDestroy(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_SWAPCHAIN pSwapchain)
289{
290 vboxWddmSwapchainAllocRemoveAllInternal(pDevExt, pSwapchain, TRUE);
291 vboxWddmSwapchainRelease(pSwapchain);
292}
293
294static BOOLEAN vboxWddmSwapchainCtxAddLocked(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXWDDM_SWAPCHAIN pSwapchain)
295{
296 if (vboxWddmSwapchainRetain(pDevExt, pSwapchain))
297 {
298 Assert(!pSwapchain->hSwapchainKm);
299 Assert(!pSwapchain->pContext);
300 pSwapchain->pContext = pContext;
301 pSwapchain->hSwapchainKm = vboxWddmHTablePut(&pContext->Swapchains, pSwapchain);
302 InsertHeadList(&pDevExt->SwapchainList3D, &pSwapchain->DevExtListEntry);
303 return TRUE;
304 }
305 return FALSE;
306}
307
308static VOID vboxWddmSwapchainCtxRemoveLocked(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXWDDM_SWAPCHAIN pSwapchain)
309{
310 Assert(pSwapchain->hSwapchainKm);
311 Assert(pSwapchain->pContext);
312 void * pTst = vboxWddmHTableRemove(&pContext->Swapchains, pSwapchain->hSwapchainKm);
313 Assert(pTst == pSwapchain);
314 RemoveEntryList(&pSwapchain->DevExtListEntry);
315 pSwapchain->pContext = NULL;
316 pSwapchain->hSwapchainKm = NULL;
317 if (pSwapchain->pLastReportedRects)
318 {
319 vboxVideoCmCmdRelease(pSwapchain->pLastReportedRects);
320 pSwapchain->pLastReportedRects = NULL;
321 }
322 vboxWddmSwapchainRelease(pSwapchain);
323}
324
325BOOLEAN vboxWddmSwapchainCtxAdd(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXWDDM_SWAPCHAIN pSwapchain)
326{
327 BOOLEAN bRc;
328 ExAcquireFastMutex(&pDevExt->ContextMutex);
329 bRc = vboxWddmSwapchainCtxAddLocked(pDevExt, pContext, pSwapchain);
330 ExReleaseFastMutex(&pDevExt->ContextMutex);
331 return bRc;
332}
333
334VOID vboxWddmSwapchainCtxRemove(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXWDDM_SWAPCHAIN pSwapchain)
335{
336 ExAcquireFastMutex(&pDevExt->ContextMutex);
337 vboxWddmSwapchainCtxRemoveLocked(pDevExt, pContext, pSwapchain);
338 ExReleaseFastMutex(&pDevExt->ContextMutex);
339}
340
341VOID vboxWddmSwapchainCtxDestroyAll(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_CONTEXT pContext)
342{
343 VBOXWDDM_HTABLE_ITERATOR Iter;
344 ExAcquireFastMutex(&pDevExt->ContextMutex);
345 vboxWddmHTableIterInit(&pContext->Swapchains, &Iter);
346 do
347 {
348 PVBOXWDDM_SWAPCHAIN pSwapchain = (PVBOXWDDM_SWAPCHAIN)vboxWddmHTableIterNext(&Iter, NULL);
349 if (!pSwapchain)
350 break;
351
352 /* yes, we can call remove locked even when using iterator */
353 vboxWddmSwapchainCtxRemoveLocked(pDevExt, pContext, pSwapchain);
354// vboxWddmHTableIterRemoveCur(&Iter);
355
356 vboxWddmSwapchainDestroy(pDevExt, pSwapchain);
357 } while (1);
358 ExReleaseFastMutex(&pDevExt->ContextMutex);
359}
360
361NTSTATUS vboxWddmSwapchainCtxEscape(PDEVICE_EXTENSION pDevExt, PVBOXWDDM_CONTEXT pContext, PVBOXDISPIFESCAPE_SWAPCHAININFO pSwapchainInfo, UINT cbSize)
362{
363 Assert((cbSize >= RT_OFFSETOF(VBOXDISPIFESCAPE_SWAPCHAININFO, SwapchainInfo.ahAllocs[0])));
364 if (cbSize < RT_OFFSETOF(VBOXDISPIFESCAPE_SWAPCHAININFO, SwapchainInfo.ahAllocs[0]))
365 return STATUS_INVALID_PARAMETER;
366 Assert(cbSize >= RT_OFFSETOF(VBOXDISPIFESCAPE_SWAPCHAININFO, SwapchainInfo.ahAllocs[pSwapchainInfo->SwapchainInfo.cAllocs]));
367 if (cbSize < RT_OFFSETOF(VBOXDISPIFESCAPE_SWAPCHAININFO, SwapchainInfo.ahAllocs[pSwapchainInfo->SwapchainInfo.cAllocs]))
368 return STATUS_INVALID_PARAMETER;
369
370 PVBOXWDDM_SWAPCHAIN pSwapchain;
371 PVBOXWDDM_ALLOCATION *apAlloc = NULL;
372 if (pSwapchainInfo->SwapchainInfo.cAllocs)
373 {
374 apAlloc = (PVBOXWDDM_ALLOCATION *)vboxWddmMemAlloc(sizeof (PVBOXWDDM_ALLOCATION) * pSwapchainInfo->SwapchainInfo.cAllocs);
375 Assert(apAlloc);
376 if (!apAlloc)
377 return STATUS_NO_MEMORY;
378 for (UINT i = 0; i < pSwapchainInfo->SwapchainInfo.cAllocs; ++i)
379 {
380 DXGKARGCB_GETHANDLEDATA GhData;
381 GhData.hObject = pSwapchainInfo->SwapchainInfo.ahAllocs[i];
382 GhData.Type = DXGK_HANDLE_ALLOCATION;
383 GhData.Flags.Value = 0;
384 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pDevExt->u.primary.DxgkInterface.DxgkCbGetHandleData(&GhData);
385 Assert(pAlloc);
386 if (!pAlloc)
387 return STATUS_INVALID_PARAMETER;
388 apAlloc[i] = pAlloc;
389 }
390 }
391
392 if (pSwapchainInfo->SwapchainInfo.hSwapchainKm)
393 {
394// ExAcquireFastMutex(&pContext->SwapchainMutex);
395 ExAcquireFastMutex(&pDevExt->ContextMutex);
396 pSwapchain = (PVBOXWDDM_SWAPCHAIN)vboxWddmHTableGet(&pContext->Swapchains, (VBOXWDDM_HANDLE)pSwapchainInfo->SwapchainInfo.hSwapchainKm);
397 Assert(pSwapchain);
398 if (!pSwapchain)
399 {
400 ExReleaseFastMutex(&pDevExt->ContextMutex);
401 return STATUS_INVALID_PARAMETER;
402 }
403 Assert(pSwapchain->hSwapchainKm == pSwapchainInfo->SwapchainInfo.hSwapchainKm);
404 Assert(pSwapchain->pContext == pContext);
405 if (pSwapchain->pContext != pContext)
406 {
407 ExReleaseFastMutex(&pDevExt->ContextMutex);
408 return STATUS_INVALID_PARAMETER;
409 }
410 }
411 else if (pSwapchainInfo->SwapchainInfo.cAllocs)
412 {
413 pSwapchain = vboxWddmSwapchainCreate();
414 if (!pSwapchain)
415 return STATUS_NO_MEMORY;
416
417 ExAcquireFastMutex(&pDevExt->ContextMutex);
418 BOOLEAN bRc = vboxWddmSwapchainCtxAddLocked(pDevExt, pContext, pSwapchain);
419 Assert(bRc);
420 }
421 else
422 return STATUS_INVALID_PARAMETER;
423
424 memset(&pSwapchain->ViewRect, 0, sizeof (pSwapchain->ViewRect));
425 if (pSwapchain->pLastReportedRects)
426 {
427 vboxVideoCmCmdRelease(pSwapchain->pLastReportedRects);
428 pSwapchain->pLastReportedRects = NULL;
429 }
430
431 vboxWddmSwapchainAllocRemoveAll(pDevExt, pSwapchain);
432
433 if (pSwapchainInfo->SwapchainInfo.cAllocs)
434 {
435 for (UINT i = 0; i < pSwapchainInfo->SwapchainInfo.cAllocs; ++i)
436 {
437 vboxWddmSwapchainAllocAdd(pDevExt, pSwapchain, apAlloc[i]);
438 }
439 pSwapchain->hSwapchainUm = pSwapchainInfo->SwapchainInfo.hSwapchainUm;
440 }
441 else
442 {
443 vboxWddmSwapchainCtxRemoveLocked(pDevExt, pContext, pSwapchain);
444 }
445
446// ExReleaseFastMutex(&pContext->SwapchainMutex);
447 ExReleaseFastMutex(&pDevExt->ContextMutex);
448
449 if (pSwapchainInfo->SwapchainInfo.cAllocs)
450 {
451 Assert(pSwapchain->pContext);
452 Assert(pSwapchain->hSwapchainKm);
453 pSwapchainInfo->SwapchainInfo.hSwapchainKm = pSwapchain->hSwapchainKm;
454 }
455 else
456 {
457 vboxWddmSwapchainDestroy(pDevExt, pSwapchain);
458 pSwapchainInfo->SwapchainInfo.hSwapchainKm = 0;
459 }
460
461 return STATUS_SUCCESS;
462}
463
464#define VBOXWDDM_REG_DRVKEY_PREFIX L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\"
465
466NTSTATUS vboxWddmRegQueryDrvKeyName(PDEVICE_EXTENSION pDevExt, ULONG cbBuf, PWCHAR pBuf, PULONG pcbResult)
467{
468 WCHAR fallBackBuf[2];
469 PWCHAR pSuffix;
470 bool bFallback = false;
471
472 if (cbBuf > sizeof(VBOXWDDM_REG_DRVKEY_PREFIX))
473 {
474 memcpy(pBuf, VBOXWDDM_REG_DRVKEY_PREFIX, sizeof (VBOXWDDM_REG_DRVKEY_PREFIX));
475 pSuffix = pBuf + (sizeof (VBOXWDDM_REG_DRVKEY_PREFIX)-2)/2;
476 cbBuf -= sizeof (VBOXWDDM_REG_DRVKEY_PREFIX)-2;
477 }
478 else
479 {
480 pSuffix = fallBackBuf;
481 cbBuf = sizeof (fallBackBuf);
482 bFallback = true;
483 }
484
485 NTSTATUS Status = IoGetDeviceProperty (pDevExt->pPDO,
486 DevicePropertyDriverKeyName,
487 cbBuf,
488 pSuffix,
489 &cbBuf);
490 if (Status == STATUS_SUCCESS && bFallback)
491 Status = STATUS_BUFFER_TOO_SMALL;
492 if (Status == STATUS_BUFFER_TOO_SMALL)
493 *pcbResult = cbBuf + sizeof (VBOXWDDM_REG_DRVKEY_PREFIX)-2;
494
495 return Status;
496}
497
498#define VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_VISTA L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Control\\VIDEO\\"
499#define VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_WIN7 L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\UnitedVideo\\CONTROL\\VIDEO\\"
500
501#define VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_RELX L"Attach.RelativeX"
502#define VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_RELY L"Attach.RelativeY"
503#define VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_DESKTOP L"Attach.ToDesktop"
504
505NTSTATUS vboxWddmRegQueryDisplaySettingsKeyName(PDEVICE_EXTENSION pDevExt, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
506 ULONG cbBuf, PWCHAR pBuf, PULONG pcbResult)
507{
508 NTSTATUS Status = STATUS_SUCCESS;
509 PWCHAR pSuffix;
510 bool bFallback = false;
511 const WCHAR* pKeyPrefix;
512 UINT cbKeyPrefix;
513 winVersion_t ver = vboxQueryWinVersion();
514 if (ver == WINVISTA)
515 {
516 pKeyPrefix = VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_VISTA;
517 cbKeyPrefix = sizeof (VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_VISTA);
518 }
519 else
520 {
521 Assert(ver == WIN7);
522 pKeyPrefix = VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_WIN7;
523 cbKeyPrefix = sizeof (VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_WIN7);
524 }
525
526 ULONG cbResult = cbKeyPrefix + pDevExt->VideoGuid.Length + 2 + 8; // L"\\" + "XXXX"
527 if (cbBuf >= cbResult)
528 {
529 wcscpy(pBuf, pKeyPrefix);
530 pSuffix = pBuf + (cbKeyPrefix-2)/2;
531 memcpy(pSuffix, pDevExt->VideoGuid.Buffer, pDevExt->VideoGuid.Length);
532 pSuffix += pDevExt->VideoGuid.Length/2;
533 pSuffix[0] = L'\\';
534 pSuffix += 1;
535 swprintf(pSuffix, L"%04d", VidPnSourceId);
536 }
537 else
538 {
539 Status = STATUS_BUFFER_TOO_SMALL;
540 }
541
542 *pcbResult = cbResult;
543
544 return Status;
545}
546
547#define VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Video\\"
548#define VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY_SUBKEY L"\\Video"
549
550NTSTATUS vboxWddmRegQueryVideoGuidString(ULONG cbBuf, PWCHAR pBuf, PULONG pcbResult)
551{
552 HANDLE hKey;
553 NTSTATUS Status = vboxWddmRegOpenKey(&hKey, VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY, GENERIC_READ);
554 Assert(Status == STATUS_SUCCESS);
555 if (Status == STATUS_SUCCESS)
556 {
557 struct
558 {
559 KEY_BASIC_INFORMATION Name;
560 WCHAR Buf[256];
561 } Buf;
562 WCHAR KeyBuf[sizeof (VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY)/2 + 256 + 64];
563 wcscpy(KeyBuf, VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY);
564 ULONG ResultLength;
565 BOOL bFound = FALSE;
566 for (ULONG i = 0; !bFound; ++i)
567 {
568 RtlZeroMemory(&Buf, sizeof (Buf));
569 Status = ZwEnumerateKey(hKey, i, KeyBasicInformation, &Buf, sizeof (Buf), &ResultLength);
570 Assert(Status == STATUS_SUCCESS);
571 /* we should not encounter STATUS_NO_MORE_ENTRIES here since this would mean we did not find our entry */
572 if (Status != STATUS_SUCCESS)
573 break;
574
575 HANDLE hSubKey;
576 PWCHAR pSubBuf = KeyBuf + (sizeof (VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY) - 2)/2;
577 memcpy(pSubBuf, Buf.Name.Name, Buf.Name.NameLength);
578 pSubBuf += Buf.Name.NameLength/2;
579 memcpy(pSubBuf, VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY_SUBKEY, sizeof (VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY_SUBKEY));
580 Status = vboxWddmRegOpenKey(&hSubKey, KeyBuf, GENERIC_READ);
581 Assert(Status == STATUS_SUCCESS);
582 if (Status == STATUS_SUCCESS)
583 {
584 struct
585 {
586 KEY_VALUE_PARTIAL_INFORMATION Info;
587 UCHAR Buf[sizeof (L"VBoxVideoWddm")]; /* should be enough */
588 } KeyData;
589 ULONG cbResult;
590 UNICODE_STRING RtlStr;
591 RtlInitUnicodeString(&RtlStr, L"Service");
592 Status = ZwQueryValueKey(hSubKey,
593 &RtlStr,
594 KeyValuePartialInformation,
595 &KeyData.Info,
596 sizeof(KeyData),
597 &cbResult);
598 Assert(Status == STATUS_SUCCESS || STATUS_BUFFER_TOO_SMALL || STATUS_BUFFER_OVERFLOW);
599 if (Status == STATUS_SUCCESS)
600 {
601 if (KeyData.Info.Type == REG_SZ)
602 {
603 if (KeyData.Info.DataLength == sizeof (L"VBoxVideoWddm"))
604 {
605 if (!wcscmp(L"VBoxVideoWddm", (PWCHAR)KeyData.Info.Data))
606 {
607 bFound = TRUE;
608 *pcbResult = Buf.Name.NameLength + 2;
609 if (cbBuf >= Buf.Name.NameLength + 2)
610 {
611 memcpy(pBuf, Buf.Name.Name, Buf.Name.NameLength + 2);
612 }
613 else
614 {
615 Status = STATUS_BUFFER_TOO_SMALL;
616 }
617 }
618 }
619 }
620 }
621
622 NTSTATUS tmpStatus = ZwClose(hSubKey);
623 Assert(tmpStatus == STATUS_SUCCESS);
624 }
625 else
626 break;
627 }
628 NTSTATUS tmpStatus = ZwClose(hKey);
629 Assert(tmpStatus == STATUS_SUCCESS);
630 }
631
632 return Status;
633}
634
635NTSTATUS vboxWddmRegOpenKey(OUT PHANDLE phKey, IN PWCHAR pName, IN ACCESS_MASK fAccess)
636{
637 OBJECT_ATTRIBUTES ObjAttr;
638 UNICODE_STRING RtlStr;
639
640 RtlInitUnicodeString(&RtlStr, pName);
641 InitializeObjectAttributes(&ObjAttr, &RtlStr, OBJ_CASE_INSENSITIVE, NULL, NULL);
642
643 return ZwOpenKey(phKey, fAccess, &ObjAttr);
644}
645
646NTSTATUS vboxWddmRegOpenDisplaySettingsKey(IN PDEVICE_EXTENSION pDeviceExtension, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, OUT PHANDLE phKey)
647{
648 WCHAR Buf[512];
649 ULONG cbBuf = sizeof(Buf);
650 NTSTATUS Status = vboxWddmRegQueryDisplaySettingsKeyName(pDeviceExtension, VidPnSourceId, cbBuf, Buf, &cbBuf);
651 Assert(Status == STATUS_SUCCESS);
652 if (Status == STATUS_SUCCESS)
653 {
654 Status = vboxWddmRegOpenKey(phKey, Buf, GENERIC_READ);
655 Assert(Status == STATUS_SUCCESS);
656 if(Status == STATUS_SUCCESS)
657 return STATUS_SUCCESS;
658 }
659
660 /* fall-back to make the subsequent VBoxVideoCmnRegXxx calls treat the fail accordingly
661 * basically needed to make as less modifications to the current XPDM code as possible */
662 *phKey = NULL;
663
664 return Status;
665}
666
667NTSTATUS vboxWddmRegDisplaySettingsQueryRelX(HANDLE hKey, int * pResult)
668{
669 DWORD dwVal;
670 NTSTATUS Status = vboxWddmRegQueryValueDword(hKey, VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_RELX, &dwVal);
671 Assert(Status == STATUS_SUCCESS);
672 if (Status == STATUS_SUCCESS)
673 {
674 *pResult = (int)dwVal;
675 }
676
677 return Status;
678}
679
680NTSTATUS vboxWddmRegDisplaySettingsQueryRelY(HANDLE hKey, int * pResult)
681{
682 DWORD dwVal;
683 NTSTATUS Status = vboxWddmRegQueryValueDword(hKey, VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_RELY, &dwVal);
684 Assert(Status == STATUS_SUCCESS);
685 if (Status == STATUS_SUCCESS)
686 {
687 *pResult = (int)dwVal;
688 }
689
690 return Status;
691}
692
693NTSTATUS vboxWddmDisplaySettingsQueryPos(IN PDEVICE_EXTENSION pDeviceExtension, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, POINT * pPos)
694{
695 HANDLE hKey;
696 NTSTATUS Status = vboxWddmRegOpenDisplaySettingsKey(pDeviceExtension, VidPnSourceId, &hKey);
697 Assert(Status == STATUS_SUCCESS);
698 if (Status == STATUS_SUCCESS)
699 {
700 int x, y;
701 Status = vboxWddmRegDisplaySettingsQueryRelX(hKey, &x);
702 Assert(Status == STATUS_SUCCESS);
703 if (Status == STATUS_SUCCESS)
704 {
705 Status = vboxWddmRegDisplaySettingsQueryRelY(hKey, &y);
706 Assert(Status == STATUS_SUCCESS);
707 if (Status == STATUS_SUCCESS)
708 {
709 pPos->x = x;
710 pPos->y = y;
711 }
712 }
713 NTSTATUS tmpStatus = ZwClose(hKey);
714 Assert(tmpStatus == STATUS_SUCCESS);
715 }
716 return Status;
717}
718
719NTSTATUS vboxWddmRegQueryValueDword(IN HANDLE hKey, IN PWCHAR pName, OUT PDWORD pDword)
720{
721 struct
722 {
723 KEY_VALUE_PARTIAL_INFORMATION Info;
724 UCHAR Buf[32]; /* should be enough */
725 } Buf;
726 ULONG cbBuf;
727 UNICODE_STRING RtlStr;
728 RtlInitUnicodeString(&RtlStr, pName);
729 NTSTATUS Status = ZwQueryValueKey(hKey,
730 &RtlStr,
731 KeyValuePartialInformation,
732 &Buf.Info,
733 sizeof(Buf),
734 &cbBuf);
735 if (Status == STATUS_SUCCESS)
736 {
737 if (Buf.Info.Type == REG_DWORD)
738 {
739 Assert(Buf.Info.DataLength == 4);
740 *pDword = *((PULONG)Buf.Info.Data);
741 return STATUS_SUCCESS;
742 }
743 }
744
745 return STATUS_INVALID_PARAMETER;
746}
747
748NTSTATUS vboxWddmRegSetValueDword(IN HANDLE hKey, IN PWCHAR pName, OUT DWORD val)
749{
750 UNICODE_STRING RtlStr;
751 RtlInitUnicodeString(&RtlStr, pName);
752 return ZwSetValueKey(hKey, &RtlStr,
753 NULL, /* IN ULONG TitleIndex OPTIONAL, reserved */
754 REG_DWORD,
755 &val,
756 sizeof(val));
757}
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