VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/xpdm/VBoxDispDriver.cpp@ 52476

Last change on this file since 52476 was 52476, checked in by vboxsync, 10 years ago

VBoxDisp: Parfait warning.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 36.4 KB
Line 
1/* $Id: VBoxDispDriver.cpp 52476 2014-08-22 14:41:54Z vboxsync $ */
2
3/** @file
4 * VBox XPDM Display driver interface functions
5 */
6
7/*
8 * Copyright (C) 2011-2012 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include "VBoxDisp.h"
20#include "VBoxDispMini.h"
21#include "VBoxDispDDraw.h"
22#include <iprt/initterm.h>
23
24/* Engine version we're running on, set in DrvEnableDriver */
25static ULONG g_EngineVersionDDI = DDI_DRIVER_VERSION_NT4;
26
27/* Callback function supported by our driver, stored in index/address pairs (see winddi.h) */
28/* NT4 version */
29static DRVFN g_aDrvFnTableNT4[] =
30{
31 /* Required functions */
32 {INDEX_DrvGetModes, (PFN) VBoxDispDrvGetModes },
33 {INDEX_DrvEnablePDEV, (PFN) VBoxDispDrvEnablePDEV },
34 {INDEX_DrvCompletePDEV, (PFN) VBoxDispDrvCompletePDEV },
35 {INDEX_DrvDisablePDEV, (PFN) VBoxDispDrvDisablePDEV },
36 {INDEX_DrvEnableSurface, (PFN) VBoxDispDrvEnableSurface },
37 {INDEX_DrvDisableSurface, (PFN) VBoxDispDrvDisableSurface },
38 {INDEX_DrvAssertMode, (PFN) VBoxDispDrvAssertMode },
39 /* Drawing commands */
40 {INDEX_DrvLineTo, (PFN) VBoxDispDrvLineTo },
41 {INDEX_DrvStrokePath, (PFN) VBoxDispDrvStrokePath },
42 {INDEX_DrvFillPath, (PFN) VBoxDispDrvFillPath },
43 {INDEX_DrvPaint, (PFN) VBoxDispDrvPaint },
44 {INDEX_DrvTextOut, (PFN) VBoxDispDrvTextOut },
45 {INDEX_DrvSaveScreenBits, (PFN) VBoxDispDrvSaveScreenBits },
46 /* BitBlt's*/
47 {INDEX_DrvBitBlt, (PFN) VBoxDispDrvBitBlt },
48 {INDEX_DrvStretchBlt, (PFN) VBoxDispDrvStretchBlt, },
49 {INDEX_DrvCopyBits, (PFN) VBoxDispDrvCopyBits },
50 /* Brush related */
51 {INDEX_DrvRealizeBrush, (PFN) VBoxDispDrvRealizeBrush },
52 {INDEX_DrvDitherColor, (PFN) VBoxDispDrvDitherColor },
53 /* Pointer related */
54 {INDEX_DrvSetPointerShape, (PFN) VBoxDispDrvSetPointerShape },
55 {INDEX_DrvMovePointer, (PFN) VBoxDispDrvMovePointer },
56 /* Misc */
57 {INDEX_DrvDisableDriver, (PFN) VBoxDispDrvDisableDriver },
58 {INDEX_DrvSetPalette, (PFN) VBoxDispDrvSetPalette },
59 {INDEX_DrvEscape, (PFN) VBoxDispDrvEscape },
60#ifdef VBOX_WITH_DDRAW
61 {INDEX_DrvGetDirectDrawInfo, (PFN) VBoxDispDrvGetDirectDrawInfo},
62 {INDEX_DrvEnableDirectDraw, (PFN) VBoxDispDrvEnableDirectDraw },
63 {INDEX_DrvDisableDirectDraw, (PFN) VBoxDispDrvDisableDirectDraw},
64#endif
65 /* g_aDrvFnTableNT4, NT4 specific */
66 {INDEX_DrvOffset, (PFN) VBoxDispDrvOffset } /*Obsolete*/
67};
68
69/* WIN2K+ version */
70static DRVFN g_aDrvFnTableNT5[] =
71{
72 /* Required functions */
73 {INDEX_DrvGetModes, (PFN) VBoxDispDrvGetModes },
74 {INDEX_DrvEnablePDEV, (PFN) VBoxDispDrvEnablePDEV },
75 {INDEX_DrvCompletePDEV, (PFN) VBoxDispDrvCompletePDEV },
76 {INDEX_DrvDisablePDEV, (PFN) VBoxDispDrvDisablePDEV },
77 {INDEX_DrvEnableSurface, (PFN) VBoxDispDrvEnableSurface },
78 {INDEX_DrvDisableSurface, (PFN) VBoxDispDrvDisableSurface },
79 {INDEX_DrvAssertMode, (PFN) VBoxDispDrvAssertMode },
80 /* Drawing commands */
81 {INDEX_DrvLineTo, (PFN) VBoxDispDrvLineTo },
82 {INDEX_DrvStrokePath, (PFN) VBoxDispDrvStrokePath },
83 {INDEX_DrvFillPath, (PFN) VBoxDispDrvFillPath },
84 {INDEX_DrvPaint, (PFN) VBoxDispDrvPaint },
85 {INDEX_DrvTextOut, (PFN) VBoxDispDrvTextOut },
86 {INDEX_DrvSaveScreenBits, (PFN) VBoxDispDrvSaveScreenBits },
87 /* BitBlt's*/
88 {INDEX_DrvBitBlt, (PFN) VBoxDispDrvBitBlt },
89 {INDEX_DrvStretchBlt, (PFN) VBoxDispDrvStretchBlt, },
90 {INDEX_DrvCopyBits, (PFN) VBoxDispDrvCopyBits },
91 /* Brush related */
92 {INDEX_DrvRealizeBrush, (PFN) VBoxDispDrvRealizeBrush },
93 {INDEX_DrvDitherColor, (PFN) VBoxDispDrvDitherColor },
94 /* Pointer related */
95 {INDEX_DrvSetPointerShape, (PFN) VBoxDispDrvSetPointerShape },
96 {INDEX_DrvMovePointer, (PFN) VBoxDispDrvMovePointer },
97 /* Misc */
98 {INDEX_DrvDisableDriver, (PFN) VBoxDispDrvDisableDriver },
99 {INDEX_DrvSetPalette, (PFN) VBoxDispDrvSetPalette },
100 {INDEX_DrvEscape, (PFN) VBoxDispDrvEscape },
101#ifdef VBOX_WITH_DDRAW
102 {INDEX_DrvGetDirectDrawInfo, (PFN) VBoxDispDrvGetDirectDrawInfo},
103 {INDEX_DrvEnableDirectDraw, (PFN) VBoxDispDrvEnableDirectDraw },
104 {INDEX_DrvDisableDirectDraw, (PFN) VBoxDispDrvDisableDirectDraw},
105#endif
106 /* g_aDrvFnTableNT5, NT5 specific */
107 {INDEX_DrvNotify, (PFN) VBoxDispDrvNotify },
108#ifdef VBOX_WITH_DDRAW
109 {INDEX_DrvDeriveSurface, (PFN) VBoxDispDrvDeriveSurface }
110#endif
111};
112
113#ifdef VBOX_WITH_CROGL
114typedef struct
115{
116 DWORD dwVersion;
117 DWORD dwDriverVersion;
118 WCHAR szDriverName[256];
119} OPENGL_INFO, *POPENGL_INFO;
120#endif
121
122RT_C_DECLS_BEGIN
123ULONG __cdecl DbgPrint(PCH pszFormat, ...)
124{
125 va_list args;
126 va_start(args, pszFormat);
127 RTLogBackdoorPrintfV(pszFormat, args);
128 va_end(args);
129
130 return 0;
131}
132RT_C_DECLS_END
133
134VOID _wcsncpy(WCHAR *pwcd, WCHAR *pwcs, ULONG dstsize)
135{
136 ULONG cnt=0;
137
138 while (*pwcs!=*L"")
139 {
140 if (cnt>=dstsize)
141 {
142 break;
143 }
144
145 *pwcd = *pwcs;
146
147 pwcs++;
148 pwcd++;
149 cnt ++;
150 }
151
152 if (cnt<dstsize)
153 {
154 memset(pwcd, 0, (dstsize-cnt) * sizeof(WCHAR));
155 }
156}
157
158#define VBOXDISPSETCIEC(_ciec, _x, _y, _lum) \
159 do { \
160 _ciec.x = _x; \
161 _ciec.y = _y; \
162 _ciec.Y = _lum; \
163 } while (0)
164
165
166#define VBOXDISPMAKELOGFONTW(_font, _w, _h, _weight, _clip, _quality, _pitch, _name) \
167 do { \
168 _font.lfHeight = _w; \
169 _font.lfWidth = _h; \
170 _font.lfEscapement = 0; \
171 _font.lfOrientation = 0; \
172 _font.lfWeight = _weight; \
173 _font.lfItalic = 0; \
174 _font.lfUnderline = 0; \
175 _font.lfStrikeOut = 0; \
176 _font.lfCharSet = ANSI_CHARSET; \
177 _font.lfOutPrecision = OUT_DEFAULT_PRECIS; \
178 _font.lfClipPrecision = _clip; \
179 _font.lfQuality = _quality; \
180 _font.lfPitchAndFamily = (_pitch) | FF_DONTCARE; \
181 memset(_font.lfFaceName, 0, sizeof(_font.lfFaceName)); \
182 memcpy(_font.lfFaceName, _name, sizeof(_name)); \
183 } while (0)
184
185static int VBoxDispInitDevice(PVBOXDISPDEV pDev, DEVMODEW *pdm, GDIINFO *pGdiInfo, DEVINFO *pDevInfo)
186{
187 VIDEO_MODE_INFORMATION *pModesTable = NULL, selectedMode;
188 ULONG cModes, i=0;
189 int rc;
190
191 LOGF_ENTER();
192
193 memset(&selectedMode, 0, sizeof(VIDEO_MODE_INFORMATION));
194
195 /* Get a list of supported modes by both miniport and display driver */
196 rc = VBoxDispMPGetVideoModes(pDev->hDriver, &pModesTable, &cModes);
197 VBOX_WARNRC_RETRC(rc);
198
199 /* Check if requested mode is available in the list */
200 if ((g_EngineVersionDDI < DDI_DRIVER_VERSION_NT5)
201 && (pdm->dmBitsPerPel==0)
202 && (pdm->dmPelsWidth==0)
203 && (pdm->dmPelsHeight==0)
204 && (pdm->dmDisplayFrequency==0))
205 {
206 /* Special case for NT4, just return default(first) mode */
207 memcpy(&selectedMode, &pModesTable[0], sizeof(VIDEO_MODE_INFORMATION));
208 }
209 else
210 {
211 for (; i<cModes; ++i)
212 {
213 if ((pdm->dmBitsPerPel == (pModesTable[i].BitsPerPlane * pModesTable[i].NumberOfPlanes))
214 && (pdm->dmPelsWidth == pModesTable[i].VisScreenWidth)
215 && (pdm->dmPelsHeight == pModesTable[i].VisScreenHeight)
216 && (pdm->dmDisplayFrequency == pModesTable[i].Frequency))
217 {
218 memcpy(&selectedMode, &pModesTable[i], sizeof(VIDEO_MODE_INFORMATION));
219 break;
220 }
221 }
222 }
223 EngFreeMem(pModesTable);
224
225 if (i>=cModes)
226 {
227 WARN(("can't support requested mode %dx%d@%dbpp(%dHz)!",
228 pdm->dmPelsWidth, pdm->dmPelsHeight, pdm->dmBitsPerPel, pdm->dmDisplayFrequency));
229 return VERR_NOT_SUPPORTED;
230 }
231
232 LOG(("match for requested mode %dx%d@%dbpp(%dHz)",
233 selectedMode.VisScreenWidth, selectedMode.VisScreenHeight, selectedMode.BitsPerPlane, selectedMode.Frequency));
234
235 /* Update private device info with mode information */
236 pDev->mode.ulIndex = selectedMode.ModeIndex;
237 pDev->mode.ulWidth = selectedMode.VisScreenWidth;
238 pDev->mode.ulHeight = selectedMode.VisScreenHeight;
239 pDev->mode.ulBitsPerPel = selectedMode.BitsPerPlane * selectedMode.NumberOfPlanes;
240 pDev->mode.lScanlineStride = selectedMode.ScreenStride;
241 pDev->mode.flMaskR = selectedMode.RedMask;
242 pDev->mode.flMaskG = selectedMode.GreenMask;
243 pDev->mode.flMaskB = selectedMode.BlueMask;
244 pDev->mode.ulPaletteShift = (pDev->mode.ulBitsPerPel==8) ? (8-selectedMode.NumberRedBits) : 0;
245
246 /* Fill GDIINFO structure */
247 memset(pGdiInfo, 0, sizeof(GDIINFO));
248
249 pGdiInfo->ulVersion = (g_EngineVersionDDI<DDI_DRIVER_VERSION_NT5) ? GDI_DRIVER_VERSION:0x5000;
250 pGdiInfo->ulVersion |= VBOXDISPDRIVERVERSION;
251
252 pGdiInfo->ulTechnology = DT_RASDISPLAY;
253
254 pGdiInfo->ulHorzSize = selectedMode.XMillimeter;
255 pGdiInfo->ulVertSize = selectedMode.YMillimeter;
256
257 pGdiInfo->ulHorzRes = pDev->mode.ulWidth;
258 pGdiInfo->ulVertRes = pDev->mode.ulHeight;
259
260 pGdiInfo->cBitsPixel = pDev->mode.ulBitsPerPel;
261 pGdiInfo->cPlanes = selectedMode.NumberOfPlanes;
262
263 pGdiInfo->ulNumColors = (pDev->mode.ulBitsPerPel==8) ? 20 : ((ULONG)(-1));
264
265 pGdiInfo->ulLogPixelsX = pdm->dmLogPixels;
266 pGdiInfo->ulLogPixelsY = pdm->dmLogPixels;
267 if (pdm->dmLogPixels!=96)
268 {
269 WARN(("requested logical pixel res %d isn't 96", pdm->dmLogPixels));
270 }
271
272 pGdiInfo->flTextCaps = TC_RA_ABLE;
273
274 pGdiInfo->ulDACRed = selectedMode.NumberRedBits;
275 pGdiInfo->ulDACGreen = selectedMode.NumberGreenBits;
276 pGdiInfo->ulDACBlue = selectedMode.NumberBlueBits;
277
278 pGdiInfo->ulAspectX = 0x24;
279 pGdiInfo->ulAspectY = 0x24;
280 /* note: ulAspectXY should be square root of sum of squares of x and y aspects */
281 pGdiInfo->ulAspectXY = 0x33;
282
283 /* search for "styled cosmetic lines" on msdn for more info */
284 pGdiInfo->xStyleStep = 1;
285 pGdiInfo->yStyleStep = 1;
286 pGdiInfo->denStyleStep = 3;
287
288 pGdiInfo->ulNumPalReg = (pDev->mode.ulBitsPerPel==8) ? (1<<pDev->mode.ulBitsPerPel) : 0;
289
290 /* @todo: might want to implement IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES in miniport driver
291 * and query host for this info there
292 */
293 VBOXDISPSETCIEC(pGdiInfo->ciDevice.Red, 6700, 3300, 0);
294 VBOXDISPSETCIEC(pGdiInfo->ciDevice.Green, 2100, 7100, 0);
295 VBOXDISPSETCIEC(pGdiInfo->ciDevice.Blue, 1400, 800, 0);
296 VBOXDISPSETCIEC(pGdiInfo->ciDevice.AlignmentWhite, 3127, 3290, 0);
297 VBOXDISPSETCIEC(pGdiInfo->ciDevice.Cyan, 0, 0, 0);
298 VBOXDISPSETCIEC(pGdiInfo->ciDevice.Magenta, 0, 0, 0);
299 VBOXDISPSETCIEC(pGdiInfo->ciDevice.Yellow, 0, 0, 0);
300 pGdiInfo->ciDevice.RedGamma = 20000;
301 pGdiInfo->ciDevice.GreenGamma = 20000;
302 pGdiInfo->ciDevice.BlueGamma = 20000;
303
304 pGdiInfo->ulPrimaryOrder = PRIMARY_ORDER_CBA;
305
306 pGdiInfo->ulHTPatternSize = HT_PATSIZE_4x4_M;
307 switch (pDev->mode.ulBitsPerPel)
308 {
309 case 8:
310 {
311 pGdiInfo->ulHTOutputFormat = HT_FORMAT_8BPP;
312 break;
313 }
314 case 16:
315 {
316 pGdiInfo->ulHTOutputFormat = HT_FORMAT_16BPP;
317 break;
318 }
319 case 24:
320 {
321 pGdiInfo->ulHTOutputFormat = HT_FORMAT_24BPP;
322 break;
323 }
324 case 32:
325 {
326 pGdiInfo->ulHTOutputFormat = HT_FORMAT_32BPP;
327 break;
328 }
329 }
330 pGdiInfo->flHTFlags = HT_FLAG_ADDITIVE_PRIMS;
331
332 pGdiInfo->ulVRefresh = selectedMode.Frequency;
333
334 /* 0 means BitBlt's are accelerated by driver */
335 pGdiInfo->ulBltAlignment = 0;
336
337 pGdiInfo->ulPhysicalPixelCharacteristics = PPC_UNDEFINED;
338 pGdiInfo->ulPhysicalPixelGamma = PPG_DEFAULT;
339
340 /* Fill DEVINFO structure */
341 memset(pDevInfo, 0, sizeof(DEVINFO));
342
343 pDevInfo->flGraphicsCaps = GCAPS_OPAQUERECT;
344#ifdef VBOX_WITH_DDRAW
345 pDevInfo->flGraphicsCaps |= GCAPS_DIRECTDRAW;
346#endif
347 VBOXDISPMAKELOGFONTW(pDevInfo->lfDefaultFont,
348 16, 7, FW_BOLD, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, VARIABLE_PITCH, L"System");
349
350 VBOXDISPMAKELOGFONTW(pDevInfo->lfAnsiVarFont,
351 12, 9, FW_NORMAL, CLIP_STROKE_PRECIS, PROOF_QUALITY, VARIABLE_PITCH, L"MS Sans Serif");
352
353 VBOXDISPMAKELOGFONTW(pDevInfo->lfAnsiFixFont,
354 12, 9, FW_NORMAL, CLIP_STROKE_PRECIS, PROOF_QUALITY, FIXED_PITCH, L"Courier");
355 pDevInfo->cFonts = 0;
356 pDevInfo->cxDither = 8;
357 pDevInfo->cyDither = 8;
358 pDevInfo->hpalDefault = 0;
359 pDevInfo->flGraphicsCaps2 = 0;
360
361 switch (pDev->mode.ulBitsPerPel)
362 {
363 case 8:
364 {
365 pDevInfo->flGraphicsCaps |= GCAPS_PALMANAGED|GCAPS_COLOR_DITHER;
366 pDevInfo->iDitherFormat = BMF_8BPP;
367 break;
368 }
369 case 16:
370 {
371 pDevInfo->iDitherFormat = BMF_16BPP;
372 break;
373 }
374 case 24:
375 {
376 pDevInfo->iDitherFormat = BMF_24BPP;
377 break;
378 }
379 case 32:
380 {
381 pDevInfo->iDitherFormat = BMF_32BPP;
382 break;
383 }
384 }
385
386 LOGF_LEAVE();
387 return rc;
388}
389
390/* Display Driver entry point,
391 * Returns DDI version number and callbacks supported by driver.
392 */
393BOOL DrvEnableDriver(ULONG iEngineVersion, ULONG cj, PDRVENABLEDATA pded)
394{
395 /*@todo: can't link with hal.lib
396 int irc = RTR0Init(0);
397 if (RT_FAILURE(irc))
398 {
399 LOGREL(("failed to init IPRT (rc=%#x)", irc));
400 return FALSE;
401 }
402 */
403
404 LOGF(("iEngineVersion=%#08X, cj=%d", iEngineVersion, cj));
405
406 g_EngineVersionDDI = iEngineVersion;
407
408 /* Driver can't work if we can't fill atleast first 3 fields in passed PDRVENABLEDATA */
409 if (cj < (2*sizeof(ULONG)+sizeof(DRVFN*)))
410 {
411 WARN(("cj<%d, terminating\n", sizeof(DRVENABLEDATA)));
412 return FALSE;
413 }
414
415 /* Report driver DDI version and appropriate callbacks table based on engine DDI */
416 if (iEngineVersion>=DDI_DRIVER_VERSION_NT5)
417 {
418 /* WIN2K and above */
419 pded->iDriverVersion = DDI_DRIVER_VERSION_NT5;
420 pded->pdrvfn = g_aDrvFnTableNT5;
421 pded->c = RT_ELEMENTS(g_aDrvFnTableNT5);
422 }
423 else
424 {
425 /* NT4_SP3 and below*/
426 pded->iDriverVersion = DDI_DRIVER_VERSION_NT4;
427 pded->pdrvfn = g_aDrvFnTableNT4;
428 pded->c = RT_ELEMENTS(g_aDrvFnTableNT4);
429 }
430
431 LOGF_LEAVE();
432 return TRUE;
433}
434
435/* Free all resources allocated in DrvEnableDriver */
436VOID APIENTRY VBoxDispDrvDisableDriver()
437{
438 LOGF_ENTER();
439
440 /* Intentionally left blank */
441
442 LOGF_LEAVE();
443 return;
444}
445
446/* Returns video modes supported by our device/driver
447 * Note: If we fail here we'd be asked to enter 800x600@4bpp mode later in VBoxDispDrvEnablePDEV.
448 */
449ULONG APIENTRY VBoxDispDrvGetModes(HANDLE hDriver, ULONG cjSize, DEVMODEW *pdm)
450{
451 int rc;
452 VIDEO_MODE_INFORMATION *pModesTable;
453 ULONG cModes;
454 LOGF_ENTER();
455
456 rc = VBoxDispMPGetVideoModes(hDriver, &pModesTable, &cModes);
457 VBOX_WARNRC_RETV(rc, 0);
458
459 if (!pdm) /* return size of buffer required to store all supported modes */
460 {
461 EngFreeMem(pModesTable);
462 LOGF_LEAVE();
463 return cModes * sizeof(DEVMODEW);
464 }
465
466 ULONG mode, cMaxNodes=cjSize/sizeof(DEVMODEW);
467
468 for (mode=0; mode<cModes && mode<cMaxNodes; ++mode, ++pdm)
469 {
470 memset(pdm, 0, sizeof(DEVMODEW));
471 memcpy(pdm->dmDeviceName, VBOXDISP_DEVICE_NAME, sizeof(VBOXDISP_DEVICE_NAME));
472
473 pdm->dmSpecVersion = DM_SPECVERSION;
474 pdm->dmDriverVersion = DM_SPECVERSION;
475 pdm->dmSize = sizeof(DEVMODEW);
476 pdm->dmDriverExtra = 0;
477
478 pdm->dmBitsPerPel = pModesTable[mode].NumberOfPlanes*pModesTable[mode].BitsPerPlane;
479 pdm->dmPelsWidth = pModesTable[mode].VisScreenWidth;
480 pdm->dmPelsHeight = pModesTable[mode].VisScreenHeight;
481 pdm->dmDisplayFrequency = pModesTable[mode].Frequency;
482 pdm->dmDisplayFlags = 0;
483 pdm->dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFREQUENCY|DM_DISPLAYFLAGS;
484 }
485 EngFreeMem(pModesTable);
486
487 LOG(("%d mode(s) reported", mode));
488
489 LOGF_LEAVE();
490 return mode * sizeof(DEVMODEW);
491}
492
493/* First function which is called after entry point, provides info about device to GDI.
494 * Returns pointer to our driver private info structure which would be passed by GDI to our other callbacks.
495 */
496DHPDEV APIENTRY
497VBoxDispDrvEnablePDEV(DEVMODEW *pdm, LPWSTR pwszLogAddress, ULONG cPat, HSURF *phsurfPatterns,
498 ULONG cjCaps, ULONG *pdevcaps,
499 ULONG cjDevInfo, DEVINFO *pdi,
500 HDEV hdev, PWSTR pwszDeviceName, HANDLE hDriver)
501{
502 PVBOXDISPDEV pDev = NULL;
503 GDIINFO gdiInfo;
504 DEVINFO devInfo;
505 int rc;
506
507 /* Next 3 are only used for printer drivers */
508 NOREF(pwszLogAddress);
509 NOREF(cPat);
510 NOREF(phsurfPatterns);
511 NOREF(pwszDeviceName);
512
513 LOGF_ENTER();
514
515 pDev = (PVBOXDISPDEV) EngAllocMem(FL_ZERO_MEMORY, sizeof(VBOXDISPDEV), MEM_ALLOC_TAG);
516 if (!pDev)
517 {
518 WARN(("EngAllocMem failed!\n"));
519 return NULL;
520 }
521 pDev->hDriver = hDriver;
522
523 ULONG ulRegistryFlags = 0;
524 rc = VBoxDispMPQueryRegistryFlags(hDriver, &ulRegistryFlags);
525 if (RT_SUCCESS(rc))
526 {
527 pDev->bBitmapCacheDisabled = (ulRegistryFlags & VBOXVIDEO_REGISTRY_FLAGS_DISABLE_BITMAP_CACHE) != 0;
528 LOG(("Bitmap cache %s", pDev->bBitmapCacheDisabled? "disabled": "enabled"));
529 }
530
531 /* Initialize device structure and query miniport to fill device and gdi infos */
532 rc = VBoxDispInitDevice(pDev, pdm, &gdiInfo, &devInfo);
533 if (RT_FAILURE(rc))
534 {
535 VBOX_WARNRC(rc);
536 EngFreeMem(pDev);
537 return NULL;
538 }
539
540 /* Initialize mouse pointer caps */
541 rc = VBoxDispInitPointerCaps(pDev, &devInfo);
542 if (RT_FAILURE(rc))
543 {
544 VBOX_WARNRC(rc);
545 }
546
547 /* Initialize palette */
548 rc = VBoxDispInitPalette(pDev, &devInfo);
549 if (RT_FAILURE(rc))
550 {
551 VBOX_WARNRC(rc);
552 EngFreeMem(pDev);
553 return NULL;
554 }
555
556 if(g_EngineVersionDDI >= DDI_DRIVER_VERSION_NT5)
557 {
558 devInfo.flGraphicsCaps2 |= GCAPS2_RESERVED1;
559 }
560
561 /* Copy gathered info to supplied buffers */
562 memcpy(pdevcaps, &gdiInfo, min(sizeof(GDIINFO), cjCaps));
563 memcpy(pdi, &devInfo, min(sizeof(DEVINFO), cjDevInfo));
564
565 LOGF_LEAVE();
566 return (DHPDEV)pDev;
567}
568
569/* Called to provide us GDI handle for our device, which we should use later for GDI calls */
570VOID APIENTRY VBoxDispDrvCompletePDEV(DHPDEV dhpdev, HDEV hdev)
571{
572 LOGF_ENTER();
573
574 ((PVBOXDISPDEV)dhpdev)->hDevGDI = hdev;
575
576 LOGF_LEAVE();
577}
578
579/* Called to free resources allocated for device in VBoxDispDrvEnablePDEV */
580VOID APIENTRY VBoxDispDrvDisablePDEV(DHPDEV dhpdev)
581{
582 LOGF_ENTER();
583
584 VBoxDispDestroyPalette((PVBOXDISPDEV) dhpdev);
585
586 EngFreeMem(dhpdev);
587
588 LOGF_LEAVE();
589}
590
591/* Called to create and associate surface with device */
592HSURF APIENTRY VBoxDispDrvEnableSurface(DHPDEV dhpdev)
593{
594 int rc;
595 PVBOXDISPDEV pDev = (PVBOXDISPDEV)dhpdev;
596
597 LOGF_ENTER();
598
599 /* Switch device to mode requested in VBoxDispDrvEnablePDEV */
600 rc = VBoxDispMPSetCurrentMode(pDev->hDriver, pDev->mode.ulIndex);
601 VBOX_WARNRC_RETV(rc, NULL);
602
603 /* Map fb and vram */
604 rc = VBoxDispMPMapMemory(pDev, &pDev->memInfo);
605 VBOX_WARNRC_RETV(rc, NULL);
606
607 /* Clear mapped memory, to avoid garbage while video mode is switching */
608 /* @todo: VIDEO_MODE_NO_ZERO_MEMORY does nothing in miniport's IOCTL_VIDEO_SET_CURRENT_MODE*/
609 memset(pDev->memInfo.FrameBufferBase, 0, pDev->mode.ulHeight * abs(pDev->mode.lScanlineStride));
610
611 /* Allocate memory for pointer attrs */
612 rc = VBoxDispInitPointerAttrs(pDev);
613 VBOX_WARNRC_RETV(rc, NULL);
614
615 /* Init VBVA */
616 rc = VBoxDispVBVAInit(pDev);
617 VBOX_WARNRC_RETV(rc, NULL);
618
619 /* Enable VBVA */
620 if (pDev->hgsmi.bSupported)
621 {
622 if (pDev->mode.ulBitsPerPel==16 || pDev->mode.ulBitsPerPel==24 || pDev->mode.ulBitsPerPel==32)
623 {
624 VBVABUFFER *pVBVA = (VBVABUFFER *)((uint8_t *)pDev->memInfo.VideoRamBase+pDev->layout.offVBVABuffer);
625 pDev->hgsmi.bSupported = VBoxVBVAEnable(&pDev->vbvaCtx, &pDev->hgsmi.ctx, pVBVA, -1);
626 LogRel(("VBoxDisp[%d]: VBVA %senabled\n", pDev->iDevice, pDev->hgsmi.bSupported? "":"not "));
627 }
628 }
629
630 /* Inform host */
631 if (pDev->hgsmi.bSupported)
632 {
633 VBoxHGSMIProcessDisplayInfo(&pDev->hgsmi.ctx, pDev->iDevice, pDev->orgDev.x, pDev->orgDev.y,
634 0, abs(pDev->mode.lScanlineStride), pDev->mode.ulWidth, pDev->mode.ulHeight,
635 (uint16_t)pDev->mode.ulBitsPerPel, VBVA_SCREEN_F_ACTIVE);
636 }
637
638#ifdef VBOX_WITH_VIDEOHWACCEL
639 VBoxDispVHWAEnable(pDev);
640#endif
641
642 /* Set device palette if needed */
643 if (pDev->mode.ulBitsPerPel == 8)
644 {
645 rc = VBoxDispSetPalette8BPP(pDev);
646 VBOX_WARNRC_RETV(rc, NULL);
647 }
648
649 pDev->orgDisp.x = 0;
650 pDev->orgDisp.y = 0;
651
652 /* Create GDI managed bitmap, which resides in our framebuffer memory */
653 ULONG iFormat;
654 SIZEL size;
655
656 switch (pDev->mode.ulBitsPerPel)
657 {
658 case 8:
659 {
660 iFormat = BMF_8BPP;
661 break;
662 }
663 case 16:
664 {
665 iFormat = BMF_16BPP;
666 break;
667 }
668 case 24:
669 {
670 iFormat = BMF_24BPP;
671 break;
672 }
673 case 32:
674 {
675 iFormat = BMF_32BPP;
676 break;
677 }
678 }
679
680 size.cx = pDev->mode.ulWidth;
681 size.cy = pDev->mode.ulHeight;
682
683 pDev->surface.hBitmap = EngCreateBitmap(size, pDev->mode.lScanlineStride, iFormat,
684 pDev->mode.lScanlineStride>0 ? BMF_TOPDOWN:0,
685 pDev->memInfo.FrameBufferBase);
686 if (!pDev->surface.hBitmap)
687 {
688 WARN(("EngCreateBitmap failed!"));
689 return NULL;
690 }
691 pDev->surface.psoBitmap = EngLockSurface((HSURF)pDev->surface.hBitmap);
692
693 /* Create device-managed surface */
694 pDev->surface.hSurface = EngCreateDeviceSurface((DHSURF)pDev, size, iFormat);
695 if (!pDev->surface.hSurface)
696 {
697 WARN(("EngCreateDeviceSurface failed!"));
698 VBoxDispDrvDisableSurface(dhpdev);
699 return NULL;
700 }
701
702 FLONG flHooks = HOOK_BITBLT|HOOK_TEXTOUT|HOOK_FILLPATH|HOOK_COPYBITS|HOOK_STROKEPATH|HOOK_LINETO|
703 HOOK_PAINT|HOOK_STRETCHBLT;
704
705 /* Associate created surface with our device */
706 if (!EngAssociateSurface(pDev->surface.hSurface, pDev->hDevGDI, flHooks))
707 {
708 WARN(("EngAssociateSurface failed!"));
709 VBoxDispDrvDisableSurface(dhpdev);
710 return NULL;
711 }
712
713 pDev->surface.ulFormat = iFormat;
714 pDev->flDrawingHooks = flHooks;
715
716 LOG(("Created surface %p for physical device %p", pDev->surface.hSurface, pDev));
717
718 LOGF_LEAVE();
719 return pDev->surface.hSurface;
720}
721
722VOID APIENTRY VBoxDispDrvDisableSurface(DHPDEV dhpdev)
723{
724 PVBOXDISPDEV pDev = (PVBOXDISPDEV)dhpdev;
725 LOGF_ENTER();
726
727 if (pDev->surface.hSurface)
728 {
729 EngDeleteSurface(pDev->surface.hSurface);
730 pDev->surface.hSurface = NULL;
731 }
732
733 if (pDev->surface.psoBitmap)
734 {
735 Assert(pDev->surface.hBitmap);
736 EngUnlockSurface(pDev->surface.psoBitmap);
737 pDev->surface.psoBitmap = NULL;
738 }
739
740 if (pDev->surface.hBitmap)
741 {
742 EngDeleteSurface((HSURF) pDev->surface.hBitmap);
743 pDev->surface.hBitmap = NULL;
744 }
745
746 int rc;
747 rc = VBoxDispMPUnmapMemory(pDev);
748 VBOX_WARNRC(rc);
749
750 LOGF_LEAVE();
751}
752
753BOOL APIENTRY
754VBoxDispDrvRealizeBrush(BRUSHOBJ *pbo, SURFOBJ *psoTarget, SURFOBJ *psoPattern, SURFOBJ *psoMask,
755 XLATEOBJ *pxlo, ULONG iHatch)
756{
757 BOOL bRc = FALSE;
758 LOGF_ENTER();
759
760 if (VBoxDispIsScreenSurface(psoTarget))
761 {
762 PVBOXDISPDEV pDev = (PVBOXDISPDEV)psoTarget->dhpdev;
763
764 if (pDev->vbvaCtx.pVBVA && (pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
765 {
766 if (pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents & VBOX_VIDEO_INFO_HOST_EVENTS_F_VRDP_RESET)
767 {
768 vrdpReset(pDev);
769 pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents &= ~VBOX_VIDEO_INFO_HOST_EVENTS_F_VRDP_RESET;
770 }
771
772 if (pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_VRDP)
773 {
774 bRc = vrdpDrvRealizeBrush(pbo, psoTarget, psoPattern, psoMask, pxlo, iHatch);
775 }
776 }
777 }
778
779 LOGF_LEAVE();
780 return bRc;
781}
782
783ULONG APIENTRY VBoxDispDrvDitherColor(DHPDEV dhpdev, ULONG iMode, ULONG rgb, ULONG *pul)
784{
785 ULONG rc;
786 LOGF_ENTER();
787
788 /* There is no EngDitherColor on NT4, so take the easy path and tell the graphics
789 * engine to create a halftone approximation.
790 */
791 rc = DCR_HALFTONE;
792
793 LOGF_LEAVE();
794 return rc;
795}
796
797/* Called to reset device to default mode or to mode specified with dhpdev */
798BOOL APIENTRY VBoxDispDrvAssertMode(DHPDEV dhpdev, BOOL bEnable)
799{
800 PVBOXDISPDEV pDev = (PVBOXDISPDEV) dhpdev;
801 int rc;
802 LOGF_ENTER();
803
804 if (!bEnable)
805 {
806 LOGF(("!bEnable"));
807#ifdef VBOX_WITH_VIDEOHWACCEL
808 /* tells we can not process host commands any more and ensures that
809 * we've completed processing of the host VHWA commands
810 */
811 VBoxDispVHWADisable(pDev);
812#endif
813
814 /* disable VBVA */
815 if (pDev->hgsmi.bSupported)
816 {
817 VBoxVBVADisable(&pDev->vbvaCtx, &pDev->hgsmi.ctx, -1);
818 }
819
820 /* reset the device to default mode */
821 rc = VBoxDispMPResetDevice(pDev->hDriver);
822 VBOX_WARNRC_RETV(rc, FALSE);
823 }
824 else
825 {
826 LOGF(("bEnable"));
827
828 /* switch device to previous pDev mode */
829 rc = VBoxDispMPSetCurrentMode(pDev->hDriver, pDev->mode.ulIndex);
830 VBOX_WARNRC_RETV(rc, NULL);
831
832 /* enable VBVA */
833 if (pDev->hgsmi.bSupported)
834 {
835 if (pDev->mode.ulBitsPerPel==16 || pDev->mode.ulBitsPerPel==24 || pDev->mode.ulBitsPerPel==32)
836 {
837 VBVABUFFER *pVBVA = (VBVABUFFER *)((uint8_t *)pDev->memInfo.VideoRamBase+pDev->layout.offVBVABuffer);
838 pDev->hgsmi.bSupported = VBoxVBVAEnable(&pDev->vbvaCtx, &pDev->hgsmi.ctx, pVBVA, -1);
839 LogRel(("VBoxDisp[%d]: VBVA %senabled\n", pDev->iDevice, pDev->hgsmi.bSupported? "":"not "));
840 }
841 }
842
843 /* inform host */
844 if (pDev->hgsmi.bSupported)
845 {
846 VBoxHGSMIProcessDisplayInfo(&pDev->hgsmi.ctx, pDev->iDevice, pDev->orgDev.x, pDev->orgDev.y,
847 0, abs(pDev->mode.lScanlineStride), pDev->mode.ulWidth, pDev->mode.ulHeight,
848 (uint16_t)pDev->mode.ulBitsPerPel, VBVA_SCREEN_F_ACTIVE);
849 }
850
851#ifdef VBOX_WITH_VIDEOHWACCEL
852 /* tells we can process host commands */
853 VBoxDispVHWAEnable(pDev);
854#endif
855
856 /* Associate back GDI bitmap residing in our framebuffer memory with GDI's handle to our device */
857 if (!EngAssociateSurface((HSURF)pDev->surface.hBitmap, pDev->hDevGDI, 0))
858 {
859 WARN(("EngAssociateSurface on bitmap failed"));
860 return FALSE;
861 }
862
863 /* Associate device managed surface with GDI's handle to our device */
864 if (!EngAssociateSurface(pDev->surface.hSurface, pDev->hDevGDI, pDev->flDrawingHooks))
865 {
866 WARN(("EngAssociateSurface on surface failed"));
867 return FALSE;
868 }
869 }
870
871 LOGF_LEAVE();
872 return TRUE;
873}
874
875ULONG APIENTRY VBoxDispDrvEscape(SURFOBJ *pso, ULONG iEsc, ULONG cjIn, PVOID pvIn, ULONG cjOut, PVOID pvOut)
876{
877 PVBOXDISPDEV pDev = (PVBOXDISPDEV)pso->dhpdev;
878 LOGF_ENTER();
879
880 switch (iEsc)
881 {
882#ifdef VBOX_WITH_CROGL
883 case OPENGL_GETINFO:
884 {
885 if (pvOut && cjOut >= sizeof(OPENGL_INFO))
886 {
887 POPENGL_INFO pInfo = (POPENGL_INFO)pvOut;
888
889 pInfo->dwVersion = 2;
890 pInfo->dwDriverVersion = 1;
891 pInfo->szDriverName[0] = 'V';
892 pInfo->szDriverName[1] = 'B';
893 pInfo->szDriverName[2] = 'o';
894 pInfo->szDriverName[3] = 'x';
895 pInfo->szDriverName[4] = 'O';
896 pInfo->szDriverName[5] = 'G';
897 pInfo->szDriverName[6] = 'L';
898 pInfo->szDriverName[7] = 0;
899
900 LOG(("OPENGL_GETINFO ok"));
901 return cjOut;
902 }
903 else
904 {
905 WARN(("OPENGL_GETINFO invalid parms"));
906 return 0;
907 }
908 }
909 case QUERYESCSUPPORT:
910 {
911 if (pvIn && cjIn == sizeof(DWORD))
912 {
913 DWORD nEscapeQuery = *(DWORD *)pvIn;
914
915 if (nEscapeQuery==OPENGL_GETINFO)
916 {
917 LOG(("QUERYESCSUPPORT OPENGL_GETINFO"));
918 return 1;
919 }
920 else
921 {
922 LOG(("QUERYESCSUPPORT unsupported query %d", nEscapeQuery));
923 return 0;
924 }
925 }
926 else
927 {
928 WARN(("QUERYESCSUPPORT invalid parms"));
929 return 0;
930 }
931 }
932#endif
933 case VBOXESC_ISVRDPACTIVE:
934 {
935 if (pDev && pDev->vbvaCtx.pVBVA && pDev->vbvaCtx.pVBVA->hostFlags.u32HostEvents&VBVA_F_MODE_VRDP)
936 {
937 LOGF(("VBOXESC_ISVRDPACTIVE: 1"));
938 return 1;
939 }
940 LOGF(("VBOXESC_ISVRDPACTIVE: 0"));
941 return 0;
942 }
943 case VBOXESC_SETVISIBLEREGION:
944 {
945 LOGF(("VBOXESC_SETVISIBLEREGION"));
946 LPRGNDATA lpRgnData = (LPRGNDATA)pvIn;
947 DWORD cRects;
948
949 if ( cjIn >= sizeof(RGNDATAHEADER)
950 && pvIn
951 && lpRgnData->rdh.dwSize == sizeof(RGNDATAHEADER)
952 && lpRgnData->rdh.iType == RDH_RECTANGLES
953 && (cRects = lpRgnData->rdh.nCount) <= _1M
954 && cjIn == cRects * (uint64_t)sizeof(RECT) + sizeof(RGNDATAHEADER))
955 {
956 /** @todo this whole conversion thing could maybe be skipped
957 * since RTRECT matches the RECT layout. */
958#if 0
959 AssertCompile(sizeof(RTRECT) == sizeof(RECT));
960 AssertCompileMembersSameSizeAndOffset(RTRECT, xLeft, RECT, left);
961 AssertCompileMembersSameSizeAndOffset(RTRECT, xBottom, RECT, bottom);
962 AssertCompileMembersSameSizeAndOffset(RTRECT, xRight, RECT, right);
963 AssertCompileMembersSameSizeAndOffset(RTRECT, xTop, RECT, top);
964
965 rc = VBoxDispMPSetVisibleRegion(pDev->hDriver, (PRTRECT)&lpRgnData->Buffer[0], cRects);
966 VBOX_WARNRC(rc);
967#else
968 DWORD i;
969 PRTRECT pRTRect;
970 int rc;
971 RECT *pRect = (RECT *)&lpRgnData->Buffer;
972
973 pRTRect = (PRTRECT) EngAllocMem(0, cRects*sizeof(RTRECT), MEM_ALLOC_TAG);
974 if (!pRTRect)
975 {
976 WARN(("failed to allocate %d bytes", cRects*sizeof(RTRECT)));
977 break;
978 }
979
980 for (i = 0; i < cRects; ++i)
981 {
982 LOG(("New visible rectangle (%d,%d) (%d,%d)",
983 pRect[i].left, pRect[i].bottom, pRect[i].right, pRect[i].top));
984 pRTRect[i].xLeft = pRect[i].left;
985 pRTRect[i].yBottom = pRect[i].bottom;
986 pRTRect[i].xRight = pRect[i].right;
987 pRTRect[i].yTop = pRect[i].top;
988 }
989
990 rc = VBoxDispMPSetVisibleRegion(pDev->hDriver, pRTRect, cRects);
991 VBOX_WARNRC(rc);
992
993 EngFreeMem(pRTRect);
994
995#endif
996 if (RT_SUCCESS(rc))
997 {
998 LOGF_LEAVE();
999 return 1;
1000 }
1001 }
1002 else
1003 {
1004 if (pvIn)
1005 {
1006 WARN(("check failed rdh.dwSize=%x iType=%d size=%d expected size=%d",
1007 lpRgnData->rdh.dwSize, lpRgnData->rdh.iType, cjIn,
1008 lpRgnData->rdh.nCount * sizeof(RECT) + sizeof(RGNDATAHEADER)));
1009 }
1010 }
1011 break;
1012 }
1013 case VBOXESC_ISANYX:
1014 {
1015 if (pvOut && cjOut == sizeof(DWORD))
1016 {
1017 DWORD cbReturned;
1018 DWORD dwrc = EngDeviceIoControl(pDev->hDriver, IOCTL_VIDEO_VBOX_ISANYX, NULL, 0,
1019 pvOut, sizeof (uint32_t), &cbReturned);
1020 if (dwrc == NO_ERROR && cbReturned == sizeof (uint32_t))
1021 return 1;
1022 WARN(("EngDeviceIoControl failed, dwrc(%d), cbReturned(%d)", dwrc, cbReturned));
1023 return 0;
1024 }
1025 else
1026 {
1027 WARN(("VBOXESC_ISANYX invalid parms"));
1028 return 0;
1029 }
1030 break;
1031 }
1032 default:
1033 {
1034 LOG(("unsupported iEsc %#x", iEsc));
1035 }
1036 }
1037
1038 LOGF_LEAVE();
1039 return 0;
1040}
1041
1042#define FB_OFFSET(_dev, _x, _y) ((_y)*pDev->mode.lScanlineStride) + ((_x)*((pDev->mode.ulBitsPerPel+1)/8))
1043/* Obsolete, NT4 specific. Called to set display offset in virtual desktop */
1044BOOL APIENTRY VBoxDispDrvOffset(SURFOBJ* pso, LONG x, LONG y, FLONG flReserved)
1045{
1046 PVBOXDISPDEV pDev = (PVBOXDISPDEV)pso->dhpdev;
1047 LOGF(("%x %x %x\n", x, y, flReserved));
1048
1049 pDev->memInfo.FrameBufferBase = ((BYTE*)pDev->memInfo.VideoRamBase) + pDev->layout.offFramebuffer
1050 - FB_OFFSET(pDev, x, y);
1051
1052 pDev->orgDisp.x = x;
1053 pDev->orgDisp.y = y;
1054
1055 LOGF_LEAVE();
1056 return TRUE;
1057}
1058
1059/* Called to notify driver about various events */
1060VOID APIENTRY VBoxDispDrvNotify(SURFOBJ *pso, ULONG iType, PVOID pvData)
1061{
1062 PVBOXDISPDEV pDev = (PVBOXDISPDEV)pso->dhpdev;
1063 LOGF_ENTER();
1064
1065 switch (iType)
1066 {
1067 case DN_DEVICE_ORIGIN:
1068 {
1069 /*device origin in dualview*/
1070 POINTL *pOrg = (POINTL *)pvData;
1071 if (pOrg)
1072 {
1073 LOG(("DN_DEVICE_ORIGIN (pso=%p, pDev[%d]=%p) old=%d,%d new=%d,%d",
1074 pso, pDev->iDevice, pDev, pDev->orgDev.x, pDev->orgDev.y, pOrg->x, pOrg->y));
1075 if (pDev->orgDev.x!=pOrg->x || pDev->orgDev.y!=pOrg->y)
1076 {
1077 pDev->orgDev = *pOrg;
1078
1079 /* Inform host about display change */
1080 VBoxHGSMIProcessDisplayInfo(&pDev->hgsmi.ctx, pDev->iDevice, pDev->orgDev.x, pDev->orgDev.y,
1081 0, abs(pDev->mode.lScanlineStride),
1082 pDev->mode.ulWidth, pDev->mode.ulHeight,
1083 (uint16_t)pDev->mode.ulBitsPerPel, VBVA_SCREEN_F_ACTIVE);
1084 }
1085 }
1086 else
1087 {
1088 WARN(("DN_DEVICE_ORIGIN pvData==NULL"));
1089 }
1090
1091 break;
1092 }
1093 case DN_DRAWING_BEGIN:
1094 {
1095 /*first drawing op is about to happen for this device*/
1096 LOG(("DN_DRAWING_BEGIN (pso=%p, pDev[%d]=%p)", pso, pDev->iDevice, pDev));
1097 break;
1098 }
1099 default:
1100 {
1101 LOG(("unknown iType=%#x", iType));
1102 }
1103 }
1104
1105 LOGF_LEAVE();
1106 return;
1107}
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