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.
300 lines
9.0 KiB
300 lines
9.0 KiB
/****************************** Module Header ******************************\
|
|
* Module Name: winprop.c
|
|
*
|
|
* Copyright (c) 1985 - 1999, Microsoft Corporation
|
|
*
|
|
* This module contains routines having to do with window properties.
|
|
*
|
|
* History:
|
|
* 11-13-90 DarrinM Created.
|
|
\***************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
/***************************************************************************\
|
|
* InternalSetProp
|
|
*
|
|
* SetProp searches the linked-list of window property structures for the
|
|
* specified key. If found, the existing property structure is changed to
|
|
* hold the new hData handle. If no property is found with the specified key
|
|
* a new property structure is created and initialized.
|
|
*
|
|
* Since property keys are retained as atoms, we convert the incoming pszKey
|
|
* to an atom before lookup or storage. pszKey might actually be an atom
|
|
* already, so we keep a flag, PROPF_STRING, so we know whether the atom was
|
|
* created by the system or whether it was passed in. This way we know
|
|
* whether we should destroy it when the property is destroyed.
|
|
*
|
|
* Several property values are for User's private use. These properties are
|
|
* denoted with the flag PROPF_INTERNAL. Depending on the fInternal flag,
|
|
* either internal (User) or external (application) properties are set/get/
|
|
* removed/enumerated, etc.
|
|
*
|
|
* History:
|
|
* 11-14-90 darrinm Rewrote from scratch with new data structures and
|
|
* algorithms.
|
|
\***************************************************************************/
|
|
|
|
BOOL InternalSetProp(
|
|
PWND pwnd,
|
|
LPWSTR pszKey,
|
|
HANDLE hData,
|
|
DWORD dwFlags)
|
|
{
|
|
PPROP pprop;
|
|
|
|
if (pszKey == NULL) {
|
|
RIPERR0(ERROR_INVALID_PARAMETER,
|
|
RIP_WARNING,
|
|
"Invalid parameter \"pszKey\" (NULL) to InternalSetProp");
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* If no property list exists for this window, create one.
|
|
*/
|
|
pprop = _FindProp(pwnd, pszKey, dwFlags & PROPF_INTERNAL);
|
|
if (pprop == NULL) {
|
|
|
|
/*
|
|
* pszKey must be an atom within the server.
|
|
*/
|
|
UserAssert(!IS_PTR(pszKey));
|
|
|
|
/*
|
|
* CreateProp allocates the property and links it into the window's
|
|
* property list.
|
|
*/
|
|
pprop = CreateProp(pwnd);
|
|
if (pprop == NULL)
|
|
return FALSE;
|
|
|
|
pprop->atomKey = PTR_TO_ID(pszKey);
|
|
pprop->fs = (WORD)dwFlags;
|
|
}
|
|
|
|
pprop->hData = hData;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* InternalRemoveProp
|
|
*
|
|
* Remove the specified property from the specified window's property list.
|
|
* The property's hData handle is returned to the caller who can then free
|
|
* it or whatever. NOTE: This also applies to internal properties as well --
|
|
* InternalRemoveProp will free the property structure and atom (if created
|
|
* by User) but will not free the hData itself.
|
|
*
|
|
* History:
|
|
* 11-14-90 darrinm Rewrote from scratch with new data structures and
|
|
* algorithms.
|
|
\***************************************************************************/
|
|
|
|
HANDLE InternalRemoveProp(
|
|
PWND pwnd,
|
|
LPWSTR pszKey,
|
|
BOOL fInternal)
|
|
{
|
|
PPROP pprop;
|
|
PPROP ppropLast;
|
|
HANDLE hT;
|
|
|
|
/*
|
|
* Find the property to be removed.
|
|
*/
|
|
pprop = _FindProp(pwnd, pszKey, fInternal);
|
|
if (pprop == NULL)
|
|
return NULL;
|
|
|
|
/*
|
|
* Remember what it was pointing at.
|
|
*/
|
|
hT = pprop->hData;
|
|
|
|
/*
|
|
* Move the property at the end of the list into this slot.
|
|
*/
|
|
pwnd->ppropList->iFirstFree--;
|
|
ppropLast = &pwnd->ppropList->aprop[pwnd->ppropList->iFirstFree];
|
|
*pprop = *ppropLast;
|
|
RtlZeroMemory(ppropLast, sizeof(*ppropLast));
|
|
|
|
return hT;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* _BuildPropList
|
|
*
|
|
* This is a unique client/server routine - it builds a list of Props and
|
|
* returns it to the client. Unique since the client doesn't know how
|
|
* big the list is ahead of time.
|
|
*
|
|
* 29-Jan-1992 JohnC Created.
|
|
\***************************************************************************/
|
|
|
|
NTSTATUS _BuildPropList(
|
|
PWND pwnd,
|
|
PROPSET aPropSet[],
|
|
UINT cPropMax,
|
|
PUINT pcPropNeeded)
|
|
{
|
|
UINT i;
|
|
PPROPLIST ppropList;
|
|
PPROP pProp;
|
|
DWORD iRetCnt = 0; // The number of Props returned
|
|
DWORD iProp = 0;
|
|
PPROPSET pPropSetLast = (aPropSet + cPropMax - 1);
|
|
NTSTATUS Status;
|
|
|
|
/*
|
|
* If the Window does not have a property list then we're done
|
|
*/
|
|
ppropList = pwnd->ppropList;
|
|
if (ppropList == NULL) {
|
|
*pcPropNeeded = 0;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* For each element in the property list enumerate it.
|
|
* (only if it is not internal!)
|
|
*/
|
|
Status = STATUS_SUCCESS;
|
|
pProp = ppropList->aprop;
|
|
for (i = ppropList->iFirstFree; i > 0; i--) {
|
|
|
|
/*
|
|
* if we run out of space in shared memory return
|
|
* STATUS_BUFFER_TOO_SMALL
|
|
*/
|
|
if (&aPropSet[iProp] > pPropSetLast) {
|
|
|
|
/*
|
|
* Reset to the beginning of the output
|
|
* buffer so we can continue and compute
|
|
* the needed space.
|
|
*/
|
|
iProp = 0;
|
|
Status = STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
if (!(pProp->fs & PROPF_INTERNAL)) {
|
|
aPropSet[iProp].hData = pProp->hData;
|
|
aPropSet[iProp].atom = pProp->atomKey;
|
|
iProp++;
|
|
iRetCnt++;
|
|
}
|
|
pProp++;
|
|
}
|
|
|
|
/*
|
|
* Return the number of PROPLISTs given back to the client
|
|
*/
|
|
|
|
*pcPropNeeded = iRetCnt;
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* CreateProp
|
|
*
|
|
* Create a property structure and link it at the head of the specified
|
|
* window's property list.
|
|
*
|
|
* History:
|
|
* 11-14-90 darrinm Rewrote from scratch with new data structures and
|
|
* algorithms.
|
|
\***************************************************************************/
|
|
|
|
PPROP CreateProp(
|
|
PWND pwnd)
|
|
{
|
|
PPROPLIST ppropList;
|
|
PPROP pprop;
|
|
|
|
if (pwnd->ppropList == NULL) {
|
|
pwnd->ppropList = (PPROPLIST)DesktopAlloc(pwnd->head.rpdesk,
|
|
sizeof(PROPLIST),
|
|
DTAG_PROPLIST);
|
|
if (pwnd->ppropList == NULL) {
|
|
return NULL;
|
|
}
|
|
pwnd->ppropList->cEntries = 1;
|
|
} else if (pwnd->ppropList->iFirstFree == pwnd->ppropList->cEntries) {
|
|
ppropList = (PPROPLIST)DesktopAlloc(pwnd->head.rpdesk,
|
|
sizeof(PROPLIST) + pwnd->ppropList->cEntries * sizeof(PROP),
|
|
DTAG_PROPLIST);
|
|
if (ppropList == NULL) {
|
|
return NULL;
|
|
}
|
|
RtlCopyMemory(ppropList, pwnd->ppropList, sizeof(PROPLIST) + (pwnd->ppropList->cEntries - 1) * sizeof(PROP));
|
|
DesktopFree(pwnd->head.rpdesk, pwnd->ppropList);
|
|
pwnd->ppropList = ppropList;
|
|
pwnd->ppropList->cEntries++;
|
|
}
|
|
pprop = &pwnd->ppropList->aprop[pwnd->ppropList->iFirstFree];
|
|
pwnd->ppropList->iFirstFree++;
|
|
|
|
return pprop;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* DeleteProperties
|
|
*
|
|
* When a window is destroyed we want to destroy all its accompanying
|
|
* properties. DestroyProperties does this, including destroying any hData
|
|
* that was allocated by User for internal properties. Any atoms created
|
|
* along with the properties are destroyed as well. hData in application
|
|
* properties are not destroyed automatically; we assume the application
|
|
* is taking care of that itself (in its WM_DESTROY handler or similar).
|
|
*
|
|
* History:
|
|
* 11-14-90 darrinm Rewrote from scratch with new data structures and
|
|
* algorithms.
|
|
\***************************************************************************/
|
|
|
|
void DeleteProperties(
|
|
PWND pwnd)
|
|
{
|
|
PPROP pprop;
|
|
UINT i;
|
|
|
|
UserAssert(pwnd->ppropList);
|
|
|
|
/*
|
|
* Loop through the whole list of properties on this window.
|
|
*/
|
|
pprop = pwnd->ppropList->aprop;
|
|
for (i = pwnd->ppropList->iFirstFree; i > 0; i--) {
|
|
|
|
/*
|
|
* Is this an internal property? If so, free any data we allocated
|
|
* for it.
|
|
*/
|
|
if ((pprop->fs & PROPF_INTERNAL) && !(pprop->fs & PROPF_NOPOOL)) {
|
|
UserFreePool(pprop->hData);
|
|
}
|
|
|
|
/*
|
|
* Advance to the next property in the list.
|
|
*/
|
|
pprop++;
|
|
}
|
|
|
|
/*
|
|
* All properties gone, free the property list and clear out the
|
|
* window's property list pointer.
|
|
*/
|
|
DesktopFree(pwnd->head.rpdesk, pwnd->ppropList);
|
|
pwnd->ppropList = NULL;
|
|
}
|
|
|