1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * PURPOSE: Window properties 5 * FILE: win32ss/user/ntuser/prop.c 6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) 7 */ 8 9 #include <win32k.h> 10 DBG_DEFAULT_CHANNEL(UserProp); 11 12 /* STATIC FUNCTIONS **********************************************************/ 13 14 PPROPERTY 15 FASTCALL 16 IntGetProp( 17 _In_ PWND Window, 18 _In_ ATOM Atom, 19 _In_ BOOLEAN SystemProp) 20 { 21 PLIST_ENTRY ListEntry; 22 PPROPERTY Property; 23 UINT i; 24 WORD SystemFlag = SystemProp ? PROPERTY_FLAG_SYSTEM : 0; 25 26 NT_ASSERT(UserIsEntered()); 27 ListEntry = Window->PropListHead.Flink; 28 29 for (i = 0; i < Window->PropListItems; i++) 30 { 31 Property = CONTAINING_RECORD(ListEntry, PROPERTY, PropListEntry); 32 ListEntry = ListEntry->Flink; 33 34 if (Property->Atom == Atom && 35 (Property->fs & PROPERTY_FLAG_SYSTEM) == SystemFlag) 36 { 37 return Property; 38 } 39 } 40 NT_ASSERT(ListEntry == &Window->PropListHead); 41 return NULL; 42 } 43 44 HANDLE 45 FASTCALL 46 UserGetProp( 47 _In_ PWND Window, 48 _In_ ATOM Atom, 49 _In_ BOOLEAN SystemProp) 50 { 51 PPROPERTY Prop; 52 53 NT_ASSERT(UserIsEntered()); 54 Prop = IntGetProp(Window, Atom, SystemProp); 55 return Prop ? Prop->Data : NULL; 56 } 57 58 _Success_(return) 59 HANDLE 60 FASTCALL 61 UserRemoveProp( 62 _In_ PWND Window, 63 _In_ ATOM Atom, 64 _In_ BOOLEAN SystemProp) 65 { 66 PPROPERTY Prop; 67 HANDLE Data; 68 69 NT_ASSERT(UserIsEnteredExclusive()); 70 Prop = IntGetProp(Window, Atom, SystemProp); 71 if (Prop == NULL) 72 { 73 return NULL; 74 } 75 76 Data = Prop->Data; 77 RemoveEntryList(&Prop->PropListEntry); 78 UserHeapFree(Prop); 79 Window->PropListItems--; 80 return Data; 81 } 82 83 _Success_(return) 84 BOOL 85 FASTCALL 86 UserSetProp( 87 _In_ PWND Window, 88 _In_ ATOM Atom, 89 _In_ HANDLE Data, 90 _In_ BOOLEAN SystemProp) 91 { 92 PPROPERTY Prop; 93 94 NT_ASSERT(UserIsEnteredExclusive()); 95 Prop = IntGetProp(Window, Atom, SystemProp); 96 if (Prop == NULL) 97 { 98 Prop = UserHeapAlloc(sizeof(PROPERTY)); 99 if (Prop == NULL) 100 { 101 return FALSE; 102 } 103 Prop->Atom = Atom; 104 Prop->fs = SystemProp ? PROPERTY_FLAG_SYSTEM : 0; 105 InsertTailList(&Window->PropListHead, &Prop->PropListEntry); 106 Window->PropListItems++; 107 } 108 109 Prop->Data = Data; 110 return TRUE; 111 } 112 113 VOID 114 FASTCALL 115 UserRemoveWindowProps( 116 _In_ PWND Window) 117 { 118 PLIST_ENTRY ListEntry; 119 PPROPERTY Property; 120 121 NT_ASSERT(UserIsEnteredExclusive()); 122 while (!IsListEmpty(&Window->PropListHead)) 123 { 124 ListEntry = Window->PropListHead.Flink; 125 Property = CONTAINING_RECORD(ListEntry, PROPERTY, PropListEntry); 126 RemoveEntryList(&Property->PropListEntry); 127 UserHeapFree(Property); 128 Window->PropListItems--; 129 } 130 return; 131 } 132 133 /* FUNCTIONS *****************************************************************/ 134 135 NTSTATUS 136 APIENTRY 137 NtUserBuildPropList( 138 _In_ HWND hWnd, 139 _Out_writes_bytes_to_opt_(BufferSize, *Count * sizeof(PROPLISTITEM)) LPVOID Buffer, 140 _In_ DWORD BufferSize, 141 _Out_opt_ DWORD *Count) 142 { 143 PWND Window; 144 PPROPERTY Property; 145 PLIST_ENTRY ListEntry; 146 PROPLISTITEM listitem = { 0 }, *li; 147 NTSTATUS Status; 148 DWORD Cnt = 0; 149 150 TRACE("Enter NtUserBuildPropList\n"); 151 UserEnterShared(); 152 153 Window = UserGetWindowObject(hWnd); 154 if (Window == NULL) 155 { 156 Status = STATUS_INVALID_HANDLE; 157 goto Exit; 158 } 159 160 if (Buffer) 161 { 162 if (!BufferSize || (BufferSize % sizeof(PROPLISTITEM) != 0)) 163 { 164 Status = STATUS_INVALID_PARAMETER; 165 goto Exit; 166 } 167 168 /* Copy list */ 169 li = (PROPLISTITEM *)Buffer; 170 ListEntry = Window->PropListHead.Flink; 171 while ((BufferSize >= sizeof(PROPLISTITEM)) && 172 (ListEntry != &Window->PropListHead)) 173 { 174 Property = CONTAINING_RECORD(ListEntry, PROPERTY, PropListEntry); 175 ListEntry = ListEntry->Flink; 176 if (!(Property->fs & PROPERTY_FLAG_SYSTEM)) 177 { 178 listitem.Atom = Property->Atom; 179 listitem.Data = Property->Data; 180 181 Status = MmCopyToCaller(li, &listitem, sizeof(PROPLISTITEM)); 182 if (!NT_SUCCESS(Status)) 183 { 184 goto Exit; 185 } 186 187 BufferSize -= sizeof(PROPLISTITEM); 188 Cnt++; 189 li++; 190 } 191 } 192 193 } 194 else 195 { 196 /* FIXME: This counts user and system props */ 197 Cnt = Window->PropListItems * sizeof(PROPLISTITEM); 198 } 199 200 if (Count) 201 { 202 Status = MmCopyToCaller(Count, &Cnt, sizeof(DWORD)); 203 if (!NT_SUCCESS(Status)) 204 { 205 goto Exit; 206 } 207 } 208 209 Status = STATUS_SUCCESS; 210 211 Exit: 212 TRACE("Leave NtUserBuildPropList, ret=%lx\n", Status); 213 UserLeave(); 214 215 return Status; 216 } 217 218 HANDLE 219 APIENTRY 220 NtUserRemoveProp( 221 _In_ HWND hWnd, 222 _In_ ATOM Atom) 223 { 224 PWND Window; 225 HANDLE Data = NULL; 226 227 TRACE("Enter NtUserRemoveProp\n"); 228 UserEnterExclusive(); 229 230 Window = UserGetWindowObject(hWnd); 231 if (Window == NULL) 232 { 233 goto Exit; 234 } 235 236 Data = UserRemoveProp(Window, Atom, FALSE); 237 238 Exit: 239 TRACE("Leave NtUserRemoveProp, ret=%p\n", Data); 240 UserLeave(); 241 242 return Data; 243 } 244 245 BOOL 246 APIENTRY 247 NtUserSetProp( 248 _In_ HWND hWnd, 249 _In_ ATOM Atom, 250 _In_ HANDLE Data) 251 { 252 PWND Window; 253 BOOL Ret; 254 255 TRACE("Enter NtUserSetProp\n"); 256 UserEnterExclusive(); 257 258 Window = UserGetWindowObject(hWnd); 259 if (Window == NULL) 260 { 261 Ret = FALSE; 262 goto Exit; 263 } 264 265 Ret = UserSetProp(Window, Atom, Data, FALSE); 266 267 Exit: 268 TRACE("Leave NtUserSetProp, ret=%i\n", Ret); 269 UserLeave(); 270 271 return Ret; 272 } 273 274 /* EOF */ 275