/***************************************************************************\ * * File: ApiStubs.cpp * * Description: * ApiStubs.cpp exposes all public DirectUser API's in the Win32 world. * * * History: * 1/18/2000: JStall: Created * * Copyright (C) 2000 by Microsoft Corporation. All rights reserved. * \***************************************************************************/ #include "stdafx.h" #include "WinAPI.h" #include "DwpEx.h" #define DUSER_API #pragma warning(disable: 4296) // expression is always false // // Undefine the macros declared in ObjectAPI because they will be redefined // here for the WinAPI handle-based API's. // #undef BEGIN_API #undef END_API #undef BEGIN_API_NOLOCK #undef END_API_NOLOCK #undef BEGIN_API_NOCONTEXT #undef END_API_NOCONTEXT #undef CHECK_MODIFY #undef VALIDATE_GADGETCONTEXT #undef VALIDATE_VALUE #undef VALIDATE_HWND #undef VALIDATE_REGION #undef VALIDATE_OBJECT #undef VALIDATE_EVENTGADGET #undef VALIDATE_EVENTGADGET_NOCONTEXT #undef VALIDATE_VISUAL #undef VALIDATE_ROOTGADGET #undef VALIDATE_VISUAL_OR_NULL #undef VALIDATE_TRANSITION #undef VALIDATE_FLAGS #undef VALIDATE_RANGE #undef VALIDATE_CODE_PTR #undef VALIDATE_CODE_PTR_OR_NULL #undef VALIDATE_READ_PTR #undef VALIDATE_READ_PTR_ #undef VALIDATE_READ_PTR_OR_NULL_ #undef VALIDATE_READ_STRUCT #undef VALIDATE_WRITE_PTR #undef VALIDATE_WRITE_PTR_ #undef VALIDATE_WRITE_PTR_OR_NULL_ #undef VALIDATE_WRITE_STRUCT #undef VALIDATE_STRING_PTR #undef VALIDATE_STRINGA_PTR #undef VALIDATE_STRINGW_PTR // // SET_RETURN is a convenient macro that converts from DirectUser error // conditions and sets up the return value. // // NOTE: This MUST be a macro (and not an inline function) because we CANNOT // evaluate success unless hr was actually successful. Unfortunately with // function calls, success would need to be evaluated to call the function. // #define SET_RETURN(hr, success) \ do { \ if (SUCCEEDED(hr)) { \ retval = success; \ } else { \ SetError(hr); \ } \ } while (0) \ template inline void SetError(T dwErr) { SetLastError((DWORD) dwErr); } // // API Entry / Exit setup rountines // #define BEGIN_RECV(type, value, defermsg) \ type retval = value; \ type errret = value; \ UNREFERENCED_PARAMETER(errret); \ \ if (!IsInitContext()) { \ PromptInvalid("Must initialize Context before using thread"); \ SetError(DU_E_NOCONTEXT); \ goto rawErrorExit; \ } \ \ { \ ContextLock cl; \ if (!cl.LockNL(defermsg)) { \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ Context * pctxThread = cl.pctx; \ AssertInstance(pctxThread); \ UNREFERENCED_PARAMETER(pctxThread); \ #define END_RECV() \ goto ErrorExit; \ ErrorExit: \ /* Unlocks the Context here */ \ ; \ } \ rawErrorExit: \ return retval; #define BEGIN_RECV_NOLOCK(type, value) \ type retval = value; \ type errret = value; \ UNREFERENCED_PARAMETER(errret); \ \ if (!IsInitContext()) { \ PromptInvalid("Must initialize Context before using thread"); \ SetError(DU_E_NOCONTEXT); \ goto rawErrorExit; \ } \ \ { \ Context * pctxThread = ::GetContext(); \ AssertInstance(pctxThread); \ #define END_RECV_NOLOCK() \ goto ErrorExit; \ ErrorExit: \ ; \ } \ rawErrorExit: \ return retval; #define BEGIN_RECV_NOCONTEXT(type, value) \ type retval = value; \ type errret = value; \ UNREFERENCED_PARAMETER(errret); \ #define END_RECV_NOCONTEXT() \ goto ErrorExit; \ ErrorExit: \ return retval; #define CHECK_MODIFY() \ if (pctxThread->IsReadOnly()) { \ PromptInvalid("Can not call modifying function while in read-only state / callback"); \ SetError(DU_E_READONLYCONTEXT); \ goto ErrorExit; \ } \ // // Individual parameter validation rountines // #define VALIDATE_GADGETCONTEXT(gad) \ { \ Context * pctxGad = (p##gad)->GetContext(); \ if (pctxThread != pctxGad) { \ PromptInvalid("Must use Gadget inside correct Context"); \ SetError(DU_E_INVALIDCONTEXT); \ goto ErrorExit; \ } \ } #define VALIDATE_VALUE(x, v) \ if (x != v) { \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } #define VALIDATE_HWND(wnd) \ if ((h##wnd == NULL) || (!IsWindow(h##wnd))) { \ PromptInvalid("Handle is not a valid Window"); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } #define VALIDATE_REGION(rgn) \ if (h##rgn == NULL) { \ PromptInvalid("Handle is not a valid region"); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } #define VALIDATE_OBJECT(obj) \ { \ p##obj = BaseObject::ValidateHandle(h##obj); \ if (p##obj == NULL) { \ PromptInvalid("Handle is not a valid object"); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ } #define VALIDATE_EVENTGADGET(gad) \ { \ p##gad = ValidateBaseGadget(h##gad); \ if (p##gad == NULL) { \ PromptInvalid("Handle is not a valid Gadget"); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ VALIDATE_GADGETCONTEXT(gad) \ } #define VALIDATE_EVENTGADGET_NOCONTEXT(gad) \ { \ p##gad = ValidateBaseGadget(h##gad); \ if (p##gad == NULL) { \ PromptInvalid("Handle is not a valid Gadget"); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ } #define VALIDATE_VISUAL(gad) \ { \ p##gad = ValidateVisual(h##gad); \ if (p##gad == NULL) { \ PromptInvalid("Handle is not a valid Gadget"); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ VALIDATE_GADGETCONTEXT(gad) \ } #define VALIDATE_ROOTGADGET(gad) \ { \ { \ DuVisual * pgadTemp = ValidateVisual(h##gad); \ if (pgadTemp == NULL) { \ PromptInvalid("Handle is not a valid Gadget"); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ if (!pgadTemp->IsRoot()) { \ goto ErrorExit; \ } \ VALIDATE_GADGETCONTEXT(gadTemp) \ p##gad = (DuRootGadget *) pgadTemp; \ } \ } #define VALIDATE_VISUAL_OR_NULL(gad) \ { \ if (h##gad == NULL) { \ p##gad = NULL; \ } else { \ p##gad = ValidateVisual(h##gad); \ if (p##gad == NULL) { \ PromptInvalid("Handle is not a valid Gadget"); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ VALIDATE_GADGETCONTEXT(gad) \ } \ } #define VALIDATE_TRANSITION(trx) \ { \ BaseObject * pbase##trx = BaseObject::ValidateHandle(h##trx); \ p##trx = CastTransition(pbase##trx); \ if (p##trx == NULL) { \ PromptInvalid("Handle is not a valid Transition"); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ } #define VALIDATE_FLAGS(f, m) \ if ((f & m) != f) { \ PromptInvalid("Specified flags are invalid"); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } #define VALIDATE_RANGE(i, a, b) \ if (((i) < (a)) || ((i) > (b))) { \ PromptInvalid("Value is outside expected range"); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ #define VALIDATE_CODE_PTR(p) \ if ((p == NULL) || IsBadCode(p)) { \ PromptInvalid("Bad code pointer: " STRINGIZE(p)); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ #define VALIDATE_CODE_PTR_OR_NULL(p) \ if ((p != NULL) && IsBadCode((FARPROC) p)) { \ PromptInvalid("Bad code pointer: " STRINGIZE(p)); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ #define VALIDATE_READ_PTR(p) \ if ((p == NULL) || IsBadRead(p, sizeof(char *))) { \ PromptInvalid("Bad read pointer: " STRINGIZE(p)); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ #define VALIDATE_READ_PTR_(p, b) \ if ((p == NULL) || IsBadRead(p, b)) { \ PromptInvalid("Bad read pointer: " STRINGIZE(p)); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ #define VALIDATE_READ_PTR_OR_NULL_(p, b) \ if ((p != NULL) && IsBadRead(p, b)) { \ PromptInvalid("Bad read pointer: " STRINGIZE(p)); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ #define VALIDATE_READ_STRUCT(p, s) \ if ((p == NULL) || IsBadRead(p, sizeof(s))) { \ PromptInvalid("Bad read pointer: " STRINGIZE(p)); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ if (p->cbSize != sizeof(s)) { \ PromptInvalid("Structure is not expected size for " STRINGIZE(s)); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } #define VALIDATE_WRITE_PTR(p) \ if ((p == NULL) || IsBadWrite(p, sizeof(char *))) { \ PromptInvalid("Bad write pointer: " STRINGIZE(p)); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ #define VALIDATE_WRITE_PTR_(p, b) \ if ((p == NULL) || IsBadWrite(p, b)) { \ PromptInvalid("Bad write pointer: " STRINGIZE(p)); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ #define VALIDATE_WRITE_PTR_OR_NULL_(p, b) \ if ((p != NULL) && IsBadWrite(p, b)) { \ PromptInvalid("Bad write pointer: " STRINGIZE(p)); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ #define VALIDATE_WRITE_STRUCT(p, s) \ if ((p == NULL) || IsBadWrite(p, sizeof(s))) { \ PromptInvalid("Bad write pointer: " STRINGIZE(p)); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ if (p->cbSize != sizeof(s)) { \ PromptInvalid("Structure is not expected size for " STRINGIZE(s)); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } #define VALIDATE_STRING_PTR(p, cch) \ if ((p == NULL) || IsBadString(p, cch)) { \ PromptInvalid("Bad string pointer: " STRINGIZE(p)); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ #define VALIDATE_STRINGA_PTR(p, cch) \ if ((p == NULL) || IsBadStringA(p, cch)) { \ PromptInvalid("Bad string pointer: " STRINGIZE(p)); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ #define VALIDATE_STRINGW_PTR(p, cch) \ if ((p == NULL) || IsBadStringW(p, cch)) { \ PromptInvalid("Bad string pointer: " STRINGIZE(p)); \ SetError(E_INVALIDARG); \ goto ErrorExit; \ } \ /***************************************************************************\ ***************************************************************************** * * DirectUser CORE API * * InitGadgets() initializes a DirectUser Context. The Context is valid in * the Thread until it is explicitely destroyed with ::DeleteHandle() or the * thread exits. * * NOTE: It is VERY important that the first time this function is called is * NOT in DllMain() because we need to initialize the SRT. DllMain() * serializes access across all threads, so we will deadlock. After the first * Context is successfully created, additional Contexts can be created inside * DllMain(). * * * ***************************************************************************** \***************************************************************************/ DUSER_API HDCONTEXT WINAPI InitGadgets( IN INITGADGET * pInit) { Context * pctxNew; HRESULT hr; BEGIN_RECV_NOCONTEXT(HDCONTEXT, NULL); VALIDATE_READ_STRUCT(pInit, INITGADGET); VALIDATE_RANGE(pInit->nThreadMode, IGTM_MIN, IGTM_MAX); VALIDATE_RANGE(pInit->nMsgMode, IGMM_MIN, IGMM_MAX); VALIDATE_RANGE(pInit->nPerfMode, IGPM_MIN, IGPM_MAX); hr = ResourceManager::InitContextNL(pInit, FALSE, &pctxNew); SET_RETURN(hr, (HDCONTEXT) GetHandle(pctxNew)); END_RECV_NOCONTEXT(); } /***************************************************************************\ * * InitGadgetComponent (API) * * InitGadgetComponent() initializes optional DirectUser/Gadget components * that are not initialized by default. It is usually best to call this * function separately for each optional component to track individual * failures when initializing. * * Components were successfully initialized. * CreateTransition * UninitializeGadgetComponent * \***************************************************************************/ DUSER_API BOOL WINAPI InitGadgetComponent( IN UINT nOptionalComponent) // Optional component ID { HRESULT hr; // // InitComponentNL() doesn't actually synchronize on a Context, but needs // a context to be initialized so that the threading model is determined. // BEGIN_RECV(BOOL, FALSE, ContextLock::edNone); VALIDATE_RANGE(nOptionalComponent, IGC_MIN, IGC_MAX); CHECK_MODIFY(); hr = ResourceManager::InitComponentNL(nOptionalComponent); SET_RETURN(hr, TRUE); END_RECV(); } /***************************************************************************\ * * UninitGadgetComponent (API) * * UninitGadgetComponent() shuts down and cleans up optional DirectUser/Gadget * components that were previously initialized. * * Components were successfully uninitialized. * InitGadgetComponent * \***************************************************************************/ DUSER_API BOOL WINAPI UninitGadgetComponent( IN UINT nOptionalComponent) // Optional component { HRESULT hr; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_RANGE(nOptionalComponent, IGC_MIN, IGC_MAX); CHECK_MODIFY(); hr = ResourceManager::UninitComponentNL(nOptionalComponent); SET_RETURN(hr, TRUE); END_RECV(); } /***************************************************************************\ * * DeleteHandle (API) * * DeleteHandle() deletes any DirectUser handle by destroying the object and * cleaning up associated resources. After calling, the specified handle is * no longer valid. It may be used again later by another object. * * It is very important that only valid handles are given to ::DeleteHandle(). * Passing invalid handles (including previously deleted handles) will crash * DirectUser. * * Object was successfully deleted. * CreateGadget * CreateTransition * CreateAction * \***************************************************************************/ DUSER_API BOOL WINAPI DeleteHandle( IN HANDLE h) // Handle to delete { BEGIN_RECV_NOLOCK(BOOL, FALSE); BaseObject * pobj = BaseObject::ValidateHandle(h); if (pobj != NULL) { if (pobj->GetHandleType() == htContext) { // // When destroying a Context, we can't lock it or it won't get // destroyed. This is okay since the ResourceManager serialize // the requests when it locks the thread-list. // pobj->xwDeleteHandle(); retval = TRUE; } else { // // When destroying a normal object, lock the Context that the // object resides in. // ContextLock cl; if (cl.LockNL(ContextLock::edDefer, pctxThread)) { ObjectLock ol(pobj); CHECK_MODIFY(); pobj->xwDeleteHandle(); retval = TRUE; } } } // // NOTE: The object may not be deleted yet if there are any outstanding // locks against it. If it is a Gadget, it may be locked by one of the // message queues. // END_RECV_NOLOCK(); } /***************************************************************************\ * * DUserDeleteGadget (API) * * TODO: Document this API * \***************************************************************************/ DUSER_API HRESULT WINAPI DUserDeleteGadget( IN DUser::Gadget * pg) { BEGIN_RECV_NOLOCK(HRESULT, E_INVALIDARG); MsgObject * pmo = MsgObject::CastMsgObject(pg); if (pmo == NULL) { PromptInvalid("Must specify a valid Gadget to delete"); return E_INVALIDARG; } { // // When destroying a normal object, lock the Context that the // object resides in. // ContextLock cl; if (cl.LockNL(ContextLock::edDefer, pctxThread)) { ObjectLock ol(pmo); CHECK_MODIFY(); pmo->xwDeleteHandle(); retval = S_OK; } } // // NOTE: The object may not be deleted yet if there are any outstanding // locks against it. If it is a Gadget, it may be locked by one of the // message queues. // END_RECV_NOLOCK(); } /***************************************************************************\ * * IsStartDelete (API) * * TODO: Document this API * \***************************************************************************/ DUSER_API BOOL WINAPI IsStartDelete( IN HANDLE hobj, IN BOOL * pfStarted) { BaseObject * pobj; BEGIN_RECV(BOOL, FALSE, ContextLock::edNone); VALIDATE_WRITE_PTR(pfStarted); VALIDATE_OBJECT(obj); *pfStarted = pobj->IsStartDelete(); retval = TRUE; END_RECV(); } /***************************************************************************\ * * GetContext (API) * * TODO: Document this API * \***************************************************************************/ DUSER_API HDCONTEXT WINAPI GetContext( IN HANDLE h) { BEGIN_RECV_NOCONTEXT(HDCONTEXT, NULL); // TODO: Totally rewrite this nonsense. { DuEventGadget * pgad; HGADGET hgad = (HGADGET) h; VALIDATE_EVENTGADGET_NOCONTEXT(gad); if (pgad != NULL) { retval = (HDCONTEXT) GetHandle(pgad->GetContext()); } } END_RECV_NOCONTEXT(); } /***************************************************************************\ * * IsInsideContext (API) * * TODO: Document this API * \***************************************************************************/ DUSER_API BOOL WINAPI IsInsideContext(HANDLE h) { BOOL fInside = FALSE; if ((h != NULL) && IsInitThread()) { __try { DuEventGadget * pgad = ValidateBaseGadget((HGADGET) h); if (pgad != NULL) { Context * pctxThread = GetContext(); fInside = (pctxThread == pgad->GetContext()); } else if (BaseObject::ValidateHandle(h) != NULL) { fInside = TRUE; } } __except(EXCEPTION_EXECUTE_HANDLER) { fInside = FALSE; } } return fInside; } /***************************************************************************\ * * CreateGadget (API) * * CreateGadget() creates a new Gadget of a given type. Depending on the * specific flags, different Gadgets will actually be instantiated. Once a * Gadget of a specific type has been created, it can not be changed into a * different type without being deleted and recreated. * * * Specifies both what type of Gadget to created and any creation-time * properties of that Gadget * * GC_HWNDHOST Creates a top-level Gadget that can host a * GadgetTree inside the client area of a given * HWND. hParent must be a valid HWND. * GC_NCHOST Creates a top-level Gadget that can host a * GadgetTree inside the non-client area of a given * HWND. hParent must be a valid HWND. * GC_DXHOST Creates a top-level Gadget that can host a * GadgetTree inside a DXSurface. hParent must be * an LPCRECT specifying the area of the surface * the tree will be displayed on. * GC_COMPLEX Creates a sub-level Gadget that is optimized for * a complex subtree below it containing many other * Gadgets. More expensive than a Simple Gadget, * Complex Gadgets provide optimized region management * and are more equivalent to HWND's in both * functionality and design. hParent must specify a * valid HGADGET. * GC_SIMPLE Creates a sub-level Gadget that is optimized for * a simple subtree below it containing a few Gadgets. * Simple Gadgets are cheaper to create and often use * than Complex Gadgets if optimized region management * is not needed. hParent must specify a valid * HGADGET. * GC_DETACHED Creates a Gadget not integrated into a given Gadget * tree. Since they are separated from a tree, * operations must be explicitely forwarded to * Detached Gadgets during processing. hParent is * ignored. * GC_MESSAGE Creates a message-only Gadget that can receive and * send messages, but does not participate in any * visual or interactive manner. hParent is ignored. *
* * * Returns a handle to the newly created Gadget * or NULL if the creation failed. * DeleteHandle * \***************************************************************************/ DUSER_API HGADGET WINAPI CreateGadget( IN HANDLE hParent, // Handle to parent IN UINT nFlags, // Creation flags IN GADGETPROC pfnProc, // Pointer to the Gadget procedure IN void * pvGadgetData) // User data associated with this Gadget { BEGIN_RECV(HGADGET, NULL, ContextLock::edDefer); HRESULT hr; CREATE_INFO ci; ci.pfnProc = pfnProc; ci.pvData = pvGadgetData; switch (nFlags & GC_TYPE) { case GC_HWNDHOST: { HWND hwndContainer = (HWND) hParent; VALIDATE_HWND(wndContainer); DuRootGadget * pgadRoot; hr = GdCreateHwndRootGadget(hwndContainer, &ci, &pgadRoot); SET_RETURN(hr, (HGADGET) GetHandle(pgadRoot)); } break; case GC_NCHOST: { HWND hwndContainer = (HWND) hParent; VALIDATE_HWND(wndContainer); DuRootGadget * pgadRoot; hr = GdCreateNcRootGadget(hwndContainer, &ci, &pgadRoot); SET_RETURN(hr, (HGADGET) GetHandle(pgadRoot)); } break; case GC_DXHOST: { const RECT * prcContainerRect = (const RECT *) hParent; VALIDATE_READ_PTR_(prcContainerRect, sizeof(RECT)); DuRootGadget * pgadRoot; hr = GdCreateDxRootGadget(prcContainerRect, &ci, &pgadRoot); SET_RETURN(hr, (HGADGET) GetHandle(pgadRoot)); } break; case GC_COMPLEX: PromptInvalid("Complex Gadgets are not yet implemented"); SetError(E_NOTIMPL); break; case GC_SIMPLE: { DuVisual * pgadParent; HGADGET hgadParent = (HGADGET) hParent; VALIDATE_VISUAL_OR_NULL(gadParent); if (pgadParent == NULL) { pgadParent = GetCoreSC()->pconPark->GetRoot(); if (pgadParent == NULL) { // // The Parking Gadget has already been destroyed, so can not // create a new child. // SetError(E_INVALIDARG); goto ErrorExit; } } DuVisual * pgadChild; hr = pgadParent->AddChild(&ci, &pgadChild); SET_RETURN(hr, (HGADGET) GetHandle(pgadChild)); } break; case GC_DETACHED: PromptInvalid("Detached Gadgets are not yet implemented"); SetError(E_NOTIMPL); break; case GC_MESSAGE: { VALIDATE_VALUE(hParent, NULL); VALIDATE_CODE_PTR(pfnProc); // MsgGadget's must have a GadgetProc DuListener * pgadNew; hr = DuListener::Build(&ci, &pgadNew); SET_RETURN(hr, (HGADGET) GetHandle(pgadNew)); } break; default: PromptInvalid("Invalid Gadget type"); SetError(E_INVALIDARG); } END_RECV(); } /***************************************************************************\ * * GetGadgetFocus (API) * * GetGadgetFocus() returns the Gadget with current keyboard focus or NULL * if no Gadget currently has focus. * * Gadget with keyboard focus. * SetGadgetFocus * GM_CHANGESTATE * \***************************************************************************/ DUSER_API HGADGET WINAPI GetGadgetFocus() { BEGIN_RECV(HGADGET, NULL, ContextLock::edNone); retval = (HGADGET) GetHandle(DuRootGadget::GetFocus()); END_RECV(); } /***************************************************************************\ * * SetGadgetFocus (API) * * SetGadgetFocus() moves keyboard focus to the specified Gadget. Both the * current Gadget with keyboard focus and the Gadget being specified will be * sent a GM_CHANGESTATE message with nCode=GSTATE_KEYBOARDFOCUS notifying of * the focus change. * * Focus was successfully moved. * GetGadgetFocus * GM_CHANGESTATE * \***************************************************************************/ DUSER_API BOOL WINAPI SetGadgetFocus( IN HGADGET hgadFocus) // Gadget to receive focus. { DuVisual * pgadFocus; DuRootGadget * pgadRoot; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_VISUAL(gadFocus); CHECK_MODIFY(); // // TODO: Do we need to only allow the app to change focus if on the same // thread? USER does this. // pgadRoot = pgadFocus->GetRoot(); if (pgadRoot != NULL) { retval = pgadRoot->xdSetKeyboardFocus(pgadFocus); } END_RECV(); } /***************************************************************************\ * * IsGadgetParentChainStyle (API) * * IsGadgetParentChainStyle() checks if a Gadget parent change has the * specified style bits set. * * Gadget was successfully checked. * GetGadgetStyle * SetGadgetStyle * \***************************************************************************/ DUSER_API BOOL WINAPI IsGadgetParentChainStyle( IN HGADGET hgad, // Gadget to check visibility IN UINT nStyle, // Style bits to check OUT BOOL * pfChain, // Chain state IN UINT nFlags) // Optional flags { DuVisual * pgad; BEGIN_RECV(BOOL, FALSE, ContextLock::edNone); VALIDATE_VISUAL(gad); VALIDATE_VALUE(nFlags, 0); VALIDATE_FLAGS(nStyle, GS_VALID); VALIDATE_WRITE_PTR_(pfChain, sizeof(BOOL)); CHECK_MODIFY(); *pfChain = pgad->IsParentChainStyle(nStyle); retval = TRUE; END_RECV(); } /***************************************************************************\ * * SetGadgetFillI (API) * * SetGadgetFillI() specifies an optional brush to fill the Gadget's * background with when drawing. The background will be filled before the * Gadget is given the GM_PAINT message to draw. * * Fill was successfully set. * UtilDrawBlendRect * GM_PAINT * \***************************************************************************/ DUSER_API BOOL WINAPI SetGadgetFillI( IN HGADGET hgadChange, // Gadget to change IN HBRUSH hbrFill, // Brush to fill with or NULL to remove IN BYTE bAlpha, // Alpha level to apply brush IN int w, // Optional width of brush when // alpha-blending or 0 for default IN int h) // Optional height of brush when // alpha-blending or 0 for default { DuVisual * pgadChange; HRESULT hr; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_VISUAL(gadChange); CHECK_MODIFY(); hr = pgadChange->SetFill(hbrFill, bAlpha, w, h); SET_RETURN(hr, TRUE); END_RECV(); } /***************************************************************************\ * * SetGadgetFillF (API) * * SetGadgetFillF() specifies an optional brush to fill the Gadget's * background with when drawing. The background will be filled before the * Gadget is given the GM_PAINT message to draw. * * Fill was successfully set. * UtilDrawBlendRect * GM_PAINT * \***************************************************************************/ DUSER_API BOOL WINAPI SetGadgetFillF( IN HGADGET hgadChange, // Gadget to change IN Gdiplus::Brush * pgpbr) // Brush to fill with or NULL to remove { DuVisual * pgadChange; HRESULT hr; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_VISUAL(gadChange); CHECK_MODIFY(); hr = pgadChange->SetFill(pgpbr); SET_RETURN(hr, TRUE); END_RECV(); } /***************************************************************************\ * * GetGadgetScale (API) * * GetGadgetScale() returns the Gadget's scaling factor. If the Gadget is * not scaled, the factors will be X=1.0, Y=1.0. * * Successfully returned scaling factor * SetGadgetScale * GetGadgetRotation * SetGadgetRotation * GetGadgetRect * SetGadgetRect * \***************************************************************************/ DUSER_API BOOL WINAPI GetGadgetScale( IN HGADGET hgad, // Gadget to check OUT float * pflX, // Horizontal scaling factor OUT float * pflY) // Vertical scaling factor { DuVisual * pgad; BEGIN_RECV(BOOL, FALSE, ContextLock::edNone); VALIDATE_VISUAL(gad); VALIDATE_WRITE_PTR_(pflX, sizeof(float)); VALIDATE_WRITE_PTR_(pflY, sizeof(float)); pgad->GetScale(pflX, pflY); retval = TRUE; END_RECV(); } /***************************************************************************\ * * SetGadgetScale (API) * * SetGadgetScale() changes the specified Gadget's scaling factor. Scaling * is determined from the upper-left corner of the Gadget and is applied * dynamically during painting and hit-testing. The Gadget's logical * rectangle set by SetGadgetRect() does not change. * * When scaling is applied to a Gadget, the entire subtree of that Gadget is * scaled. To remove any scaling factor, use X=1.0, Y=1.0. * * Successfully changed scaling factor * GetGadgetScale * GetGadgetRotation * SetGadgetRotation * GetGadgetRect * SetGadgetRect * \***************************************************************************/ DUSER_API BOOL WINAPI SetGadgetScale( IN HGADGET hgadChange, // Gadget to change IN float flX, // New horizontal scaling factor IN float flY) // New vertical scaling factor { DuVisual * pgadChange; HRESULT hr; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_VISUAL(gadChange); CHECK_MODIFY(); hr = pgadChange->xdSetScale(flX, flY); SET_RETURN(hr, TRUE); END_RECV(); } /***************************************************************************\ * * GetGadgetRotation (API) * * GetGadgetRotation() returns the Gadget's rotation factor in radians. If * a Gadget is not rotated, the factor will be 0.0. * * Successfully returned rotation factor * GetGadgetScale * SetGadgetScale * SetGadgetRotation * GetGadgetRect * SetGadgetRect * \***************************************************************************/ DUSER_API BOOL WINAPI GetGadgetRotation( IN HGADGET hgad, // Gadget to check OUT float * pflRotationRad) // Rotation factor in radians { DuVisual * pgad; BEGIN_RECV(BOOL, FALSE, ContextLock::edNone); VALIDATE_VISUAL(gad); VALIDATE_WRITE_PTR_(pflRotationRad, sizeof(float)); *pflRotationRad = pgad->GetRotation(); retval = TRUE; END_RECV(); } /***************************************************************************\ * * SetGadgetRotation (API) * * SetGadgetRotation() changes the specified Gadget's rotation factor in * radians. Scaling is determined from the upper-left corner of the Gadget * and is applied dynamically during painting and hit-testing. The Gadget's * logical rectangle set by SetGadgetRect() does not change. * * When rotation is applied to a Gadget, the entire subtree of that Gadget is * rotated. To remove any rotation factor, use 0.0. * * Successfully changed scaling factor * GetGadgetScale * SetGadgetScale * GetGadgetRotation * GetGadgetRect * SetGadgetRect * \***************************************************************************/ DUSER_API BOOL WINAPI SetGadgetRotation( IN HGADGET hgadChange, // Gadget to change IN float flRotationRad) // New rotation factor in radians { DuVisual * pgadChange; HRESULT hr; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_VISUAL(gadChange); CHECK_MODIFY(); hr = pgadChange->xdSetRotation(flRotationRad); SET_RETURN(hr, TRUE); END_RECV(); } //------------------------------------------------------------------------------ DUSER_API BOOL WINAPI GetGadgetCenterPoint(HGADGET hgad, float * pflX, float * pflY) { DuVisual * pgad; BEGIN_RECV(BOOL, FALSE, ContextLock::edNone); VALIDATE_VISUAL(gad); VALIDATE_WRITE_PTR_(pflX, sizeof(float)); VALIDATE_WRITE_PTR_(pflY, sizeof(float)); pgad->GetCenterPoint(pflX, pflY); retval = TRUE; END_RECV(); } //------------------------------------------------------------------------------ DUSER_API BOOL WINAPI SetGadgetCenterPoint(HGADGET hgadChange, float flX, float flY) { DuVisual * pgadChange; HRESULT hr; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_VISUAL(gadChange); CHECK_MODIFY(); hr = pgadChange->xdSetCenterPoint(flX, flY); SET_RETURN(hr, TRUE); END_RECV(); } //------------------------------------------------------------------------------ DUSER_API BOOL WINAPI GetGadgetBufferInfo( IN HGADGET hgad, // Gadget to check OUT BUFFER_INFO * pbi) // Buffer information { DuVisual * pgad; HRESULT hr; BEGIN_RECV(BOOL, FALSE, ContextLock::edNone); VALIDATE_VISUAL(gad); VALIDATE_WRITE_STRUCT(pbi, BUFFER_INFO); VALIDATE_FLAGS(pbi->nMask, GBIM_VALID); if (!pgad->IsBuffered()) { PromptInvalid("Gadget is not GS_BUFFERED"); SetError(DU_E_NOTBUFFERED); goto ErrorExit; } hr = pgad->GetBufferInfo(pbi); SET_RETURN(hr, TRUE); END_RECV(); } //------------------------------------------------------------------------------ DUSER_API BOOL WINAPI SetGadgetBufferInfo( IN HGADGET hgadChange, // Gadget to change IN const BUFFER_INFO * pbi) // Buffer information { DuVisual * pgadChange; HRESULT hr; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_VISUAL(gadChange); VALIDATE_READ_STRUCT(pbi, BUFFER_INFO); VALIDATE_FLAGS(pbi->nMask, GBIM_VALID); if (!pgadChange->IsBuffered()) { PromptInvalid("Gadget is not GS_BUFFERED"); SetError(DU_E_NOTBUFFERED); goto ErrorExit; } hr = pgadChange->SetBufferInfo(pbi); SET_RETURN(hr, TRUE); END_RECV(); } //------------------------------------------------------------------------------ DUSER_API BOOL WINAPI GetGadgetRgn( IN HGADGET hgad, // Gadget to get region of IN UINT nRgnType, // Type of region OUT HRGN hrgn, // Specified region IN UINT nFlags) // Modifying flags { DuVisual * pgad; HRESULT hr; BEGIN_RECV(BOOL, FALSE, ContextLock::edNone); VALIDATE_VISUAL(gad); VALIDATE_RANGE(nRgnType, GRT_MIN, GRT_MAX); VALIDATE_REGION(rgn); hr = pgad->GetRgn(nRgnType, hrgn, nFlags); SET_RETURN(hr, TRUE); END_RECV(); } //------------------------------------------------------------------------------ DUSER_API BOOL WINAPI GetGadgetRootInfo( IN HGADGET hgadRoot, // RootGadget to modify IN ROOT_INFO * pri) // Information { DuRootGadget * pgadRoot; BEGIN_RECV(BOOL, FALSE, ContextLock::edNone); VALIDATE_ROOTGADGET(gadRoot); VALIDATE_WRITE_STRUCT(pri, ROOT_INFO); VALIDATE_FLAGS(pri->nMask, GRIM_VALID); pgadRoot->GetInfo(pri); retval = TRUE; END_RECV(); } //------------------------------------------------------------------------------ DUSER_API BOOL WINAPI SetGadgetRootInfo( IN HGADGET hgadRoot, // RootGadget to modify IN const ROOT_INFO * pri) // Information { DuRootGadget * pgadRoot; HRESULT hr; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_ROOTGADGET(gadRoot); VALIDATE_READ_STRUCT(pri, ROOT_INFO); VALIDATE_FLAGS(pri->nMask, GRIM_VALID); VALIDATE_FLAGS(pri->nOptions, GRIO_VALID); VALIDATE_RANGE(pri->nSurface, GSURFACE_MIN, GSURFACE_MAX); VALIDATE_RANGE(pri->nDropTarget, GRIDT_MIN, GRIDT_MAX); hr = pgadRoot->SetInfo(pri); SET_RETURN(hr, TRUE); END_RECV(); } //------------------------------------------------------------------------------ DUSER_API HRESULT WINAPI DUserSendMethod( IN MethodMsg * pmsg) // Message to send { Context * pctxGad, * pctxSend; HGADGET hgadMsg; MsgObject * pmo; UINT nResult; HRESULT hr; UINT hm; // // Validation for DUserSendMethod() is a little unusual because the // caller doesn't need to be in the same Context as the Gadget itself. This // means we need to get the Context from the Gadget and not use TLS. // // The Caller must be initialized, but we WON'T take the context-lock. // TODO: Investigate whether we should actually do this because it may // allow us to take off the lock on the DUserHeap. // // NOTE: This code has been HIGHLY optimized so that in-context Send // messages will be as fast as possible. // nResult = DU_S_NOTHANDLED; if ((pmsg == NULL) || ((hgadMsg = pmsg->hgadMsg) == NULL) || (pmsg->nMsg >= GM_EVENT)) { PromptInvalid("Invalid parameters to SendGadgetMethod()"); hr = E_INVALIDARG; goto Exit; } pmo = reinterpret_cast(hgadMsg); hm = pmo->GetHandleMask(); if (!TestFlag(hm, hmMsgObject)) { PromptInvalid("Object is not a valid Gadget"); hr = E_INVALIDARG; goto Exit; } if (TestFlag(hm, hmEventGadget)) { DuEventGadget * pgadMsg = static_cast(pmo); pctxSend = RawGetContext(); pctxGad = pgadMsg->GetContext(); AssertMsg(pctxGad != NULL, "Fully created DuEventGadget must have a Context"); if (pctxSend->IsOrphanedNL() || pctxGad->IsOrphanedNL()) { PromptInvalid("Illegally using an orphaned Context"); hr = E_INVALIDARG; goto Exit; } if (pctxSend == pctxGad) { pmo->InvokeMethod(pmsg); hr = S_OK; goto Exit; } else { hr = GetCoreSC(pctxSend)->xwSendMethodNL(GetCoreSC(pctxGad), pmsg, pmo); } } else { // // For non-BaseGadgets, use the current context. This means that we can // invoke directly. // pmo->InvokeMethod(pmsg); hr = S_OK; } Exit: return hr; } /***************************************************************************\ * * SendGadgetEvent (API) * * SendGadgetEvent() sends a message to the specified Gadget. The function * calls the Gadget procedure and does not return until the Gadget has * processed the message. * * * Several members of the GMSG must be previously filled to correctly send * the message to the specified Gadget. * * cbSize Size of the message being sent in bytes. * nMsg ID of the message. * hgadMsg Gadget that the message is being sent to. * result Default result value. *
* * * * Specifies optional flags to modify how the message is sent to the Gadget. * * SGM_BUBBLE The message will be fully routed and bubbled inside * the Gadget Tree. If this flag is not specified, the * message will only be sent directly to the Gadget and * any attached Message Handlers. *
* * * * Return value specifying how message was handled: * * GPR_COMPLETE The message was completely handled by a Gadget * in the processing loop. * GPR_PARTIAL The message was partially handled by one or * more Gadget in the processing loop, but was never * completely handled. * GPR_NOTHANDLED The message was never handled by any Gadgets in * the processing loop. *
*
* * RegisterGadgetMessage * RegisterGadgetMessageString * UnregisterGadgetMessage * UnregisterGadgetMessageString * AddGadgetMessageHandler * RemoveGadgetMessageHandler * GMSG * GadgetMessaging * \***************************************************************************/ DUSER_API HRESULT WINAPI DUserSendEvent( IN EventMsg * pmsg, // Message to send IN UINT nFlags) // Optional flags to modifying sending { Context * pctxGad, * pctxSend; HGADGET hgadMsg; DuEventGadget * pgad; HRESULT nResult; UINT hm; // // Validation for SendGadgetEvent() is a little unusual because the // caller doesn't need to be in the same Context as the Gadget itself. This // means we need to get the Context from the Gadget and not use TLS. // // The Caller must be initialized, but we WON'T take the context-lock. // TODO: Investigate whether we should actually do this because it may // allow us to take off the lock on the DUserHeap. // // NOTE: This code has been HIGHLY optimized so that in-context Send // messages will be as fast as possible. // nResult = E_INVALIDARG; if ((pmsg == NULL) || ((hgadMsg = pmsg->hgadMsg) == NULL) || (pmsg->nMsg < GM_EVENT)) { PromptInvalid("Invalid parameters to SendGadgetEvent()"); goto Error; } pgad = reinterpret_cast(hgadMsg); hm = pgad->GetHandleMask(); if (!TestFlag(hm, hmEventGadget)) { PromptInvalid("Object is not a valid BaseGadget"); goto Error; } pctxSend = RawGetContext(); pctxGad = pgad->GetContext(); AssertMsg(pctxGad != NULL, "Fully created DuEventGadget must have a Context"); if (pctxSend->IsOrphanedNL() || pctxGad->IsOrphanedNL()) { PromptInvalid("Illegally using an orphaned Context"); goto Error; } if (pctxSend == pctxGad) { const GPCB & cb = pgad->GetCallback(); if (TestFlag(nFlags, SGM_FULL) && TestFlag(hm, hmVisual)) { nResult = cb.xwInvokeFull((const DuVisual *) pgad, pmsg, 0); } else { nResult = cb.xwInvokeDirect(pgad, pmsg, 0); } } else { nResult = GetCoreSC(pctxSend)->xwSendEventNL(GetCoreSC(pctxGad), pmsg, pgad, nFlags); } return nResult; Error: return E_INVALIDARG; } //------------------------------------------------------------------------------ DUSER_API HRESULT WINAPI DUserPostMethod( IN MethodMsg * pmsg) // Message to post { Context * pctxGad, * pctxSend; HGADGET hgadMsg; MsgObject * pmo; UINT nResult; HRESULT hr; UINT hm; // // Validation for PostGadgetEvent() is a little unusual because the // caller doesn't need to be in the same Context as the Gadget itself. This // means we need to get the Context from the Gadget and not use TLS. // nResult = DU_S_NOTHANDLED; if ((pmsg == NULL) || ((hgadMsg = pmsg->hgadMsg) == NULL) || (pmsg->nMsg >= GM_EVENT)) { PromptInvalid("Invalid parameters to DUserPostMethod()"); hr = E_INVALIDARG; goto Exit; } pmo = reinterpret_cast(hgadMsg); hm = pmo->GetHandleMask(); if (!TestFlag(hm, hmMsgObject)) { PromptInvalid("Object is not a valid Gadget"); hr = E_INVALIDARG; goto Exit; } if (TestFlag(hm, hmEventGadget)) { DuEventGadget * pgad = static_cast(pmo); pctxSend = RawGetContext(); pctxGad = pgad->GetContext(); AssertMsg(pctxGad != NULL, "Fully created Gadgets must have a Context"); } else { // // For non-BaseGadgets, use the current context. // pctxSend = pctxGad = GetContext(); if (pctxGad == NULL) { PromptInvalid("Must initialize Context before using thread"); hr = DU_E_NOCONTEXT; goto Exit; } } if (pctxSend->IsOrphanedNL() || pctxGad->IsOrphanedNL()) { PromptInvalid("Illegally using an orphaned Context"); hr = E_INVALIDARG; goto Exit; } hr = GetCoreSC(pctxSend)->PostMethodNL(GetCoreSC(pctxGad), pmsg, pmo); Exit: return hr; } /***************************************************************************\ * * DUserPostEvent (API) * * DUserPostEvent() posts a message to the specified Gadget. The function * calls the Gadget procedure and returns after the message has bee successfully * posted to the owning messsage queue. * * * Several members of the GMSG must be previously filled to correctly send * the message to the specified Gadget. * * cbSize Size of the message being sent in bytes. * nMsg ID of the message. * hgadMsg Gadget that the message is being sent to. * result Default result value. *
* * * * Specifies optional flags to modify how the message is sent to the Gadget. * * SGM_BUBBLE The message will be fully routed and bubbled inside * the Gadget Tree. If this flag is not specified, the * message will only be sent directly to the Gadget and * any attached Message Handlers. *
* * * * Message was successfully posted to the destination Gadget's queue. * * * SendGadgetEvent * RegisterGadgetMessage * RegisterGadgetMessageString * UnregisterGadgetMessage * UnregisterGadgetMessageString * AddGadgetMessageHandler * RemoveGadgetMessageHandler * GMSG * GadgetMessaging * \***************************************************************************/ DUSER_API HRESULT WINAPI DUserPostEvent( IN EventMsg * pmsg, // Message to post IN UINT nFlags) // Optional flags modifiying posting { Context * pctxGad; HGADGET hgad; DuEventGadget * pgad; HRESULT hr; // // Validation for PostGadgetEvent() is a little unusual because the // caller doesn't need to be in the same Context as the Gadget itself. This // means we need to get the Context from the Gadget and not use TLS. // BEGIN_RECV_NOCONTEXT(BOOL, FALSE); VALIDATE_READ_PTR_(pmsg, pmsg->cbSize); VALIDATE_FLAGS(nFlags, SGM_VALID); if (pmsg->nMsg < GM_EVENT) { PromptInvalid("Can not post private messages"); SetError(E_INVALIDARG); goto ErrorExit; } if (!IsInitContext()) { PromptInvalid("Must initialize Context before using thread"); SetError(DU_E_NOCONTEXT); goto ErrorExit; } hgad = pmsg->hgadMsg; VALIDATE_EVENTGADGET_NOCONTEXT(gad); pctxGad = pgad->GetContext(); if (pctxGad->IsOrphanedNL()) { PromptInvalid("Illegally using an orphaned Context"); goto ErrorExit; } hr = GetCoreSC()->PostEventNL(GetCoreSC(pctxGad), pmsg, pgad, nFlags); SET_RETURN(hr, TRUE); END_RECV_NOCONTEXT(); } //------------------------------------------------------------------------------ DUSER_API BOOL WINAPI FireGadgetMessages( IN FGM_INFO * rgFGM, // Collection of messsages to fire IN int cMsgs, // Number of messages IN UINT idQueue) // Queue to send messages { Context * pctxGad, * pctxCheck; HGADGET hgad; DuEventGadget * pgad; HRESULT hr; int idx; // // Validation for FireGadgetMessages() is a little unusual because the // caller doesn't need to be in the same Context as the Gadget itself. This // means we need to get the Context from the Gadget and not use TLS. // BEGIN_RECV_NOCONTEXT(BOOL, FALSE); if (cMsgs <= 0) { PromptInvalid("Must specify a valid number of messages to process."); SetError(E_INVALIDARG); goto ErrorExit; } hgad = rgFGM[0].pmsg->hgadMsg; VALIDATE_EVENTGADGET_NOCONTEXT(gad); pctxGad = pgad->GetContext(); for (idx = 0; idx < cMsgs; idx++) { FGM_INFO & fgm = rgFGM[idx]; EventMsg * pmsg = fgm.pmsg; VALIDATE_READ_PTR_(pmsg, pmsg->cbSize); VALIDATE_FLAGS(fgm.nFlags, SGM_VALID); if (pmsg->nMsg <= 0) { PromptInvalid("Can not post private messages"); SetError(E_INVALIDARG); goto ErrorExit; } if (TestFlag(fgm.nFlags, SGM_RECEIVECONTEXT)) { PromptInvalid("Can not use SGM_RECEIVECONTEXT with FireGadgetMessage"); SetError(E_INVALIDARG); goto ErrorExit; } hgad = pmsg->hgadMsg; VALIDATE_EVENTGADGET_NOCONTEXT(gad); pctxCheck = pgad->GetContext(); if (pctxCheck != pctxGad) { PromptInvalid("All Gadgets must be inside the same Context"); SetError(DU_E_INVALIDCONTEXT); goto ErrorExit; } // // Store the validated Gadget back so that it doesn't need to be // revalidated. // fgm.pvReserved = pgad; } hr = GetCoreSC()->xwFireMessagesNL(GetCoreSC(pctxGad), rgFGM, cMsgs, idQueue); SET_RETURN(hr, TRUE); END_RECV_NOCONTEXT(); } /***************************************************************************\ * * GetMessageEx (API) * \***************************************************************************/ DUSER_API BOOL WINAPI GetMessageExA( IN LPMSG lpMsg, IN HWND hWnd, IN UINT wMsgFilterMin, IN UINT wMsgFilterMax) { BEGIN_RECV_NOCONTEXT(BOOL, FALSE); Context * pctxThread = RawGetContext(); if (pctxThread == NULL) { retval = GetMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); } else { retval = GetCoreSC(pctxThread)->xwProcessNL(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, PM_REMOVE, CoreSC::smGetMsg | CoreSC::smAnsi); } END_RECV_NOCONTEXT(); } DUSER_API BOOL WINAPI GetMessageExW( IN LPMSG lpMsg, IN HWND hWnd, IN UINT wMsgFilterMin, IN UINT wMsgFilterMax) { BEGIN_RECV_NOCONTEXT(BOOL, FALSE); Context * pctxThread = RawGetContext(); if (pctxThread == NULL) { retval = GetMessageW(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); } else { retval = GetCoreSC(pctxThread)->xwProcessNL(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, PM_REMOVE, CoreSC::smGetMsg); } END_RECV_NOCONTEXT(); } /***************************************************************************\ * * PeekMessageEx (API) * \***************************************************************************/ DUSER_API BOOL WINAPI PeekMessageExA( IN LPMSG lpMsg, IN HWND hWnd, IN UINT wMsgFilterMin, IN UINT wMsgFilterMax, IN UINT wRemoveMsg) { BEGIN_RECV_NOCONTEXT(BOOL, FALSE); Context * pctxThread = RawGetContext(); if (pctxThread == NULL) { retval = PeekMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); } else { retval = GetCoreSC(pctxThread)->xwProcessNL(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg, CoreSC::smAnsi); } END_RECV_NOCONTEXT(); } DUSER_API BOOL WINAPI PeekMessageExW( IN LPMSG lpMsg, IN HWND hWnd, IN UINT wMsgFilterMin, IN UINT wMsgFilterMax, IN UINT wRemoveMsg) { BEGIN_RECV_NOCONTEXT(BOOL, FALSE); Context * pctxThread = RawGetContext(); if (pctxThread == NULL) { retval = PeekMessageW(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); } else { retval = GetCoreSC(pctxThread)->xwProcessNL(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg, 0); } END_RECV_NOCONTEXT(); } /***************************************************************************\ * * WaitMessageEx (API) * \***************************************************************************/ DUSER_API BOOL WINAPI WaitMessageEx() { BEGIN_RECV_NOCONTEXT(BOOL, FALSE); Context * pctxThread = RawGetContext(); if (pctxThread == NULL) { retval = WaitMessage(); } else { AssertInstance(pctxThread); GetCoreSC(pctxThread)->WaitMessage(); retval = TRUE; } END_RECV_NOCONTEXT(); } /***************************************************************************\ * * RegisterGadgetMessage (API) * * RegisterGadgetMessage() defines a new private Gadget message that is * guaranteed to be unique throughout the process. This MSGID can be used * when calling SendGadgetEvent or PostGadgetEvent. The MSGID is only * valid for the lifetime of the process. * * * Multiple calls to RegisterGadgetMessage() with the same ID will produce * the same MSGID. * * RegisterGadgetMessage() differs in use from RegisterWindowMessage() in * that Gadgets are encouraged to use RegisterGadgetMessage() for all * private messages. This helps with version compatibility problems where * newer Gadget control implementations may use additional message and could * potentially overrun any static MSGID assignments. * * The MSGID's returned from RegisterGadgetMessage() and * RegisterGadgetMessageString() are guaranteed to not conflict with each * other. However, RegisterGadgetMessage() is the preferred mechanism for * registering private messages because of the reduced likelihood of * ID conflicts. * * * ID of new message or 0 if failed. * SendGadgetEvent * RegisterGadgetMessageString * UnregisterGadgetMessage * UnregisterGadgetMessageString * AddGadgetMessageHandler * RemoveGadgetMessageHandler * GMSG * GadgetMessaging * \***************************************************************************/ DUSER_API MSGID WINAPI RegisterGadgetMessage( IN const GUID * pguid) // Unique GUID of message to register { HRESULT hr; MSGID msgid; BEGIN_RECV_NOCONTEXT(MSGID, PRID_Unused); hr = DuEventPool::RegisterMessage(pguid, ptGlobal, &msgid); SET_RETURN(hr, msgid); END_RECV_NOCONTEXT(); } /***************************************************************************\ * * RegisterGadgetMessageString (API) * * RegisterGadgetMessageString() defines a new private Gadget message that is * guaranteed to be unique throughout the process. This MSGID can be used * when calling SendGadgetEvent() or PostGadgetEvent(). The MSGID is only * valid for the lifetime of the process. * * * See RegisterGadgetMessage() for more information about MSGID's. * * * ID of new message or 0 if failed. * SendGadgetEvent * RegisterGadgetMessage * UnregisterGadgetMessage * UnregisterGadgetMessageString * AddGadgetMessageHandler * RemoveGadgetMessageHandler * GMSG * GadgetMessaging * \***************************************************************************/ DUSER_API MSGID WINAPI RegisterGadgetMessageString( IN LPCWSTR pszName) // Unique string ID of message to register { HRESULT hr; MSGID msgid; BEGIN_RECV_NOCONTEXT(MSGID, PRID_Unused); VALIDATE_STRINGW_PTR(pszName, 128); hr = DuEventPool::RegisterMessage(pszName, ptGlobal, &msgid); SET_RETURN(hr, msgid); END_RECV_NOCONTEXT(); } /***************************************************************************\ * * UnregisterGadgetMessage (API) * * UnregisterGadgetMessage() decreases the reference count of a private * message by one. When the reference count reaches 0, resources allocated * to store information about that private message are released, and the * MSGID is no longer valid. * * Message was successfully unregistered. * SendGadgetEvent * RegisterGadgetMessage * RegisterGadgetMessageString * UnregisterGadgetMessageString * AddGadgetMessageHandler * RemoveGadgetMessageHandler * GMSG * GadgetMessaging * \***************************************************************************/ DUSER_API BOOL WINAPI UnregisterGadgetMessage( IN const GUID * pguid) // Unique GUID of message to unregister { HRESULT hr; BEGIN_RECV_NOCONTEXT(BOOL, FALSE); hr = DuEventPool::UnregisterMessage(pguid, ptGlobal); SET_RETURN(hr, TRUE); END_RECV_NOCONTEXT(); } /***************************************************************************\ * * UnregisterGadgetMessageString (API) * * UnregisterGadgetMessageString() decreases the reference count of a private * message by one. When the reference count reaches 0, resources allocated * to store information about that private message are released, and the * MSGID is no longer valid. * * Message was successfully unregistered. * SendGadgetEvent * RegisterGadgetMessage * RegisterGadgetMessageString * UnregisterGadgetMessage * AddGadgetMessageHandler * RemoveGadgetMessageHandler * GMSG * GadgetMessaging * \***************************************************************************/ DUSER_API BOOL WINAPI UnregisterGadgetMessageString( IN LPCWSTR pszName) // Unique string ID of message to register { HRESULT hr; BEGIN_RECV_NOCONTEXT(BOOL, FALSE); VALIDATE_STRINGW_PTR(pszName, 128); hr = DuEventPool::UnregisterMessage(pszName, ptGlobal); SET_RETURN(hr, TRUE); END_RECV_NOCONTEXT(); } //------------------------------------------------------------------------------ DUSER_API BOOL WINAPI FindGadgetMessages( IN const GUID ** rgpguid, // GUID's of messages to find OUT MSGID * rgnMsg, // MSGID's of corresponding to messages IN int cMsgs) // Number of messages { HRESULT hr; BEGIN_RECV(BOOL, FALSE, ContextLock::edNone); VALIDATE_RANGE(cMsgs, 1, 1000); // Ensure don't have an excessive number of lookups hr = DuEventPool::FindMessages(rgpguid, rgnMsg, cMsgs, ptGlobal); SET_RETURN(hr, TRUE); END_RECV(); } /***************************************************************************\ * * AddGadgetMessageHandler (API) * * AddGadgetMessageHandler() adds a given Gadget to the list of message * handlers for another Gadget. Messages that are sent directly to hgadMsg * will also be sent to hgadHandler as an GMF_EVENT. * * * A message handler can be any Gadget. Once registered, hgadHandler will * receive all messages sent to hgadMsg with a corresponding MSGID. Any * valid public or private message can be listened it. If nMsg==0, all * messages will be sent to hgadHandler. * * A single hgadHandler may be registered multiple times to handle different * messages from hgadMsg. * * * Handler was successfully added. * SendGadgetEvent * RegisterGadgetMessage * RegisterGadgetMessageString * UnregisterGadgetMessage * UnregisterGadgetMessageString * RemoveGadgetMessageHandler * GMSG * GadgetMessaging * \***************************************************************************/ DUSER_API BOOL WINAPI AddGadgetMessageHandler( IN HGADGET hgadMsg, // Gadget to attach to IN MSGID nMsg, // Message to watch for IN HGADGET hgadHandler) // Gadget to notify { DuEventGadget * pgadMsg; DuEventGadget * pgadHandler; HRESULT hr; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_EVENTGADGET(gadMsg); VALIDATE_EVENTGADGET(gadHandler); if (((nMsg < PRID_GlobalMin) && (nMsg > 0)) || (nMsg < 0)) { PromptInvalid("nMsg must be a valid MSGID"); goto ErrorExit; } CHECK_MODIFY(); hr = pgadMsg->AddMessageHandler(nMsg, pgadHandler); SET_RETURN(hr, TRUE); END_RECV(); } /***************************************************************************\ * * RemoveGadgetMessageHandler (API) * * RemoveGadgetMessageHandler() removes the specified hgadHandler from the * list of message handlers attached to hgadMsg. Only the first hgadHandler * with a corresponding nMsg will be removed. * * Handler was successfully removed. * SendGadgetEvent * RegisterGadgetMessage * RegisterGadgetMessageString * UnregisterGadgetMessage * UnregisterGadgetMessageString * AddGadgetMessageHandler * GMSG * GadgetMessaging * \***************************************************************************/ DUSER_API BOOL WINAPI RemoveGadgetMessageHandler( IN HGADGET hgadMsg, // Gadget to detach from IN MSGID nMsg, // Message being watched for IN HGADGET hgadHandler) // Gadget being notified { DuEventGadget * pgadMsg; DuEventGadget * pgadHandler; HRESULT hr; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_EVENTGADGET(gadMsg); VALIDATE_EVENTGADGET(gadHandler); if (((nMsg < PRID_GlobalMin) && (nMsg > 0)) || (nMsg < 0)) { PromptInvalid("nMsg must be a valid MSGID"); goto ErrorExit; } CHECK_MODIFY(); hr = pgadMsg->RemoveMessageHandler(nMsg, pgadHandler); SET_RETURN(hr, TRUE); END_RECV(); } /***************************************************************************\ * * GetGadgetStyle (API) * * GetGadgetStyle() returns the current style of the given Gadget. * * * For a list of Gadget styles, see SetGadgetStyle(). * * * Current style of Gadget. * SetGadgetStyle * GadgetStyles * \***************************************************************************/ DUSER_API UINT WINAPI GetGadgetStyle( IN HGADGET hgad) // Handle of Gadget { DuVisual * pgad; BEGIN_RECV(UINT, 0, ContextLock::edNone); VALIDATE_VISUAL(gad); retval = pgad->GetStyle(); END_RECV(); } /***************************************************************************\ * * SetGadgetStyle (API) * * SetGadgetStyle() changes the current style of the given Gadget. Only the * styles specified by nMask are actually changed. If multiple style changes * are requested, but any changes fail, the successfully change styles will * not be reverted back. * * * nNewStyle can be a combination of the following flags: * * GS_RELATIVE The position of the Gadget is internally stored * relative to parent. This is the preferred style * if the Gadget will be moved more frequently, * such as when scrolling. * GS_VISIBLE The Gadget is visible. * GS_ENABLED The Gadget can receive input. * GS_BUFFERED Drawing of the Gadget is double-buffered. * GS_ALLOWSUBCLASS Gadget supports being subclassed. * GS_WANTFOCUS Gadget can receive keyboard focus. * GS_CLIPINSIDE Drawing of this Gadget will be clipped inside * the Gadget. * GS_CLIPSIBLINGS Drawing of this Gadget will exclude any area of * overlapping siblings that are higher in z-order. * GS_OPAQUE HINT: Support for composited drawing is * unnecessary. * GS_ZEROORIGIN Set the origin to (0,0) *
* * * All style changes were successful. * GetGadgetStyle * GadgetStyles * \***************************************************************************/ DUSER_API BOOL WINAPI SetGadgetStyle( IN HGADGET hgadChange, // Gadget to change IN UINT nNewStyle, // New style IN UINT nMask) // Style bits to change { DuVisual * pgadChange; HRESULT hr; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_VISUAL(gadChange); VALIDATE_FLAGS(nNewStyle, GS_VALID); VALIDATE_FLAGS(nMask, GS_VALID); CHECK_MODIFY(); hr = pgadChange->xdSetStyle(nNewStyle, nMask); SET_RETURN(hr, TRUE); END_RECV(); } //------------------------------------------------------------------------------ DUSER_API PRID WINAPI RegisterGadgetProperty( IN const GUID * pguid) // Unique GUID of message to register { HRESULT hr; PRID prid; BEGIN_RECV_NOCONTEXT(PRID, PRID_Unused); hr = DuVisual::RegisterPropertyNL(pguid, ptGlobal, &prid); SET_RETURN(hr, prid); END_RECV_NOCONTEXT(); } //------------------------------------------------------------------------------ DUSER_API BOOL WINAPI UnregisterGadgetProperty( const GUID * pguid) { HRESULT hr; BEGIN_RECV_NOCONTEXT(BOOL, FALSE); hr = DuVisual::UnregisterPropertyNL(pguid, ptGlobal); SET_RETURN(hr, TRUE); END_RECV_NOCONTEXT(); } //------------------------------------------------------------------------------ DUSER_API BOOL WINAPI GetGadgetProperty(HGADGET hgad, PRID id, void ** ppvValue) { DuVisual * pgad; HRESULT hr; BEGIN_RECV(BOOL, FALSE, ContextLock::edNone); VALIDATE_VISUAL(gad); VALIDATE_WRITE_PTR_(ppvValue, sizeof(ppvValue)); CHECK_MODIFY(); hr = pgad->GetProperty(id, ppvValue); SET_RETURN(hr, TRUE); END_RECV(); } //------------------------------------------------------------------------------ DUSER_API BOOL WINAPI SetGadgetProperty(HGADGET hgad, PRID id, void * pvValue) { DuVisual * pgad; HRESULT hr; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_VISUAL(gad); CHECK_MODIFY(); hr = pgad->SetProperty(id, pvValue); SET_RETURN(hr, TRUE); END_RECV(); } //--------------------------------------------------------------------------- DUSER_API BOOL WINAPI RemoveGadgetProperty(HGADGET hgad, PRID id) { DuVisual * pgad; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_VISUAL(gad); CHECK_MODIFY(); pgad->RemoveProperty(id, FALSE /* Can't free memory for Global property*/); retval = TRUE; END_RECV(); } //--------------------------------------------------------------------------- DUSER_API BOOL WINAPI EnumGadgets(HGADGET hgadEnum, GADGETENUMPROC pfnProc, void * pvData, UINT nFlags) { DuVisual * pgadEnum; HRESULT hr; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_FLAGS(nFlags, GENUM_VALID); VALIDATE_VISUAL(gadEnum); VALIDATE_CODE_PTR(pfnProc); CHECK_MODIFY(); hr = pgadEnum->xwEnumGadgets(pfnProc, pvData, nFlags); SET_RETURN(hr, TRUE); END_RECV(); } /***************************************************************************\ * * GetGadgetSize (API) * * GetGadgetSize() is a high-performance mechanism of retreiving the Gadget's * logical size. * * Successfully returned size in logical pixels. * GetGadgetRect * SetGadgetRect * GadgetStyles * \***************************************************************************/ DUSER_API BOOL WINAPI GetGadgetSize( IN HGADGET hgad, // Handle of Gadget OUT SIZE * psizeLogicalPxl) // Size in logical pixels { DuVisual * pgad; BEGIN_RECV(BOOL, FALSE, ContextLock::edNone); VALIDATE_VISUAL(gad); VALIDATE_WRITE_PTR_(psizeLogicalPxl, sizeof(SIZE)); pgad->GetSize(psizeLogicalPxl); retval = TRUE; END_RECV(); } /***************************************************************************\ * * GetGadgetRect (API) * * GetGadgetRect() is a flexible mechanism of retreiving the Gadget's * logical rectangle or actual bounding box. * * * nFlags can be a combination of the following flags: * * SGR_CLIENT Coordinates are relative to the Gadget itself. * SGR_PARENT Coordinates are relative to the Gadget's parent. * SGR_CONTAINER Coordinates are relative to the Gadget's root * container. * SGR_DESKTOP Coordinates are relative to the Windows desktop. * SGR_ACTUAL Return the bounding rectangle of the Gadget. If * this flag is specified, a bounding box is * computed from all transformations applied from * the root to the Gadget itself. If this flag is * not specified, the rectangle returned will be in * logical coordinates. *
* * * Rectangle was successfully retreived. * SetGadgetRect * GetGadgetRotation * SetGadgetRotation * GetGadgetScale * SetGadgetScale * \***************************************************************************/ DUSER_API BOOL WINAPI GetGadgetRect( IN HGADGET hgad, // Handle of Gadget OUT RECT * prcPxl, // Rectangle in specified pixels IN UINT nFlags) // Rectangle to retrieve { DuVisual * pgad; BEGIN_RECV(BOOL, FALSE, ContextLock::edNone); VALIDATE_FLAGS(nFlags, SGR_VALID_GET); VALIDATE_VISUAL(gad); VALIDATE_WRITE_PTR_(prcPxl, sizeof(RECT)); if (TestFlag(nFlags, SGR_ACTUAL)) { AssertMsg(0, "TODO: Not Implemented"); } else { pgad->GetLogRect(prcPxl, nFlags); retval = TRUE; } END_RECV(); } /***************************************************************************\ * * SetGadgetRect (API) * * SetGadgetRect() changes the size or position of a given Gadget. * * * nFlags can be a combination of the following flags: * * SGR_MOVE Move to Gadget to a new location specified by * x, y. * SGR_SIZE Change the Gadget's size to width w and height h. * SGR_CLIENT Coordinates are relative to the Gadget itself. * SGR_PARENT Coordinates are relative to the Gadget's parent. * SGR_CONTAINER Coordinates are relative to the Gadget's root * container. * SGR_DESKTOP Coordinates are relative to the Windows desktop. * SGR_OFFSET Coordinates are relative to the Gadget's current * location. * SGR_ACTUAL Return the bounding rectangle of the Gadget. If * this flag is specified, a bounding box is * computed from all transformations applied from * the root to the Gadget itself. If this flag is * not specified, the rectangle returned will be in * logical coordinates. *
* * * Rectangle was successfully retreived. * SetGadgetRect * GetGadgetRotation * SetGadgetRotation * GetGadgetScale * SetGadgetScale * \***************************************************************************/ DUSER_API BOOL WINAPI SetGadgetRect( IN HGADGET hgadChange, // Gadget to change IN int x, // New horizontal position IN int y, // New vertical position IN int w, // New width IN int h, // New height IN UINT nFlags) // Flags specifying what to change { DuVisual * pgadChange; HRESULT hr; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_FLAGS(nFlags, SGR_VALID_SET); VALIDATE_VISUAL(gadChange); CHECK_MODIFY(); if (pgadChange->IsRoot()) { if (TestFlag(nFlags, SGR_MOVE)) { PromptInvalid("Can not move a RootGadget"); SetError(E_INVALIDARG); goto ErrorExit; } } // // Ensure that size is non-negative // if (TestFlag(nFlags, SGR_SIZE)) { if (w < 0) { w = 0; } if (h < 0) { h = 0; } } if (TestFlag(nFlags, SGR_ACTUAL)) { // AssertMsg(0, "TODO: Not Implemented"); ClearFlag(nFlags, SGR_ACTUAL); hr = pgadChange->xdSetLogRect(x, y, w, h, nFlags); } else { hr = pgadChange->xdSetLogRect(x, y, w, h, nFlags); } SET_RETURN(hr, TRUE); END_RECV(); } /***************************************************************************\ * * FindGadgetFromPoint (API) * * FindGadgetFromPoint() determines which Gadget a contains the specified * point. * * Gadget containing point or NULL for none. * \***************************************************************************/ DUSER_API HGADGET WINAPI FindGadgetFromPoint( IN HGADGET hgad, // Gadget to search from IN POINT ptContainerPxl, // Point to search from in container pixels IN UINT nStyle, // Required style flags OUT POINT * pptClientPxl) // Optional translated point in client pixels. { DuVisual * pgad; BEGIN_RECV(HGADGET, NULL, ContextLock::edNone); VALIDATE_FLAGS(nStyle, GS_VALID); VALIDATE_VISUAL(gad); VALIDATE_WRITE_PTR_OR_NULL_(pptClientPxl, sizeof(POINT)); retval = (HGADGET) GetHandle(pgad->FindFromPoint(ptContainerPxl, nStyle, pptClientPxl)); END_RECV(); } /***************************************************************************\ * * MapGadgetPoints (API) * * MapGadgetPoints() converts a set of points in client-pixels relative to * one Gadget into points in client-pixels relative to another Gadget. * * Gadget containing point or NULL for none. * \***************************************************************************/ DUSER_API BOOL WINAPI MapGadgetPoints( IN HGADGET hgadFrom, IN HGADGET hgadTo, IN OUT POINT * rgptClientPxl, IN int cPts) { DuVisual * pgadFrom, * pgadTo; BEGIN_RECV(BOOL, FALSE, ContextLock::edNone); VALIDATE_VISUAL(gadFrom); VALIDATE_VISUAL(gadTo); VALIDATE_WRITE_PTR_(rgptClientPxl, sizeof(POINT) * cPts); if (pgadFrom->GetRoot() != pgadTo->GetRoot()) { PromptInvalid("Must be in the same tree"); SetError(E_INVALIDARG); goto ErrorExit; } DuVisual::MapPoints(pgadFrom, pgadTo, rgptClientPxl, cPts); retval = TRUE; END_RECV(); } /***************************************************************************\ * * SetGadgetOrder (API) * * SetGadgetOrder() changes the Gadget's z-order relative to its siblings. * The parent of the Gadget is not changed. * * * nFlags can be a combination of the following flags: * * GORDER_ANY The order does not matter. * GORDER_BEFORE Move this gadget in-front of sibling hgadOther. * GORDER_BEHIND Move this gadget behind sibling hgadOther. * GORDER_TOP Move this gadget to front of sibling z-order. * GORDER_BOTTOM Move this gadget to bottom of sibling z-order. * GORDER_FORWARD Move this gadget forward in sibling z-order. * GORDER_BACKWARD Move this gadget backward in sibling z-order. *
* * * Gadget z-order was successfully changed. * SetGadgetParent * \***************************************************************************/ DUSER_API BOOL WINAPI SetGadgetOrder( IN HGADGET hgadMove, // Gadget to be moved IN HGADGET hgadOther, // Gadget to moved relative to IN UINT nCmd) // Type of move { DuVisual * pgadMove; DuVisual * pgadOther; HRESULT hr; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_RANGE(nCmd, GORDER_MIN, GORDER_MAX); VALIDATE_VISUAL(gadMove); VALIDATE_VISUAL_OR_NULL(gadOther); CHECK_MODIFY(); hr = pgadMove->xdSetOrder(pgadOther, nCmd); SET_RETURN(hr, TRUE); END_RECV(); } /***************************************************************************\ * * SetGadgetParent (API) * * SetGadgetParent() changes the Gadget's parent. * * * nFlags can be a combination of the following flags: * * GORDER_ANY The order does not matter. * GORDER_BEFORE Move this gadget in-front of sibling hgadOther. * GORDER_BEHIND Move this gadget behind sibling hgadOther. * GORDER_TOP Move this gadget to front of sibling z-order. * GORDER_BOTTOM Move this gadget to bottom of sibling z-order. * GORDER_FORWARD Move this gadget forward in sibling z-order. * GORDER_BACKWARD Move this gadget backward in sibling z-order. *
* * * Gadget parent and z-order were successfully changed. * SetGadgetOrder * GetGadget * \***************************************************************************/ DUSER_API BOOL WINAPI SetGadgetParent( IN HGADGET hgadMove, // Gadget to be moved IN HGADGET hgadParent, // New parent IN HGADGET hgadOther, // Gadget to moved relative to IN UINT nCmd) // Type of move { DuVisual * pgadMove; DuVisual * pgadParent; DuVisual * pgadOther; HRESULT hr; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_RANGE(nCmd, GORDER_MIN, GORDER_MAX); VALIDATE_VISUAL(gadMove); VALIDATE_VISUAL_OR_NULL(gadParent); VALIDATE_VISUAL_OR_NULL(gadOther); CHECK_MODIFY(); if (pgadMove->IsRoot()) { PromptInvalid("Can not change a RootGadget's parent"); SetError(E_INVALIDARG); goto ErrorExit; } // // Check that can become a child of the specified parent // if ((!pgadMove->IsRelative()) && pgadParent->IsRelative()) { PromptInvalid("Can not set non-relative child to a relative parent"); SetError(DU_E_BADCOORDINATEMAP); goto ErrorExit; } // // DuVisual::xdSetParent() handles if pgadParent is NULL and will move to the // parking window. // hr = pgadMove->xdSetParent(pgadParent, pgadOther, nCmd); SET_RETURN(hr, TRUE); END_RECV(); } /***************************************************************************\ * * GetGadget (API) * * GetGadget() retrieves the Gadget that has the specified relationship to * the specified Gadget. * * * nFlags can be a combination of the following flags: * * GG_PARENT Return the parent of the specified Gadget. * GG_NEXT Return the next sibling behind the specified * Gadget. * GG_PREV Return the previous sibling before the * specified Gadget. * GG_TOPCHILD Return the Gadget's top z-ordered child. * GG_BOTTOMCHILD Return the Gadget's bottom z-ordered child. *
* * * Related Gadget or NULL for none. * SetGadgetOrder * SetGadgetParent * \***************************************************************************/ DUSER_API HGADGET WINAPI GetGadget( IN HGADGET hgad, // Handle of Gadget IN UINT nCmd) // Relationship { DuVisual * pgad; BEGIN_RECV(HGADGET, NULL, ContextLock::edNone); VALIDATE_VISUAL(gad); VALIDATE_RANGE(nCmd, GG_MIN, GG_MAX); retval = (HGADGET) GetHandle(pgad->GetGadget(nCmd)); END_RECV(); } /***************************************************************************\ * * InvalidateGadget (API) * * InvalidateGadget() marks a Gadget to be repainted during the next painting * cycle. * * Gadget was successfully invalidated. * GM_PAINT * \***************************************************************************/ DUSER_API BOOL WINAPI InvalidateGadget( IN HGADGET hgad) // Gadget to repaint { DuVisual * pgad; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_VISUAL(gad); CHECK_MODIFY(); pgad->Invalidate(); retval = TRUE; END_RECV(); } //--------------------------------------------------------------------------- DUSER_API UINT WINAPI GetGadgetMessageFilter(HGADGET hgad, void * pvCookie) { DuEventGadget * pgad; BEGIN_RECV(UINT, 0, ContextLock::edNone); VALIDATE_EVENTGADGET(gad); VALIDATE_VALUE(pvCookie, NULL); retval = (pgad->GetFilter() & GMFI_VALID); END_RECV(); } //--------------------------------------------------------------------------- DUSER_API BOOL WINAPI SetGadgetMessageFilter(HGADGET hgadChange, void * pvCookie, UINT nNewFilter, UINT nMask) { DuEventGadget * pgadChange; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_EVENTGADGET(gadChange); VALIDATE_FLAGS(nNewFilter, GMFI_VALID); VALIDATE_VALUE(pvCookie, NULL); CHECK_MODIFY(); pgadChange->SetFilter(nNewFilter, nMask); retval = TRUE; END_RECV(); } //--------------------------------------------------------------------------- DUSER_API BOOL WINAPI ForwardGadgetMessage(HGADGET hgadRoot, UINT nMsg, WPARAM wParam, LPARAM lParam, LRESULT * pr) { DuVisual * pgadRoot; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_VISUAL(gadRoot); VALIDATE_WRITE_PTR(pr); CHECK_MODIFY(); retval = GdForwardMessage(pgadRoot, nMsg, wParam, lParam, pr); END_RECV(); } //--------------------------------------------------------------------------- DUSER_API BOOL WINAPI DrawGadgetTree(HGADGET hgadDraw, HDC hdcDraw, const RECT * prcDraw, UINT nFlags) { DuVisual * pgadDraw; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_VISUAL(gadDraw); VALIDATE_READ_PTR_OR_NULL_(prcDraw, sizeof(RECT)); VALIDATE_FLAGS(nFlags, GDRAW_VALID); retval = GdxrDrawGadgetTree(pgadDraw, hdcDraw, prcDraw, nFlags); END_RECV(); } /***************************************************************************\ ***************************************************************************** * * DirectUser GADGET API * * * ***************************************************************************** \***************************************************************************/ /***************************************************************************\ * * DUserRegisterGuts * * DUserRegisterGuts() registers the implementation of a MsgClass. * \***************************************************************************/ DUSER_API HCLASS WINAPI DUserRegisterGuts( IN OUT DUser::MessageClassGuts * pmcInfo) // Class information { MsgClass * pmcNew; HRESULT hr; BEGIN_RECV_NOCONTEXT(HCLASS, NULL); VALIDATE_WRITE_STRUCT(pmcInfo, DUser::MessageClassGuts); hr = GetClassLibrary()->RegisterGutsNL(pmcInfo, &pmcNew); SET_RETURN(hr, (HCLASS) GetHandle(pmcNew)); END_RECV_NOCONTEXT(); } /***************************************************************************\ * * DUserRegisterStub * * DUserRegisterStub() registers a Stub for a MsgClass * \***************************************************************************/ DUSER_API HCLASS WINAPI DUserRegisterStub( IN OUT DUser::MessageClassStub * pmcInfo) // Class information { MsgClass * pmcFind; HRESULT hr; BEGIN_RECV_NOCONTEXT(HCLASS, NULL); VALIDATE_WRITE_STRUCT(pmcInfo, DUser::MessageClassStub); hr = GetClassLibrary()->RegisterStubNL(pmcInfo, &pmcFind); SET_RETURN(hr, (HCLASS) GetHandle(pmcFind)); END_RECV_NOCONTEXT(); } /***************************************************************************\ * * DUserRegisterSuper * * DUserRegisterSuper() registers a Super for a MsgClass * \***************************************************************************/ DUSER_API HCLASS WINAPI DUserRegisterSuper( IN OUT DUser::MessageClassSuper * pmcInfo) // Class information { MsgClass * pmcFind; HRESULT hr; BEGIN_RECV_NOCONTEXT(HCLASS, NULL); VALIDATE_WRITE_STRUCT(pmcInfo, DUser::MessageClassSuper); hr = GetClassLibrary()->RegisterSuperNL(pmcInfo, &pmcFind); SET_RETURN(hr, (HCLASS) GetHandle(pmcFind)); END_RECV_NOCONTEXT(); } /***************************************************************************\ * * DUserFindClass * * DUserFindClass() finds a previously registered Gadget Class * \***************************************************************************/ DUSER_API HCLASS WINAPI DUserFindClass( IN LPCWSTR pszName, IN DWORD nVersion) { const MsgClass * pmcFind = NULL; ATOM atom; HRESULT hr; BEGIN_RECV_NOCONTEXT(HCLASS, NULL); VALIDATE_VALUE(nVersion, 1); // Currently, all classes are version 1 atom = FindAtomW(pszName); if (atom == 0) { hr = DU_E_NOTFOUND; } else { pmcFind = GetClassLibrary()->FindClass(atom); hr = S_OK; } SET_RETURN(hr, (HCLASS) GetHandle(pmcFind)); END_RECV_NOCONTEXT(); } /***************************************************************************\ * * DUserBuildGadget * * DUserBuildGadget() creates a fully initialized Gadget using the specified * MsgClass. * \***************************************************************************/ DUSER_API DUser::Gadget * WINAPI DUserBuildGadget( IN HCLASS hcl, // Class to construct IN DUser::Gadget::ConstructInfo * pciData) // Construction data { MsgClass * pmc = ValidateMsgClass(hcl); if (pmc == NULL) { return NULL; } MsgObject * pmoNew; HRESULT hr = pmc->xwBuildObject(&pmoNew, pciData); if (FAILED(hr)) { return NULL; } return pmoNew->GetGadget(); } //------------------------------------------------------------------------------ DUSER_API BOOL WINAPI DUserInstanceOf(DUser::Gadget * pg, HCLASS hclTest) { MsgObject * pmo; MsgClass * pmcTest; pmo = MsgObject::CastMsgObject(pg); if (pmo == NULL) { PromptInvalid("The specified Gadget is invalid"); goto Error; } pmcTest = ValidateMsgClass(hclTest); if (pmcTest == NULL) { PromptInvalid("The specified class is invalid"); goto Error; } return pmo->InstanceOf(pmcTest); Error: SetError(E_INVALIDARG); return FALSE; } //------------------------------------------------------------------------------ DUSER_API DUser::Gadget * WINAPI DUserCastClass(DUser::Gadget * pg, HCLASS hclTest) { MsgObject * pmo; MsgClass * pmcTest; // // A NULL MsgObject is a valid input, so return NULL. // pmo = MsgObject::CastMsgObject(pg); if (pmo == NULL) { return NULL; } // // The HCLASS must be valid. // pmcTest = ValidateMsgClass(hclTest); if (pmcTest == NULL) { PromptInvalid("The specified class is invalid"); goto Error; } return pmo->CastClass(pmcTest); Error: SetError(E_INVALIDARG); return NULL; } //------------------------------------------------------------------------------ DUSER_API DUser::Gadget * WINAPI DUserCastDirect(HGADGET hgad) { return MsgObject::CastGadget(hgad); } //------------------------------------------------------------------------------ DUSER_API HGADGET WINAPI DUserCastHandle(DUser::Gadget * pg) { return MsgObject::CastHandle(pg); } //------------------------------------------------------------------------------ DUSER_API void * WINAPI DUserGetGutsData(DUser::Gadget * pg, HCLASS hclData) { MsgObject * pmo; MsgClass * pmcData; pmo = MsgObject::CastMsgObject(pg); if (pmo == NULL) { PromptInvalid("The specified Gadget is invalid"); goto Error; } pmcData = ValidateMsgClass(hclData); if (pmcData == NULL) { PromptInvalid("The specified class is invalid"); goto Error; } return pmo->GetGutsData(pmcData); Error: SetError(E_INVALIDARG); return NULL; } /***************************************************************************\ ***************************************************************************** * * DirectUser GADGET API * * * ***************************************************************************** \***************************************************************************/ //--------------------------------------------------------------------------- DUSER_API BOOL WINAPI AttachWndProcA(HWND hwnd, ATTACHWNDPROC pfn, void * pvThis) { HRESULT hr = GdAttachWndProc(hwnd, pfn, pvThis, TRUE); if (SUCCEEDED(hr)) { return TRUE; } else { SetError(hr); return FALSE; } } //--------------------------------------------------------------------------- DUSER_API BOOL WINAPI AttachWndProcW(HWND hwnd, ATTACHWNDPROC pfn, void * pvThis) { HRESULT hr = GdAttachWndProc(hwnd, pfn, pvThis, FALSE); if (SUCCEEDED(hr)) { return TRUE; } else { SetError(hr); return FALSE; } } //--------------------------------------------------------------------------- DUSER_API BOOL WINAPI DetachWndProc(HWND hwnd, ATTACHWNDPROC pfn, void * pvThis) { HRESULT hr = GdDetachWndProc(hwnd, pfn, pvThis); if (SUCCEEDED(hr)) { return TRUE; } else { SetError(hr); return FALSE; } } /***************************************************************************\ ***************************************************************************** * * DirectUser MOTION API * * * ***************************************************************************** \***************************************************************************/ //--------------------------------------------------------------------------- DUSER_API HTRANSITION WINAPI CreateTransition(const GTX_TRXDESC * ptx) { BEGIN_RECV(HTRANSITION, NULL, ContextLock::edDefer); VALIDATE_READ_PTR_(ptx, sizeof(GTX_TRXDESC)); CHECK_MODIFY(); retval = (HTRANSITION) GetHandle(GdCreateTransition(ptx)); END_RECV(); } //--------------------------------------------------------------------------- DUSER_API BOOL WINAPI PlayTransition(HTRANSITION htrx, const GTX_PLAY * pgx) { Transition * ptrx; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_TRANSITION(trx); VALIDATE_READ_PTR_(pgx, sizeof(GTX_PLAY)); VALIDATE_FLAGS(pgx->nFlags, GTX_EXEC_VALID); retval = ptrx->Play(pgx); END_RECV(); } //--------------------------------------------------------------------------- DUSER_API BOOL WINAPI GetTransitionInterface(HTRANSITION htrx, IUnknown ** ppUnk) { Transition * ptrx; BEGIN_RECV(BOOL, FALSE, ContextLock::edNone); VALIDATE_TRANSITION(trx); VALIDATE_WRITE_PTR(ppUnk); retval = ptrx->GetInterface(ppUnk); END_RECV(); } //--------------------------------------------------------------------------- DUSER_API BOOL WINAPI BeginTransition(HTRANSITION htrx, const GTX_PLAY * pgx) { Transition * ptrx; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_TRANSITION(trx); VALIDATE_READ_PTR_(pgx, sizeof(GTX_PLAY)); retval = ptrx->Begin(pgx); END_RECV(); } //--------------------------------------------------------------------------- DUSER_API BOOL WINAPI PrintTransition(HTRANSITION htrx, float fProgress) { Transition * ptrx; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_TRANSITION(trx); retval = ptrx->Print(fProgress); END_RECV(); } //--------------------------------------------------------------------------- DUSER_API BOOL WINAPI EndTransition(HTRANSITION htrx, const GTX_PLAY * pgx) { Transition * ptrx; BEGIN_RECV(BOOL, FALSE, ContextLock::edDefer); VALIDATE_TRANSITION(trx); VALIDATE_READ_PTR_(pgx, sizeof(GTX_PLAY)); retval = ptrx->End(pgx); END_RECV(); } //--------------------------------------------------------------------------- DUSER_API HACTION WINAPI CreateAction(const GMA_ACTION * pma) { BEGIN_RECV(HACTION, NULL, ContextLock::edNone); VALIDATE_READ_STRUCT(pma, GMA_ACTION); retval = GdCreateAction(pma); END_RECV(); } //--------------------------------------------------------------------------- DUSER_API BOOL WINAPI GetActionTimeslice(DWORD * pdwTimeslice) { BEGIN_RECV(BOOL, FALSE, ContextLock::edNone); VALIDATE_WRITE_PTR(pdwTimeslice); *pdwTimeslice = GetMotionSC()->GetTimeslice(); retval = TRUE; END_RECV(); } //--------------------------------------------------------------------------- DUSER_API BOOL WINAPI SetActionTimeslice(DWORD dwTimeslice) { BEGIN_RECV(BOOL, FALSE, ContextLock::edNone); GetMotionSC()->SetTimeslice(dwTimeslice); retval = TRUE; END_RECV(); } /***************************************************************************\ ***************************************************************************** * * DirectUser UTIL API * * * ***************************************************************************** \***************************************************************************/ //--------------------------------------------------------------------------- DUSER_API COLORREF WINAPI GetStdColorI(UINT c) { BEGIN_RECV_NOCONTEXT(COLORREF, RGB(0, 0, 0)); VALIDATE_RANGE(c, 0, SC_MAXCOLORS); retval = GdGetColorInfo(c)->GetColorI(); END_RECV_NOCONTEXT(); } //--------------------------------------------------------------------------- DUSER_API Gdiplus::Color WINAPI GetStdColorF(UINT c) { BEGIN_RECV_NOCONTEXT(Gdiplus::Color, Gdiplus::Color((Gdiplus::ARGB) Gdiplus::Color::Black)); VALIDATE_RANGE(c, 0, SC_MAXCOLORS); retval = GdGetColorInfo(c)->GetColorF(); END_RECV_NOCONTEXT(); } //--------------------------------------------------------------------------- DUSER_API HBRUSH WINAPI GetStdColorBrushI(UINT c) { BEGIN_RECV(HBRUSH, NULL, ContextLock::edNone); VALIDATE_RANGE(c, 0, SC_MAXCOLORS); retval = GetMotionSC()->GetBrushI(c); END_RECV(); } //--------------------------------------------------------------------------- DUSER_API Gdiplus::Brush * WINAPI GetStdColorBrushF(UINT c) { BEGIN_RECV(Gdiplus::Brush *, NULL, ContextLock::edNone); VALIDATE_RANGE(c, 0, SC_MAXCOLORS); retval = GetMotionSC()->GetBrushF(c); END_RECV(); } //--------------------------------------------------------------------------- DUSER_API HPEN WINAPI GetStdColorPenI(UINT c) { BEGIN_RECV(HPEN, NULL, ContextLock::edNone); VALIDATE_RANGE(c, 0, SC_MAXCOLORS); retval = GetMotionSC()->GetPenI(c); END_RECV(); } //--------------------------------------------------------------------------- DUSER_API Gdiplus::Pen * WINAPI GetStdColorPenF(UINT c) { BEGIN_RECV(Gdiplus::Pen *, NULL, ContextLock::edNone); VALIDATE_RANGE(c, 0, SC_MAXCOLORS); retval = GetMotionSC()->GetPenF(c); END_RECV(); } //--------------------------------------------------------------------------- DUSER_API LPCWSTR WINAPI GetStdColorName(UINT c) { BEGIN_RECV_NOCONTEXT(LPCWSTR, NULL); VALIDATE_RANGE(c, 0, SC_MAXCOLORS); retval = GdGetColorInfo(c)->GetName(); END_RECV_NOCONTEXT(); } //--------------------------------------------------------------------------- DUSER_API UINT WINAPI FindStdColor(LPCWSTR pszName) { BEGIN_RECV_NOCONTEXT(UINT, SC_Black); VALIDATE_STRINGW_PTR(pszName, 50); retval = GdFindStdColor(pszName); END_RECV_NOCONTEXT(); } //--------------------------------------------------------------------------- DUSER_API HPALETTE WINAPI GetStdPalette() { BEGIN_RECV_NOCONTEXT(HPALETTE, NULL); retval = GdGetStdPalette(); END_RECV_NOCONTEXT(); } //--------------------------------------------------------------------------- DUSER_API BOOL WINAPI UtilSetBackground(HGADGET hgadChange, HBRUSH hbrBack) { BOOL fSuccess = FALSE; if (SetGadgetFillI(hgadChange, hbrBack, BLEND_OPAQUE, 0, 0)) { UINT nStyle = hbrBack != NULL ? GS_OPAQUE : 0; fSuccess = SetGadgetStyle(hgadChange, nStyle, GS_OPAQUE); } return fSuccess; } //--------------------------------------------------------------------------- DUSER_API HFONT WINAPI UtilBuildFont(LPCWSTR pszName, int idxDeciSize, DWORD nFlags, HDC hdcDevice) { return GdBuildFont(pszName, idxDeciSize, nFlags, hdcDevice); } //--------------------------------------------------------------------------- DUSER_API BOOL WINAPI UtilDrawBlendRect(HDC hdcDest, const RECT * prcDest, HBRUSH hbrFill, BYTE bAlpha, int wBrush, int hBrush) { return GdDrawBlendRect(hdcDest, prcDest, hbrFill, bAlpha, wBrush, hBrush); } //--------------------------------------------------------------------------- DUSER_API BOOL WINAPI UtilDrawOutlineRect(HDC hdc, const RECT * prcPxl, HBRUSH hbrDraw, int nThickness) { return GdDrawOutlineRect(hdc, prcPxl, hbrDraw, nThickness); } //--------------------------------------------------------------------------- DUSER_API COLORREF WINAPI UtilGetColor(HBITMAP hbmp, POINT * pptPxl) { return GdGetColor(hbmp, pptPxl); } /***************************************************************************\ * * GetGadgetTicket * * The GetGadgetTicket function returns the ticket that can be used to * identify the specified gadget. * * * A handle to the gadget to retrieve the ticket for. * * * * If the function succeeds, the return value is a 32-bit ticket that * can be used to identify the specified gadget. * If the function fails, the return value is zero. * * * * Tickets are created to give an external identity to a gadget. A * is guaranteed to be 32 bits on all platforms. If no ticket is * currently associated with this gadget, one is allocated. * * * LookupGadgetTicket * \***************************************************************************/ DUSER_API DWORD WINAPI GetGadgetTicket( IN HGADGET hgad) // Handle of Gadget { DuVisual * pgad; DWORD dwTicket; HRESULT hr; BEGIN_RECV(DWORD, 0, ContextLock::edNone); VALIDATE_VISUAL(gad); hr = pgad->GetTicket(&dwTicket); SET_RETURN(hr, dwTicket); END_RECV(); } /***************************************************************************\ * * LookupGadgetTicket * * The LookupGadgetTicket function returns the gadget that is associated with * the specified ticket. * * * A ticket that has been associated with a gadget via the * GetGadgetTicket function. * * * * If the function succeeds, the return value is a handle to the gadget * associated with the ticket. * If the function fails, the return value is NULL. * * * GetGadgetTicket * \***************************************************************************/ DUSER_API HGADGET WINAPI LookupGadgetTicket( IN DWORD dwTicket) // Ticket { BEGIN_RECV(HGADGET, NULL, ContextLock::edNone); retval = DuVisual::LookupTicket(dwTicket); END_RECV(); }