void DDErrorBox( char *location, HRESULT error )
 {
  char title[256];
  char *error_string;

  strcpy( title, "Error At: " );
  strcat( title, location );

  error_string = D3DRMErrorToString( error );
   
  MessageBox( 0, error_string, title, MB_OK );
 }
STDMETHODIMP CVWRenderRoot::Update()
{
	HRESULT hr = S_OK;

	if (!m_pVWRender3D)
		return E_NOTINITIALIZED;

	EnterCriticalSection(&m_CS);

	CRect rectBack, rectWnd;
	static iBlt = 0;

	if (m_bFPSEnabled)
		dwBltTime = GetTickCount();

	if (GetWindowRect(m_hWnd, &rectWnd) == NULL)
	{
		ASSERT(FALSE);
		goto e_Update;
	}

	if (m_pddsFrontBuffer && m_pddsFrontBuffer->IsLost() == DDERR_SURFACELOST)
	{
		m_pddsFrontBuffer->Restore();
		// Should NOT call HandleSizeInternal from rendering thread. Seems OK to remove
		// this now after testing with new drop of Win2K.
		// It seems that just restoring the back buffer (if it exists) don't quite cut it.
//		if (FAILED(hr = HandleSizeInternal(rectWnd.Width(), rectWnd.Height(), m_bUseHWAcceleration, VARIANT_TRUE)))
//			goto e_Update;
	}

	if (m_bUseBackBuffer || !m_bUseHWAcceleration)
	{
		if (!m_pddsBackBuffer)
		{
			// Must have failed to create the back buffer.
			hr = E_FAIL;
			goto e_Update;
		}

		// Is device is smaller than window?
		if (m_iCurrentCX < rectWnd.Width())
			rectWnd.right = rectWnd.left + m_iCurrentCX;
		if (m_iCurrentCY < rectWnd.Height())
			rectWnd.bottom = rectWnd.top + m_iCurrentCY;

		hr = m_pddsFrontBuffer->SetClipper(m_lpDDClipper);
 		if (FAILED(hr))
		{
 			TRACE(CString(D3DRMErrorToString(hr))+ CString("\n"));
			goto e_Update;
 		}
		
 		// Now strech blt from back buffer to front.
 		rectBack.left = 0;
 		rectBack.top = 0;
 		if (m_bFastMode)
		{
 			rectBack.right = rectWnd.Width() >> 1;
			rectBack.bottom = rectWnd.Height() >> 1;
 		}
		else
 		{
 			rectBack.right = rectWnd.Width();
 			rectBack.bottom = rectWnd.Height();
 		}
		
		// Now strech blt from back buffer to front.
		if ((rectWnd.left != rectWnd.right) && 
			(rectWnd.top != rectWnd.bottom)) 
		{
			hr = m_pddsFrontBuffer->Blt(&rectWnd,m_pddsBackBuffer,&rectBack,DDBLT_WAIT,NULL); 
			if (FAILED(hr))
			{
				TRACE(CString(D3DRMErrorToString(hr))+ CString("\n"));
				goto e_Update;
			}
		}
	}