Remote Display Driver's VideoPortInitialize() returns STATUS_UNSUCCESSFUL (0xC0000001)

Hi,

In order to create winlogon sessions I’ve implemented an RDS Protocol
Provider, which in turn requires input and display driver handles. For
the display driver I’ve taken the mirror driver sample from the
7600.16385.1 WDK. I modified the sample to only set the Remote Display
Driver functions[1] for the display driver .dll. (Display driver
functions at [DD], miniport driver functions at [MP])

When I start my on-demand driver service (using ‘net start’) it says
“System error 31 has occurred”. Tracing in windbg I see
VideoPortInitialize() returns STATUS_UNSUCCESSFUL (0xC0000001) in my
DriverEntry. Further stepping inside VideoPortInitialize I see
VIDEOPRT.SYS!VpGetFlags() failing[3].

Can you give any clues or suggestions on how I can find what the problem is?

Additional Info

Driver running on Win2012r2 in a VirtualBox VM on Win7 x64 host.
Driver is installed by right-clicking the .inf and choosing Install.
Driver is signed with self-signed cert, cert CA is added to system.
Bcdedit says testsigning is enabled.
Driver built on Win7 x64 host with the 7600 WDK, calling nmake directly.
Signing/inf/cat creation is my own, but roughly mirror what VS2013 or
2015 do if you create a Driver project (signtool on drivers, stampinf,
inf2cat, signtool on cat).

I noticed that the DriverEntry docs[2] say that HwVidQueryInterface is
required but the VIDEO_HW_INITIALIZATION_DATA docs[3] say it is
optional. I tried with and without but get the same error.

I manually signed/installed the stock mirror driver sample but get the
same error.

This is the first NT driver I’ve worked with; don’t be shy to insult my
intelligence with “obvious” suggestions.

Really appreciate any insight you have.

-Nathan

[1] Remote Display Drivers
https://docs.microsoft.com/en-us/windows-hardware/drivers/display/remote-display-drivers

[2] Video Miniport DriverEntry
https://msdn.microsoft.com/en-us/library/windows/hardware/ff556159(v=vs.85).aspx

[3] VIDEO_HW_INITIALIZATION_DATA
https://msdn.microsoft.com/en-us/library/windows/hardware/ff570505(v=vs.85).aspx

[4] Windbg stepping:

VIDEOPRT!pMiniportInit+0x8a:
fffff800cd00a9ba e845dfffff call VIDEOPRT!VpGetFlags (fffff800cd008904)
kd> p
VIDEOPRT!pMiniportInit+0x8f:
fffff800cd00a9bf 85c0 test eax,eax kd\> p VIDEOPRT!pMiniportInit+0x91: fffff800cd00a9c1 790a jns VIDEOPRT!pMiniportInit+0x9d
(fffff800cd00a9cd) kd\> p VIDEOPRT!pMiniportInit+0x93: fffff800cd00a9c3 b8010000c0 mov eax,0C0000001h

[DD] Display driver functions
static DRVFN gadrvfn =
{
// A Remote Display Driver requires these and only these
//
https://docs.microsoft.com/en-us/windows-hardware/drivers/display/remote-display-drivers
{ INDEX_DrvAssertMode, (PFN) DrvAssertMode },
{ INDEX_DrvBitBlt, (PFN) DrvBitBlt },
{ INDEX_DrvCompletePDEV, (PFN) DrvCompletePDEV },
{ INDEX_DrvCopyBits, (PFN) DrvCopyBits },
{ INDEX_DrvDisableDriver, (PFN) DrvDisableDriver },
{ INDEX_DrvDisablePDEV, (PFN) DrvDisablePDEV },
{ INDEX_DrvDisableSurface, (PFN) DrvDisableSurface },
{ INDEX_DrvEnablePDEV, (PFN) DrvEnablePDEV },
{ INDEX_DrvEnableSurface, (PFN) DrvEnableSurface },
{ INDEX_DrvEscape, (PFN) DrvEscape },
{ INDEX_DrvGetModes, (PFN) DrvGetModes },
{ INDEX_DrvMovePointer, (PFN) DrvMovePointer },
{ INDEX_DrvResetPDEV, (PFN) DrvResetPDEV },
{ INDEX_DrvSetPointerShape, (PFN) DrvSetPointerShape },

};

[MP] Miniport driver entry:

ULONG DriverEntry (PVOID Context1, PVOID Context2)
{
VIDEO_HW_INITIALIZATION_DATA hwInitData;
ULONG status;

VideoDebugPrint((0, “MYVIDEOMP: [Driver Entry]\n”));

VideoPortZeroMemory(&hwInitData, sizeof(VIDEO_HW_INITIALIZATION_DATA));
hwInitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);

hwInitData.HwFindAdapter = &MirrorFindAdapter;
hwInitData.HwInitialize = &MirrorInitialize;
hwInitData.HwStartIO = &MirrorStartIO;
hwInitData.HwResetHw = &MirrorResetHW;
hwInitData.HwInterrupt = &MirrorVidInterrupt;
hwInitData.HwGetPowerState = &MirrorGetPowerState;
hwInitData.HwSetPowerState = &MirrorSetPowerState;
hwInitData.HwGetVideoChildDescriptor = &MirrorGetChildDescriptor;
hwInitData.HwQueryInterface = &MirrorVidQueryInterface;

status = VideoPortInitialize(Context1, Context2, &hwInitData, NULL);

VideoDebugPrint((0, “MYVIDEOMP: VideoPortInitialize returns 0x%x\n”,
status));

return status;

}

xxxxx@spicycrypto.ca wrote:

In order to create winlogon sessions I’ve implemented an RDS Protocol
Provider, which in turn requires input and display driver handles.

I don’t know that driver type.  Are you really supposed to create your
own drivers, or are you supposed to get handles to an existing driver?

When I start my on-demand driver service (using ‘net start’) it says
“System error 31 has occurred”.

Right, because that’s not how you launch a video miniport driver.  GDI
has to do it.  When an triggers the creation, GDI will launch the
port/miniport pair, and will load the display driver DLL.  The sample
includes an application that shows how to do that.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Tim, thanks for the feedback.

On 31/10/17 08:40 PM, xxxxx@probo.com wrote:

xxxxx@spicycrypto.ca wrote:
> In order to create winlogon sessions I’ve implemented an RDS Protocol
> Provider, which in turn requires input and display driver handles.

I don’t know that driver type.  Are you really supposed to create your
own drivers, or are you supposed to get handles to an existing driver?

I’d love to use existing drivers. I have been going back and forth with
MS 2nd level support for some weeks, and the implication is I need to
write my own, though it is difficult to get definitive info. All other
implementations that I’m aware of use their own drivers.

> When I start my on-demand driver service (using ‘net start’) it says
> “System error 31 has occurred”.

Right, because that’s not how you launch a video miniport driver.  GDI
has to do it.  When an triggers the creation, GDI will launch the
port/miniport pair, and will load the display driver DLL.  The sample
includes an application that shows how to do that.

Interesting. All the RDSProtocolProvider+driver implementations
(including one from MS) which I’m aware of install a service that will
“net start” / “net stop”. But I see now that they do not call
VIDEOPRT!VideoPortInitialize when they do so. They do take the form of
traditional display/miniport pair, even to the point of naming (e.g. MS
has RdpVideoMiniport.sys), and e.g. .inf files are clearly based on the
original MS sample with Display/Miniport nomenclature.

So despite looking like miniport drivers, the fact that they don’t call
VideoPortInitialize() means they’re not standard video miniport drivers.

Does anybody have suggestions on how to find out what variation of video
driver the Remote Desktop Services Protocol Provider really wants?

GetInputHandles[1] says it wants straight-up I8042prt and Mouclass
drivers, but GetVideoHandle[2] is quite a bit more vague, “Obtains the
handle of the video device for the protocol.”

Thanks for any tips!

-Nathan

[1] https://msdn.microsoft.com/en-us/library/hh707208(v=vs.85).aspx
[2] https://msdn.microsoft.com/en-us/library/hh707215(v=vs.85).aspx

xxxxx@spicycrypto.ca wrote:

Interesting. All the RDSProtocolProvider+driver implementations
(including one from MS) which I’m aware of install a service that will
“net start” / “net stop”. But I see now that they do not call
VIDEOPRT!VideoPortInitialize when they do so. They do take the form of
traditional display/miniport pair, even to the point of naming (e.g. MS
has RdpVideoMiniport.sys), and e.g. .inf files are clearly based on the
original MS sample with Display/Miniport nomenclature.

Can you not just use RdpVideoMiniport.sys?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

On 01/11/17 02:08 PM, xxxxx@probo.com wrote:

xxxxx@spicycrypto.ca wrote:
> Interesting. All the RDSProtocolProvider+driver implementations
> (including one from MS) which I’m aware of install a service that will
> “net start” / “net stop”. But I see now that they do not call
> VIDEOPRT!VideoPortInitialize when they do so. They do take the form of
> traditional display/miniport pair, even to the point of naming (e.g. MS
> has RdpVideoMiniport.sys), and e.g. .inf files are clearly based on the
> original MS sample with Display/Miniport nomenclature.

Can you not just use RdpVideoMiniport.sys?

I’ve tried NtCreateFile(\Device\RdpVideoMiniport0)[1], but when I pass
the handle to RDS it disconnects the session and says the video handle
is invalid[2]. I could not obtain any info on what that black box wants
from the handle.

(My direct “can I use the RDP drivers?” queries haven’t found their way
from MS support to an internal dev that is able/willing to answer (yet?).)

Looking at a couple examples of “remote display driver miniport” .sys
files I see they are WDM drivers that IoCreateDevice() with all device
types like FILE_DEVICE_MULTI_UNC_PROVIDER or FILE_DEVICE_TERMSRV.
I also see evidence of them handling typical video miniport functions
like HwStartIO which makes me think this is some kind of hybrid video
miniport driver.

Thanks for your ideas.

-Nathan

[1]
HANDLE_PTR GetVideoDriverHandle(void)
{

static HANDLE handle = NULL;

wchar_t driver = L"\Device\RdpVideoMiniport0";
UNICODE_STRING objname;
RtlInitUnicodeString(&objname, driver);
OBJECT_ATTRIBUTES obj = { 0 };
InitializeObjectAttributes(&obj, &objname, OBJ_CASE_INSENSITIVE,
NULL /*root*/, NULL /* security */);
IO_STATUS_BLOCK io = { 0 };
NTSTATUS status = NtCreateFile(&handle, GENERIC_READ | GENERIC_WRITE
| SYNCHRONIZE, &obj, &io, NULL, 0, 0, FILE_OPEN_IF, 0, NULL, 0);
DPRINTF(“NtCreateFile = 0x%x handle = 0x%p\n”, status, handle);

return (HANDLE_PTR) &handle;
}

[2]
Event Viewer for Applications and Services Logs -> Microsoft -> Windows
-> TerminalServices-LocalSession-Manager -> Operational says:

“Attempt to send connect(2) message to Windows video subsystem failed.
The relevant status code was 0xD0000008”.

(0xD0000008 appears to be 0xC0000008 (STATUS_INVALID_HANDLE) with the
reserved “N” bit set.)