|  | /* | 
|  | * Window properties | 
|  | * | 
|  | * Copyright 1995, 1996 Alexandre Julliard | 
|  | */ | 
|  |  | 
|  | #include <string.h> | 
|  |  | 
|  | #include "windef.h" | 
|  | #include "wingdi.h" | 
|  | #include "wine/winuser16.h" | 
|  | #include "win.h" | 
|  | #include "heap.h" | 
|  | #include "debugtools.h" | 
|  |  | 
|  | DEFAULT_DEBUG_CHANNEL(prop) | 
|  |  | 
|  |  | 
|  | typedef struct tagPROPERTY | 
|  | { | 
|  | struct tagPROPERTY *next;     /* Next property in window list */ | 
|  | HANDLE            handle;   /* User's data */ | 
|  | LPSTR               string;   /* Property string (or atom) */ | 
|  | } PROPERTY; | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           PROP_FindProp | 
|  | */ | 
|  | static PROPERTY *PROP_FindProp( HWND hwnd, LPCSTR str ) | 
|  | { | 
|  | ATOM atom; | 
|  | PROPERTY *prop; | 
|  | WND *pWnd = WIN_FindWndPtr( hwnd ); | 
|  |  | 
|  | if (!pWnd) return NULL; | 
|  | if (HIWORD(str)) | 
|  | { | 
|  | atom = GlobalFindAtomA( str ); | 
|  | for (prop = pWnd->pProp; prop; prop = prop->next) | 
|  | { | 
|  | if (HIWORD(prop->string)) | 
|  | { | 
|  | if (!lstrcmpiA( prop->string, str )) goto END; | 
|  | } | 
|  | else if (LOWORD(prop->string) == atom) goto END; | 
|  | } | 
|  | } | 
|  | else  /* atom */ | 
|  | { | 
|  | atom = LOWORD(str); | 
|  | for (prop = pWnd->pProp; (prop); prop = prop->next) | 
|  | { | 
|  | if (HIWORD(prop->string)) | 
|  | { | 
|  | if (GlobalFindAtomA( prop->string ) == atom) goto END; | 
|  | } | 
|  | else if (LOWORD(prop->string) == atom) goto END; | 
|  | } | 
|  | } | 
|  | prop = NULL; | 
|  | END: | 
|  | WIN_ReleaseWndPtr(pWnd); | 
|  | return prop; | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           GetProp16   (USER.25) | 
|  | */ | 
|  | HANDLE16 WINAPI GetProp16( HWND16 hwnd, LPCSTR str ) | 
|  | { | 
|  | return (HANDLE16)GetPropA( hwnd, str ); | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           GetPropA   (USER32.281) | 
|  | */ | 
|  | HANDLE WINAPI GetPropA( HWND hwnd, LPCSTR str ) | 
|  | { | 
|  | PROPERTY *prop = PROP_FindProp( hwnd, str ); | 
|  |  | 
|  | if (HIWORD(str)) | 
|  | TRACE("(%08x,'%s'): returning %08x\n", | 
|  | hwnd, str, prop ? prop->handle : 0 ); | 
|  | else | 
|  | TRACE("(%08x,#%04x): returning %08x\n", | 
|  | hwnd, LOWORD(str), prop ? prop->handle : 0 ); | 
|  |  | 
|  | return prop ? prop->handle : 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           GetPropW   (USER32.282) | 
|  | */ | 
|  | HANDLE WINAPI GetPropW( HWND hwnd, LPCWSTR str ) | 
|  | { | 
|  | LPSTR strA; | 
|  | HANDLE ret; | 
|  |  | 
|  | if (!HIWORD(str)) return GetPropA( hwnd, (LPCSTR)(UINT)LOWORD(str) ); | 
|  | strA = HEAP_strdupWtoA( GetProcessHeap(), 0, str ); | 
|  | ret = GetPropA( hwnd, strA ); | 
|  | HeapFree( GetProcessHeap(), 0, strA ); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           SetProp16   (USER.26) | 
|  | */ | 
|  | BOOL16 WINAPI SetProp16( HWND16 hwnd, LPCSTR str, HANDLE16 handle ) | 
|  | { | 
|  | return (BOOL16)SetPropA( hwnd, str, handle ); | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           SetPropA   (USER32.497) | 
|  | */ | 
|  | BOOL WINAPI SetPropA( HWND hwnd, LPCSTR str, HANDLE handle ) | 
|  | { | 
|  | PROPERTY *prop; | 
|  |  | 
|  | if (HIWORD(str)) | 
|  | TRACE("%04x '%s' %08x\n", hwnd, str, handle ); | 
|  | else | 
|  | TRACE("%04x #%04x %08x\n", | 
|  | hwnd, LOWORD(str), handle ); | 
|  |  | 
|  | if (!(prop = PROP_FindProp( hwnd, str ))) | 
|  | { | 
|  | /* We need to create it */ | 
|  | WND *pWnd = WIN_FindWndPtr( hwnd ); | 
|  | if (!pWnd) return FALSE; | 
|  | if (!(prop = HeapAlloc( SystemHeap, 0, sizeof(*prop) ))) | 
|  | { | 
|  | WIN_ReleaseWndPtr(pWnd); | 
|  | return FALSE; | 
|  | } | 
|  | if (!(prop->string = SEGPTR_STRDUP(str))) | 
|  | { | 
|  | HeapFree( SystemHeap, 0, prop ); | 
|  | WIN_ReleaseWndPtr(pWnd); | 
|  | return FALSE; | 
|  |  | 
|  | } | 
|  | prop->next  = pWnd->pProp; | 
|  | pWnd->pProp = prop; | 
|  | WIN_ReleaseWndPtr(pWnd); | 
|  | } | 
|  | prop->handle = handle; | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           SetPropW   (USER32.498) | 
|  | */ | 
|  | BOOL WINAPI SetPropW( HWND hwnd, LPCWSTR str, HANDLE handle ) | 
|  | { | 
|  | BOOL ret; | 
|  | LPSTR strA; | 
|  |  | 
|  | if (!HIWORD(str)) | 
|  | return SetPropA( hwnd, (LPCSTR)(UINT)LOWORD(str), handle ); | 
|  | strA = HEAP_strdupWtoA( GetProcessHeap(), 0, str ); | 
|  | ret = SetPropA( hwnd, strA, handle ); | 
|  | HeapFree( GetProcessHeap(), 0, strA ); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           RemoveProp16   (USER.24) | 
|  | */ | 
|  | HANDLE16 WINAPI RemoveProp16( HWND16 hwnd, LPCSTR str ) | 
|  | { | 
|  | return (HANDLE16)RemovePropA( hwnd, str ); | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           RemovePropA   (USER32.442) | 
|  | */ | 
|  | HANDLE WINAPI RemovePropA( HWND hwnd, LPCSTR str ) | 
|  | { | 
|  | ATOM atom; | 
|  | HANDLE handle; | 
|  | PROPERTY **pprop, *prop; | 
|  | WND *pWnd = WIN_FindWndPtr( hwnd ); | 
|  |  | 
|  | if (HIWORD(str)) | 
|  | TRACE("%04x '%s'\n", hwnd, str ); | 
|  | else | 
|  | TRACE("%04x #%04x\n", hwnd, LOWORD(str)); | 
|  |  | 
|  |  | 
|  | if (!pWnd) return (HANDLE)0; | 
|  | if (HIWORD(str)) | 
|  | { | 
|  | atom = GlobalFindAtomA( str ); | 
|  | for (pprop=(PROPERTY**)&pWnd->pProp; (*pprop); pprop = &(*pprop)->next) | 
|  | { | 
|  | if (HIWORD((*pprop)->string)) | 
|  | { | 
|  | if (!lstrcmpiA( (*pprop)->string, str )) break; | 
|  | } | 
|  | else if (LOWORD((*pprop)->string) == atom) break; | 
|  | } | 
|  | } | 
|  | else  /* atom */ | 
|  | { | 
|  | atom = LOWORD(str); | 
|  | for (pprop=(PROPERTY**)&pWnd->pProp; (*pprop); pprop = &(*pprop)->next) | 
|  | { | 
|  | if (HIWORD((*pprop)->string)) | 
|  | { | 
|  | if (GlobalFindAtomA( (*pprop)->string ) == atom) break; | 
|  | } | 
|  | else if (LOWORD((*pprop)->string) == atom) break; | 
|  | } | 
|  | } | 
|  | WIN_ReleaseWndPtr(pWnd); | 
|  | if (!*pprop) return 0; | 
|  | prop   = *pprop; | 
|  | handle = prop->handle; | 
|  | *pprop = prop->next; | 
|  | SEGPTR_FREE(prop->string); | 
|  | HeapFree( SystemHeap, 0, prop ); | 
|  | return handle; | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           RemovePropW   (USER32.443) | 
|  | */ | 
|  | HANDLE WINAPI RemovePropW( HWND hwnd, LPCWSTR str ) | 
|  | { | 
|  | LPSTR strA; | 
|  | HANDLE ret; | 
|  |  | 
|  | if (!HIWORD(str)) | 
|  | return RemovePropA( hwnd, (LPCSTR)(UINT)LOWORD(str) ); | 
|  | strA = HEAP_strdupWtoA( GetProcessHeap(), 0, str ); | 
|  | ret = RemovePropA( hwnd, strA ); | 
|  | HeapFree( GetProcessHeap(), 0, strA ); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           PROPERTY_RemoveWindowProps | 
|  | * | 
|  | * Remove all properties of a window. | 
|  | */ | 
|  | void PROPERTY_RemoveWindowProps( WND *pWnd ) | 
|  | { | 
|  | PROPERTY *prop, *next; | 
|  |  | 
|  | for (prop = pWnd->pProp; (prop); prop = next) | 
|  | { | 
|  | next = prop->next; | 
|  | SEGPTR_FREE( prop->string ); | 
|  | HeapFree( SystemHeap, 0, prop ); | 
|  | } | 
|  | pWnd->pProp = NULL; | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           EnumProps16   (USER.27) | 
|  | */ | 
|  | INT16 WINAPI EnumProps16( HWND16 hwnd, PROPENUMPROC16 func ) | 
|  | { | 
|  | PROPERTY *prop, *next; | 
|  | WND *pWnd; | 
|  | INT16 ret = -1; | 
|  |  | 
|  | TRACE("%04x %08x\n", hwnd, (UINT)func ); | 
|  | if (!(pWnd = WIN_FindWndPtr( hwnd ))) return -1; | 
|  | for (prop = pWnd->pProp; (prop); prop = next) | 
|  | { | 
|  | /* Already get the next in case the callback */ | 
|  | /* function removes the current property.    */ | 
|  | next = prop->next; | 
|  |  | 
|  | TRACE("  Callback: handle=%08x str='%s'\n", | 
|  | prop->handle, prop->string ); | 
|  | ret = func( hwnd, SEGPTR_GET(prop->string), prop->handle ); | 
|  | if (!ret) break; | 
|  | } | 
|  | WIN_ReleaseWndPtr(pWnd); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           EnumPropsA   (USER32.186) | 
|  | */ | 
|  | INT WINAPI EnumPropsA( HWND hwnd, PROPENUMPROCA func ) | 
|  | { | 
|  | return EnumPropsExA( hwnd, (PROPENUMPROCEXA)func, 0 ); | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           EnumPropsW   (USER32.189) | 
|  | */ | 
|  | INT WINAPI EnumPropsW( HWND hwnd, PROPENUMPROCW func ) | 
|  | { | 
|  | return EnumPropsExW( hwnd, (PROPENUMPROCEXW)func, 0 ); | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           EnumPropsExA   (USER32.187) | 
|  | */ | 
|  | INT WINAPI EnumPropsExA(HWND hwnd, PROPENUMPROCEXA func, LPARAM lParam) | 
|  | { | 
|  | PROPERTY *prop, *next; | 
|  | WND *pWnd; | 
|  | INT ret = -1; | 
|  |  | 
|  | TRACE("%04x %08x %08lx\n", | 
|  | hwnd, (UINT)func, lParam ); | 
|  | if (!(pWnd = WIN_FindWndPtr( hwnd ))) return -1; | 
|  | for (prop = pWnd->pProp; (prop); prop = next) | 
|  | { | 
|  | /* Already get the next in case the callback */ | 
|  | /* function removes the current property.    */ | 
|  | next = prop->next; | 
|  |  | 
|  | TRACE("  Callback: handle=%08x str='%s'\n", | 
|  | prop->handle, prop->string ); | 
|  | ret = func( hwnd, prop->string, prop->handle, lParam ); | 
|  | if (!ret) break; | 
|  | } | 
|  | WIN_ReleaseWndPtr(pWnd); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           EnumPropsExW   (USER32.188) | 
|  | */ | 
|  | INT WINAPI EnumPropsExW(HWND hwnd, PROPENUMPROCEXW func, LPARAM lParam) | 
|  | { | 
|  | PROPERTY *prop, *next; | 
|  | WND *pWnd; | 
|  | INT ret = -1; | 
|  |  | 
|  | TRACE("%04x %08x %08lx\n", | 
|  | hwnd, (UINT)func, lParam ); | 
|  | if (!(pWnd = WIN_FindWndPtr( hwnd ))) return -1; | 
|  | for (prop = pWnd->pProp; (prop); prop = next) | 
|  | { | 
|  | /* Already get the next in case the callback */ | 
|  | /* function removes the current property.    */ | 
|  | next = prop->next; | 
|  |  | 
|  | TRACE("  Callback: handle=%08x str='%s'\n", | 
|  | prop->handle, prop->string ); | 
|  | if (HIWORD(prop->string)) | 
|  | { | 
|  | LPWSTR str = HEAP_strdupAtoW( GetProcessHeap(), 0, prop->string ); | 
|  | ret = func( hwnd, str, prop->handle, lParam ); | 
|  | HeapFree( GetProcessHeap(), 0, str ); | 
|  | } | 
|  | else | 
|  | ret = func( hwnd, (LPCWSTR)(UINT)LOWORD( prop->string ), | 
|  | prop->handle, lParam ); | 
|  | if (!ret) break; | 
|  | } | 
|  | WIN_ReleaseWndPtr(pWnd); | 
|  | return ret; | 
|  | } |