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.
 
 
 
 
 
 

389 lines
11 KiB

/****************************** Module Header ******************************\
* Module Name: class.c
*
* Copyright (c) 1985-91, Microsoft Corporation
*
* This module contains RegisterClass and the related window class management
* functions.
*
* History:
* 12-20-94 FritzS
*
\***************************************************************************/
#include "precomp.h"
#pragma hdrstop
BOOL VisWindow(DWORD);
/***************************************************************************\
* xxxSetClassIconEnum
*
*
\***************************************************************************/
BOOL xxxSetClassIconEnum(
PWND pwnd,
LPARAM lParam)
{
if (pwnd->pcls == (PCLS)lParam) {
/*
* If the window doesn't have a small icon or it comes from
* WM_QUERYDRAGICON, redraw the title. In the WM_QUERYDRAGICON
* case, get rid of the small icon so redrawing the title will
* create it if necessary.
*/
if (TestWF(pwnd, WFSMQUERYDRAGICON))
DestroyWindowSmIcon(pwnd);
if (!_GetProp(pwnd, MAKEINTATOM(gpsi->atomIconSmProp),PROPF_INTERNAL))
xxxRedrawTitle(pwnd, DC_ICON);
}
return TRUE;
}
/***************************************************************************\
* SetClassIcon
*
* Changes the big/small icon of a class. Called from SetClassWord().
*
\***************************************************************************/
PCURSOR xxxSetClassIcon(
PWND pwnd,
PCLS pcls,
PCURSOR pCursor,
int gcw)
{
PTHREADINFO pti = PtiCurrent();
PCURSOR pCursorOld;
TL tlpwndChild;
BOOL fRedraw;
/*
* Save old icon
*/
pCursorOld = ((gcw == GCL_HICON) ? pcls->spicn : pcls->spicnSm);
if (pCursorOld != pCursor) {
fRedraw = TRUE;
/*
* Set new icon
*/
if (gcw == GCL_HICON) {
/*
* Destroy private cached small icon first.
*/
if (pcls->spicnSm && !DestroyClassSmIcon(pcls))
fRedraw = FALSE;
Lock(&(pcls->spicn), pCursor);
} else {
/*
* We don't allow apps to see the small icons we create from
* their big icons. They can see their own. Saves memory
* leak problems and is easier.
*/
if (TestCF2(pcls, CFCACHEDSMICON)) {
DestroyClassSmIcon(pcls);
pCursorOld = NULL;
}
Lock(&(pcls->spicnSm), pCursor);
}
if (pcls->spicn && !pcls->spicnSm)
xxxCreateClassSmIcon(pcls);
if (fRedraw) {
if (pcls->cWndReferenceCount > 1) {
ThreadLock(pti->rpdesk->pDeskInfo->spwnd->spwndChild, &tlpwndChild);
xxxInternalEnumWindow(pti->rpdesk->pDeskInfo->spwnd->spwndChild,
(WNDENUMPROC_PWND)xxxSetClassIconEnum,
(LONG)pcls,
BWL_ENUMLIST);
ThreadUnlock(&tlpwndChild);
} else {
xxxSetClassIconEnum(pwnd, (LONG)pcls);
}
}
}
return(pCursorOld);
}
/***************************************************************************\
* DestroyClassSmIcon()
*
* Destroys the small icon of a class if we've created a cached one.
*
\***************************************************************************/
BOOL DestroyClassSmIcon(
PCLS pcls)
{
/*
* If we don't have a cached icon, then no work.
*/
if (TestCF2(pcls, CFCACHEDSMICON)) {
if (pcls->spicnSm) {
_DestroyCursor(pcls->spicnSm, CURSOR_ALWAYSDESTROY);
Unlock(&pcls->spicnSm);
}
ClrCF2(pcls, CFCACHEDSMICON);
return TRUE;
}
return FALSE;
}
/***************************************************************************\
* xxxCreateClassSmIcon
*
* Creates a cached class small icon from a class big icon.
*
\***************************************************************************/
VOID xxxCreateClassSmIcon(
PCLS pcls)
{
PCURSOR pcur;
UserAssert(pcls->cWndReferenceCount > 0);
UserAssert(pcls->spicn);
UserAssert(!pcls->spicnSm);
pcur = xxxClientCopyImage(PtoH(pcls->spicn),
pcls->spicn->rt == (WORD)RT_ICON ? IMAGE_ICON : IMAGE_CURSOR,
SYSMET(CXSMICON),
SYSMET(CYSMICON),
LR_DEFAULTCOLOR | LR_COPYFROMRESOURCE);
Lock(&pcls->spicnSm, pcur);
if (pcls->spicnSm)
SetCF2(pcls, CFCACHEDSMICON);
}
/***************************************************************************\
* SetWindowStyle
*
* Changes the style bits of a window. Called from SetWindowLong(). This
* sends two messages, a changing and a changed. Upon receipt of a
* WM_STYLECHANGING message, a window can muck with the style bits for
* validation purposes. The WM_STYLECHANGED message is simply after the
* fact.
*
\***************************************************************************/
LONG xxxSetWindowStyle(
PWND pwnd,
int gwl,
DWORD styleNew)
{
STYLESTRUCT sty;
BOOL fWasChild;
BOOL fIsChild;
/*
* HACK-O-RAMA
* A STYLESTRUCT currently has just one field: a DWORD for the style.
* Therefore, conveniently, we can pass a pointer into the stack for
* LPARAM. But, if we add stuff, we'll have to change this.
*/
sty.styleOld = ((gwl == GWL_STYLE) ? pwnd->style : pwnd->ExStyle);
sty.styleNew = styleNew;
/*
* Note that we don't do validation before _and_ after. It is sufficient
* to do our stuff at the end.
*/
/*
* We break Quicken 2.0 if we send the messages. That's why we version
* switch them.
*/
/*
* Send a WM_STYLECHANGING message to the window, so it can muck with
* the style bits. Like validate some stuff.
*/
if (TestWF(pwnd, WFWIN40COMPAT)) {
xxxSendMessage(pwnd, WM_STYLECHANGING, gwl, (LPARAM)(LPSTYLESTRUCT)&sty);
}
/*
* Now do our own validation.
*/
if (gwl == GWL_STYLE) {
BOOL fWasVisWindow;
/*
* If this is an edit control that has ES_PASSWORD set and
* the caller does not own it and is trying to reset it,
* fail the call.
*/
if ((PpiCurrent() != GETPTI(pwnd)->ppi) &&
(GETFNID(pwnd) == FNID_EDIT) &&
(sty.styleOld & ES_PASSWORD) &&
!(sty.styleNew & ES_PASSWORD)) {
RIPERR0(ERROR_ACCESS_DENIED,
RIP_WARNING,
"Access denied in xxxSetWindowStyle");
return 0;
}
/* Listbox ownerdraw style check was moved to the client side (client\ntstubs.c) */
/*
* Do proper validation on style bits
*/
if (pwnd->spwndParent == PWNDDESKTOP(pwnd))
sty.styleNew |= WS_CLIPSIBLINGS;
/*
* If the clipping-ness is changing, invalidate the dc cache.
*/
if ((sty.styleNew & (WS_CLIPCHILDREN | WS_CLIPSIBLINGS)) !=
(sty.styleOld & (WS_CLIPCHILDREN | WS_CLIPSIBLINGS))) {
InvalidateDCCache(pwnd, IDC_DEFAULT);
}
/*
* This breaks all Paradox dialogs 1.0-5.0 that have combos. They
* enumerate all child windows, add on minimized, then sit in a peek
* loop. After that they enumerate all child windows and remove
* WS_MINIMIZE--except the code below won't let them.
*
* Result is weird painting and an inability to use the dialog any
* more short of dismissing it
*
* Temp fix: Check for child window first.
*/
/*
* if this window is REALLY minimized (minimized bit is set and caption
* present bit is removed), then don't allow app to remove the minimize
* bit -- this fixes FoxBlow's attempt at being the OS -- jeffbog
*/
if (!TestWF(pwnd, WFCHILD) &&
TestWF(pwnd, WFMINIMIZED) &&
!TestWF(pwnd, WFCPRESENT) &&
!(sty.styleNew & WS_MINIMIZE)) {
sty.styleNew |= WS_MINIMIZE;
}
/*
* If we're changing the child bit, deal with spmenu appropriately.
* If we're turning into a child, change spmenu to an id. If we're
* turning into a top level window, turn spmenu into a menu.
*/
fWasChild = TestwndChild(pwnd);
pwnd->style = sty.styleNew;
fIsChild = TestwndChild(pwnd);
/*
* If we turned into a top level window, change spmenu to NULL.
* If we turned into a child from a top level window, unlock spmenu.
*/
if (fWasChild && !fIsChild)
pwnd->spmenu = NULL;
if (!fWasChild && fIsChild) {
ClrWF(pwnd, WFMPRESENT);
Unlock(&pwnd->spmenu);
}
/*
* If the visible, child, or minimized style is changing,
* then update the cVisWindows count
*/
fWasVisWindow = VisWindow(sty.styleOld);
if (fWasVisWindow != VisWindow(sty.styleNew))
{
// IncDecVisWindows(pwnd, !fWasVisWindow);
if (fWasVisWindow)
DecVisWindows(pwnd);
else
IncVisWindows(pwnd);
}
} else {
/*
* Is someone trying to toggle the WS_EX_TOPMOST style bit?
*/
if ((sty.styleOld & WS_EX_TOPMOST) != (sty.styleNew & WS_EX_TOPMOST)) {
#ifdef DEBUG
/*
* Rip in debug about this
*/
RIPMSG0(RIP_WARNING, "Can't change WS_EX_TOPMOST with SetWindowLong");
#endif
/*
* BACKWARDS COMPATIBILITY HACK
* If stuff is getting stored in the high word, then it must be
* Lotus 123-W sticking a FAR pointer in this field. So don't
* modify it.
*/
if (TestWF(pwnd, WFWIN40COMPAT) || !HIWORD(sty.styleNew)) {
/*
* Don't let the bit be flipped
*/
sty.styleNew &= ~WS_EX_TOPMOST;
sty.styleNew |= (sty.styleOld & WS_EX_TOPMOST);
}
}
pwnd->ExStyle = sty.styleNew;
}
/*
* See if we still need the 3D edge since the window styles changed.
*/
if (NeedsWindowEdge(pwnd->style, pwnd->ExStyle, TestWF(pwnd, WFWIN40COMPAT)))
SetWF(pwnd, WEFWINDOWEDGE);
else
ClrWF(pwnd, WEFWINDOWEDGE);
/*
* Send a WM_STYLECHANGED message
*/
if (TestWF(pwnd, WFWIN40COMPAT))
xxxSendMessage(pwnd, WM_STYLECHANGED, gwl, (LPARAM)(LPSTYLESTRUCT)&sty);
return(sty.styleOld);
}
/***************************************************************************\
* VisWindow
*
* Based on style, determines if this is considered to be "visible" by
* queue foreground styles.
*
\***************************************************************************/
BOOL VisWindow(
DWORD style)
{
return(((style & (WS_POPUP | WS_CHILD)) != WS_CHILD) &&
!(style & WS_MINIMIZE) &&
(style & WS_VISIBLE));
}