00001 /****************************** Module Header ******************************\ 00002 * Module Name: winprop.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * This module contains routines having to do with window properties. 00007 * 00008 * History: 00009 * 11-13-90 DarrinM Created. 00010 \***************************************************************************/ 00011 00012 #include "precomp.h" 00013 #pragma hdrstop 00014 00015 /***************************************************************************\ 00016 * InternalSetProp 00017 * 00018 * SetProp searches the linked-list of window property structures for the 00019 * specified key. If found, the existing property structure is changed to 00020 * hold the new hData handle. If no property is found with the specified key 00021 * a new property structure is created and initialized. 00022 * 00023 * Since property keys are retained as atoms, we convert the incoming pszKey 00024 * to an atom before lookup or storage. pszKey might actually be an atom 00025 * already, so we keep a flag, PROPF_STRING, so we know whether the atom was 00026 * created by the system or whether it was passed in. This way we know 00027 * whether we should destroy it when the property is destroyed. 00028 * 00029 * Several property values are for User's private use. These properties are 00030 * denoted with the flag PROPF_INTERNAL. Depending on the fInternal flag, 00031 * either internal (User) or external (application) properties are set/get/ 00032 * removed/enumerated, etc. 00033 * 00034 * History: 00035 * 11-14-90 darrinm Rewrote from scratch with new data structures and 00036 * algorithms. 00037 \***************************************************************************/ 00038 00039 BOOL InternalSetProp( 00040 PWND pwnd, 00041 LPWSTR pszKey, 00042 HANDLE hData, 00043 DWORD dwFlags) 00044 { 00045 PPROP pprop; 00046 00047 if (pszKey == NULL) { 00048 RIPERR0(ERROR_INVALID_PARAMETER, 00049 RIP_WARNING, 00050 "Invalid parameter \"pszKey\" (NULL) to InternalSetProp"); 00051 00052 return FALSE; 00053 } 00054 00055 /* 00056 * If no property list exists for this window, create one. 00057 */ 00058 pprop = _FindProp(pwnd, pszKey, dwFlags & PROPF_INTERNAL); 00059 if (pprop == NULL) { 00060 00061 /* 00062 * pszKey must be an atom within the server. 00063 */ 00064 UserAssert(!IS_PTR(pszKey)); 00065 00066 /* 00067 * CreateProp allocates the property and links it into the window's 00068 * property list. 00069 */ 00070 pprop = CreateProp(pwnd); 00071 if (pprop == NULL) 00072 return FALSE; 00073 00074 pprop->atomKey = PTR_TO_ID(pszKey); 00075 pprop->fs = (WORD)dwFlags; 00076 } 00077 00078 pprop->hData = hData; 00079 00080 return TRUE; 00081 } 00082 00083 00084 /***************************************************************************\ 00085 * InternalRemoveProp 00086 * 00087 * Remove the specified property from the specified window's property list. 00088 * The property's hData handle is returned to the caller who can then free 00089 * it or whatever. NOTE: This also applies to internal properties as well -- 00090 * InternalRemoveProp will free the property structure and atom (if created 00091 * by User) but will not free the hData itself. 00092 * 00093 * History: 00094 * 11-14-90 darrinm Rewrote from scratch with new data structures and 00095 * algorithms. 00096 \***************************************************************************/ 00097 00098 HANDLE InternalRemoveProp( 00099 PWND pwnd, 00100 LPWSTR pszKey, 00101 BOOL fInternal) 00102 { 00103 PPROP pprop; 00104 PPROP ppropLast; 00105 HANDLE hT; 00106 00107 /* 00108 * Find the property to be removed. 00109 */ 00110 pprop = _FindProp(pwnd, pszKey, fInternal); 00111 if (pprop == NULL) 00112 return NULL; 00113 00114 /* 00115 * Remember what it was pointing at. 00116 */ 00117 hT = pprop->hData; 00118 00119 /* 00120 * Move the property at the end of the list into this slot. 00121 */ 00122 pwnd->ppropList->iFirstFree--; 00123 ppropLast = &pwnd->ppropList->aprop[pwnd->ppropList->iFirstFree]; 00124 *pprop = *ppropLast; 00125 RtlZeroMemory(ppropLast, sizeof(*ppropLast)); 00126 00127 return hT; 00128 } 00129 00130 00131 /***************************************************************************\ 00132 * _BuildPropList 00133 * 00134 * This is a unique client/server routine - it builds a list of Props and 00135 * returns it to the client. Unique since the client doesn't know how 00136 * big the list is ahead of time. 00137 * 00138 * 29-Jan-1992 JohnC Created. 00139 \***************************************************************************/ 00140 00141 NTSTATUS _BuildPropList( 00142 PWND pwnd, 00143 PROPSET aPropSet[], 00144 UINT cPropMax, 00145 PUINT pcPropNeeded) 00146 { 00147 UINT i; 00148 PPROPLIST ppropList; 00149 PPROP pProp; 00150 DWORD iRetCnt = 0; // The number of Props returned 00151 DWORD iProp = 0; 00152 PPROPSET pPropSetLast = (aPropSet + cPropMax - 1); 00153 NTSTATUS Status; 00154 00155 /* 00156 * If the Window does not have a property list then we're done 00157 */ 00158 ppropList = pwnd->ppropList; 00159 if (ppropList == NULL) { 00160 *pcPropNeeded = 0; 00161 return STATUS_SUCCESS; 00162 } 00163 00164 /* 00165 * For each element in the property list enumerate it. 00166 * (only if it is not internal!) 00167 */ 00168 Status = STATUS_SUCCESS; 00169 pProp = ppropList->aprop; 00170 for (i = ppropList->iFirstFree; i > 0; i--) { 00171 00172 /* 00173 * if we run out of space in shared memory return 00174 * STATUS_BUFFER_TOO_SMALL 00175 */ 00176 if (&aPropSet[iProp] > pPropSetLast) { 00177 00178 /* 00179 * Reset to the beginning of the output 00180 * buffer so we can continue and compute 00181 * the needed space. 00182 */ 00183 iProp = 0; 00184 Status = STATUS_BUFFER_TOO_SMALL; 00185 } 00186 00187 if (!(pProp->fs & PROPF_INTERNAL)) { 00188 aPropSet[iProp].hData = pProp->hData; 00189 aPropSet[iProp].atom = pProp->atomKey; 00190 iProp++; 00191 iRetCnt++; 00192 } 00193 pProp++; 00194 } 00195 00196 /* 00197 * Return the number of PROPLISTs given back to the client 00198 */ 00199 00200 *pcPropNeeded = iRetCnt; 00201 00202 return Status; 00203 } 00204 00205 00206 /***************************************************************************\ 00207 * CreateProp 00208 * 00209 * Create a property structure and link it at the head of the specified 00210 * window's property list. 00211 * 00212 * History: 00213 * 11-14-90 darrinm Rewrote from scratch with new data structures and 00214 * algorithms. 00215 \***************************************************************************/ 00216 00217 PPROP CreateProp( 00218 PWND pwnd) 00219 { 00220 PPROPLIST ppropList; 00221 PPROP pprop; 00222 00223 if (pwnd->ppropList == NULL) { 00224 pwnd->ppropList = (PPROPLIST)DesktopAlloc(pwnd->head.rpdesk, 00225 sizeof(PROPLIST), 00226 DTAG_PROPLIST); 00227 if (pwnd->ppropList == NULL) { 00228 return NULL; 00229 } 00230 pwnd->ppropList->cEntries = 1; 00231 } else if (pwnd->ppropList->iFirstFree == pwnd->ppropList->cEntries) { 00232 ppropList = (PPROPLIST)DesktopAlloc(pwnd->head.rpdesk, 00233 sizeof(PROPLIST) + pwnd->ppropList->cEntries * sizeof(PROP), 00234 DTAG_PROPLIST); 00235 if (ppropList == NULL) { 00236 return NULL; 00237 } 00238 RtlCopyMemory(ppropList, pwnd->ppropList, sizeof(PROPLIST) + (pwnd->ppropList->cEntries - 1) * sizeof(PROP)); 00239 DesktopFree(pwnd->head.rpdesk, pwnd->ppropList); 00240 pwnd->ppropList = ppropList; 00241 pwnd->ppropList->cEntries++; 00242 } 00243 pprop = &pwnd->ppropList->aprop[pwnd->ppropList->iFirstFree]; 00244 pwnd->ppropList->iFirstFree++; 00245 00246 return pprop; 00247 } 00248 00249 00250 /***************************************************************************\ 00251 * DeleteProperties 00252 * 00253 * When a window is destroyed we want to destroy all its accompanying 00254 * properties. DestroyProperties does this, including destroying any hData 00255 * that was allocated by User for internal properties. Any atoms created 00256 * along with the properties are destroyed as well. hData in application 00257 * properties are not destroyed automatically; we assume the application 00258 * is taking care of that itself (in its WM_DESTROY handler or similar). 00259 * 00260 * History: 00261 * 11-14-90 darrinm Rewrote from scratch with new data structures and 00262 * algorithms. 00263 \***************************************************************************/ 00264 00265 void DeleteProperties( 00266 PWND pwnd) 00267 { 00268 PPROP pprop; 00269 UINT i; 00270 00271 UserAssert(pwnd->ppropList); 00272 00273 /* 00274 * Loop through the whole list of properties on this window. 00275 */ 00276 pprop = pwnd->ppropList->aprop; 00277 for (i = pwnd->ppropList->iFirstFree; i > 0; i--) { 00278 00279 /* 00280 * Is this an internal property? If so, free any data we allocated 00281 * for it. 00282 */ 00283 if ((pprop->fs & PROPF_INTERNAL) && !(pprop->fs & PROPF_NOPOOL)) { 00284 UserFreePool(pprop->hData); 00285 } 00286 00287 /* 00288 * Advance to the next property in the list. 00289 */ 00290 pprop++; 00291 } 00292 00293 /* 00294 * All properties gone, free the property list and clear out the 00295 * window's property list pointer. 00296 */ 00297 DesktopFree(pwnd->head.rpdesk, pwnd->ppropList); 00298 pwnd->ppropList = NULL; 00299 } 00300