Novell is now a part of Micro Focus

GroupWise XTD Tokenization

Articles and Tips: article

JASON HUNTINGTON
GroupWare Technical Writer
GroupWare Division

CAROL OERTLI
GroupWare Technical Editor
GroupWare Division

TIM STURDIVANT
GroupWare Technical Writer
GroupWare Division

RANDY WAKI
Software Engineer
GroupWise Client Development

01 May 1996


GroupWise XTD developer tools include the Object API (GWOAPI) for obtaining data from the GroupWise information store and C3POs for adding objects to the GroupWise object set. But what about commanding the client? Tokenization names low-level events. GroupWise uses tokens to operate as a program. You can use Visual Basic executables, DLLs using the 3rd-Party Handler, and DDE to command the GroupWise XTD 32-bit client. This article discusses using DDE to command the GroupWise XTD 32-Bit Client and using the 3rd-Party Handler.

Dynamic Data Exchange (DDE) lets Windows applications communicate. Applications can establish a DDE conversation and send messages to each other. A DDE conversation involves server and client applications. The server provides resources to the client. The client accepts processing or information from the server. The 3rd-Party Handler (formerly WOAPI) lets your DLLs monitor the GroupWise token stream. DLLs can process tokens before GroupWise, affect how GroupWise processes them, or process them instead of GroupWise.

Introduction

GroupWise XTD developer tools include the Object API (GWOAPI) for obtaining data from the GroupWise information store and C3POs for adding objects to the GroupWise object set. But what about commanding the client? Tokenization names low-level events. GroupWise uses tokens to operate as a program. You can use Visual Basic executables, DLLs using the 3rd-Party Handler, and DDE to command the GroupWise XTD 32-bit client.

GroupWise 32-bit client menus at XTD release no longer include Macro, Play and Macro, Record. However, the client will let users play executables from the Toolbar, menus, and customized views. The Tokenization story includes DDE and the 3rd-Party Handler (formerly WOAPI). The Novell SDK CD Release 8 will include C++, DLL, DDE, and VB code samples and information about obsolete, added, and modified GroupWise XTD tokens.

This article discusses using DDE to command the GroupWise XTD 32-Bit Client and using the 3rd-Party Handler.

Using DDE To Command the GroupWise XTD 32-Bit Client

Dynamic Data Exchange (DDE) lets Windows applications communicate. Applications can establish a DDE conversation and send messages to each other. A DDE conversation involves server and client applications. The server provides resources to the client. The client accepts processing or information from the server.

DDE Management Library. Use DdeInitialize( ) to register an application with DDEML. The DDE Management Library (DDEML) simplifies DDE management by providing a high-level interface.

DDE Conversations. Use DdeConnect( ) to establish a conversation. A service parameter specifies an application to establish a conversation with. A topic parameter specifies the conversation topic.

Sending DDE Messages. Use DdeClientTransaction( ) to send service and information requests between conversing applications.

Terminating a DDE Conversation. Use DdeDisconnect( ) to end a conversation, then DdeUninitialize( ) to clear application registration.

DDE, GroupWise, and Your Solution

Your solution can:

  • Share GroupWise resources using DDE Execute.

  • Obtain GroupWise processing results using DDE Request.

A DDEML-registered application can establish a conversation with GroupWise using DdeConnect( ) including a service and topic name pair from the table below. The first pair is generally recommended:


Service Name
Topic Name
Comments

GroupWise

Command

Recommended.A conversation using this pair can send anysupported command to GroupWise.

OFWin

Command

Operateslike GroupWise/Command but makes GroupWisecompatible with applications that launcha server based on the service name--in thiscase--OFWIN.EXE.

WPOffice40

Command

Includedfor backward compatibility with Office 4.x.Avoid using this pair because support mayend in future releases.

WPOffice40

GetOfficeData

Includedfor backward compatibility with Office 4.x.Support may end in future releases.

WPOffice40

GetAddressBookData

Includedfor backward compatibility with Office 4.x.Support may end in future releases.

For example:

const char lpszService[ ] =  OFWIN ; 
const char lpszTopic[ ]   =  COMMAND ; 
HDDEDATA FAR PASCAL __export

DdeCallback( UINT, UINT, HCONV, HSZ, HSZ, HDDEDATA, DWORD, DWORD );

DWORD dwDDEInst;

HSZ hszService;

HSZ hszTopic;

HCONV hConv;

/** Register with DDEML **/

DdeInitialize(&dwDDEInst,(PFNCALLBACK)DdeCallback, APPCLASS_STANDARD | APPCMD_CLIENTONLY, 0L);&
/** Create our String Handles **/

hszService = DdeCreateStringHandle(dwDDEInst, lpszService, 0);

hszTopic = DdeCreateStringHandle(dwDDEInst, lpszTopic, 0);

/** Attempt to establish connection **/

hConv = DdeConnect(dwDDEInst, hszService, hszTopic, NULL);

/** Free the string handles **/

DdeFreeStringHandle(dwDDEInst, hszService);

DdeFreeStringHandle(dwDDEInst, hszTopic);

Your solution can send GroupWise a product command (see the GroupWise Macros Manual) in a DDE Execute parameter. When GroupWise cannot process a command, it stores user-accessible error information (see DDE Error Messages below).

DDE Execute strings are null-terminated ANSI strings. Each string consists of supported macro commands. You can space-delimit multiple commands in a string.

For example:

"ViewOpenDlg( )""
"ViewOpen( Appointment!; Yes! )""
"ViewOpen( Appointment!; Yes!) FocusSet( Message! ) EditPaste( )""
"ViewOpen(Appointment!;Yes!) FocusSet(Message!)EditPaste()""
" ViewOpen(Appointment!;Yes!) FocusSet(Message!) EditPaste( ) ""

DDE ignores the remainder of a transaction containing an invalid command or syntax. See the GroupWise Macros Reference online manual for command syntax. Send GroupWise a command string as the DDE data block in a DDE Execute transaction. This is the Windows DDEClientTransaction( ), lpvData parameter.

For example:

/** lpszCmd is a pointer to an ANSI string **/

/** containing the command(s) we wish to **/

/** send to GroupWise **/

DdeClientTransaction(

  (LPBYTE)lpszCmd,

  (DWORD)_fstrlen(lpszCmd)+1,

  hConv,

  NULL,

  CF_TEXT,

  XTYP_EXECUTE,

  (DWORD)TIMEOUT_ASYNC,

  NULL );

Using DDE To Obtain GroupWise Error Information

Your solution can use DDE to request GroupWise error data. DDEGetLastError( ) returns information about the cause of the last error when DDEClientTransaction( ) returns FALSE. A DMLERR_NOTPROCESSED return value indicates GroupWise has received a command but cannot process it. Send an EnvLastError( ) DDE Request to GroupWise (see below) to return an error information string. Successful GroupWise commands empty the error value, and EnvLastError( ) returns an empty string.


Value
Description

10E1

BadParameterx, where x is the index of the bad parameter.

10E2

Failed.

10E3

Commandis invalid given current state of GroupWise.

10E4

Not found.

10E5

Syntax error.

10E7

BC(Blind Copy) doesn't apply to personal items.

10E8

Notsupported for encapsulated item attachments.

10E9

Notsupported for OLE attachments.

10EA

Themessage ID references an Out Box message that does not exist yet.

10EB

Youcannot set an alarm for a time that has already expired.

10EC

Thesource attributes of the In Box filter cannot be changed.

10ED

Thesource attributes of the Out Box filter cannot be changed.

xxxx

OtherGroupWise error.

For example:

HSZ hCmd;

/** Create a valid string handle for our command string**/

hCmd = DdeCreateStringHandle (dwDDEInst, "EnvLastError()", CP_WINANSI);"
/** Request the information **/

if ( 0 != (hReqData = DdeClientTransaction( NULL, (DWORD)0L, hConv, hCmd, CF_TEXT, 

    XTYP_REQUEST, (DWORD)2000, NULL )))

{

/** Free our string handle **/

DdeFreeStringHandle (dwDDEInst, hCmd);

  /** Get a valid pointer to the data that we can access **/

  lpDataByte = DdeAccessData (hReqData, &cbDataLen);&
  /** Copy the data into the return buffer */

  lstrcpy (lpszBuf, (LPSTR)lpDataByte);

  /** THE ERROR MESSAGE IS NOW STORED IN lpszBuf **/

  /** Free up the pointer we locked down **/

  DdeUnaccessData (hReqData);

  return TRUE;

}

Requesting GroupWise Information

To obtain GroupWise return value information, use EnvLastCmdResult( ) macro command, DDE Request, and DDE Advise loop. GroupWise returns information in ANSI strings. You can convert returned ANSI character string data to its native data type. For example, GroupWise returns a numeric value 96 as the ANSI string "96".


NativeData Type
ANSICharacter String Returned by GroupWise

Numeric

Numeric characters

Boolean

"TRUE","FALSE"

ANSI string

ANSI string

You can request GroupWise DDE Execute return information using DDE Request including EnvLastCmdResult( ).

For example:

HSZ hCmd;

/** Create a valid string handle for our command string **/

hCmd = DdeCreateStringHandle(dwDDEInst, "EnvLastCmdResult()", CP_WINANSI);"
/** Request the information **/

if ( 0 != (hReqData = DdeClientTransaction( NULL, (DWORD)0L, hConv, hCmd, CF_TEXT, 

XTYP_REQUEST, (DWORD)2000, NULL)))

{

  /** Free our string handle **/

  DdeFreeStringHandle (dwDDEInst, hCmd);

  /** Get a valid pointer to the data that we can access **/

  lpDataByte = DdeAccessData(hReqData, &cbDataLen);&
  /** Copy the data into the return buffer */

  lstrcpy (lpszBuf, (LPSTR)lpDataByte);

  /** THE COMMAND RESULT DATA IS NOW STORED IN lpszBuf **/

  /** Free up the pointer we locked down **/

  DdeUnaccessData (hReqData);

  return TRUE;

}

DDE Request. DDE Request substitutes DDE Execute command strings for DDE Item names and obtains return values. DDE Request returns a DDE data handle, then lets your solution have it. Windows imposes a 255-character limit on DDE Request command string length, including the terminating NULL character.

For example:

HSZ hCmd;

/** Create a valid string handle for our command string **/

hCmd = DdeCreateStringHandle(dwDDEInst, "AddressBookGetField( ABField: USERSNETID! )", CP_WINANSI);"
/** Request the information **/

if ( 0 != (hReqData = DdeClientTransaction( NULL, (DWORD)0L, hConv, hCmd, CF_TEXT, 

    XTYP_REQUEST, (DWORD)2000,NULL)))

{

  /** Free our string handle **/

  DdeFreeStringHandle (dwDDEInst, hCmd);

  /** Get a valid pointer to the data that we can access **/

  lpDataByte = DdeAccessData (hReqData, &cbDataLen);&
  /** Copy the data into the return buffer */

  lstrcpy (lpszBuf, (LPSTR)lpDataByte);

  /** THE COMMAND RESULT DATA IS NOW STORED IN lpszBuf **/

  /** Free up the pointer we locked down **/

  DdeUnaccessData (hReqData);

  return TRUE;

}

DDE Advise Loop. You can establish a DDE Advise loop instead of using EnvLastCmdResult( ). A DDE Advise loop returns DDE Execute values to DDE Advise Data, then GroupWise, then notifies your solution. DDE notifies your solution only of DDE Advise Data values for commands that return values and commands sent to GroupWise not using DDE Request. In an established DDE conversation, create a DDE Advise loop by sending DDE Advise Start to GroupWise with the item name string, "CommandReturn". Track the DDEClientTransaction identifier to match DDE Advise notifications and DDE Execute transactions.

For example:

HSZ hItem;

HCONV hConv;     // These two variables are

DWORD dwDDEInst; // assigned valid values

                // during DDE initialization

/** Create a valid string handle for our command string **/

hItem = DdeCreateStringHandle (dwDDEInst, "CommandReturn", CP_WINANSI);"
/** Start the Advise Loop **/

DdeClientTransaction( (LPBYTE)NULL, 0, hConv, hItem, CF_TEXT, XTYP_ADVSTART, (DWORD)TIMEOUT_ASYNC,

  &dwTransResult );&

Simultaneous Commands. DDE does not let your solution send DDE Execute during another same-conversation command. Make sure your solution does not send simultaneous multiple DDE Execute or DDE Request commands. Otherwise, a DDE Reentrancy error results and your commands may not execute.

Using the 3rd-Party Handler

The 3rd-Party Handler lets your DLLs monitor the GroupWise token stream. The interaction between GroupWise and third-party DLLs is as follows: GroupWise loads third-party DLLs at startup; GroupWise passes tokens to third-party DLLs (calling Entry once initially and then using HandleToken to direct tokens); DLLs return values indicating they did not process tokens or changing how GroupWise processes a token. (Otherwise, GroupWise does not process the token.)

Novell has removed Shared Code from GroupWise XTD. Third-party DLLs must provide their own installation and Windows Registry entries:


Key:

"HKEY_CURRENT_USER\Software\Novell\GroupWise\5.0\ThirdParty"

Item:

"DLLx"(x is a number)

ItemType:

ANSISTRING

ItemValue:

<DLLpath and filename<

DLL Loading

As GroupWise opens, it finds third-party DLLs in the Registry, then loads them in Item number order. For example, finding DLL1, DLL2, DLL4, then DLL0, GroupWise loads DLL1, then DLL2. GroupWise loads only consecutively numbered entries, starting with the first found. In the example above, GroupWise does not load DLL4 and DLL0.

Intercepting Tokens

A loaded DLL can monitor and intercept GroupWise tokens and:

  • Let a token pass to GroupWise. DLLs can pass a token unprocessed or use a token value as a trigger to process a token, then pass it on, indicating it was unprocessed. DLLs can also generate, then pass new tokens.

  • Block a token. A DLL can return a token, indicating it was processed. Processed tokens are not passed to other DLLs or GroupWise. The DLL that processes a token must provide required return values.

  • Modify the token. DLLs can monitor the token stream, intercept a token, modify it, pass it to GroupWise as a new token, then indicate that the original token was processed or modify the token, then return a value indicating it was unprocessed.

Third-Party Handler DLL Entry Points

This section describes required DLL entry points. You can call them using their ordinal values. Please note the required ordinal value of each function.

TPHVersion

Lets the DLL register its major/minor version numbers with GroupWise and pass the DLL instance handle to GroupWise. The ordinal value for TPHVersion( ) must be 1 (one).


Prototype

DWORD WINAPI TPHVersion ( VOID );

Parameters

None.

Return Values

LOWORD-LOBYTE DLL major version.LOWORD-HIBYTE DLL minor version.HIWORDDLL instance handle.

Example

DWORD WINAPI TPHVersion ( VOID ){ return MAKELONG (1, hInstance);

Compatibility

Required for DLLs. Compatibility( ) lets a DLL specify the GroupWise version to load it with and ensures compatibility between GroupWise and third-party DLLs. Your DLL can verify GroupWise versions, then return GroupWise a value indicating whether to load your DLL. A Novell application name and GroupWise version are passed as parameters to Compatibility( ). You must export Compatibility( ) at ordinal value 2 (two).

The GroupWise AppName is GROUPWISE. The AppVersion is a word value with the low-order byte containing the GroupWise major version, and the high-order byte containing the minor version.


Prototype

DWORD WINAPI Compatibility (ATOM AppName, WORD AppVersion );

Parameters

AppName

Atom of the calling application. See a Windows programming manual for Atoms information.AppVersion

GroupWise version being loaded for the calling application.

Return Values

Make sure the Compatibility( ) return value is TRUE or FALSE cast as a DWORD value. An incompatible DLL returns FALSE.

Example

DWORD WINAPI Compatibility ( ATOM AppName, WORD AppVersion){ UINT uBytes; char szAppName [BUF_SIZE]; uBytes = GetAtomName (AppName, szAppName, BUF_SIZE-1);//Get the Atom name if (uBytes -- (!lstrcmpi(szAppName, -GROUPWISE-)) --//GroupWise Atom (LOWORD (AppVersion)) == GW_MAJOR_VERSION)//GroupWise 5.x return (DWORD) TRUE; //return non-zero else //else return (DWORD) FALSE; //return FALSE}

TimeStamp

GroupWise uses TimeStamp( ) to request DLL release dates. Make sure your DLL returns its file time stamp (date and time) to GroupWise. You may return a value of zero. Although GroupWise does not use the date and time values returned, it nonetheless calls TimeStamp( ). Export TimeStamp( ) as ordinal value 3 (three).


Prototype

DWORD WINAPI TimeStamp ( VOID );

Parameters

None.

Return Values

The return value uses:


Value
Meaning
Bits
Code

LOWORD

Date

0-4

Day:1=Sun., 2=Mon, and so forth.

5-8

Month:1=January, 2=February, and so forth.

9-15

Year: 1980=0.

HIWORD

Time

0-4

Seconds:0-29 in 2 second increments.

5-10

Minutes: 0-59.

11-15

Hours: 0-23.


Example

DWORD WINAPI TimeStamp ( VOID ){ return 0;}

Entry

Called to allow the DLL to perform any required initialization; called prior to any tokens passed to DLLs. DLLs are provided with the resource language code to indicate the language being used in the calling application. Must be exported at ordinal value 4 (four).


Prototype

WORD WINAPI Entry ( WORD wLanguage );

Parameters

LanguageThe default language for the calling application.For the US version of GroupWise, the valueof the wLanguage parameter would be:

LOBYTE 'U'HIBYTE 'S'

ReturnValues

Avalue greater than zero should be returnedto indicate success. A return value lessthan or equal to zero indicates an erroroccurred.

Example

WORD WINAPI Entry ( WORD wLanguage ){ hRequestor = GlobalAddAtom ("GroupWise DLL");//Set up requestor return 1;}

Exit

Allows the DLL to execute any code for cleanup purposes (closing files or destroying dialogs) before the DLL is unloaded. This function must be exported as ordinal value 5 (five).


Prototype

WORD WINAPI Exit( VOID );

Parameters

None.

Return Values

The return value is ignored.

Example

WORD WINAPI Exit ( VOID ){ GlobalDeleteAtom (hRequestor); //Free the requestor return 1;}

HandleToken

GroupWise passes token values and parameters to HandleToken( ). GroupWise calls HandleToken( ) to pass tokens to DLLs. A DLL can then forward, modify, or block the token. A DLL can also use token values to trigger events. See Token Handling below for detailed information on handling, building and sending tokens. HandleToken( ) is called using ordinal value 6 (six).


Prototype

int WINAPI HandleToken (LPTH_RETURNVAL lpDataHWND hLinkWnd,WORD msg );

Parameters

lpDataA LPTPH_RETURNVAL structure contains two members.The first is a pointer to an LPMAC_TOKENstructure, which contains the token ID andparameter data. The second member is a pointerto an LPLPMAC_RETURNVAL structure, whichis used for return values from value-returningtokens.

hLinkWndHandle to the link window.

msgLink window execute message.

Return Values

LL_HAN_NOT_HANDLEDThe token was not processed.

DLL_HAN_NO_ERRORThe token was processed. This value should bereturned to block a token.

DLL_HAN_NOT_FOUNDThe token resulted in a GroupWise "not found"condition.

DLL_HAN_CANCELThe user cancelled the function.

DLL_HAN_TOKEN_ERRORThe token was not valid.

DLL_HAN_PARM_ERROROne or more of the parameters were invalid.

Example

int WINAPI HandleToken (LPMAC_TOKEN lpTokenData, HWND hLinkWnd, WORD msg ){return DLL_HAN_NOT_HANDLED; //Return all tokens to GroupWise unchanged}

ValidateToken

Allows a DLL to control the display of an entry on a GroupWise menu or Toolbar. Must be exported at ordinal value 7 (seven).


Prototype

DWORD WINAPI ValidateToken ( LPMAC_TOKEN lpTokenData, LPVOID lpDataTypeInfo );

Parameters

lpTokenDataLong pointer to a MAC_TOKEN structure.

lpDataTypeInfoPointer to a TPValInfo structure cast to LPVOID.

Return Values

Thereturn value should be a DWORD value containingthe appropriate table entries as the low-orderand high-order words:


Low-Order Word (LOWORD)
Description

DLL_VAL_UNKNOWN_TOKEN

This token is not recognized by the DLL.

DLL_VAL_VALIDATED

Thistoken was validated by the DLL.

DLL_VAL_UNVALIDATED

Thistoken was unvalidated by the DLL.


High-OrderWord (HIWORD)
Description

MT_MENU_ITEM_CHECKED

Changemenu item state to be checked.

MT_MENU_ITEM_UNCHECKED

Changemenu item state to be unchecked.

MT_MENU_ITEM_ENABLED

Enable menu item.

MT_MENU_ITEM_GRAYED

Gray menu item.

MT_MENU_ITEM_TRISTATE

Indicatesthe item may be in an indeterminate state.


Example

DWORD WINAPI ValidateToken ( LPMAC_TOKEN lpTokenData, LPVOID lpDataTypeInfo ){ if (lpTokenData->wTokenID == MyTheta) return MAKELONG (DLL_VAL_UNKNOWN_TOKEN, MT_MENU_ITEM_GRAYED); else return DLL_VAL_UNKNOWN_TOKEN;}

Structures, Types, and Enumerations

This section discusses MAC_PARAM, MAC_RETURNVAL, MAC_TOKEN, MAC_TOKENERROR, MAC_TOKENID, MAC_VALUE_TYPE, MAC_VARIABLE, TPH_RETURNVAL,and TPVALINFO.

MAC_PARAM

A structure used to store token parameter information.


Definition

typedef struct _tagMAC_PARAM{ MAC_VALUE_TYPE eType; WORD wReserved; WORD wFlags; union { DWORD dwValue; void far *lpvPtr; double drValue; } uData;} MAC_PARAM, NEAR *NPMAC_PARAM, FAR *LPMAC_PARAM, *PMAC_PARAM;

Types

MAC_PARAMStructure containing token parameter information.

NPMAC_PARAMNear pointer to a MAC_PARAM structure.

LPMAC_PARAMFar pointer to a MAC_PARAM structure.

PMAC_PARAMPointer to a MAC_PARAM structure.

Members

eTypeParameter type enumeration. (See MAC_VALUE_TYPE definition).

wFlagsWhen using token parameter, set wFlags to 00000;when token parameter is optional and unused,set wFlags to 08000.

StDataUnion containing parameter data.


Member
Description

dwValue

Integer data.

lpvPtr

String data.

drValue

Floating point data.

MAC_RETURNVAL

Structure is used to hold the return value information for value-returning tokens.


Definition

typedef struct _tag MAC_RETURNVAL { HSZ hszRequestor; DWORD dwMacroID; MAC_TOKENERROR eReturnCode; MAC_VARIABLE rv; } MAC_RETURNVAL, NEAR *NPMAC_RETURNVAL, FAR *LPMAC_RETURNVAL;typedef LPMAC_RETURNVAL FAR *LPLPMAC_RETURNVAL;

Types

MAC_RETURNVALStructure holding the token return value information.

PMAC_RETURNVALNear pointer to a MAC_RETURNVAL structure.

LPMAC_RETURNVALFar pointer to a MAC_RETURNVAL structure.

LPLPMAC_RETURNVALFar pointer to a LPMAC_RETURNVAL.

Members

hszRequestorUnique application identifier that sent the token.

dwMacroIDToken application identifier. Should always be0L.

eReturnCodeToken error return code. (See MAC_TOKENERRORdefinition).

rvToken return value. (See MAC_VARIABLEdefinition.)

MAC_TOKEN

Structure used to represent GroupWise tokens; contains data identifying token as well as token parameter data. When allocating memory for a MAC_TOKEN structure, memory for the first parameter is provided. If the token has more than one parameter, additional contiguous memory must be allocated for MAC.PARAM.


Definition

typedef struct _tag MAC_TOKEN{HSZ hszCommand;MAC_IPCVERSION version;HSZ hszRequestor;DWORD dwMacroId;ATOM atomApp;WORD wReserved;MAC_TOKENID wTokenId;MAC_COUNT cParam;DWORD dwFlags;DWORD dwReserved;MAC_PARAM rsParam[1];} MAC_TOKEN, NEAR *NPMAC_TOKEN, FAR *LPMAC_TOKEN;

Types

MAC_TOKENStructure used to represent actual tokens.

NPMAC_TOKENNear pointer to a MAC_TOKEN structure.

LPMAC_TOKENFar pointer to a MAC_TOKEN structure.

Members

szCommandIndicates where the token originated.

versionIndicates the IPC version and must be set to 0 (==0).

hszRequestorUnique application identifier.

dwMacroIdApplication ID for this macro token. Should always be 0L.

atomAppWhere the token is bound.

wTokenIdToken ID.

cParamNumber of token parameters.

dwFlagsWriteable or non-writeable.

dwReservedReserved.

rsParamParameter data block pointer. rsParam[0] contains data for the first parameter. Allocate memory next to the first parameter for added parameters. See MAC_PARAMdefinition.

MAC_TOKENERROR

Defines various error conditions resulting from token processing.


Definition

typedef enum{ MAC_FUNCTION_OK = MAC_NO_ERROR, MAC_FUNCTION_UNKNOWN = MAC_BASE_GENERAL_ERRORS, MAC_FUNCTION_NOTFOUND, MAC_FUNCTION_CANCEL, MAC_FUNCTION_ERROR, MAC_FUNCTION_INVALID_PARM, MAC_FUNCTION_INVALID, MAC_FUNCTION_NOT_HANDLED, MAC_FUNCTION_RETURN_LATER} MAC_TOKENERROR;

Types

MAC_TOKENERROR

Enumerated token processing error type.

Members

MAC_FUNCTION_OKFunction returned with no error condition.

MAC_NO_ERRORFunction returned with no error condition.

MAC_FUNCTION_UNKNOWNFunction is unknown.

MAC_BASE_GENERAL_ERRORSFunction is unknown.

MAC_FUNCTION_NOTFOUNDFunction resulted in a Not Found condition.

MAC_FUNCTION_CANCELFunction resulted in a Cancel condition.

MAC_FUNCTION_ERRORFunction resulted in an Error condition.

MAC_FUNCTION_INVALID_PARMFunction contained an invalid parameter.

MAC_FUNCTION_INVALIDFunction is invalid at this time.

MAC_FUNCTION_NOT_HANDLEDFunction was not handled.

MAC_FUNCTION_RETURN_LATERDelays from token handling function returns.

MAC_TOKENID

A defined type used to pass token values.


Definition

#define MAC_TOKENID WORD

MAC_VALUE_TYPE

Defines various parameter types supported by tokens.


Definition

typedef enum{ eValUndefined = VALUE_GENERAL_TYPES, eParmAny = VALUE_PARAMETER_TYPES, eParmBoolean, eParmByteSigned, eParmByteUnsigned, eParmCentimeters, eParmDwordSigned, eParmDwordUnsigned, eParmDWPUSigned, eParmDWPUUnsigned, eParmEnumeration, eParmFloat, eParmInches, eParmMillimeters, eParmPoints, eParmStringAnsi, eParmStringLabel, eParmStringOem, eParmStringWord, eParmStringVariable, eParmTokenID, eParmWordSigned, eParmWordUnsigned, eParmWPFname, eParmWPUSigned, eParmWPUUnsigned, eParmUserDialog, eValArrayDefinition = VALUE_VARIABLE_TYPES, eValBoolean, eValCentimeters, eValFloat, eValInches, eValInteger, eValMillimeters, eValPoints, eValString, eValStringAnsi, eValStringOem, eValWPUnits, eValZzzzzNoMore = VALUE_END_OF_TYPES} MAC_VALUE_TYPE;

Types

MAC_VALUE_TYPEEnumeration defining the various token parameter types.

Members

eParmUndefinedUndefined parameter type; do not use in 3rd-party DLLs.

eParmAnyDecided at run_time; do not use in 3rd-party DLLs.

eParmBooleanC Boolean type.

eParmByteSignedSigned 8-bit value.

eParmByteUnsignedUnsigned 8-bit value.

eParmCentimetersDouble.

eParmDwordSignedSigned 32-bit value.

eParmDwordUnsignedUnsigned 32-bit value.

eParmDWPUSignedSigned 32-bit unit (WPU).

eParmDWPUUnsignedUnsigned 32-bit unit (WPU).

eParmEnumerationEnumeration 16-bit value.

eParmFloatDouble.

eParmInchesDouble.

eParmMillimetersDouble.

eParmPointsDouble.

eParmStringAnsiNull-terminated ANSI string.

eParmStringLabelNull-terminated WPC word string containing a label reference.

eParmStringOemNull-terminated OEM string.

eParmStringWordNull-terminated WPC word string.

eParmStringVariableWord string containing a variable name.

eParmTokenIDUnsigned 16-bit value.

eParmWordSignedSigned 16-bit value.

eParmWordUnsignedUnsigned 16-bit value.

eParmWPFnameNull-terminated ANSI string containing a filename.

eParmWPUSignedSigned 16-bit unit (WPU).

eParmWPUUnsignedUnsigned 16-bit unit (WPU).

eParmUserDialogUser dialog buffer (like a string).

eValArrayDefinitionArray definition variable type.

eValBooleanC Boolean variable type.

eValCentimetersDouble variable type.

eValFloatDouble variable type.

eValInchesDouble variable type.

eValIntegerSigned 32-bit variable type.

eValMillimetersDouble variable type.

eValPointsDouble variable type.

eValStringNull-terminated Word String variable type.

eValStringAnsiNull-terminated ANSI string variable type.

eValStringOemNull-terminated OEM string variable type.

eValWPUnitsSigned 32-bit variable type.

eValZzzzzNoMoreNot used. Only an indication of final value in enumeration.

MAC_VARIABLE

Contains return value data for value-returning tokens.


Definition

typedef struct _tag MAC_VARIABLE { HSZ hszCommand; HSZ hszRequestor; MAC_IPCVERSION version; MAC_MACROID dwMacroID; ATOM atomApp; WORD wReserved; MAC_TOKENID wSysVarID; WZ wzSymbolName[MAC_NAME_WZCOUNT + 1]; MAC_VALUE_TYPE eType; union { BOOL fData; VALUE_FLOAT drData; VALUE_INT lData; struct { WORD wStrLen; union { WZ wzData[1]; AZ azData[1]; } uStr; } stData; } uValue;} MAC_VARIABLE, FAR *LPMAC_VARIABLE;

Types

MAC_VARIABLEStructure containing the return value information for a token.

LPMAC_VARIABLEFar pointer to a MAC_VARIABLE structure.

MAC_IPCVERSION

versionIndicates the IPC version and must be set to 0 (==0).

Members

hszCommandHandle to the string representing the command type. Either VariableGet or VariableSet.

hszRequestorHandle to a string representing name of requesting application.

dwMacroIDApplication defined macro identifier.

atomAppApplication where the request is bound.

wSysVarIDSystem variable identifier.

wzSymoblNameWord string containing the symbol name.

eTypeReturn value type. Must be in the range between VALUE_VARIABLE_TYPES+1and VALUE_END_OF_TYPES. (See MAC_VALUE_TYPEdefinition).

uValueUnion containing the actual return value.

Token Handling

This section discusses intercepting, building, and sending tokens.

Intercepting Tokens

GroupWise uses HandleToken and a valid function pointer to pass tokens to 3rd-party DLLs. DLLs can monitor tokens that the handling function receives. The handling function, which can use tokens as action triggers, has a default return value of DLL_HAN_NO_ERROR. When DLLs intercept and process value-returning tokens and do not provide GroupWise data, a system error can result. When DLLs intercept tokens that return no value, they need return only the value that indicates having processed the token. DLLs must provide return value data and allocate memory to contain it. The calling app and not DLLs deallocate return value memory when token is returned.

GroupWise supports two messages which can be sent to the link window to handle allocating memory for return value information. Applications should use this method of allocating memory for return value information in order for the calling application to be able to free the memory once the return value has been received.


Message

WPLM_ALLOC_MEM

Purpose

Allocatetoken return value memory

Example

lpMem = SendMessage( hLinkWnd, WPLM_ALLOC_MEM, 0, (LPARAM)cbMemory );


Variable
Description

lpMem

Longpointer to the block of memory allocated.

hLinkWnd

Handleto the link window. This is the HWND passedin to the token handler function.

CbMemory

Numberof bytes to allocate.


Message

WPLM_FREE_MEM

Purpose

Freetoken return value memory

Example

lpMem = SendMessage( hLinkWnd, WPLM_FREE_MEM, 0,(LPARAM)(DWORD)lpMem );


Variables
Description

lpMem

Longpointer to the block of memory to be freed.

hLinkWnd

Handleto the link window. This is the HWND passedin to the token handler function.

EventNotify Token

A special-case token sent to third-party DLLs to indicate GroupWise internal events. Do not generate in your DLLs.


Definition

EventNotify( Event: { AppInitialized! BadCustomCommand! BadCustomMessage! ContextMenu! } REQUIRED Command: ANSISTRING REQUIRED)TokenID: AFTKN_EVENT_NOTIFYReturn Value: None

Events

AppInitialized!Indicates GroupWise is loaded and running. The command string is set to "GROUPWISE: App Initialized."

BadCustomCommand!Indicates failed custom command setup. The command string is set to "GROUPWISE: Custom command improperly defined."

BadCustomMessage!Indicates failed custom message setup. The command string is set to "GROUPWISE: Custom message improperly defined."

ContextMenu!Indicates context-sensitive QuickMenu display on right click. The command string contains an ANSI-string menu identifier representation and the menu handle-both space delimited. Intercept the EventNotify token and monitor the ContextMenu! case to add GroupWise QuickMenu items.


MENU_ID
QuickMenuContext

20

OLE Object.

21

ShelfIcon or Quick Start Icon.

22

AttachmentControl (composing message, attachment selected).

23

AttachmentControl (reading message).

24

SoundItem or Control.

25

ItemList Control (In Box, Out Box, Calendar Views).

26

Movie Control.

27

Reserved.

28

MainWindow Icons (In Box, Out Box, Calendar,Mail, Appointment, and so forth).

29

In Box View.

30

Out Box View.

31

Trash View.

32

Reserved.

33

Reserved.

34

Reserved.

35

ItemList (preempted by local menu ID 25, butcan be accessed in the control space to theleft of the Column Manager).

36

BasicView (might be overridden by more specific view menus).

37

BasicItem View (might be overridden by more specific view menus).

38

FolderList Control (In Box, Out Box, Trash, Calendar Views).

39

Button Bar.

40

CC:and BC: Controls (composing message).

41

MainWindow's Shelf (no Shelf Icon selected).

42

AttachmentControl (composing message, no attachment selected).

43

Trash'sItem List (preempted by local menu ID 31but can be accessed in the control spaceto the left of the column Manager).

44

Reserved.

45

Reserved.

46

StartDate/Auto-Date Control (composing message).

47

EndDate/Duration Control (composing message).

48

To:Control (composing message).

49

MainWindow's Trash Icon.

Building Tokens

Your DLLs can generate tokens, then send them to GroupWise for processing. To build a token, (1) Create token, parameter, and return value structures; (2) fill in token data; and (3) send token to link window. Although tokens can have multiple parameters, the token structure contains a declaration for one parameter structure because parameter memory must remain together. The following functions let you allocate and manage token structures.

AllocPtr. Used to allocate memory and called by InitToken().

LPVOID WINAPI AllocPtr ( int nSize, WORD wFlags )

{

  LPVOID lpvPtr;

  if ( (hMem = GlobalAlloc (wFlags, nSize)) != NULL )

  {

     if ( (lpvPtr = GlobalLock (hMem)) != NULL )

        return lpvPtr;

     else

     {

        GlobalFree (hMem);

        return NULL;

     }

  }

  else

     return NULL;

}

FreePtr. Used to free memory allocated by ALLocPtr( ).

void WINAPI FreePtr ( LPVOID lpvPtr )

{

  HGLOBAL hMem;

  if (( hMem = (HGLOBAL)LOWORD(GlobalHandle(SELECTOROF(lpvPtr)))) != NULL)

  {

     if (!(GlobalUnlock (hMem)))

        GlobalFree (hMem);

  }

}

InitTkn. Attempts to allocate a memory block to contain a token and its specified number of parameters.

void WINAPI InitTkn ( WORD nParmCount )

{

  //Allocate one less mac_param because 1 is already defined 

  //in the MAC_TOKEN structure

  if ((lpTknData = (LPMAC_TOKEN)AllocPtr (sizeof 

  (MAC_TOKEN) +(sizeof (MAC_PARAM) *(nParmCount-1) -
  + 100), GHND)) == NULL)

  {

     lpTknData = (LPMAC_TOKEN)NULL;

  }

}

AddTknParm. Used to add parameter values to a previously allocated MAC_PARAM structure. It should be called once for each parameter a token has. If a token parameter is optional, the token value should be set to 0x8000 to inform GroupWise to ignore the parameter, otherwise it should be 00000.

void WINAPI AddTknParm ( MAC_VALUE_TYPE eType, WORD cParmNum, WORD wFlags, LPVOID lpvParm,

  DWORD dwParm, double dbParm )

{

  lpTknData--DataBlock[cParmNum].eType = eType;-
  lpTknData--DataBlock[cParmNum].wFlags = wFlags;-
  if (dwParm != 0)

     lpTknData--DataBlock[cParmNum].uData.dwValue = dwParm;-
  else

     if (dbParm != 0)

        lpTknData--DataBlock[cParmNum].uData.drValue = dbParm;-
     else

       if (lpvParm != NULL)

          lpTknData--DataBlock[cParmNum].uData.lpvPtr = lpvParm;-
}

Sending Tokens

Once the token and parameter structures have been allocated and initialized, your DLL can send the token to GroupWise by sending a message to the link window.

SendTkn. Sends the token structure to the link window using SendMessage.

hLinkWindow is the link window handle passed to TokenHandle. WPLM_EXECUTE_VALRETURN_TOKEN is the msg parameter passed to TokenHandle.

lpTPHData is a long pointer to the TPH_RETURNVAL structure.

SendMessage returns a value indicating the token processing result defined below. If the message is successful and the token can return a value, TPH_RETURNVAL structure (lpTPHData) is filled in with data.

DWORD WINAPI SendTkn ( MAC_TOKENID wTknID, WORD nParmCnt, LPLPMAC_RETURNVAL lplpTknReturn )

{

  TPH_RETURNVAL TknData;

  LPTPH_RETURNVAL lpTPHData;

// Fill global token structure

//

  lpTknData--hszCommand   = NULL;-
  lpTknData--hszRequestor = (HSZ)hRequestor;-
  lpTknData--dwMacroID    = 0L;-
  lpTknData--wTokenID     = wTknID;-
  lpTknData--cParam       = nParmCnt;-
  lpTknData--dwFlags      = NULL;-
  lpTknData--dwReserved   = NULL;-
// Fill ReturnVal structure

//

  TknData.lpTokenData             = lpTknData;

  TknData.lplpmacRetVal           = lplpTknReturn;

  lpTPHData = &TknData;&
// Value-returning token //

  dwRV = SendMessage (WPLnkWnd, WPLM_EXECUTE_VALRETURN_TOKEN, 0, (LPARAM)lpTPHData);

  FreePtr (lpTknData);

  return dwRV;

} 

// End of SendTkn( ) function

//

ReturnValues
Description

DLL_HAN_NOT_HANDLED

The token was not processed.

DLL_HAN_NO_ERROR

The token was processed with no error.

DLL_HAN_NOT_FOUND

Thetoken resulted in a GroupWise "not found" condition.

DLL_HAN_CANCEL

Theuser cancelled the function.

DLL_HAN_TOKEN_ERROR

The token was not valid.

DLL_HAN_PARM_ERROR

Oneor more of the parameters were invalid.

Memory. GroupWise allots memory to contain a return value when a DLL sends it a value-returning token. The DLL must free memory allotted for the return value structure by sending WPLM_FREE_MEM to the link window as outlined in Intercepting Tokens above.

Building Tokens

Your DLLs can generate tokens, then send them to GroupWise for processing. To build a token, (1) Create token, parameter, and return value structures; (2) fill in token data; and (3) send token to link window. Although tokens can have multiple parameters, the token structure contains a declaration for one parameter structure because parameter memory must remain together. The following functions let you allocate and manage token structures.

AllocPtr

Used to allocate memory and called by InitToken( ).

  LPVOID WINAPI AllocPtr ( int nSize, WORD wFlags )  
{


LPVOID lpvPtr;





if ( (hMem = GlobalAlloc (wFlags, nSize)) != NULL )


{


      if ( (lpvPtr = GlobalLock (hMem)) != NULL )  
         return lpvPtr;  
      else  
      {  
         GlobalFree (hMem);  
         return NULL;  
      }  
   }  
   else  
      return NULL;  
   }  

FreePtr

Used to free memory allocated by ALLocPtr( ).

  void WINAPI FreePtr ( LPVOID lpvPtr )  
   {  
      HGLOBAL hMem;  



     if (( hMem = (HGLOBAL)LOWORD(GlobalHandle( SELECTOROF(lpvPtr)))) != NULL)       {  
         if (!(GlobalUnlock (hMem)))  
         GlobalFree (hMem);  
      }  
   }  

InitTkn

Attempts to allocate a memory block to contain a token and its specified number of parameters.

  void WINAPI InitTkn ( WORD nParmCount )  
   {  
   //Allocate one less mac_param because 1 is already defined //in the MAC_TOKEN structure  
   if ((lpTknData = (LPMAC_TOKEN)AllocPtr (sizeof  (MAC_TOKEN) +(sizeof (MAC_PARAM) *(nParmCount-1)  + 100), GHND)) == NULL)  
      {  
         lpTknData = (LPMAC_TOKEN)NULL;  
      }  
   }  

AddTknParm

Used to add parameter values to a previously allocated MAC_PARAM structure. It should be called once for each parameter a token has. If a token parameter is optional, the token value should be set to 0x8000 to inform GroupWise to ignore the parameter, otherwise it should be 00000.

  void WINAPI AddTknParm ( MAC_VALUE_TYPE eType,  WORD cParmNum, WORD wFlags, LPVOID lpvParm,  DWORD dwParm, double dbParm )  
{


   lpTknData- DataBlock[cParmNum].eType = eType;  
   lpTknData- DataBlock[cParmNum].wFlags = wFlags;  



   if (dwParm != 0)  
      lpTknData- DataBlock[cParmNum].uData.dwValue = dwParm;  
   else  
   if (dbParm != 0)  
         lpTknData- DataBlock[cParmNum].uData.drValue = dbParm;  
   else  
   if (lpvParm != NULL)  
         lpTknData- DataBlock[cParmNum].uData.lpvPtr = lpvParm;  
}

-->

Sending Tokens

Once the token and parameter structures have been allocated and initialized, your DLL can send the token to GroupWise by sending a message to the link window.

SendTkn

Sends the token structure to the link window using SendMessage.

hLinkWindow is the link window handle passed to TokenHandle. WPLM_EXECUTE_VALRETURN_TOKEN is the msg parameter passed to TokenHandle.

lpTPHData is a long pointer to the TPH_RETURNVAL structure.

SendMessage returns a value indicating the token processing result defined below. If the message is successful and the token can return a value, TPH_RETURNVAL structure (lpTPHData) is filled in with data.

  DWORD WINAPI SendTkn( MAC_TOKENID wTknID, WORD nParmCnt, LPLPMAC_RETURNVAL lplpTknReturn )    {  
      TPH_RETURNVAL   TknData;  
      LPTPH_RETURNVAL lpTPHData;  



      // Fill global token structure //  
      lpTknData- hszCommand   = NULL;  
      lpTknData- hszRequestor   = (HSZ)hRequestor;  
      lpTknData- dwMacroID   = 0L;  
      lpTknData- wTokenID      = wTknID;  
      lpTknData- cParam         = nParmCnt;  
      lpTknData- dwFlags         = NULL;  
      lpTknData- dwReserved      = NULL;  



      // Fill ReturnVal structure //  
      TknData.lpTokenData       = lpTknData;  
      TknData.lplpmacRetVal    = lplpTknReturn;  



      lpTPHData =  TknData;  



      // Value-returning token //  
     dwRV = SendMessage (WPLnkWnd,  WPLM_EXECUTE_VALRETURN_TOKEN, 0,          (LPARAM)lpTPHData);  



      FreePtr (lpTknData);  
      return dwRV;  
   } // End of SendTkn( ) function //  

Return Values

Description

DLL_HAN_NOT_HANDLED

The token was not processed.

DLL_HAN_NO_ERROR

The token was processed with no error.

DLL_HAN_NOT_FOUND

The token resulted in a GroupWise "not found" condition.

DLL_HAN_CANCEL

The user cancelled the function.

DLL_HAN_TOKEN_ERROR

The token was not valid.

DLL_HAN_PARM_ERROR

One or more of the parameters were invalid.

Memory

GroupWise allots memory to contain a return value when a DLL sends it a value-returning token. The DLL must free memory allotted for the return value structure by sending WPLM_FREE_MEM to the link window as outlined in Intercepting Tokens above.

* Originally published in Novell AppNotes


Disclaimer

The origin of this information may be internal or external to Novell. While Novell makes all reasonable efforts to verify this information, Novell does not make explicit or implied claims to its validity.

© Copyright Micro Focus or one of its affiliates