Windows2003-3790/windows/advcore/duser/engine/winapi/apistubs.cpp
2020-09-30 16:53:55 +02:00

3588 lines
112 KiB
C++

/***************************************************************************\
*
* 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 <class T>
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().
*
* <package name="Core"/>
*
*****************************************************************************
\***************************************************************************/
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.
*
* <return type="BOOL"> Components were successfully initialized.</>
* <see type="function"> CreateTransition</>
* <see type="function"> 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.
*
* <return type="BOOL"> Components were successfully uninitialized.</>
* <see type="function"> 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.
*
* <return type="BOOL"> Object was successfully deleted.</>
* <see type="function"> CreateGadget</>
* <see type="function"> CreateTransition</>
* <see type="function"> 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.
*
* <param name="nFlags">
* Specifies both what type of Gadget to created and any creation-time
* properties of that Gadget
* <table item="Value" desc="Action">
* 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.
* </table>
* </param>
*
* <return type="HGADGET"> Returns a handle to the newly created Gadget
* or NULL if the creation failed.</>
* <see type="function"> 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.
*
* <return type="HGADGET"> Gadget with keyboard focus.</>
* <see type="function"> SetGadgetFocus</>
* <see type="message"> 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.
*
* <return type="BOOL"> Focus was successfully moved.</>
* <see type="function"> GetGadgetFocus</>
* <see type="message"> 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.
*
* <return type="BOOL"> Gadget was successfully checked.</>
* <see type="function"> GetGadgetStyle</>
* <see type="function"> 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.
*
* <return type="BOOL"> Fill was successfully set.</>
* <see type="function"> UtilDrawBlendRect</>
* <see type="message"> 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.
*
* <return type="BOOL"> Fill was successfully set.</>
* <see type="function"> UtilDrawBlendRect</>
* <see type="message"> 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.
*
* <return type="BOOL"> Successfully returned scaling factor</>
* <see type="function"> SetGadgetScale</>
* <see type="function"> GetGadgetRotation</>
* <see type="function"> SetGadgetRotation</>
* <see type="function"> GetGadgetRect</>
* <see type="function"> 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.
*
* <return type="BOOL"> Successfully changed scaling factor</>
* <see type="function"> GetGadgetScale</>
* <see type="function"> GetGadgetRotation</>
* <see type="function"> SetGadgetRotation</>
* <see type="function"> GetGadgetRect</>
* <see type="function"> 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.
*
* <return type="BOOL"> Successfully returned rotation factor</>
* <see type="function"> GetGadgetScale</>
* <see type="function"> SetGadgetScale</>
* <see type="function"> SetGadgetRotation</>
* <see type="function"> GetGadgetRect</>
* <see type="function"> 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.
*
* <return type="BOOL"> Successfully changed scaling factor</>
* <see type="function"> GetGadgetScale</>
* <see type="function"> SetGadgetScale</>
* <see type="function"> GetGadgetRotation</>
* <see type="function"> GetGadgetRect</>
* <see type="function"> 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<MsgObject *>(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<DuEventGadget *>(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.
*
* <param name="pmsg">
* Several members of the GMSG must be previously filled to correctly send
* the message to the specified Gadget.
* <table item="Field" desc="Description">
* 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.
* </table>
* </param>
*
* <param nane="nFlags">
* Specifies optional flags to modify how the message is sent to the Gadget.
* <table item="Value" desc="Action">
* 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.
* </table>
* </param>
*
* <return type="UINT">
* Return value specifying how message was handled:
* <table item="Value" desc="Action">
* 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.
* </table>
* </return>
*
* <see type="function"> RegisterGadgetMessage</>
* <see type="function"> RegisterGadgetMessageString</>
* <see type="function"> UnregisterGadgetMessage</>
* <see type="function"> UnregisterGadgetMessageString</>
* <see type="function"> AddGadgetMessageHandler</>
* <see type="function"> RemoveGadgetMessageHandler</>
* <see type="struct"> GMSG</>
* <see type="article"> 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<DuEventGadget *>(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<MsgObject *>(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<DuEventGadget *>(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.
*
* <param name="pmsg">
* Several members of the GMSG must be previously filled to correctly send
* the message to the specified Gadget.
* <table item="Field" desc="Description">
* 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.
* </table>
* </param>
*
* <param nane="nFlags">
* Specifies optional flags to modify how the message is sent to the Gadget.
* <table item="Value" desc="Action">
* 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.
* </table>
* </param>
*
* <return type="BOOL">
* Message was successfully posted to the destination Gadget's queue.
* </return>
*
* <see type="function"> SendGadgetEvent</>
* <see type="function"> RegisterGadgetMessage</>
* <see type="function"> RegisterGadgetMessageString</>
* <see type="function"> UnregisterGadgetMessage</>
* <see type="function"> UnregisterGadgetMessageString</>
* <see type="function"> AddGadgetMessageHandler</>
* <see type="function"> RemoveGadgetMessageHandler</>
* <see type="struct"> GMSG</>
* <see type="article"> 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.
*
* <remarks>
* 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.
* </remarks>
*
* <return type="MSGID"> ID of new message or 0 if failed.</>
* <see type="function"> SendGadgetEvent</>
* <see type="function"> RegisterGadgetMessageString</>
* <see type="function"> UnregisterGadgetMessage</>
* <see type="function"> UnregisterGadgetMessageString</>
* <see type="function"> AddGadgetMessageHandler</>
* <see type="function"> RemoveGadgetMessageHandler</>
* <see type="struct"> GMSG</>
* <see type="article"> 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.
*
* <remarks>
* See RegisterGadgetMessage() for more information about MSGID's.
* </remarks>
*
* <return type="MSGID"> ID of new message or 0 if failed.</>
* <see type="function"> SendGadgetEvent</>
* <see type="function"> RegisterGadgetMessage</>
* <see type="function"> UnregisterGadgetMessage</>
* <see type="function"> UnregisterGadgetMessageString</>
* <see type="function"> AddGadgetMessageHandler</>
* <see type="function"> RemoveGadgetMessageHandler</>
* <see type="struct"> GMSG</>
* <see type="article"> 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.
*
* <return type="BOOL"> Message was successfully unregistered.</>
* <see type="function"> SendGadgetEvent</>
* <see type="function"> RegisterGadgetMessage</>
* <see type="function"> RegisterGadgetMessageString</>
* <see type="function"> UnregisterGadgetMessageString</>
* <see type="function"> AddGadgetMessageHandler</>
* <see type="function"> RemoveGadgetMessageHandler</>
* <see type="struct"> GMSG</>
* <see type="article"> 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.
*
* <return type="BOOL"> Message was successfully unregistered.</>
* <see type="function"> SendGadgetEvent</>
* <see type="function"> RegisterGadgetMessage</>
* <see type="function"> RegisterGadgetMessageString</>
* <see type="function"> UnregisterGadgetMessage</>
* <see type="function"> AddGadgetMessageHandler</>
* <see type="function"> RemoveGadgetMessageHandler</>
* <see type="struct"> GMSG</>
* <see type="article"> 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.
*
* <remarks>
* 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.
* </remarks>
*
* <return type="BOOL"> Handler was successfully added.</>
* <see type="function"> SendGadgetEvent</>
* <see type="function"> RegisterGadgetMessage</>
* <see type="function"> RegisterGadgetMessageString</>
* <see type="function"> UnregisterGadgetMessage</>
* <see type="function"> UnregisterGadgetMessageString</>
* <see type="function"> RemoveGadgetMessageHandler</>
* <see type="struct"> GMSG</>
* <see type="article"> 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.
*
* <return type="BOOL"> Handler was successfully removed.</>
* <see type="function"> SendGadgetEvent</>
* <see type="function"> RegisterGadgetMessage</>
* <see type="function"> RegisterGadgetMessageString</>
* <see type="function"> UnregisterGadgetMessage</>
* <see type="function"> UnregisterGadgetMessageString</>
* <see type="function"> AddGadgetMessageHandler</>
* <see type="struct"> GMSG</>
* <see type="article"> 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.
*
* <remarks>
* For a list of Gadget styles, see SetGadgetStyle().
* </remarks>
*
* <return type="UINT"> Current style of Gadget.</>
* <see type="function"> SetGadgetStyle</>
* <see type="article"> 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.
*
* <param name="nNewStyle">
* nNewStyle can be a combination of the following flags:
* <table item="Value" desc="Meaning">
* 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)
* </table>
* </param>
*
* <return type="BOOL"> All style changes were successful.</>
* <see type="function"> GetGadgetStyle</>
* <see type="article"> 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.
*
* <return type="BOOL"> Successfully returned size in logical pixels.</>
* <see type="function"> GetGadgetRect</>
* <see type="function"> SetGadgetRect</>
* <see type="article"> 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.
*
* <param name=nFlags>
* nFlags can be a combination of the following flags:
* <table item="Value" desc="Meaning">
* 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.
* </table>
* </param>
*
* <return type="BOOL"> Rectangle was successfully retreived.</>
* <see type="function"> SetGadgetRect</>
* <see type="function"> GetGadgetRotation</>
* <see type="function"> SetGadgetRotation</>
* <see type="function"> GetGadgetScale</>
* <see type="function"> 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.
*
* <param name=nFlags>
* nFlags can be a combination of the following flags:
* <table item="Value" desc="Meaning">
* 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.
* </table>
* </param>
*
* <return type="BOOL"> Rectangle was successfully retreived.</>
* <see type="function"> SetGadgetRect</>
* <see type="function"> GetGadgetRotation</>
* <see type="function"> SetGadgetRotation</>
* <see type="function"> GetGadgetScale</>
* <see type="function"> 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.
*
* <return type="HGADGET"> 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.
*
* <return type="HGADGET"> 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.
*
* <param name=nFlags>
* nFlags can be a combination of the following flags:
* <table item="Value" desc="Meaning">
* 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.
* </table>
* </param>
*
* <return type="BOOL"> Gadget z-order was successfully changed.</>
* <see type="function"> 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.
*
* <param name=nFlags>
* nFlags can be a combination of the following flags:
* <table item="Value" desc="Meaning">
* 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.
* </table>
* </param>
*
* <return type="BOOL"> Gadget parent and z-order were successfully changed.</>
* <see type="function"> SetGadgetOrder</>
* <see type="function"> 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.
*
* <param name=nFlags>
* nFlags can be a combination of the following flags:
* <table item="Value" desc="Meaning">
* 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.
* </table>
* </param>
*
* <return type="BOOL"> Related Gadget or NULL for none.</>
* <see type="function"> SetGadgetOrder</>
* <see type="function"> 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.
*
* <return type="BOOL"> Gadget was successfully invalidated.</>
* <see type="message"> 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
*
* <package name="Msg"/>
*
*****************************************************************************
\***************************************************************************/
/***************************************************************************\
*
* 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
*
* <package name="Lava"/>
*
*****************************************************************************
\***************************************************************************/
//---------------------------------------------------------------------------
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
*
* <package name="Motion"/>
*
*****************************************************************************
\***************************************************************************/
//---------------------------------------------------------------------------
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
*
* <package name="Util"/>
*
*****************************************************************************
\***************************************************************************/
//---------------------------------------------------------------------------
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.
*
* <param name="hgad">
* A handle to the gadget to retrieve the ticket for.
* </param>
*
* <return type="DWORD">
* 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.
* </return>
*
* <remarks>
* 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.
* </remarks>
*
* <see type="function">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.
*
* <param name="dwTicket">
* A ticket that has been associated with a gadget via the
* GetGadgetTicket function.
* </param>
*
* <return type="HGADGET">
* 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.
* </return>
*
* <see type="function">GetGadgetTicket</>
*
\***************************************************************************/
DUSER_API HGADGET WINAPI
LookupGadgetTicket(
IN DWORD dwTicket) // Ticket
{
BEGIN_RECV(HGADGET, NULL, ContextLock::edNone);
retval = DuVisual::LookupTicket(dwTicket);
END_RECV();
}