Example #1
0
int main ()
{
    MTestName = "Log Engine Tests";

    TestLogEngineConstructor ();
    TestPut ();
    TestFormat ();
    TestGetLogLevelCode ();

    MTestReport ();
    return MTestErrors;
}
Example #2
0
int
main(int argc, char **argv)
{
  plan_tests(111);

  TestFormat();
  TestFormatLong();
  TestHHMM();
  TestTwoLines();
  TestSmart();

  return exit_status();
}
Example #3
0
int
#if _WIN32_WCE
_cdecl
#endif
main()
{
    //  afxMemDF |= allocMemDF | checkAlwaysMemDF;

    // The M4STRING package sometimes keeps a spare empty string around.
    // By allocating it here, we avoid a few bogus memory leak reports.
    c4_String empty;

#if q4_MAC_LEAK_CHECK
    DebugNewForgetLeaks();
#endif

#if q4_MWCW_PROFILER
    if(!ProfilerInit(collectDetailed, bestTimeBase, 20, 5))
    {
#endif
        TestBasics1();
        TestBasics2();
        TestNotify();
        TestCustom1();
        TestCustom2();
        TestResize();
        TestStores1();
        TestStores2();
        TestStores3();
        TestStores4();
        TestStores5();
        TestDiffer();
        TestExtend();
        TestFormat();
        TestMapped();
        TestLimits();

#if q4_MWCW_PROFILER
        ProfilerDump("\pRegress.prof");
        ProfilerTerm();
    }
Example #4
0
void Test2()
{
  char tempstr[2048];
  int  n1, n2;

  /*
   * Set up for tests that will verify what was actually produced by log messages.
   * This is used to test log levels and to test the log_vnsprintf function.
   */
  SetComponentLogBuffer(COMPONENT_MAIN, tempstr);
  SetComponentLogBuffer(COMPONENT_INIT, tempstr);
  SetComponentLogLevel(COMPONENT_MAIN, NIV_EVENT);

  LogTest("------------------------------------------------------");
  LogTest("Test string/char formats");
  TestFormat("none");
  TestFormat("String: %s", "str");
  TestFormat("String: %12s", "str");
  TestFormat("String: %-12s", "str");
  TestFormat("String: %12s", "too long string");
  TestFormat("String: %-12s", "too long string");
  TestFormat("%c", (char) 65);
  // Not tested lc, ls, C, S

  LogTest("------------------------------------------------------");
  LogTest("Test integer formats");
  TestFormat("Integer: %d %d %i %i %u %s", 1, -1, 2, -2, 3, "extra");
  TestFormat("Octal and Hex: 0%o 0x%x 0x%X %s", 0123, 0xabcdef, 0xABCDEF, "extra");
  TestFormat("Field Length: %3d %s", 1, "extra");
  TestFormat("Variable Field Length: %*d %s", 5, 123, "extra");
  TestFormat("Alignment flags: %+d %+d %-5d %-5d %05d %05d % d % d %s", 2, -2, 333, -333, 444, -444, 5, -5, "extra");
  TestFormat("Two Flags: %-05d %-05d %0-5d %0-5d %s", 333, -333, 444, -444, "extra");
  TestFormat("Two Flags: %+ d %+ d % +d % +d %s", 333, -333, 444, -444, "extra");
  TestFormat("Two Flags: %-+5d %-+5d %+-5d %+-5d %s", 333, -333, 444, -444, "extra");
  TestFormat("Two Flags: %- 5d %- 5d % -5d % -5d %s", 333, -333, 444, -444, "extra");
  TestFormat("Two Flags: %+05d %+05d %0+5d %0+5d %s", 333, -333, 444, -444, "extra");
  TestFormat("Two Flags: % 05d % 05d %0 5d %0 5d %s", 333, -333, 444, -444, "extra");
  TestFormat("Use of # Flag: %#x %#3x %#05x %#-5x %-#5x %0#5x", 1, 2, 3, 4, 5, 6);
  TestFormat("Many Flags: %#-0 +#-0 +#-0 +5d", 4);
  TestFormat("Special Flags (may not be supported) %'d %Id %s", 12345, 67, "extra");

  LogTest("------------------------------------------------------");
  LogTest("Test floating point formats");
  TestFormat("%e %E %e %E %s", 1.1, 1.1, 1.1E10, 1.1E10, "extra");
  TestFormat("%f %F %f %F %s", 1.1, 1.1, 1.1E10, 1.1E10, "extra");
  TestFormat("%g %G %g %G %s", 1.1, 1.1, 1.1E10, 1.1E10, "extra");
  TestFormat("%a %A %a %A %s", 1.1, 1.1, 1.1E10, 1.1E10, "extra");
  TestFormat("%Le %LE %Le %LE %s", (long double) 1.1, (long double) 1.1, (long double) 1.1E10, (long double) 1.1E10, "extra");
  TestFormat("%Lf %LF %Lf %LF %s", (long double) 1.1, (long double) 1.1, (long double) 1.1E10, (long double) 1.1E10, "extra");
  TestFormat("%Lg %LG %Lg %LG %s", (long double) 1.1, (long double) 1.1, (long double) 1.1E10, (long double) 1.1E10, "extra");
  TestFormat("%La %LA %La %LA %s", (long double) 1.1, (long double) 1.1, (long double) 1.1E10, (long double) 1.1E10, "extra");
  TestFormat("%lle %llE %lle %llE %s", (long double) 1.1, (long double) 1.1, (long double) 1.1E10, (long double) 1.1E10, "extra");
  TestFormat("%llf %llF %llf %llf %s", (long double) 1.1, (long double) 1.1, (long double) 1.1E10, (long double) 1.1E10, "extra");
  TestFormat("%llg %llG %llg %llG %s", (long double) 1.1, (long double) 1.1, (long double) 1.1E10, (long double) 1.1E10, "extra");
  TestFormat("%lla %llA %lla %llA %s", (long double) 1.1, (long double) 1.1, (long double) 1.1E10, (long double) 1.1E10, "extra");
  TestFormat("Field Length: %8f %8.2f %8f %8.2f %s", 1.1, 1.1, 1.1E10, 1.1E3, "extra");
  TestFormat("Field Length: %08f %08.2f %08f %08.2f %s", 1.1, 1.1, 1.1E10, 1.1E3, "extra");
  TestFormat("Field Length: %-8f %-8.2f %-8f %-8.2f %s", 1.1, 1.1, 1.1E10, 1.1E3, "extra");
  TestFormat("Variable Field Length: %*.*f %*.2f %6.*f %s", 6, 2, 1.1, 6, 2.2, 2, 3.3, "extra");
  TestFormat("Negative:      %e %E %e %E %s    ", -1.1, -1.1, -1.1E10, -1.1E10, "extra");
  TestFormat("With '+' flag: %+e %+E %+e %+E %s", 1.1, 1.1, 1.1E10, 1.1E10, "extra");
  TestFormat("With ' ' flag: % e % E % e % E %s", 1.1, 1.1, 1.1E10, 1.1E10, "extra");
  TestFormat("With '#' flag: %#8.0e %8.0e %s", 1.0, 1.0, "extra");
  TestFormat("With '#' flag: %#g %g %#5g %#5g %5g %s", 1.0, 1.0, 2.0, 10.0, 2.0, "extra");

  LogTest("------------------------------------------------------");
  LogTest("Test some special formats");
  TestFormat("pointer: %p %s", &n1, "extra");
#if 0
// we can't support %n due to security considerations
  TestFormat("count: 12345678%n %s", &n1, "extra");
  snprintf(tempstr, 2048, "count: 12345678%n %s", &n1, "extra");
  log_snprintf(tempstr, 2048, "count: 12345678%n %s", &n2, "extra");
  if (n1 != n2)
    {
      LogTest("FAILURE: 12345678%%n produced %d expected %d", n2, n1);
      exit(1);
    }
  LogTest("SUCCESS: 12345678%%n produced %d", n2);
#endif
  errno = EIO;
  TestFormat("strerror: %m %64m %s", "extra");
  TestFormat("percent char: %% %s", "extra");

  LogTest("------------------------------------------------------");
  LogTest("Test integer size qualifier tags");
  TestFormat("%hhd %s", (char) 1, "extra");
  TestFormat("%hd %s", (short) 500, "extra");
  TestFormat("%lld %s", (long long) 12345678, "extra");
  TestFormat("%Ld %s", (long long) 12345678, "extra");
  TestFormat("%ld %s", (long) 12345, "extra");
  TestFormat("%qd %s", (long long) 12345678, "extra");
  TestFormat("%jd %s", (long long) 1, "extra");
  TestFormat("%td %s", (char *) &n1 - (char *) &n2, "extra");
  TestFormat("%zd %s", sizeof(int), "extra");

  /*
   * Ganesha can't properly support the $ parameter index tag, so don't bother testing, even if it does work
   * when the indices are in ascending order.
  TestFormat("%1$08x", 6);
  TestFormat("%3$llx %2$d %1d", 1, 2, (long long)0x12345678);
   */

  LogTest("------------------------------------------------------");
  LogTest("Ganesha specific tags");
  LogTest("\nTest %%b, %%B, %%h, %%H, %%y, and %%Y. These are odd tags:");
  LogTest("   %%b, %%B, %%h, and %%H each consume int1, str2, str3 even if not all are printed");
  LogTest("   %%y and %%Y each consume int1, str2, str3, int4, str5, str6 even if not all are printed");
  LogTest("   An extra string parameter is printed to demonstrate how the parameters are consumed");
  TestGaneshaFormat(TRUE,  "str2(1) (not part of %b)", "%b %s", 1, "str2", "str3", "(not part of %b)");
  TestGaneshaFormat(TRUE,  "str2(1) : 'str3' (not part of %B)", "%B %s", 1, "str2", "str3", "(not part of %B)");
  TestGaneshaFormat(TRUE,  "str2(1) (not part of %h)", "%h %s", 1, "str2", "str3", "(not part of %h)");
  TestGaneshaFormat(TRUE,  "str2(1) : 'str3' (not part of %H)", "%H %s", 1, "str2", "str3", "(not part of %H)");
  TestGaneshaFormat(TRUE,  "str2 str5(4) (not part of %y)", "%y %s", 1, "str2", "str3", 4, "str5", "str6", "(not part of %y)");
  TestGaneshaFormat(TRUE,  "str2(1) : 'str3' -> str5(4) : 'str6' (not part of %Y)", "%Y %s", 1, "str2", "str3", 4, "str5", "str6", "(not part of %Y)");
  LogTest("\nTest new tags for reporting errno values");
  TestGaneshaFormat(TRUE,  "EINVAL(22)", "%w", EINVAL);
  TestGaneshaFormat(TRUE,  "EINVAL(22) : 'Invalid argument'", "%W", EINVAL);
  LogTest("\nTest context sensitive tags");
  LogTest("%%K, %%V, and %%v go together, defaulting to ERR_SYS");
  LogTest("%%J, %%R, and %%r go together, defaulting to ERR_POSIX");
  TestGaneshaFormat(TRUE,  "ERR_SIGACTION(5) : 'sigaction impossible' EINVAL(22) : 'Invalid argument'", "%K%V %K%V", ERR_SYS, ERR_SIGACTION, ERR_POSIX, EINVAL);
  TestGaneshaFormat(TRUE,  "ERR_SIGACTION(5) EINVAL(22)", "%K%v %K%v", ERR_SYS, ERR_SIGACTION, ERR_POSIX, EINVAL);
  TestGaneshaFormat(TRUE,  "ERR_SIGACTION(5) : 'sigaction impossible' EINVAL(22) : 'Invalid argument'", "%J%R %J%R", ERR_SYS, ERR_SIGACTION, ERR_POSIX, EINVAL);
  TestGaneshaFormat(TRUE,  "ERR_SIGACTION(5) EINVAL(22)", "%J%r %J%r", ERR_SYS, ERR_SIGACTION, ERR_POSIX, EINVAL);
  TestGaneshaFormat(TRUE,  "ERR_SIGACTION(5) : 'sigaction impossible' EINVAL(22) : 'Invalid argument'", "%V %R", ERR_SIGACTION, EINVAL);
  TestGaneshaFormat(TRUE,  "ERR_SIGACTION(5) EINVAL(22)", "%v %r", ERR_SIGACTION, EINVAL);
  LogTest("Ganesha expects it's tags to just be two characters, for example %%b");
  TestGaneshaFormat(FALSE, "str2(1) (not part of %b)", "%5b %s", 1, "str2", "str3", "(not part of %b)");
}
void Test2()
{
  char tempstr[2048];
  int  n1, n2;

  /*
   * Set up for tests that will verify what was actually produced by log messages.
   * This is used to test log levels and to test the log_vnsprintf function.
   */
  SetComponentLogBuffer(COMPONENT_MAIN, tempstr);
  SetComponentLogBuffer(COMPONENT_INIT, tempstr);
  SetComponentLogLevel(COMPONENT_MAIN, NIV_EVENT);

  LogTest("------------------------------------------------------");
  LogTest("Test string/char formats");
  TestFormat("none");
  TestFormat("String: %s", "str");
  TestFormat("String: %12s", "str");
  TestFormat("String: %-12s", "str");
  TestFormat("String: %12s", "too long string");
  TestFormat("String: %-12s", "too long string");
  TestFormat("%c", (char) 65);
  // Not tested lc, ls, C, S

  LogTest("------------------------------------------------------");
  LogTest("Test integer formats");
  TestFormat("Integer: %d %d %i %i %u %s", 1, -1, 2, -2, 3, "extra");
  TestFormat("Octal and Hex: 0%o 0x%x 0x%X %s", 0123, 0xabcdef, 0xABCDEF, "extra");
  TestFormat("Field Length: %3d %s", 1, "extra");
  TestFormat("Variable Field Length: %*d %s", 5, 123, "extra");
  TestFormat("Alignment flags: %+d %+d %-5d %-5d %05d %05d % d % d %s", 2, -2, 333, -333, 444, -444, 5, -5, "extra");
  // TestFormat("Two Flags: %-05d %-05d %0-5d %0-5d %s", 333, -333, 444, -444, "extra");
  // TestFormat("Two Flags: %+ d %+ d % +d % +d %s", 333, -333, 444, -444, "extra");
  TestFormat("Two Flags: %-+5d %-+5d %+-5d %+-5d %s", 333, -333, 444, -444, "extra");
  TestFormat("Two Flags: %- 5d %- 5d % -5d % -5d %s", 333, -333, 444, -444, "extra");
  TestFormat("Two Flags: %+05d %+05d %0+5d %0+5d %s", 333, -333, 444, -444, "extra");
  TestFormat("Two Flags: % 05d % 05d %0 5d %0 5d %s", 333, -333, 444, -444, "extra");
  TestFormat("Use of # Flag: %#x %#3x %#05x %#-5x %-#5x %0#5x", 1, 2, 3, 4, 5, 6);
  // TestFormat("Many Flags: %#-0 +#-0 +#-0 +5d", 4);
  TestFormat("Special Flags (may not be supported) %'d %Id %s", 12345, 67, "extra");

  LogTest("------------------------------------------------------");
  LogTest("Test floating point formats");
  TestFormat("%e %E %e %E %s", 1.1, 1.1, 1.1E10, 1.1E10, "extra");
  TestFormat("%f %F %f %F %s", 1.1, 1.1, 1.1E10, 1.1E10, "extra");
  TestFormat("%g %G %g %G %s", 1.1, 1.1, 1.1E10, 1.1E10, "extra");
  TestFormat("%a %A %a %A %s", 1.1, 1.1, 1.1E10, 1.1E10, "extra");
  TestFormat("%Le %LE %Le %LE %s", (long double) 1.1, (long double) 1.1, (long double) 1.1E10, (long double) 1.1E10, "extra");
  TestFormat("%Lf %LF %Lf %LF %s", (long double) 1.1, (long double) 1.1, (long double) 1.1E10, (long double) 1.1E10, "extra");
  TestFormat("%Lg %LG %Lg %LG %s", (long double) 1.1, (long double) 1.1, (long double) 1.1E10, (long double) 1.1E10, "extra");
  TestFormat("%La %LA %La %LA %s", (long double) 1.1, (long double) 1.1, (long double) 1.1E10, (long double) 1.1E10, "extra");
  TestFormat("%lle %llE %lle %llE %s", (long double) 1.1, (long double) 1.1, (long double) 1.1E10, (long double) 1.1E10, "extra");
  TestFormat("%llf %llF %llf %llf %s", (long double) 1.1, (long double) 1.1, (long double) 1.1E10, (long double) 1.1E10, "extra");
  TestFormat("%llg %llG %llg %llG %s", (long double) 1.1, (long double) 1.1, (long double) 1.1E10, (long double) 1.1E10, "extra");
  TestFormat("%lla %llA %lla %llA %s", (long double) 1.1, (long double) 1.1, (long double) 1.1E10, (long double) 1.1E10, "extra");
  TestFormat("Field Length: %8f %8.2f %8f %8.2f %s", 1.1, 1.1, 1.1E10, 1.1E3, "extra");
  TestFormat("Field Length: %08f %08.2f %08f %08.2f %s", 1.1, 1.1, 1.1E10, 1.1E3, "extra");
  TestFormat("Field Length: %-8f %-8.2f %-8f %-8.2f %s", 1.1, 1.1, 1.1E10, 1.1E3, "extra");
  TestFormat("Variable Field Length: %*.*f %*.2f %6.*f %s", 6, 2, 1.1, 6, 2.2, 2, 3.3, "extra");
  TestFormat("Negative:      %e %E %e %E %s    ", -1.1, -1.1, -1.1E10, -1.1E10, "extra");
  TestFormat("With '+' flag: %+e %+E %+e %+E %s", 1.1, 1.1, 1.1E10, 1.1E10, "extra");
  TestFormat("With ' ' flag: % e % E % e % E %s", 1.1, 1.1, 1.1E10, 1.1E10, "extra");
  TestFormat("With '#' flag: %#8.0e %8.0e %s", 1.0, 1.0, "extra");
  TestFormat("With '#' flag: %#g %g %#5g %#5g %5g %s", 1.0, 1.0, 2.0, 10.0, 2.0, "extra");

  LogTest("------------------------------------------------------");
  LogTest("Test some special formats");
  TestFormat("pointer: %p %s", &n1, "extra");
#if 0
// we can't support %n due to security considerations
  TestFormat("count: 12345678%n %s", &n1, "extra");
  snprintf(tempstr, 2048, "count: 12345678%n %s", &n1, "extra");
  log_snprintf(tempstr, 2048, "count: 12345678%n %s", &n2, "extra");
  if (n1 != n2)
    {
      LogTest("FAILURE: 12345678%%n produced %d expected %d", n2, n1);
      exit(1);
    }
  LogTest("SUCCESS: 12345678%%n produced %d", n2);
#endif
  errno = EIO;
  TestFormat("strerror: %m %64m %s", "extra");
  TestFormat("percent char: %% %s", "extra");

  LogTest("------------------------------------------------------");
  LogTest("Test integer size qualifier tags");
  TestFormat("%hhd %s", (char) 1, "extra");
  TestFormat("%hd %s", (short) 500, "extra");
  TestFormat("%lld %s", (long long) 12345678, "extra");
  TestFormat("%Ld %s", (long long) 12345678, "extra");
  TestFormat("%ld %s", (long) 12345, "extra");
  TestFormat("%qd %s", (long long) 12345678, "extra");
  TestFormat("%jd %s", (long long) 1, "extra");
  TestFormat("%td %s", (char *) &n1 - (char *) &n2, "extra");
  TestFormat("%zd %s", sizeof(int), "extra");

  /*
   * Ganesha can't properly support the $ parameter index tag, so don't bother testing, even if it does work
   * when the indices are in ascending order.
  TestFormat("%1$08x", 6);
  TestFormat("%3$llx %2$d %1d", 1, 2, (long long)0x12345678);
   */

}
BOOL DXContext::Internal_Init(DXCONTEXT_PARAMS *pParams, BOOL bFirstInit)
{
	memcpy(&m_current_mode, pParams, sizeof(DXCONTEXT_PARAMS));
	memset(&myWindowState,0,sizeof(myWindowState));

	// various checks
	if (m_current_mode.screenmode != WINDOWED)
		m_current_mode.m_skin = 0;

	// 1. destroy old window
	if (m_hwnd)
	{
		m_ignore_wm_destroy = 1;
		DestroyWindow(m_hwnd);
		m_ignore_wm_destroy = 0;
		m_hwnd = NULL;
	}

	// 2. CHECK TO MAKE SURE DIRECTX/DDRAW IS INSTALLED
	if (bFirstInit)
	{
		// Test for DirectX 9 + start it
		// note: if you don't call LoadLibrary here, and you're on a system
		//       where DX9 is missing, Direct3DCreate8() might crash; so call it.
		int d3d9_already_loaded = (GetModuleHandle("d3d9.dll") != NULL) ? 1 : 0;
		if (!d3d9_already_loaded)
			m_hmod_d3d9 = LoadLibrary("d3d9.dll");

		if ((!d3d9_already_loaded && !m_hmod_d3d9) ||
		    !(m_lpD3D = Direct3DCreate9(D3D_SDK_VERSION))
		   )
		{
			MissingDirectX(NULL);
			m_lastErr = DXC_ERR_CREATE3D;
			return FALSE;
		}

		if (!m_hmod_d3dx9)
			m_hmod_d3dx9 = FindD3DX9(m_hwnd_winamp);

		if ((!m_hmod_d3dx9))
		{
			MissingDirectX(NULL);
			m_lastErr = DXC_ERR_CREATE3D;
			return FALSE;
		}
	}

	// 3. get the smallest single rectangle that encloses ALL the monitors on the desktop:
	SetRect(&m_all_monitors_rect, 0, 0, 0, 0);
	EnumDisplayMonitors(NULL, NULL, MyMonitorEnumProc, (LPARAM)&m_all_monitors_rect);

	// 4. some DirectX- / DDraw-specific stuff.  Also determine hPluginMonitor.
	HMONITOR hPluginMonitor = NULL;
	{
		D3DADAPTER_IDENTIFIER9 temp;

		// find the ordinal # of the adapter whose GUID matches what the user picked from the config panel,
		// and whose DeviceName matches as well.
		// if no match found, use D3DADAPTER_DEFAULT.
		m_ordinal_adapter = D3DADAPTER_DEFAULT;
		int nAdapters = m_lpD3D->GetAdapterCount();
		{
			for (int i=0; i<nAdapters; i++)
			{
				if ((m_lpD3D->GetAdapterIdentifier(i, /*D3DENUM_NO_WHQL_LEVEL*/ 0, &temp) == D3D_OK) &&
				    (memcmp(&temp.DeviceIdentifier, &m_current_mode.adapter_guid, sizeof(GUID))==0) &&
				    !strcmp(temp.DeviceName, m_current_mode.adapter_devicename)
				   )
				{
					m_ordinal_adapter = i;
					break;
				}
			}
		}

		if (m_lpD3D->GetAdapterIdentifier(m_ordinal_adapter, /*D3DENUM_NO_WHQL_LEVEL*/ 0, &temp) == D3D_OK)
		{
			StringCbCopy(m_szDriver, sizeof(m_szDriver), temp.Driver);
			StringCbCopy(m_szDesc, sizeof(m_szDesc), temp.Description);
		}

		int caps_ok = 0;
		int caps_tries = 0;
		int changed_fs_disp_mode;

		// try to get the device caps for the adapter selected from the config panel.
		// if GetDeviceCaps() fails, it's probably because the adapter has been
		// removed from the system (or disabled), so we try again with other adapter(s).
		do
		{
			changed_fs_disp_mode = 0;

			SetRect(&m_monitor_rect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));

			// get bounding rect of the monitor attached to the adapter (to assist w/window positioning)
			// note: in vert/horz span setups (psuedo-multimon),
			//       this will be 2048x768 or 1024x1536 or something like that.
			hPluginMonitor = m_lpD3D->GetAdapterMonitor(m_ordinal_adapter);
			/*if (hPluginMonitor)
			{
			    MONITORINFO mi;
			    mi.cbSize = sizeof(mi);
			    if (GetMonitorInfo(hPluginMonitor, &mi))
			    {
			        memcpy(&m_monitor_rect, &mi.rcMonitor, sizeof(RECT));
			        memcpy(&m_monitor_work_rect, &mi.rcWork, sizeof(RECT));
			    }
			}*/

			if (bFirstInit)
			{
				for (int i=0; i<min(nAdapters, MAX_DXC_ADAPTERS); i++)
				{
					// if this is the first call to Init, get the display mode's original color format,
					// before we go changing it:
					D3DDISPLAYMODE d3ddm;
					if (FAILED(m_lpD3D->GetAdapterDisplayMode(i, &d3ddm)))
					{
						d3ddm.Format = D3DFMT_UNKNOWN;
					}
					m_orig_windowed_mode_format[i] = d3ddm.Format;
				}
			}

			// figure out pixel (color) format for back buffer: (m_current_mode.display_mode.Format)
			if (m_current_mode.screenmode!=FULLSCREEN && m_ordinal_adapter < MAX_DXC_ADAPTERS)
				m_current_mode.display_mode.Format = m_orig_windowed_mode_format[m_ordinal_adapter];
			// else
			// for fullscreen, use what they gave us

			if (m_current_mode.display_mode.Format == D3DFMT_UNKNOWN ||
			    !TestFormat(m_ordinal_adapter, m_current_mode.display_mode.Format))
			{
				// if they try to run the plugin without ever running the config panel
				// first (& pressing OK), then the fullscreen pixelformat hasn't been
				// chosen... so we try all the possilibities until one works:
				if (TestFormat(m_ordinal_adapter,D3DFMT_A8R8G8B8)) m_current_mode.display_mode.Format = D3DFMT_A8R8G8B8;
				else if (TestFormat(m_ordinal_adapter,D3DFMT_X8R8G8B8)) m_current_mode.display_mode.Format = D3DFMT_X8R8G8B8;
				else if (TestFormat(m_ordinal_adapter,D3DFMT_R8G8B8)) m_current_mode.display_mode.Format = D3DFMT_R8G8B8  ;
				else if (TestFormat(m_ordinal_adapter,D3DFMT_R5G6B5)) m_current_mode.display_mode.Format = D3DFMT_R5G6B5  ;
				else if (TestFormat(m_ordinal_adapter,D3DFMT_X1R5G5B5)) m_current_mode.display_mode.Format = D3DFMT_X1R5G5B5;
				else if (TestFormat(m_ordinal_adapter,D3DFMT_A1R5G5B5)) m_current_mode.display_mode.Format = D3DFMT_A1R5G5B5;
				else if (TestFormat(m_ordinal_adapter,D3DFMT_A4R4G4B4)) m_current_mode.display_mode.Format = D3DFMT_A4R4G4B4;
				else if (TestFormat(m_ordinal_adapter,D3DFMT_X4R4G4B4)) m_current_mode.display_mode.Format = D3DFMT_X4R4G4B4;
			}

			if (m_current_mode.display_mode.Format==D3DFMT_UNKNOWN)
			{
				wchar_t title[64];
				m_lastErr = DXC_ERR_FORMAT;
				MessageBoxW(m_hwnd, WASABI_API_LNGSTRINGW(IDS_DIRECTX_INIT_FAILED),
						    WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
						    MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
				return FALSE;
			}

			if (m_current_mode.screenmode == FULLSCREEN)
				changed_fs_disp_mode = CheckAndCorrectFullscreenDispMode(m_ordinal_adapter, &m_current_mode.display_mode);

			// figure out pixel format of the z-buffer: (m_zFormat)
			m_zFormat = D3DFMT_UNKNOWN;
			/*
			if      (TestDepth(m_ordinal_adapter,D3DFMT_D32         )) m_zFormat=D3DFMT_D32;
			else if (TestDepth(m_ordinal_adapter,D3DFMT_D24S8       )) m_zFormat=D3DFMT_D24S8;
			else if (TestDepth(m_ordinal_adapter,D3DFMT_D24X4S4     )) m_zFormat=D3DFMT_D24X4S4;
			else if (TestDepth(m_ordinal_adapter,D3DFMT_D24X8       )) m_zFormat=D3DFMT_D24X8;
			else if (TestDepth(m_ordinal_adapter,D3DFMT_D16         )) m_zFormat=D3DFMT_D16;
			else if (TestDepth(m_ordinal_adapter,D3DFMT_D15S1       )) m_zFormat=D3DFMT_D15S1;
			else if (TestDepth(m_ordinal_adapter,D3DFMT_D16_LOCKABLE)) m_zFormat=D3DFMT_D16_LOCKABLE;
			*/

			// get device caps:
			memset(&m_caps, 0, sizeof(m_caps));
			if (FAILED(m_lpD3D->GetDeviceCaps(m_ordinal_adapter, D3DDEVTYPE_HAL, &m_caps)))
			{
				// that adapter was found in the system, but it might be disabled
				// (i.e. 'extend my Windows desktop onto this monitor') is unchecked)
				// so, try other adapters (try all sequentially).

				if (caps_tries < nAdapters)
				{
					// try again, this time using the default adapter:
					m_ordinal_adapter = caps_tries;
					caps_tries++;
				}
				else
				{
					wchar_t title[64];
					m_lastErr = DXC_ERR_CAPSFAIL;
					MessageBoxW(m_hwnd, WASABI_API_LNGSTRINGW(IDS_DXC_ERR_CAPSFAIL),
							    WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
							    MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
					return FALSE;
				}
			}
			else
			{
				caps_ok = 1;
			}
		}
		while (!caps_ok);

		if (changed_fs_disp_mode)
		{
			wchar_t title[64];
			MessageBoxW(m_hwnd, WASABI_API_LNGSTRINGW(IDS_FS_DISPLAY_MODE_SELECTED_IS_INVALID),
					    WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_WARNING, title, 64),
					    MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
		}

		switch (m_current_mode.display_mode.Format)
		{
		case D3DFMT_R8G8B8  : m_bpp = 32; break;
		case D3DFMT_A8R8G8B8: m_bpp = 32; break;
		case D3DFMT_X8R8G8B8: m_bpp = 32; break;
		case D3DFMT_R5G6B5  : m_bpp = 16; break;
		case D3DFMT_X1R5G5B5: m_bpp = 16; break;
		case D3DFMT_A1R5G5B5: m_bpp = 16; break;
		case D3DFMT_A8R3G3B2: m_bpp = 16; break;
		case D3DFMT_A4R4G4B4: m_bpp = 16; break;
		case D3DFMT_X4R4G4B4: m_bpp = 16; break;
		case D3DFMT_R3G3B2  : m_bpp =  8; break; // misleading?  implies a palette...
		}
	}

	// 5. set m_monitor_rect and m_monitor_work_rect.
	if (hPluginMonitor)
	{
		MONITORINFO mi;
		mi.cbSize = sizeof(mi);
		if (GetMonitorInfo(hPluginMonitor, &mi))
		{
			m_monitor_rect = mi.rcMonitor;
			m_monitor_rect_orig = mi.rcMonitor;
			m_monitor_work_rect = mi.rcWork;
			m_monitor_work_rect_orig = mi.rcWork;
		}
	}

	// 6. embedded window stuff [where the plugin window is integrated w/winamp]
	if (m_current_mode.m_skin)
	{
		// set up the window's position on screen
		// note that we'd prefer to set the CLIENT size we want, but we can't, so we'll just do
		// this here, and later, adjust the client rect size to what's left...
		int size = GetWindowedModeAutoSize(0);  // note: requires 'm_monitor_rect' has been set!
		myWindowState.r.left   = GetPrivateProfileIntW(L"settings",L"avs_wx",64,m_szIniFile);
		myWindowState.r.top    = GetPrivateProfileIntW(L"settings",L"avs_wy",64,m_szIniFile);
		myWindowState.r.right  = myWindowState.r.left + GetPrivateProfileIntW(L"settings",L"avs_ww",size+24,m_szIniFile);
		myWindowState.r.bottom = myWindowState.r.top  + GetPrivateProfileIntW(L"settings",L"avs_wh",size+40,m_szIniFile);

		// only works on winamp 2.90+!
		int success = 0;
		if (GetWinampVersion(mod1.hwndParent) >= 0x2900)
		{
			SET_EMBED_GUID((&myWindowState), avs_guid);
			myWindowState.flags |= EMBED_FLAGS_NOTRANSPARENCY;
			HWND (*e)(embedWindowState *v);
			*(void**)&e = (void *)SendMessage(mod1.hwndParent,WM_WA_IPC,(LPARAM)0,IPC_GET_EMBEDIF);
			if (e)
			{
				m_current_mode.parent_window = e(&myWindowState);
				if (m_current_mode.parent_window)
				{
					SetWindowText(m_current_mode.parent_window, m_szWindowCaption);
					success = 1;
				}
			}
		}

		if (!success)
			m_current_mode.m_skin = 0;
	}

	// remember the client rect that was originally desired...
	RECT windowed_mode_desired_client_rect;
	windowed_mode_desired_client_rect.top    = GetPrivateProfileIntW(L"settings",L"nMainWndTop",-1,m_szIniFile);
	windowed_mode_desired_client_rect.left   = GetPrivateProfileIntW(L"settings",L"nMainWndLeft",-1,m_szIniFile);
	windowed_mode_desired_client_rect.right  = GetPrivateProfileIntW(L"settings",L"nMainWndRight",-1,m_szIniFile);
	windowed_mode_desired_client_rect.bottom = GetPrivateProfileIntW(L"settings",L"nMainWndBottom",-1,m_szIniFile);

	// ...and in case windowed mode init fails severely,
	// set it up to try next time for a simple 256x256 window.
	WriteSafeWindowPos();

	// 7. create the window, if not already created
	if (!m_hwnd)
	{
		m_hwnd = CreateWindowEx(
		           MY_EXT_WINDOW_STYLE, // extended style
		           MAKEINTATOM(m_classAtom), // class
		           m_szWindowCaption, // caption
		           MY_WINDOW_STYLE, // style
		           0, // left
		           0, // top
		           256,  // temporary width
		           256,  // temporary height
		           m_current_mode.parent_window,  // parent window
		           NULL, // menu
		           m_hInstance, // instance
		           (LPVOID)m_uWindowLong
		         ); // parms

		if (!m_hwnd)
		{
			wchar_t title[64];
			m_lastErr = DXC_ERR_CREATEWIN;
			MessageBoxW(m_hwnd, WASABI_API_LNGSTRINGW(IDS_CREATEWINDOW_FAILED),
					    WASABI_API_LNGSTRINGW_BUF(IDS_MILKDROP_ERROR, title, 64),
					    MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
			return FALSE;
		}

		SendMessage(m_hwnd_winamp, WM_WA_IPC, (WPARAM)m_hwnd, IPC_SETVISWND);

		if (m_current_mode.m_skin)
		{
			if (GetWinampVersion(mod1.hwndParent) < 0x5051)
				ShowWindow(m_current_mode.parent_window,SW_SHOWNA); // showing the parent wnd will make it size the child, too
			else
				SendMessage(m_current_mode.parent_window, WM_USER+102, 0, 0); // benski> major hack alert. winamp's embedwnd will call ShowWindow in response.  SendMessage moves us over to the main thread (we're currently sitting on the viz thread)
		}		
	}

	// 8. minimize winamp before creating devices & such, so there aren't
	//    any confusing window-focus issues
	MinimizeWinamp(hPluginMonitor);

	// 9. loop to try and create the window.
	//      if in windowed mode and not enough vidmem, it will try again w/smaller window
	//      (repeatedly, until window client size would be < 64)
	int iteration = 0;
	int device_ok = 0;
	do
	{
		// set the window position
		if (m_current_mode.screenmode==DESKTOP ||
		    m_current_mode.screenmode==FAKE_FULLSCREEN)
		{
			int x = m_monitor_rect.right - m_monitor_rect.left;
			int y = m_monitor_rect.bottom - m_monitor_rect.top;

			if (x >= y*2)
			{
				// (pseudo-multimon modes like 2048x768)
				int mid = (m_monitor_rect.left + m_monitor_rect.right)/2;
				if (m_current_mode.m_dualhead_horz==1) // show on left side
					m_monitor_rect.right = mid;
				else if (m_current_mode.m_dualhead_horz==2) // show on right side
					m_monitor_rect.left = mid;
			}
			else if (y > x*4/3)
			{
				// (pseudo-multimon modes like 1024x1536)
				int mid = (m_monitor_rect.top + m_monitor_rect.bottom)/2;
				if (m_current_mode.m_dualhead_vert==1) // show on top half
					m_monitor_rect.bottom = mid;
				else if (m_current_mode.m_dualhead_vert==2) // show on bottom half
					m_monitor_rect.top = mid;
			}

			// recompute width & height (into x,y):
			x = m_monitor_rect.right - m_monitor_rect.left;
			y = m_monitor_rect.bottom - m_monitor_rect.top;

			m_client_width  = x;
			m_client_height = y;
			m_window_width  = x;
			m_window_height = y;

			if (m_current_mode.screenmode == DESKTOP)
			{
				// note: we initially hide the window, and then
				// only display it once the desktop is all nice & ready.
				// see CPluginShell::DrawAndDisplay().

				RECT r = m_monitor_rect;

				// if possible, shrink the desktop window so it doesn't cover the taskbar.
				HWND hTaskbar = FindWindow("Shell_TrayWnd", "");
				if (hTaskbar)
				{
					RECT taskbar;
					GetWindowRect(hTaskbar, &taskbar);
					int tbw = taskbar.right - taskbar.left;
					int tbh = taskbar.bottom-taskbar.top;

					if (taskbar.bottom == m_monitor_rect.bottom &&
					    taskbar.left == m_monitor_rect.left &&
					    taskbar.right == m_monitor_rect.right)
					{
						r.bottom -= tbh;
					}
					else if (taskbar.top == m_monitor_rect.top &&
					         taskbar.left == m_monitor_rect.left &&
					         taskbar.right == m_monitor_rect.right)
					{
						r.top += tbh;
					}
					else if (taskbar.left == m_monitor_rect.left &&
					         taskbar.top == m_monitor_rect.top &&
					         taskbar.bottom == m_monitor_rect.bottom)
					{
						r.left += tbw;
					}
					else if (taskbar.right == m_monitor_rect.right &&
					         taskbar.top == m_monitor_rect.top &&
					         taskbar.bottom == m_monitor_rect.bottom)
					{
						r.right -= tbw;
					}

					m_client_width  = r.right - r.left;
					m_client_height = r.bottom - r.top;
					m_REAL_client_width = m_client_width;
					m_REAL_client_height = m_client_height;
					m_window_width  = m_client_width;
					m_window_height = m_client_height;

					//...ok, but text is squished - some w/h is not right...

				}

				SetWindowPos(m_hwnd,HWND_BOTTOM,r.left,r.top,r.right-r.left,r.bottom-r.top,SWP_HIDEWINDOW);
			}
			else // FAKE_FULLSCREEN
			{
				if (memcmp(&m_all_monitors_rect, &m_monitor_rect, sizeof(RECT))==0)
				{
					// there's only one display, and it's entirely covered
					// by the plugin -> PUT THE PLUGIN ABOVE THE TASKBAR
					// -> normally, if the user clicked another window,
					//      it would pop the taskbar to the top; but we don't
					//      have to worry about that here, since we're taking
					//      up the whole screen.
					// -> don't worry about making the text, etc. avoid
					//      the taskbar in this case (see DrawAndDisplay())
					// -> DO worry about hiding the mouse cursor in this case
					//      (see WM_SETCURSOR handler)

					m_fake_fs_covers_all = 1;
					//SetWindowPos(m_hwnd,HWND_TOPMOST,m_monitor_rect.left,m_monitor_rect.top,m_window_width,m_window_height,SWP_SHOWWINDOW);
				}
				else
				{
					// there is space to work outside of the plugin window.
					// -> here we pretty much have to let the taskbar stay on
					//   top, because it really likes to be there; i.e.,
					//   if you click any other window, it automatically
					//   pops up again.
					// -> therefore, TRY TO KEEP THE WINDOW ON BOTTOM
					//      (below the taskbar). (see PushWindowToBack)
					// -> don't worry about hiding the mouse cursor in this case
					//      (see WM_SETCURSOR handler)
					// -> DO worry about making the text, etc. avoid
					//      the taskbar in this case (see DrawAndDisplay())

					// (note that if taskbar is in the way, they can move it,
					//   since there are other monitors available)

					m_fake_fs_covers_all = 0;
					//SetWindowPos(m_hwnd,HWND_TOP,m_monitor_rect.left,m_monitor_rect.top,m_window_width,m_window_height,SWP_SHOWWINDOW);
				}

				SetWindowPos(m_hwnd,HWND_TOPMOST,m_monitor_rect.left,m_monitor_rect.top,m_window_width,m_window_height,SWP_SHOWWINDOW);
			}
		}
		else if (m_current_mode.screenmode == FULLSCREEN)
		{
			int x = m_current_mode.display_mode.Width ;
			int y = m_current_mode.display_mode.Height;
			int cx = m_monitor_rect.right - m_monitor_rect.left;
			int cy = m_monitor_rect.bottom - m_monitor_rect.top;

			// test #1
			if (x >= y*2 || y > x*4/3)     // tackle problem of vert/horz spans
			{
				wchar_t title[64];
				int ret = MessageBoxW(m_hwnd, WASABI_API_LNGSTRINGW(IDS_TRYING_TO_ENTER_FS_MODE_WITH_MULTIPLE_DISPLAYS),
									  WASABI_API_LNGSTRINGW_BUF(IDS_TIP, title, 64),
									  MB_OKCANCEL|MB_SETFOREGROUND|MB_TOPMOST);
				if (ret==IDCANCEL)
				{
					m_lastErr = DXC_ERR_USER_CANCELED;
					return FALSE;
				}
			}

			// test #2
			if ((cx >= cy*2 && x < y*2) || (cy > cx*4/3 && y <= x*4/3))
			{
				wchar_t title[64];
				int ret = MessageBoxW(m_hwnd, WASABI_API_LNGSTRINGW(IDS_TRYING_TO_ENTER_FS_MODE_WITH_MULTIPLE_DISPLAYS_2),
									  WASABI_API_LNGSTRINGW_BUF(IDS_TIP, title, 64),
									  MB_OKCANCEL|MB_SETFOREGROUND|MB_TOPMOST);
				if (ret==IDCANCEL)
				{
					m_lastErr = DXC_ERR_USER_CANCELED;
					return FALSE;
				}
			}

			m_client_width  = x;
			m_client_height = y;
			m_window_width  = x;
			m_window_height = y;
			SetWindowPos(m_hwnd,HWND_TOPMOST,m_monitor_rect.left,m_monitor_rect.top,m_window_width,m_window_height,SWP_SHOWWINDOW);
		}
		else // WINDOWED
		{
			RECT margin;
			if (m_current_mode.m_skin)
			{
				RECT r1, r2;
				GetWindowRect(m_current_mode.parent_window, &r1);
				GetWindowRect(m_hwnd , &r2);
				margin.left  = r2.left - r1.left;
				margin.right = r1.right - r2.right;
				margin.top   = r2.top - r1.top;
				margin.bottom= r1.bottom - r2.bottom;
			}
			else
			{
				RECT r1;
				SetRect(&r1, 0, 0, 256, 256);
				AdjustWindowRect(&r1, MY_WINDOW_STYLE, 0);
				margin.left  = 0 - r1.left;
				margin.right = r1.right - 256;
				margin.top   = 0 - r1.top;
				margin.bottom= r1.bottom - 256;
			}

			int autosize = 1;

			RECT r = windowed_mode_desired_client_rect;
			if (iteration==0 && r.top != -1 && r.left != -1 && r.bottom != -1 && r.right != -1)
			{
				// use prev. window coordinates:
				m_REAL_client_width  = r.right - r.left;
				m_REAL_client_height = r.bottom - r.top;
				GetSnappedClientSize();
				if (m_current_mode.m_skin) // check this here in case they got a non-aligned size by resizing when "integrated with winamp" was unchecked, then checked it & ran the plugin...
				{
					// STRANGE ALIGNMENTS FOR THE WINDOW FRAME: (required by winamp 2):
					// the window frame's width must be divisible by 25, and height by 29.
					if (GetWinampVersion(mod1.hwndParent) < 0x4000) // ... winamp 5 doesn't have this prob.  (test vs. 0x4000 because winamp5 betas have version tags like 0x4987)
					{
						m_REAL_client_width  = ((m_client_width + margin.left + margin.right)/25)*25 - margin.left - margin.right;
						m_REAL_client_height = ((m_client_height + margin.top + margin.bottom)/29)*29 - margin.top - margin.bottom;
						GetSnappedClientSize();
					}
				}

				// transform screen-space CLIENT rect into screen-space WINDOW rect
				r.top    = windowed_mode_desired_client_rect.top    - margin.top;
				r.left   = windowed_mode_desired_client_rect.left   - margin.left;
				r.right  = r.left + margin.left + m_REAL_client_width  + margin.right;
				r.bottom = r.top  + margin.top  + m_REAL_client_height + margin.bottom;

				// make sure the window is entirely visible on the selected monitor;
				//   otherwise, autosize/place it.
				// (note that this test is only appled 1) at startup, and 2) after a resize/max/restore.
				//  this test is not applied when merely moving the window.)
				if (r.top    >= m_monitor_work_rect.top &&
				    r.left   >= m_monitor_work_rect.left &&
				    r.right  <= m_monitor_work_rect.right &&
				    r.bottom <= m_monitor_work_rect.bottom)
				{
					if (m_current_mode.m_skin)
					{
						m_window_width  = m_REAL_client_width ; // m_window_width/height are for OUR borderless window, not the embedwnd parent frame.
						m_window_height = m_REAL_client_height;
						SetWindowPos(m_current_mode.parent_window,HWND_NOTOPMOST, r.left, r.top, r.right-r.left, r.bottom-r.top, /*SWP_SHOWWINDOW|*//*SWP_ASYNCWINDOWPOS*/0);
						SetWindowPos(m_hwnd ,HWND_NOTOPMOST, windowed_mode_desired_client_rect.left,
						             windowed_mode_desired_client_rect.top,
						             m_REAL_client_width,
						             m_REAL_client_height,
						             SWP_SHOWWINDOW);
					}
					else
					{
						m_window_width  = r.right - r.left;
						m_window_height = r.bottom - r.top;
						SetWindowPos(m_hwnd,HWND_NOTOPMOST,r.left,r.top,m_window_width,m_window_height,SWP_SHOWWINDOW);
					}

					autosize = 0;
				}
			}

			if (autosize)
			{
				int size = GetWindowedModeAutoSize(iteration); // note: requires 'm_monitor_rect' has been set!

				m_REAL_client_width  = size;
				m_REAL_client_height = size;
				GetSnappedClientSize();

				if (m_current_mode.m_skin)
				{
					// STRANGE ALIGNMENTS FOR THE WINDOW FRAME: (required by winamp 2):
					// the window frame's width must be divisible by 25, and height by 29.
					if (GetWinampVersion(mod1.hwndParent) < 0x4000) // ... winamp 5 doesn't have this prob.  (test vs. 0x4000 because winamp5 betas have version tags like 0x4987)
					{
						m_REAL_client_width  = ((m_client_width + margin.left + margin.right)/25)*25 - margin.left - margin.right;
						m_REAL_client_height = ((m_client_height + margin.top + margin.bottom)/29)*29 - margin.top - margin.bottom;
						GetSnappedClientSize();
					}

					m_window_width  = m_client_width ; // m_window_width/height are for OUR [borderless] window, not the parent window (which is the embedwnd frame).
					m_window_height = m_client_height;
					SetWindowPos(m_current_mode.parent_window,HWND_NOTOPMOST, m_monitor_work_rect.left+32, m_monitor_work_rect.top+32, m_client_width + margin.left + margin.right, m_client_height + margin.top + margin.bottom, /*SWP_SHOWWINDOW|*//*SWP_ASYNCWINDOWPOS*/0);
					SetWindowPos(m_hwnd ,HWND_NOTOPMOST, m_monitor_work_rect.left+32 + margin.left, m_monitor_work_rect.top+32 + margin.top, m_client_width, m_client_height, SWP_SHOWWINDOW);
				}
				else
				{
					SetRect(&r, 0, 0, size, size);
					AdjustWindowRect(&r, MY_WINDOW_STYLE, 0);

					m_window_width  = r.right - r.left;
					m_window_height = r.bottom - r.top;

					SetWindowPos(m_hwnd,HWND_NOTOPMOST, m_monitor_work_rect.left+32, m_monitor_work_rect.top+32, m_window_width, m_window_height, SWP_SHOWWINDOW);
				}
			}
		}

		m_frame_delay = 1;      // set this to 2 if you use triple buffering!

		{
			m_current_mode.display_mode.Width  = m_client_width;
			m_current_mode.display_mode.Height = m_client_height;

			// set up m_d3dpp (presentation parameters):
			ZeroMemory(&m_d3dpp,sizeof(m_d3dpp));
			m_d3dpp.Windowed         = (m_current_mode.screenmode==FULLSCREEN) ? 0 : 1;
			m_d3dpp.BackBufferFormat = m_current_mode.display_mode.Format;
			m_d3dpp.BackBufferWidth  = m_client_width;
			m_d3dpp.BackBufferHeight = m_client_height;
			m_d3dpp.BackBufferCount  = m_current_mode.nbackbuf;
			if (m_current_mode.screenmode==FULLSCREEN)
				m_d3dpp.SwapEffect   = D3DSWAPEFFECT_DISCARD;//D3DSWAPEFFECT_FLIP;
			else    // windowed or fake FS
				m_d3dpp.SwapEffect   = (m_current_mode.allow_page_tearing) ? D3DSWAPEFFECT_DISCARD : D3DSWAPEFFECT_COPY;//D3DSWAPEFFECT_DISCARD;//D3DSWAPEFFECT_FLIP;
			// note: multisampling is only allowed if swapeffect is DISCARD!
			m_d3dpp.MultiSampleType  = (m_d3dpp.SwapEffect==D3DSWAPEFFECT_DISCARD) ? m_current_mode.multisamp : D3DMULTISAMPLE_NONE;
			//m_d3dpp.hDeviceWindow  = m_hwnd;
			if (m_current_mode.screenmode==FULLSCREEN)
			{
				m_d3dpp.FullScreen_RefreshRateInHz = m_current_mode.display_mode.RefreshRate;//D3DPRESENT_RATE_DEFAULT;
				m_d3dpp.PresentationInterval       = m_current_mode.allow_page_tearing ? D3DPRESENT_INTERVAL_IMMEDIATE : D3DPRESENT_INTERVAL_ONE;//D3DPRESENT_INTERVAL_IMMEDIATE;//D3DPRESENT_INTERVAL_ONE;
			}
			if (m_zFormat != D3DFMT_UNKNOWN)
			{
				m_d3dpp.EnableAutoDepthStencil=TRUE;
				m_d3dpp.AutoDepthStencilFormat=m_zFormat;
			}

			// finally, create the device:
			HRESULT hRes;
			if (FAILED(hRes = m_lpD3D->CreateDevice(
			                    m_ordinal_adapter,
			                    D3DDEVTYPE_HAL,
			                    m_hwnd,
			                    (m_caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) ? D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING,
			                    &m_d3dpp,
			                    &m_lpDevice)))
			{
				int code = LOWORD(hRes);

				wchar_t str[1024];
				if (code==2156) //D3DERR_NOTAVAILABLE
				{
					m_lastErr = DXC_ERR_CREATEDEV_NOT_AVAIL;

					wchar_t str[2048];
					WASABI_API_LNGSTRINGW_BUF(IDS_UNABLE_TO_CREATE_DIRECTX_DEVICE, str, 2048);

					if (m_current_mode.screenmode == FULLSCREEN)
						StringCbCatW(str, sizeof(str), WASABI_API_LNGSTRINGW(IDS_OLDER_DISPLAY_ADAPTER_CATENATION));
					else
						StringCbCatW(str, sizeof(str), WASABI_API_LNGSTRINGW(IDS_OLDER_DISPLAY_ADAPTER_CATENATION_2));

					MessageBoxW(m_hwnd,str,
							   WASABI_API_LNGSTRINGW(IDS_MILKDROP_ERROR),
							   MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
					return FALSE;
				}
				else if (m_current_mode.screenmode==WINDOWED && m_client_width>64)
				{
					// DO NOTHING; try again w/smaller window
				}
				else if (m_current_mode.screenmode != WINDOWED || m_client_width <= 64)
				{
					// usually, code==2154 here, which is D3DERR_OUTOFVIDEOMEMORY
					m_lastErr = DXC_ERR_CREATEDEV_PROBABLY_OUTOFVIDEOMEMORY;
					StringCbPrintfW(str, sizeof(str), WASABI_API_LNGSTRINGW(IDS_DIRECTX_INIT_FAILED_X), LOWORD(hRes));

					// NOTE: *A 'SUGGESTION' SCREEN SHOULD APPEAR NEXT, PROVIDED BY THE CALLER*
					MessageBoxW(m_hwnd, str,
							    WASABI_API_LNGSTRINGW(IDS_MILKDROP_ERROR),
							    MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
					return FALSE;
				}
			}
			else
			{
				device_ok = 1;
			}
		}

		iteration++;
	}
	while (!device_ok);

	// set initial viewport
	SetViewport();

	// for desktop mode, push window to back again:
	if (m_current_mode.screenmode==DESKTOP)
		SetWindowPos(m_hwnd,HWND_BOTTOM,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);

	if (m_current_mode.m_skin)
	{
		if (GetWinampVersion(mod1.hwndParent) < 0x5051) 
			SetFocus(m_current_mode.parent_window);
		else
			PostMessage(m_current_mode.parent_window, WM_USER+103, 0, 0); 
		
		//SetActiveWindow(m_current_mode.parent_window);
		//SetForegroundWindow(m_current_mode.parent_window);
	}

	/*if (m_current_mode.screenmode == WINDOWED)
		SaveWindow();*/

	// return success
	m_ready = TRUE;
	// benski> a little hack to get the window size correct. it seems to work
	if (m_current_mode.screenmode==WINDOWED)
		PostMessage(m_hwnd, WM_USER+555, 0, 0);
	return TRUE;
}