Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1220 lines
34 KiB

/*==========================================================================
*
* Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
*
* File: ddefwp.c
* Content: DirectDraw processing of Window messages
* Takes care of palette changes, mode setting
* History:
* Date By Reason
* ==== == ======
* 26-mar-95 craige initial implementation
* 01-apr-95 craige happy fun joy updated header file
* 06-may-95 craige use driver-level csects only
* 02-jun-95 craige flesh it out
* 06-jun-95 craige added SetAppHWnd
* 07-jun-95 craige more fleshing...
* 12-jun-95 craige new process list stuff
* 16-jun-95 craige new surface structure
* 25-jun-95 craige one ddraw mutex
* 30-jun-95 kylej use GetProcessPrimary instead of lpPrimarySurface
* invalidate all primary surfaces upon focus lost
* or regained.
* 30-jun-95 craige minimze window for CAD, ALT-TAB, ALT-ESC or CTRL-ESC
* 04-jul-95 craige YEEHAW: new driver struct
* 06-jul-95 craige prevent reentry
* 08-jul-95 craige allow dsound to share
* 08-jul-95 kylej remove call to ResetSysPalette
* 11-jul-95 craige DSoundHelp & internalSetAppHWnd needs to take a pid
* 13-jul-95 craige first step in mode set fix; made it work.
* 15-jul-95 craige unhook at WM_DESTROY; don't escape on ALT; do a
* SetActiveWindow( NULL ) to stop tray from showing
* our button as depressed
* 17-jul-95 craige don't process hot key messages & activation messages
* for non-excl mode apps; SetActiveWindow is bogus,
* get bottom window in Z order and make it foreground
* 18-jul-95 craige use flags instead of refcnt to track WININFO
* 29-jul-95 toddla make ALT+TAB and CTRL+ESC work.
* 31-jul-95 toddla make ALT+TAB and CTRL+ESC work better.
* 09-aug-95 craige bug 424 - allow switching to/from apps without primary
* surfaces to work
* 09-aug-95 craige bug 404 - don't pass WM_ACTIVATEAPP messages to dsound
* if app iconic
* 10-aug-95 toddla check WININFO_DSOUNDHOOKED before calling DSound
* 10-aug-95 toddla handle unhooking after/during WM_DESTROY right.
* 13-aug-95 toddla added WININFO_ACTIVELIE
* 23-aug-95 craige bug 388,610
* 25-aug-95 craige bug 709
* 27-aug-95 craige bug 735: call SetPaletteAlways
* 04-sep-95 craige bug 894: force mode set when activating
* 09-sep-95 toddla dont send nested WM_ACTIVATEAPP messages
* 26-sep-95 craige bug 1364: use new csect to avoid dsound deadlock
* 09-jan-96 kylej new interface structures
* 13-apr-96 colinmc Bug 17736: No notification to driver of flip to GDI
* 20-apr-96 kylej Bug 16747: Make exclusive window visible if it is not.
* 23-apr-96 kylej Bug 14680: Make sure exclusive window is not maximized.
* 16-may-96 kylej Bug 23013: pass the correct flags to StartExclusiveMode
* 17-may-96 colinmc Bug 23029: Alt-tabbing straight back to a full screen
* does not send the app an WM_ACTIVATEAPP
*
***************************************************************************/
#include "ddrawpr.h"
#define TOPMOST_ID 0x4242
#define TOPMOST_TIMEOUT 1500
#define USESHOWWINDOW
#ifdef WIN95
extern CRITICAL_SECTION csWindowList;
#define ENTERWINDOWLISTCSECT EnterCriticalSection( &csWindowList );
#define LEAVEWINDOWLISTCSECT LeaveCriticalSection( &csWindowList );
#elif defined(WINNT)
extern HANDLE hWindowListMutex;
#define ENTERWINDOWLISTCSECT WaitForSingleObject(hWindowListMutex,INFINITE);
#define LEAVEWINDOWLISTCSECT ReleaseMutex(hWindowListMutex);
#else
#error "Win95 or winnt- make up your mind!"
#endif
#ifdef GDIDDPAL
/*
* getPalette
*
* Get a pointer to a palette object.
* Takes a lock on the driver object and the palette object.
*/
LPDDRAWI_DDRAWPALETTE_LCL getPalette( LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
{
LPDDRAWI_DDRAWPALETTE_LCL ppal_lcl;
LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
if( pdrv_lcl->lpGbl->dwFlags & DDRAWI_HASGDIPALETTE )
{
psurf_lcl = pdrv_lcl->lpPrimary;
if( psurf_lcl != NULL )
{
ppal_lcl = psurf_lcl->lpDDPalette;
return ppal_lcl;
}
}
return NULL;
} /* getPalette */
#endif
static LONG bHelperStarting=0;
static BOOL bStartHelper=0;
static BYTE sys_key=0;
static DWORD sys_state=0;
/*
* IsTaskWindow
*/
BOOL IsTaskWindow(HWND hwnd)
{
DWORD dwStyleEx = GetWindowLong(hwnd, GWL_EXSTYLE);
// Following windows do not qualify to be shown in task list:
// Switch Window, Hidden windows (unless they are the active
// window), Disabled windows, Kanji Conv windows.
return(((dwStyleEx & WS_EX_APPWINDOW) ||
!(dwStyleEx & WS_EX_TOOLWINDOW)) &&
IsWindowVisible(hwnd) &&
IsWindowEnabled(hwnd));
}
/*
* CountTaskWindows
*/
int CountTaskWindows()
{
HWND hwnd;
int n;
for (n=0,
hwnd = GetWindow(GetDesktopWindow(), GW_CHILD);
hwnd!= NULL;
hwnd = GetWindow(hwnd, GW_HWNDNEXT))
{
if (IsTaskWindow(hwnd))
n++;
}
return n;
}
//
// make the passed window fullscreen and topmost and set a timer
// to make the window topmost again, what a hack.
//
void MakeFullscreen(HWND hwnd)
{
SetWindowPos(hwnd, NULL, 0, 0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
SWP_NOZORDER | SWP_NOACTIVATE);
if (GetForegroundWindow() == hwnd)
{
// If the exclusive mode window is not visible, make it so.
if(!IsWindowVisible( hwnd ) )
{
ShowWindow(hwnd, SW_SHOW);
}
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
// If the exclusive mode window is maximized, restore it.
if( IsZoomed( hwnd ) )
{
ShowWindow(hwnd, SW_RESTORE);
}
}
SetTimer(hwnd, TOPMOST_ID, TOPMOST_TIMEOUT, NULL);
}
/*
* handleActivateApp
*/
void handleActivateApp(
LPDDRAWI_DIRECTDRAW_LCL this_lcl,
LPWINDOWINFO pwinfo,
BOOL is_active )
{
LPDDRAWI_DDRAWPALETTE_INT ppal_int;
LPDDRAWI_DDRAWPALETTE_LCL ppal_lcl;
LPDDRAWI_DIRECTDRAW_GBL this;
LPDDRAWI_DDRAWSURFACE_INT psurf_int;
LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
LPDDRAWI_DDRAWSURFACE_GBL psurf;
DWORD pid;
HRESULT ddrval;
BOOL has_excl;
this = this_lcl->lpGbl;
pid = GetCurrentProcessId();
psurf_int = this_lcl->lpPrimary;
if( psurf_int != NULL )
{
psurf_lcl = psurf_int->lpLcl;
psurf = psurf_lcl->lpGbl;
ppal_int = psurf_lcl->lpDDPalette;
if( NULL != ppal_int )
{
ppal_lcl = ppal_int->lpLcl;
}
else
{
ppal_lcl = NULL;
}
}
else
{
psurf_lcl = NULL;
ppal_lcl = NULL;
}
has_excl = ( this->lpExclusiveOwner == this_lcl );
/*
* stuff to do before the mode set if deactivating
*/
if( !is_active )
{
/*
* flip back to GDI if deactivating
*/
if( (psurf_lcl != NULL) && has_excl )
{
if( !(psurf->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE) ) //psurf->fpVidMem != this->fpPrimaryOrig )
{
FlipToGDISurface( this_lcl, psurf_int); //, this->fpPrimaryOrig );
}
}
}
/*
* stuff to do before mode set if activating
*/
else
{
/*
* restore exclusive mode
*/
if( this_lcl->dwLocalFlags & DDRAWILCL_ISFULLSCREEN )
{
this->dwFlags |= DDRAWI_FULLSCREEN;
}
StartExclusiveMode( this_lcl, pwinfo->DDInfo.dwDDFlags, pid );
has_excl = TRUE;
}
if( has_excl )
{
/*
* Exclusive mode app losing or gaining focus.
* If gaining focus, invalidate all non-exclusive mode primary
* surfaces. If losing focus, invalidate the exclusive-mode
* primary surface so that non-exclusive apps can restore
* their primaries.
*
* NOTE: This call MUST come after FlipToGDISurface, or
* else FlipToGDISurface will fail. craige 7/4/95
*
* NOTE: if we are coming in or out of exclusive mode,
* we need to invalidate all surfaces so that resources are
* available. craige 7/9/94
*
*/
InvalidateAllSurfaces( this );
}
/*
* restore hwnd if we are about to be activated
*/
if ( (pwinfo->DDInfo.dwDDFlags & DDSCL_FULLSCREEN) &&
!(pwinfo->DDInfo.dwDDFlags & DDSCL_NOWINDOWCHANGES) &&
IsWindowVisible(pwinfo->hWnd))
{
if (is_active)
{
pwinfo->dwFlags |= WININFO_SELFSIZE;
#ifdef USESHOWWINDOW
ShowWindow(pwinfo->hWnd, SW_SHOWNOACTIVATE);
#else
SetWindowPos(pwinfo->hWnd, NULL, 0, 0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
SWP_NOZORDER | SWP_NOACTIVATE);
#endif
pwinfo->dwFlags &= ~WININFO_SELFSIZE;
}
}
/*
* restore the mode
*/
if( !is_active )
{
if( (this->lpExclusiveOwner == NULL) || has_excl )
{
DPF( 2, "INACTIVE: %08lx: Restoring original mode (%ld)", GetCurrentProcessId(), this->dwModeIndexOrig );
RestoreDisplayMode( this_lcl, TRUE );
}
}
else
{
DPF( 2, "ACTIVE: %08lx: Setting app's preferred mode (%ld)", GetCurrentProcessId(), this_lcl->dwPreferredMode );
SetDisplayMode( this_lcl, this_lcl->dwPreferredMode, TRUE, TRUE );
}
/*
* stuff to do after the mode set if activating
*/
if( is_active )
{
/*
* restore the palette
*/
if( ppal_lcl != NULL )
{
ddrval = SetPaletteAlways( psurf_int, (LPDIRECTDRAWPALETTE) ppal_int );
DPF( 3, "SetPalette, ddrval = %08lx (%ld)", ddrval, LOWORD( ddrval ) );
}
}
/*
* stuff to do after the mode set if deactivating
*/
else
{
if( has_excl )
{
DoneExclusiveMode( this_lcl );
}
}
/*
* minimize window if deactivating
*/
if ( (pwinfo->DDInfo.dwDDFlags & DDSCL_FULLSCREEN) &&
!(pwinfo->DDInfo.dwDDFlags & DDSCL_NOWINDOWCHANGES) &&
IsWindowVisible(pwinfo->hWnd))
{
pwinfo->dwFlags |= WININFO_SELFSIZE;
if( is_active )
{
MakeFullscreen(pwinfo->hWnd);
}
else
{
#ifdef USESHOWWINDOW
ShowWindow(pwinfo->hWnd, SW_SHOWMINNOACTIVE);
#else
SetWindowPos(pwinfo->hWnd, NULL, 0, 0, 0, 0,
SWP_NOZORDER | SWP_NOACTIVATE);
#endif
}
pwinfo->dwFlags &= ~WININFO_SELFSIZE;
}
#ifdef WIN95
/*
* if we got deactivated because of a syskey
* then send that key to user now.
* This is unnecessary for NT.
*
* NOTE because we disabled all the task-switching
* hot keys the system did not see the hot key that
* caused us to deactivate.
*
* if there is only one window to activate, activate the
* desktop (shell window)
*/
if( has_excl && sys_key && !is_active )
{
if (CountTaskWindows() <= 1)
{
DPF( 2, "activating the desktop" );
SetForegroundWindow(GetWindow(pwinfo->hWnd, GW_HWNDLAST));
// we just activated the desktop, so we *dont* want
// to force a ALT+ESC or ALT+TAB, we do want to force
// a CTRL+ESC.
if (sys_key != VK_ESCAPE || (sys_state & 0x20000000))
sys_key = 0;
}
if (sys_key)
{
BYTE state_key;
BOOL state_key_down;
DPF( 2, "sending sys key to USER key=%04x state=%08x",sys_key,sys_state);
if (sys_state & 0x20000000)
state_key = VK_MENU;
else
state_key = VK_CONTROL;
state_key_down = GetAsyncKeyState(state_key) < 0;
if (!state_key_down)
keybd_event(state_key, 0, 0, 0);
keybd_event(sys_key, 0, 0, 0);
keybd_event(sys_key, 0, KEYEVENTF_KEYUP, 0);
if (!state_key_down)
keybd_event(state_key, 0, KEYEVENTF_KEYUP, 0);
}
}
#endif
sys_key = 0;
} /* handleActivateApp */
static DWORD dwTime2=0;
/*
* tryHotKey
*/
static void tryHotKey( WORD flags )
{
static int iState=0;
static DWORD dwTime=0;
#define TOGGLE1 0xe02a
#define TOGGLE2 0xe036
if( !bHelperStarting )
{
if( iState == 0 )
{
if( flags == TOGGLE1 )
{
dwTime = timeGetTime();
iState++;
}
}
else
{
if( iState == 5 )
{
iState = 0;
if( flags == TOGGLE2 )
{
if( (timeGetTime() - dwTime) < 2500 )
{
if( InterlockedExchange( &bHelperStarting, TRUE ) )
{
return;
}
dwTime2 = timeGetTime();
DPF( 2, "********** GET READY FOR A SURPRISE **********" );
return;
}
}
}
else
{
if( !(iState & 1) )
{
iState = (flags == TOGGLE1) ? iState+1 : 0;
}
else
{
iState = (flags == TOGGLE2) ? iState+1 : 0;
}
}
}
}
else
{
if( !bStartHelper )
{
bHelperStarting = FALSE;
dwTime2 = 0;
}
}
return;
} /* tryHotKey */
static LPWINDOWINFO GetWindowInfo( HWND hwnd )
{
LPWINDOWINFO lpwi=lpWindowInfo;
while( NULL != lpwi )
{
if( lpwi->hWnd == hwnd )
{
return lpwi;
}
lpwi = lpwi->lpLink;
}
return NULL;
}
static void delete_wininfo( LPWINDOWINFO curr )
{
LPWINDOWINFO prev;
if( NULL == curr )
return;
// curr is at the head of the list, delete it and return
if( curr == lpWindowInfo )
{
lpWindowInfo = curr->lpLink;
MemFree( curr );
return;
}
if( NULL == lpWindowInfo )
return;
// find curr in the list, delete it and return
for(prev=lpWindowInfo; NULL != prev->lpLink; prev = prev->lpLink)
{
if( curr == prev->lpLink )
{
break;
}
}
if( NULL == prev->lpLink )
{
// couldn't find it
return;
}
prev->lpLink = curr->lpLink;
MemFree( curr );
}
/*
* WindowProc
*/
ULONG WINAPI WindowProc(
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam )
{
#ifdef GDIDDPAL
LPDDRAWI_DDRAWPALETTE_LCL ppal_lcl;
#endif
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
BOOL is_active;
LPWINDOWINFO curr;
WNDPROC proc;
BOOL get_away;
DWORD rc;
BOOL is_hot;
BOOL is_excl;
/*
* find the hwnd
*/
curr = GetWindowInfo(hWnd);
if( curr == NULL || curr->dwSmag != WININFO_MAGIC )
{
DPF( 0, "FATAL ERROR! Window Proc Called for hWnd %08lx, but not in list!", hWnd );
DEBUG_BREAK();
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
/*
* unhook at destroy (or if the WININFO_UNHOOK bit is set)
*/
proc = curr->lpWndProc;
if( uMsg == WM_NCDESTROY )
{
DPF (2, "*** WM_NCDESTROY unhooking window ***" );
curr->dwFlags |= WININFO_UNHOOK;
}
if( curr->dwFlags & WININFO_UNHOOK )
{
DPF (2, "*** Unhooking window proc" );
if (curr->dwFlags & WININFO_ZOMBIE)
{
DPF (2, "*** Freeing ZOMBIE WININFO ***" );
delete_wininfo( curr );
}
SetWindowLong( hWnd, GWL_WNDPROC, (LONG) proc );
rc = CallWindowProc( proc, hWnd, uMsg, wParam, lParam );
return rc;
}
/*
* Code to defer app activation of minimized app until it is restored.
*/
switch( uMsg )
{
#ifdef WIN95
case WM_POWERBROADCAST:
if( (wParam == PBT_APMSUSPEND) || (wParam == PBT_APMSTANDBY) )
#else
//winnt doesn't know about standby vs suspend
case WM_POWER:
if( wParam == PWR_SUSPENDREQUEST)
#endif
{
DPF( 2, "WM_POWERBROADCAST: deactivating application" );
SendMessage( hWnd, WM_ACTIVATEAPP, 0, GetCurrentThreadId() );
}
break;
case WM_SIZE:
DPF( 2, "WM_SIZE hWnd=%X wp=%04X, lp=%08X", hWnd, wParam, lParam);
if( !(curr->dwFlags & WININFO_INACTIVATEAPP)
&& ((wParam == SIZE_RESTORED) || (wParam == SIZE_MAXIMIZED))
&& !(curr->dwFlags & WININFO_SELFSIZE)
&& (GetForegroundWindow() == hWnd) )
{
DPF( 2, "WM_SIZE: Window restored, sending WM_ACTIVATEAPP" );
PostMessage( hWnd, WM_ACTIVATEAPP, 1, GetCurrentThreadId() );
}
else
{
DPF( 1, "WM_SIZE: Window restored, NOT sending WM_ACTIVATEAPP" );
}
break;
case WM_ACTIVATEAPP:
if( IsIconic( hWnd ) && wParam )
{
DPF( 2, "WM_ACTIVATEAPP: Ignoring while minimized" );
return 0;
}
else
{
curr->dwFlags |= WININFO_INACTIVATEAPP;
}
break;
}
/*
* direct sound need to be called?
*/
if ( curr->dwFlags & WININFO_DSOUNDHOOKED )
{
if( curr->lpDSoundCallback != NULL )
{
curr->lpDSoundCallback( hWnd, uMsg, wParam, lParam );
}
}
/*
* is directdraw involved here?
*/
if( !(curr->dwFlags & WININFO_DDRAWHOOKED) )
{
rc = CallWindowProc( proc, hWnd, uMsg, wParam, lParam );
// clear the WININFO_INACTIVATEAPP bit, but make sure to make sure
// we are still hooked!
if (uMsg == WM_ACTIVATEAPP && (GetWindowInfo(hWnd) != NULL))
{
curr->dwFlags &= ~WININFO_INACTIVATEAPP;
}
return rc;
}
#ifdef DEBUG
if ( (curr->DDInfo.dwDDFlags & DDSCL_FULLSCREEN) &&
!(curr->DDInfo.dwDDFlags & DDSCL_NOWINDOWCHANGES) &&
!IsIconic(hWnd) )
{
if (GetForegroundWindow() == hWnd)
{
HWND hwndT;
RECT rc,rcT;
GetWindowRect(hWnd, &rc);
for (hwndT = GetWindow(hWnd, GW_HWNDFIRST);
hwndT && hwndT != hWnd;
hwndT = GetWindow(hwndT, GW_HWNDNEXT))
{
if (IsWindowVisible(hwndT))
{
GetWindowRect(hwndT, &rcT);
if (IntersectRect(&rcT, &rcT, &rc))
{
DPF(1, "Window %08x is on top of us!!", hwndT);
}
}
}
}
}
#endif
/*
* NOTE: we don't take the DLL csect here. By not doing this, we can
* up the performance here. However, this means that the application
* could have a separate thread kill exclusive mode while window
* messages were being processed. This could cause our death.
* Is this OK?
*/
this_lcl = curr->DDInfo.lpDD_lcl;
switch( uMsg )
{
/*
* WM_SYSKEYUP
*
* watch for system keys of app trying to switch away from us...
*
* we only need to do this on Win95 because we have disabled all
* the task-switching hot keys. on NT we will get switched
* away from normaly by the system.
*/
//#ifdef WIN95
case WM_SYSKEYUP:
DPF( 0, "WM_SYSKEYUP: wParam=%08lx lParam=%08lx", wParam, lParam );
get_away = FALSE;
is_hot = FALSE;
if( wParam == VK_TAB )
{
if( lParam & 0x20000000l )
{
if( curr->dwFlags & WININFO_IGNORENEXTALTTAB )
{
DPF( 2, "AHHHHHHHHHHHH Ignoring AltTab" );
}
else
{
get_away = TRUE;
}
}
}
else if( wParam == VK_ESCAPE )
{
get_away = TRUE;
}
else if( wParam == VK_SHIFT )
{
if( HIBYTE( HIWORD( lParam ) ) == 0xe0 )
{
tryHotKey( HIWORD( lParam ) );
}
}
is_excl = ((this_lcl->dwLocalFlags & DDRAWILCL_HASEXCLUSIVEMODE) != 0);
if( get_away && dwTime2 != 0 )
{
if( timeGetTime() - dwTime2 < 2500 )
{
DPF( 2, "********** WANT TO SEE SOMETHING _REALLY_ SCARY? *************" );
bStartHelper = TRUE;
is_hot = TRUE;
}
else
{
bHelperStarting = FALSE;
dwTime2 = 0;
}
}
else
{
bHelperStarting = FALSE;
}
curr->dwFlags &= ~WININFO_IGNORENEXTALTTAB;
if( (get_away && is_excl) || is_hot )
{
DPF( 2, "Hot key pressed, switching away from app" );
if( is_hot && !is_excl )
{
PostMessage( hWnd, WM_USER+0x1234, 0xFFBADADD, 0xFFADDBAD );
}
else
{
sys_key = (BYTE)wParam;
sys_state = (DWORD)lParam;
PostMessage( hWnd, WM_ACTIVATEAPP, 0, GetCurrentThreadId() );
}
}
break;
//#endif
/*
* WM_SYSCOMMAND
*
* watch for screen savers, and don't allow them!
*
*/
case WM_SYSCOMMAND:
is_excl = ((this_lcl->dwLocalFlags & DDRAWILCL_HASEXCLUSIVEMODE) != 0);
if( is_excl )
{
switch( wParam )
{
case SC_SCREENSAVE:
DPF( 1, "Ignoring screen saver!" );
return 1;
}
}
break;
case WM_TIMER:
if (wParam == TOPMOST_ID )
{
if ( GetForegroundWindow() == hWnd && !IsIconic(hWnd) )
{
DPF(2, "Bringing window to top");
curr->dwFlags |= WININFO_SELFSIZE;
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
curr->dwFlags &= ~WININFO_SELFSIZE;
}
KillTimer(hWnd, wParam);
return 0;
}
break;
#ifdef USESHOWWINDOW
case WM_DISPLAYCHANGE:
DPF( 2, "WM_DISPLAYCHANGE: %dx%dx%d", LOWORD(lParam), HIWORD(lParam), wParam );
//
// WM_DISPLAYCHANGE is *sent* to the thread that called
// change display settings, we will most likely have the
// direct draw lock, make sure we set the WININFO_SELFSIZE
// bit while calling down the chain to prevent deadlock
//
curr->dwFlags |= WININFO_SELFSIZE;
if ( (curr->DDInfo.dwDDFlags & DDSCL_FULLSCREEN) &&
!(curr->DDInfo.dwDDFlags & DDSCL_NOWINDOWCHANGES) )
{
MakeFullscreen(hWnd);
}
rc = CallWindowProc( proc, hWnd, uMsg, wParam, lParam );
// clear the WININFO_SELFSIZE bit, but make sure to make sure
// we are still hooked!
if (GetWindowInfo(hWnd) != NULL)
{
curr->dwFlags &= ~WININFO_SELFSIZE;
}
return rc;
#endif
/*
* WM_ACTIVATEAPP
*
* the application has been reactivated. In this case, we need to
* reset the mode
*
*/
case WM_ACTIVATEAPP:
is_excl = ((this_lcl->dwLocalFlags & DDRAWILCL_HASEXCLUSIVEMODE) != 0);
if( is_excl )
{
is_active = (BOOL)wParam && GetForegroundWindow() == hWnd && !IsIconic(hWnd);
if (!is_active && wParam != 0)
{
DPF( 2, "WM_ACTIVATEAPP: setting wParam to 0, not realy active");
wParam = 0;
}
if( is_active )
{
DPF( 2, "WM_ACTIVATEAPP: BEGIN Activating app pid=%08lx, tid=%08lx",
GetCurrentProcessId(), GetCurrentThreadId() );
}
else
{
DPF( 2, "WM_ACTIVATEAPP: BEGIN Deactivating app pid=%08lx, tid=%08lx",
GetCurrentProcessId(), GetCurrentThreadId() );
}
ENTER_DDRAW();
if( is_active && (this_lcl->dwLocalFlags & DDRAWILCL_ACTIVEYES) )
{
DPF( 2, "*** Already activated" );
}
else
if( !is_active && (this_lcl->dwLocalFlags & DDRAWILCL_ACTIVENO) )
{
DPF( 2, "*** Already deactivated" );
}
else
{
DPF( 2, "*** Active state changing" );
this_lcl->dwLocalFlags &= ~(DDRAWILCL_ACTIVEYES|DDRAWILCL_ACTIVENO);
if( is_active )
{
this_lcl->dwLocalFlags |= DDRAWILCL_ACTIVEYES;
}
else
{
this_lcl->dwLocalFlags |= DDRAWILCL_ACTIVENO;
}
if( is_active )
{
if (GetAsyncKeyState( VK_MENU ) < 0)
DPF(1, "ALT key is DOWN");
if (GetKeyState( VK_MENU ) < 0)
DPF(1, "we think the ALT key is DOWN");
if( GetAsyncKeyState( VK_MENU ) < 0 )
{
curr->dwFlags |= WININFO_IGNORENEXTALTTAB;
DPF( 2, "AHHHHHHH Setting to ignore next alt tab" );
}
else
{
curr->dwFlags &= ~WININFO_IGNORENEXTALTTAB;
}
}
handleActivateApp( this_lcl, curr, is_active );
}
#ifdef DEBUG
if( is_active )
{
DPF( 2, "WM_ACTIVATEAPP: DONE Activating app pid=%08lx, tid=%08lx",
GetCurrentProcessId(), GetCurrentThreadId() );
}
else
{
DPF( 2, "WM_ACTIVATEAPP: DONE Deactivating app pid=%08lx, tid=%08lx",
GetCurrentProcessId(), GetCurrentThreadId() );
}
#endif
LEAVE_DDRAW();
if( !is_active && bStartHelper )
{
PostMessage( hWnd, WM_USER+0x1234, 0xFFBADADD, 0xFFADDBAD );
}
}
rc = CallWindowProc( proc, hWnd, uMsg, wParam, lParam );
// clear the WININFO_INACTIVATEAPP bit, but make sure to make sure
// we are still hooked!
if (GetWindowInfo(hWnd) != NULL)
{
curr->dwFlags &= ~WININFO_INACTIVATEAPP;
}
return rc;
break;
case WM_USER+0x1234:
if( wParam == 0xFFBADADD && lParam == 0xFFADDBAD )
{
if( bStartHelper )
{
HelperCreateThread();
}
bHelperStarting = FALSE;
bStartHelper = FALSE;
dwTime2 = 0;
return 0;
}
break;
#ifdef GDIDDPAL
case WM_PALETTECHANGED:
if( (HWND) wParam == hWnd )
{
break;
}
// fall through
case WM_QUERYNEWPALETTE:
ENTER_DDRAW();
ppal_lcl = getPalette( this_lcl );
if( ppal_lcl != NULL )
{
}
LEAVE_DDRAW();
break;
case WM_PAINT:
ENTER_DDRAW();
ppal_lcl = getPalette( this_lcl );
if( ppal_lcl != NULL )
{
}
LEAVE_DDRAW();
break;
#endif
}
rc = CallWindowProc( proc, hWnd, uMsg, wParam, lParam );
return rc;
} /* WindowProc */
#undef DPF_MODNAME
#define DPF_MODNAME "SetCooperativeLevel"
/*
* internalSetAppHWnd
*
* Set the WindowList struct up with the app's hwnd info
* Must be called with DLL & driver locks taken.
*/
HRESULT internalSetAppHWnd(
LPDDRAWI_DIRECTDRAW_LCL this_lcl,
HWND hWnd,
DWORD dwFlags,
BOOL is_ddraw,
WNDPROC lpDSoundWndProc,
DWORD pid )
{
LPWINDOWINFO curr;
LPWINDOWINFO prev;
/*
* find the window list item associated with this process
*/
curr = lpWindowInfo;
prev = NULL;
while( curr != NULL )
{
if( curr->dwPid == pid )
{
break;
}
prev = curr;
curr = curr->lpLink;
}
/*
* check if this is OK
*/
if( curr == NULL )
{
if( hWnd == NULL )
{
DPF( 1, "HWnd must be specified" );
return DDERR_NOHWND;
}
}
else
{
if( hWnd != NULL )
{
if( curr->hWnd != hWnd )
{
DPF( 1, "Hwnd %08lx no good: Different Hwnd (%08lx) already set for process",
hWnd, curr->hWnd );
return DDERR_HWNDALREADYSET;
}
}
}
/*
* are we shutting an HWND down?
*/
if( hWnd == NULL )
{
if( is_ddraw )
{
curr->dwFlags &= ~WININFO_DDRAWHOOKED;
}
else
{
curr->dwFlags &= ~WININFO_DSOUNDHOOKED;
}
if( (curr->dwFlags & (WININFO_DSOUNDHOOKED|WININFO_DDRAWHOOKED)) == 0 )
{
if( IsWindow(curr->hWnd) )
{
WNDPROC proc;
proc = (WNDPROC) GetWindowLong( curr->hWnd, GWL_WNDPROC );
if( proc != (WNDPROC) WindowProc &&
proc != (WNDPROC) curr->lpWndProc )
{
DPF( 2, "Window has been subclassed; cannot restore!" );
curr->dwFlags |= WININFO_ZOMBIE;
}
else if (GetWindowThreadProcessId(curr->hWnd, NULL) !=
GetCurrentThreadId())
{
DPF( 2, "intra-thread window unhook, letting window proc do it" );
curr->dwFlags |= WININFO_UNHOOK;
curr->dwFlags |= WININFO_ZOMBIE;
PostMessage(curr->hWnd, WM_NULL, 0, 0);
}
else
{
DPF( 2, "Unsubclassing window %08lx", curr->hWnd );
SetWindowLong( curr->hWnd, GWL_WNDPROC, (LONG) curr->lpWndProc );
delete_wininfo( curr );
}
}
else
{
delete_wininfo( curr );
}
}
}
/*
* changing or adding an hwnd then...
*/
else
{
/*
* brand new object...
*/
if( curr == NULL )
{
if( GetWindowInfo(hWnd) != NULL)
{
DPF_ERR("Window already has WinInfo structure");
return DDERR_INVALIDPARAMS;
}
curr = MemAlloc( sizeof( WINDOWINFO ) );
if( curr == NULL )
{
return DDERR_OUTOFMEMORY;
}
curr->dwSmag = WININFO_MAGIC;
curr->dwPid = pid;
curr->lpLink = lpWindowInfo;
lpWindowInfo = curr;
curr->hWnd = hWnd;
curr->lpWndProc = (WNDPROC) GetWindowLong( hWnd, GWL_WNDPROC );
SetWindowLong( hWnd, GWL_WNDPROC, (LONG) WindowProc );
}
/*
* set ddraw/dsound specific data
*/
if( is_ddraw )
{
curr->DDInfo.lpDD_lcl = this_lcl;
curr->DDInfo.dwDDFlags = dwFlags;
curr->dwFlags |= WININFO_DDRAWHOOKED;
}
else
{
curr->lpDSoundCallback = lpDSoundWndProc;
curr->dwFlags |= WININFO_DSOUNDHOOKED;
}
DPF( 1, "Subclassing window %08lx", curr->hWnd );
}
return DD_OK;
} /* internalSetAppHWnd */
#undef DPF_MODNAME
/*
* SetAppHWnd
*
* Set the WindowList struct up with the app's hwnd info
*/
HRESULT SetAppHWnd(
LPDDRAWI_DIRECTDRAW_LCL this_lcl,
HWND hWnd,
DWORD dwFlags )
{
DWORD pid;
HRESULT ddrval;
/*
* set up the window
*/
if( hWnd && (dwFlags & DDSCL_EXCLUSIVE) )
{
/*
* make the window fullscreen and topmost
*/
if ( (dwFlags & DDSCL_FULLSCREEN) &&
!(dwFlags & DDSCL_NOWINDOWCHANGES))
{
MakeFullscreen(hWnd);
}
}
pid = GETCURRPID();
ENTERWINDOWLISTCSECT
ddrval = internalSetAppHWnd( this_lcl, hWnd, dwFlags, TRUE, NULL, pid );
LEAVEWINDOWLISTCSECT
return ddrval;
} /* SetAppHWnd */
/*
* DSoundHelp
*/
HRESULT __stdcall DSoundHelp( HWND hWnd, WNDPROC lpWndProc, DWORD pid )
{
HRESULT ddrval;
DPF( 1, "DSoundHelp: hWnd = %08lx, lpWndProc = %08lx, pid = %08lx", hWnd, lpWndProc, pid );
ENTERWINDOWLISTCSECT
ddrval = internalSetAppHWnd( NULL, hWnd, 0, FALSE, lpWndProc, pid );
LEAVEWINDOWLISTCSECT
return ddrval;
} /* DSoundHelp */