2.2 Sample Code

This section covers the following:

To create a valid TPH, we are required to have seven methods in our DLL even though some of them are not used by the GroupWise client. The reason the unused methods are required is because the methods that are used, are called from the GroupWise client by their exported order number. This is why they are required to be exported in a specific order. In C++, this is easily accomplished in the.DEF file. The following is a sample from a C++ .DEF file and also identifies the order in which the methods must be exported:

EXPORTS
     TPHVersion     @1
     Compatibility  @2
     TimeStamp      @3
     Entry          @4
     Exit           @5
     HandleToken    @6
     ValidateToken  @7

In Delphi, you need to use the following code in the file that contains the TPH methods:

exports
     TPHVersion     index 1 resident,
     Compatibility  index 2 resident,
     TimeStamp      index 3 resident,
     Entry          index 4 resident,
     Exit           index 5 resident,
     HandleToken    index 6 resident,
     ValidateToken  index 7 resident;
begin
end.

Below are skeletons of source code for all the required TPH methods, written in C++ and Delphi formats. These skeletons will be the basis for our example and we will add functionality to them as we go.

2.2.1 C++ Skeleton

For C++, note that all the methods require the WINAPI specifier before the method name:

DWORD WINAPI TPHVersion ( void ) 
{
     return 0;
}
DWORD WINAPI Compatibility( ATOM AppAtom, WORD AppVersion) 
{
     // Greater than or equal to GroupWise 5.2
     if (5 >= LOBYTE(AppVersion) && 2 >= HIBYTE(AppVersion)) 
     {
          return (DWORD) TRUE;
     }
     else 
     {
          return (DWORD) FALSE;
     }
}
DWORD WINAPI TimeStamp( void ) 
{
      return 0;
}
WORD WINAPI Entry( WORD wLanguage) 
{
     if ('U' == (char) LOBYTE(wLanguage) && 'S' == (char)HIBYTE(wLanguage)) 
     {
          return 1;
     }
     else 
     {
          return 0;
     }
}
WORD WINAPI Exit( void ) 
{
     return 1;
}
int WINAPI HandleToken(LPTPH_RETURNVAL lpTokenData, HWND hLinkWnd, WORD msg )
{
     return DLL_HAN_NOT_HANDLED;
}
DWORD WINAPI ValidateToken(LPMAC_TOKEN lpTokenData, Lpvoid lpDataTypeInfo)
{
      return DLL_VAL_UNKNOWN_TOKEN;
}

2.2.2 Delphi Skeleton

For Delphi, note that all the functions require the export and stdcall specifier after the parameter list:

Function TPHVersion: LongInt;export; stdcall;
begin
     result := 0;
end;

Function Compatibility(AppName: ATOM; AppVersion: Word): LongInt; export; stdcall;
begin
     if (5 >= LO(AppVersion) and 2 >= HI(AppVersion) then
     begin
          result := 1;
     end
     else
     begin
          result := 0;
     end;
end;

Function TimeStamp: LongInt; export; stdcall;
begin
     result := 0;
end;

Function Entry(wLanguage: Word): SmallInt; export; stdcall;
begin
     if ( 'U' = Chr(LO(wLanguage)) and 'S' = Chr(HI(wLanguage)) then
     begin
          result  := 1;
     end
     else
     begin
          result  := 0;
     end;
end;

Function Exit: SmallInt; export; stdcall;
begin
     result := 1;
end;

Function HandleToken(lpTokenData: LPTPH_RETURNVAL; hLinkWnd: HWND; msg: Word): SmallInt; export; stdcall;
begin
     result := SmallInt(DLL_HAN_NOT_HANDLED);
end;

Function ValidateToken(lpTokenData: LPMAC_TOKEN; lpDataTypeInfo: LPVOID): LongInt; export; stdcall;
begin
     result := 0;
end;