[vbox-dev] Custom front-end using non-OSE SDK

Brad Robinson brobinson at cantabilesoftware.com
Wed Oct 28 13:01:36 GMT 2009


Hi Vitali,

> There is no any special connections between IFramebuffer and VRDP
> server. Or in other words, VRDP server can work with any Framebuffer
> implementation. VRDP server uses public Framebuffer methods to access
> the screen bitmap (Address, Width, Height, BitsPerPixel, etc). If there
> is no framebuffer, then of course VRDP server can't get the screen image.

Ah I see.  I'd previously assumed that the frame buffer was responsible for
forwarding screen data to the VRDP server.  It makes sense now why there's
no built-in implementation.

So today I wrote my own IFrameBuffer implementation which I derived from
what I could glean from the information in the SDK reference and by browsing
the OSE VBoxSDL app.

Unfortunately, I must still be misunderstanding something as I now get a
crash shortly after the VM enters the running state.  I've double checked my
code for any obvious logic errors and also set breakpoints on every method
call and stepped through the whole lot, but I still don't understand what
I'm doing wrong.  It seems to be a heap corruption shortly after I return
the address ptr through get_Address - as if VBox is freeing that pointer.
If you have the time to review this I'd be very grateful.  The code for my
IFramebuffer implementation is below - it's pretty trivial, or the full
project is here: http://download.cantabilesoftware.com/VBoxTest.zip .  (I
really hope this isn't just a silly mistake on my part).

Regarding the sharing violation, I spent some time investigating this and
believe the problem is related to the call to RTLogCreateEx in
ConsoleImpl.cpp (about line 4562) not having a matching RTLogDestroy.  I
don't have a build environment for the OSE setup so I'm not able to test it
just now. 

Again, I really appreciate the help in trying resolve these issues.

Brad 



// Constructor
CFramebuffer::CFramebuffer()
{
	m_pVRAM=NULL;

	m_nWidth=640;
	m_nHeight=480;
	m_nBPP=32;
	m_nBytesPerLine=m_nWidth * 4;
	m_nPixelFormat=FramebufferPixelFormat_Opaque;    // Force non-direct
mode by default
	m_bUsesGuestVRAM=false;

	InitializeCriticalSection(&m_cs);

	ResizeInternal();
}

// Destructor
CFramebuffer::~CFramebuffer()
{
	FreeVRAM();
	DeleteCriticalSection(&m_cs);
}

// Free any allocated video ram
void CFramebuffer::FreeVRAM()
{
	// Quit if not allocated
	if (!m_pVRAM)
		return;

	// Dont free guest VRAM
	if (!m_bUsesGuestVRAM)
	{
		HeapFree(GetProcessHeap(), 0, m_pVRAM);
	}

	// Zap ptr
	m_pVRAM=NULL;
}

void CFramebuffer::ResizeInternal()
{
	// Work out whether to use guest VRAM or allocate our own
    m_bUsesGuestVRAM=false;
    if (m_nPixelFormat==FramebufferPixelFormat_FOURCC_RGB && m_pVRAM!=NULL)
    {
        switch (m_nBPP)
        {
            case 16:
            case 24:
            case 32:
                m_bUsesGuestVRAM=true;
                break;
		}
	}

	if (!m_bUsesGuestVRAM)
	{
		// If not using guest VRAM, always use 32bpp format
        m_nPixelFormat=FramebufferPixelFormat_FOURCC_RGB;
        m_nBPP=32;
        m_nBytesPerLine = m_nWidth * 4;

		// Allocate memory buffer
		m_pVRAM=(BYTE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
(m_nHeight * m_nBytesPerLine));
	}

}


// Implementation of get_Address
STDMETHODIMP CFramebuffer::get_Address(BYTE * * aAddress)
{
	*aAddress=m_pVRAM;
	return S_OK;
}

// Implementation of get_Width
STDMETHODIMP CFramebuffer::get_Width(ULONG * aWidth)
{
	*aWidth=m_nWidth;
	return S_OK;
}

// Implementation of get_Height
STDMETHODIMP CFramebuffer::get_Height(ULONG * aHeight)
{
	*aHeight=m_nHeight;
	return S_OK;
}

// Implementation of get_BitsPerPixel
STDMETHODIMP CFramebuffer::get_BitsPerPixel(ULONG * aBitsPerPixel)
{
	*aBitsPerPixel=m_nBPP;
	return S_OK;
}

// Implementation of get_BytesPerLine
STDMETHODIMP CFramebuffer::get_BytesPerLine(ULONG * aBytesPerLine)
{
	*aBytesPerLine=m_nBytesPerLine;
	return S_OK;
}

// Implementation of get_PixelFormat
STDMETHODIMP CFramebuffer::get_PixelFormat(ULONG * aPixelFormat)
{
	*aPixelFormat=m_nPixelFormat;
	return S_OK;
}

// Implementation of get_UsesGuestVRAM
STDMETHODIMP CFramebuffer::get_UsesGuestVRAM(BOOL * aUsesGuestVRAM)
{
	*aUsesGuestVRAM=m_bUsesGuestVRAM;
	return S_OK;
}

// Implementation of get_HeightReduction
STDMETHODIMP CFramebuffer::get_HeightReduction(ULONG * aHeightReduction)
{
	*aHeightReduction=0;
	return S_OK;
}

// Implementation of get_Overlay
STDMETHODIMP CFramebuffer::get_Overlay(IFramebufferOverlay * * aOverlay)
{
	*aOverlay=NULL;
	return S_OK;
}

// Implementation of get_WinId
STDMETHODIMP CFramebuffer::get_WinId(ULONG64 * aWinId)
{
	*aWinId=0;
	return S_OK;
}

// Implementation of Lock
STDMETHODIMP CFramebuffer::Lock()
{
	EnterCriticalSection(&m_cs);
	return S_OK;
}

// Implementation of Unlock
STDMETHODIMP CFramebuffer::Unlock()
{
	LeaveCriticalSection(&m_cs);
	return S_OK;
}

// Implementation of NotifyUpdate
STDMETHODIMP CFramebuffer::NotifyUpdate(
        ULONG aX,
        ULONG aY,
        ULONG aWidth,
        ULONG aHeight
    )
{
	// Nothing to do!
	return S_OK;
}

// Implementation of RequestResize
STDMETHODIMP CFramebuffer::RequestResize(
        ULONG aScreenId,
        ULONG aPixelFormat,
        BYTE * aVRAM,
        ULONG aBitsPerPixel,
        ULONG aBytesPerLine,
        ULONG aWidth,
        ULONG aHeight,
        BOOL * aFinished
    )
{
	// Free old video memory
	FreeVRAM();

	// Store passed in params
	m_pVRAM=aVRAM;
	m_nBPP=aBitsPerPixel;
	m_nBytesPerLine=aBytesPerLine;
	m_nWidth=aWidth;
	m_nHeight=aHeight;
	m_nPixelFormat=aPixelFormat;

	ResizeInternal();

	*aFinished=TRUE;
	return S_OK;
}


// Implementation of VideoModeSupported
STDMETHODIMP CFramebuffer::VideoModeSupported(
        ULONG aWidth,
        ULONG aHeight,
        ULONG aBpp,
        BOOL * aSupported
    )
{
	// Any 32-bpp format is ok
	*aSupported=(aBpp==32);
	return S_OK;
}

// Implementation of GetVisibleRegion
STDMETHODIMP CFramebuffer::GetVisibleRegion(
        BYTE * aRectangles,
        ULONG aCount,
        ULONG * aCountCopied
    )
{
	return E_NOTIMPL;
}

// Implementation of SetVisibleRegion
STDMETHODIMP CFramebuffer::SetVisibleRegion(
        BYTE * aRectangles,
        ULONG aCount
    )
{
	return E_NOTIMPL;
}

// Implementation of ProcessVHWACommand
STDMETHODIMP CFramebuffer::ProcessVHWACommand(
        BYTE * aCommand
	)
{
	// Not supported
	return E_NOTIMPL;
}



 

-----Original Message-----
From: Vitali.Pelenjow at Sun.COM [mailto:Vitali.Pelenjow at Sun.COM] 
Sent: Wednesday, 28 October 2009 1:20 AM
To: Brad Robinson; vbox-dev at virtualbox.org
Subject: Re: [vbox-dev] Custom front-end using non-OSE SDK

/* Resending to vbox-dev */

There is no any special connections between IFramebuffer and VRDP
server. Or in other words, VRDP server can work with any Framebuffer
implementation. VRDP server uses public Framebuffer methods to access
the screen bitmap (Address, Width, Height, BitsPerPixel, etc). If there
is no framebuffer, then of course VRDP server can't get the screen image.

We decided to not to implement a "method that creates a Framebuffer"
because Framebuffer implementation is very frontend dependent and it is
trivial to implement a Framebuffer, which only allocates a memory block
and lets VM to use it (which is what you need).

Vitali.

Brad Robinson wrote:
> Hi Vitali,
>
> I suspected this was the issue from examining the source for VBoxHeadless,
> however I believe this is something I _can't_ implement because it needs
to
> work with VBox's built in VRDP server - hence my posting here.
>
> What I need is either an API to create frame buffers that are connected to
> the VRDP server, or simply a method that creates them and wires them up.
>
> Brad
>
>
> -----Original Message-----
> From: Vitali.Pelenjow at Sun.COM [mailto:Vitali.Pelenjow at Sun.COM] 
> Sent: Tuesday, 27 October 2009 7:16 PM
> To: Brad Robinson
> Cc: vbox-dev at virtualbox.org
> Subject: Re: [vbox-dev] Custom front-end using non-OSE SDK
>
> Hi Brad,
>
> you get a black VRDP screen because your VM does not have a framebuffer.
> It is necessary to implement IFramebuffer interface and then register it 
> with the display:
>
> IFramebuffer  *pFramebuffer = new MyFramebuffer();
> CComPtr <IDisplay> display;
> m_spConsole->get_Display(&display);
> display->SetFramebuffer(0, pFramebuffer);
>
> The Framebuffer implementation should allocate a memory buffer for the 
> VM screen in RequestResize method.
>
> Best regards,
> Vitali.
>
> Brad Robinson wrote:
>   
>> Hi Frank/All,
>>
>> I've put a sample program that demonstrates the problems I'm seeing here:
>> http://download.cantabilesoftware.com/VBoxTest.zip.
>>
>> It's a simple Windows dialog app that hosts a VBox VM using the COM API
>>     
> from
>   
>> the SDK.  Error handling is minimal. I've included VS2005
>> solution/project/source code + x86 and x64 executables.
>>
>> To use it:
>>
>> 1. Copy the appropriate exe to c:\program files\sun\virtualbox (not sure
>>     
> why
>   
>> this is necessary, but not a big issue)
>> 2. Run it
>> 3. Enter the name of a VBox machine with VRDP enabled
>> 4. Click Power Up.
>> 5. Connect to the machine from remote desktop, notice the blank screen.
>> 6. Type something on the keyboard
>> 7. Close remote desktop
>> 8. Click Save State to close the machine.
>> 9. Click Power Up again, notice the error.
>> 10. Close VBoxTest and run up the same machine in the regular Virtual Box
>> front end.  Notice keys typed in RD above were received.
>>
>> The issues are:
>>
>> 1. Blank VRDP screen
>> 2. Inability to relaunch the same VM 
>>
>> What I'm trying to build is a VBox front end that will host a machine and
>> run it as a Windows system tray Icon.  I have few environments where I
>>     
> need
>   
>> to have a number of server type machines running for development purposes
>> and most of the time I just want them out of the way.  I'm happy to
>>     
> release
>   
>> this to the community if I can get it working, but I'm not having much
>>     
> luck.
>   
>> I've already tried spawning VBoxHeadless which seems to work fine until
>> shutdown/logoff when Windows just kills it without it or my app having a
>> chance to save it.
>>
>> Any help in resolving these issues would be greatly appreciated.
>>
>> Brad
>>
>> -----Original Message-----
>> From: Frank.Mehnert at Sun.COM [mailto:Frank.Mehnert at Sun.COM] 
>> Sent: Monday, 26 October 2009 11:56 PM
>> To: Brad Robinson
>> Subject: Re: [vbox-dev] Custom front-end using non-OSE SDK
>>
>> Brad,
>>
>> please reply to the mailing list if possible because I get tons of mails
>> each day and probably other developers want to follow the discussion as
>> well.
>>
>> On Monday 26 October 2009, Brad Robinson wrote:
>>   
>>     
>>> Thanks for getting back to me on this.  I'll put together a simpler 
>>> example as my real project brings in a couple of custom libraries you 
>>> won't be interested in.  Shall I just email it directly to you?
>>>     
>>>       
>> That would be possible. Or, if the compressed code isn't too long, you
>>     
> could
>   
>> post it to the mailing list as well.
>>
>>   
>>     
>>> Btw: I've noticed in the VBoxHeadless OSE source code there's code 
>>> that sets a "new VRDPFramebuffer" to each display of the console...  
>>> this is what I suspect I'm missing, but not sure how to implement with
>>>       
> the
>   
>>>     
>>>       
>> SDK.
>>
>> Right, the VRDPFramebuffer is closed source and actually I'm not sure if
>>     
> you
>   
>> will be able to write a custom frontend which can do RDP. Did you already
>> have a look at VBoxSDL?
>>
>> Kind regards,
>>
>> Frank
>> --
>> Dr.-Ing. Frank Mehnert
>>
>> Sitz der Gesellschaft:
>> Sun Microsystems GmbH, Sonnenallee 1, 85551 Kirchheim-Heimstetten
>> Amtsgericht München: HRB 161028
>> Geschäftsführer: Thomas Schröder, Wolfgang Engels, Wolf Frenkel
>>     
> Vorsitzender
>   
>> des Aufsichtsrates: Martin Häring
>>
>>
>> _______________________________________________
>> vbox-dev mailing list
>> vbox-dev at virtualbox.org
>> http://vbox.innotek.de/mailman/listinfo/vbox-dev
>>   
>>     
>
>   






More information about the vbox-dev mailing list