VirtualBox

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

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

wddm: bugfix

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.1 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 UNICODE_STRING* pVGuid = vboxWddmVGuidGet(pDevExt);
514 Assert(pVGuid);
515 if (!pVGuid)
516 return STATUS_UNSUCCESSFUL;
517
518 winVersion_t ver = vboxQueryWinVersion();
519 if (ver == WINVISTA)
520 {
521 pKeyPrefix = VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_VISTA;
522 cbKeyPrefix = sizeof (VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_VISTA);
523 }
524 else
525 {
526 Assert(ver == WIN7);
527 pKeyPrefix = VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_WIN7;
528 cbKeyPrefix = sizeof (VBOXWDDM_REG_DISPLAYSETTINGSKEY_PREFIX_WIN7);
529 }
530
531 ULONG cbResult = cbKeyPrefix + pVGuid->Length + 2 + 8; // L"\\" + "XXXX"
532 if (cbBuf >= cbResult)
533 {
534 wcscpy(pBuf, pKeyPrefix);
535 pSuffix = pBuf + (cbKeyPrefix-2)/2;
536 memcpy(pSuffix, pVGuid->Buffer, pVGuid->Length);
537 pSuffix += pVGuid->Length/2;
538 pSuffix[0] = L'\\';
539 pSuffix += 1;
540 swprintf(pSuffix, L"%04d", VidPnSourceId);
541 }
542 else
543 {
544 Status = STATUS_BUFFER_TOO_SMALL;
545 }
546
547 *pcbResult = cbResult;
548
549 return Status;
550}
551
552#define VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Video\\"
553#define VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY_SUBKEY L"\\Video"
554
555NTSTATUS vboxWddmRegQueryVideoGuidString(ULONG cbBuf, PWCHAR pBuf, PULONG pcbResult)
556{
557 HANDLE hKey;
558 NTSTATUS Status = vboxWddmRegOpenKey(&hKey, VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY, GENERIC_READ);
559 Assert(Status == STATUS_SUCCESS);
560 if (Status == STATUS_SUCCESS)
561 {
562 struct
563 {
564 KEY_BASIC_INFORMATION Name;
565 WCHAR Buf[256];
566 } Buf;
567 WCHAR KeyBuf[sizeof (VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY)/2 + 256 + 64];
568 wcscpy(KeyBuf, VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY);
569 ULONG ResultLength;
570 BOOL bFound = FALSE;
571 for (ULONG i = 0; !bFound; ++i)
572 {
573 RtlZeroMemory(&Buf, sizeof (Buf));
574 Status = ZwEnumerateKey(hKey, i, KeyBasicInformation, &Buf, sizeof (Buf), &ResultLength);
575 Assert(Status == STATUS_SUCCESS);
576 /* we should not encounter STATUS_NO_MORE_ENTRIES here since this would mean we did not find our entry */
577 if (Status != STATUS_SUCCESS)
578 break;
579
580 HANDLE hSubKey;
581 PWCHAR pSubBuf = KeyBuf + (sizeof (VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY) - 2)/2;
582 memcpy(pSubBuf, Buf.Name.Name, Buf.Name.NameLength);
583 pSubBuf += Buf.Name.NameLength/2;
584 memcpy(pSubBuf, VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY_SUBKEY, sizeof (VBOXWDDM_REG_DISPLAYSETTINGSVIDEOKEY_SUBKEY));
585 Status = vboxWddmRegOpenKey(&hSubKey, KeyBuf, GENERIC_READ);
586 Assert(Status == STATUS_SUCCESS);
587 if (Status == STATUS_SUCCESS)
588 {
589 struct
590 {
591 KEY_VALUE_PARTIAL_INFORMATION Info;
592 UCHAR Buf[sizeof (L"VBoxVideoWddm")]; /* should be enough */
593 } KeyData;
594 ULONG cbResult;
595 UNICODE_STRING RtlStr;
596 RtlInitUnicodeString(&RtlStr, L"Service");
597 Status = ZwQueryValueKey(hSubKey,
598 &RtlStr,
599 KeyValuePartialInformation,
600 &KeyData.Info,
601 sizeof(KeyData),
602 &cbResult);
603 Assert(Status == STATUS_SUCCESS || STATUS_BUFFER_TOO_SMALL || STATUS_BUFFER_OVERFLOW);
604 if (Status == STATUS_SUCCESS)
605 {
606 if (KeyData.Info.Type == REG_SZ)
607 {
608 if (KeyData.Info.DataLength == sizeof (L"VBoxVideoWddm"))
609 {
610 if (!wcscmp(L"VBoxVideoWddm", (PWCHAR)KeyData.Info.Data))
611 {
612 bFound = TRUE;
613 *pcbResult = Buf.Name.NameLength + 2;
614 if (cbBuf >= Buf.Name.NameLength + 2)
615 {
616 memcpy(pBuf, Buf.Name.Name, Buf.Name.NameLength + 2);
617 }
618 else
619 {
620 Status = STATUS_BUFFER_TOO_SMALL;
621 }
622 }
623 }
624 }
625 }
626
627 NTSTATUS tmpStatus = ZwClose(hSubKey);
628 Assert(tmpStatus == STATUS_SUCCESS);
629 }
630 else
631 break;
632 }
633 NTSTATUS tmpStatus = ZwClose(hKey);
634 Assert(tmpStatus == STATUS_SUCCESS);
635 }
636
637 return Status;
638}
639
640NTSTATUS vboxWddmRegOpenKey(OUT PHANDLE phKey, IN PWCHAR pName, IN ACCESS_MASK fAccess)
641{
642 OBJECT_ATTRIBUTES ObjAttr;
643 UNICODE_STRING RtlStr;
644
645 RtlInitUnicodeString(&RtlStr, pName);
646 InitializeObjectAttributes(&ObjAttr, &RtlStr, OBJ_CASE_INSENSITIVE, NULL, NULL);
647
648 return ZwOpenKey(phKey, fAccess, &ObjAttr);
649}
650
651NTSTATUS vboxWddmRegOpenDisplaySettingsKey(IN PDEVICE_EXTENSION pDeviceExtension, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, OUT PHANDLE phKey)
652{
653 WCHAR Buf[512];
654 ULONG cbBuf = sizeof(Buf);
655 NTSTATUS Status = vboxWddmRegQueryDisplaySettingsKeyName(pDeviceExtension, VidPnSourceId, cbBuf, Buf, &cbBuf);
656 Assert(Status == STATUS_SUCCESS);
657 if (Status == STATUS_SUCCESS)
658 {
659 Status = vboxWddmRegOpenKey(phKey, Buf, GENERIC_READ);
660 Assert(Status == STATUS_SUCCESS);
661 if(Status == STATUS_SUCCESS)
662 return STATUS_SUCCESS;
663 }
664
665 /* fall-back to make the subsequent VBoxVideoCmnRegXxx calls treat the fail accordingly
666 * basically needed to make as less modifications to the current XPDM code as possible */
667 *phKey = NULL;
668
669 return Status;
670}
671
672NTSTATUS vboxWddmRegDisplaySettingsQueryRelX(HANDLE hKey, int * pResult)
673{
674 DWORD dwVal;
675 NTSTATUS Status = vboxWddmRegQueryValueDword(hKey, VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_RELX, &dwVal);
676 Assert(Status == STATUS_SUCCESS);
677 if (Status == STATUS_SUCCESS)
678 {
679 *pResult = (int)dwVal;
680 }
681
682 return Status;
683}
684
685NTSTATUS vboxWddmRegDisplaySettingsQueryRelY(HANDLE hKey, int * pResult)
686{
687 DWORD dwVal;
688 NTSTATUS Status = vboxWddmRegQueryValueDword(hKey, VBOXWDDM_REG_DISPLAYSETTINGS_ATTACH_RELY, &dwVal);
689 Assert(Status == STATUS_SUCCESS);
690 if (Status == STATUS_SUCCESS)
691 {
692 *pResult = (int)dwVal;
693 }
694
695 return Status;
696}
697
698NTSTATUS vboxWddmDisplaySettingsQueryPos(IN PDEVICE_EXTENSION pDeviceExtension, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, POINT * pPos)
699{
700 Assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
701 HANDLE hKey;
702 NTSTATUS Status = vboxWddmRegOpenDisplaySettingsKey(pDeviceExtension, VidPnSourceId, &hKey);
703 Assert(Status == STATUS_SUCCESS);
704 if (Status == STATUS_SUCCESS)
705 {
706 int x, y;
707 Status = vboxWddmRegDisplaySettingsQueryRelX(hKey, &x);
708 Assert(Status == STATUS_SUCCESS);
709 if (Status == STATUS_SUCCESS)
710 {
711 Status = vboxWddmRegDisplaySettingsQueryRelY(hKey, &y);
712 Assert(Status == STATUS_SUCCESS);
713 if (Status == STATUS_SUCCESS)
714 {
715 pPos->x = x;
716 pPos->y = y;
717 }
718 }
719 NTSTATUS tmpStatus = ZwClose(hKey);
720 Assert(tmpStatus == STATUS_SUCCESS);
721 }
722 return Status;
723}
724
725NTSTATUS vboxWddmRegQueryValueDword(IN HANDLE hKey, IN PWCHAR pName, OUT PDWORD pDword)
726{
727 struct
728 {
729 KEY_VALUE_PARTIAL_INFORMATION Info;
730 UCHAR Buf[32]; /* should be enough */
731 } Buf;
732 ULONG cbBuf;
733 UNICODE_STRING RtlStr;
734 RtlInitUnicodeString(&RtlStr, pName);
735 NTSTATUS Status = ZwQueryValueKey(hKey,
736 &RtlStr,
737 KeyValuePartialInformation,
738 &Buf.Info,
739 sizeof(Buf),
740 &cbBuf);
741 if (Status == STATUS_SUCCESS)
742 {
743 if (Buf.Info.Type == REG_DWORD)
744 {
745 Assert(Buf.Info.DataLength == 4);
746 *pDword = *((PULONG)Buf.Info.Data);
747 return STATUS_SUCCESS;
748 }
749 }
750
751 return STATUS_INVALID_PARAMETER;
752}
753
754NTSTATUS vboxWddmRegSetValueDword(IN HANDLE hKey, IN PWCHAR pName, OUT DWORD val)
755{
756 UNICODE_STRING RtlStr;
757 RtlInitUnicodeString(&RtlStr, pName);
758 return ZwSetValueKey(hKey, &RtlStr,
759 NULL, /* IN ULONG TitleIndex OPTIONAL, reserved */
760 REG_DWORD,
761 &val,
762 sizeof(val));
763}
764
765UNICODE_STRING* vboxWddmVGuidGet(PDEVICE_EXTENSION pDevExt)
766{
767 if (pDevExt->VideoGuid.Buffer)
768 return &pDevExt->VideoGuid;
769
770 Assert(KeGetCurrentIrql() == PASSIVE_LEVEL);
771 WCHAR VideoGuidBuf[512];
772 ULONG cbVideoGuidBuf = sizeof (VideoGuidBuf);
773 NTSTATUS Status = vboxWddmRegQueryVideoGuidString(cbVideoGuidBuf, VideoGuidBuf, &cbVideoGuidBuf);
774 Assert(Status == STATUS_SUCCESS);
775 if (Status == STATUS_SUCCESS)
776 {
777 PWCHAR pBuf = (PWCHAR)vboxWddmMemAllocZero(cbVideoGuidBuf);
778 Assert(pBuf);
779 if (pBuf)
780 {
781 memcpy(pBuf, VideoGuidBuf, cbVideoGuidBuf);
782 RtlInitUnicodeString(&pDevExt->VideoGuid, pBuf);
783 return &pDevExt->VideoGuid;
784 }
785 }
786
787 return NULL;
788}
789
790VOID vboxWddmVGuidFree(PDEVICE_EXTENSION pDevExt)
791{
792 if (pDevExt->VideoGuid.Buffer)
793 {
794 vboxWddmMemFree(pDevExt->VideoGuid.Buffer);
795 pDevExt->VideoGuid.Buffer = NULL;
796 }
797}
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