|
|
/****************************** 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; }
|