Apple Macintosh
Providers on the Macintosh can reside in any program – application, desk accessory, system extension, etc. – and can register their presence with the license system management layer. Once a provider is registered, it can receive any of the five standard License Service functions. Providers can also unregister at any time to remove themselves from the system.
Macintosh applications statically link with the LSAPI.o library, which coordinates the interaction between the licensed application and the installed providers (a system extension must also be installed in the user's System Folder). Applications do not interact directly with the registered license providers.
Developers may contact Sassafras Software at (603) 643-3351 or Apple Computer's Developer Relations group at (408) 996-1010 for further information.
Data Structures
To provide source-level compatibility with other operating system platforms, all strings pointed to below are NULL-terminated.
Each provider must register with the license system management layer before it can handle License Service calls. To register, a provider fills in the appropriate fields in a LS_PROVIDER_ELEMENT structure, and calls LSRegister().
LS_PROVIDER_ELEMENT = record
lsLink: Ptr; {for management layer use}
lsType: integer; {for management layer use}
lsInternal: LongInt; {for management layer use}
lsReserved: LongInt; {for management layer use}
lsAddr: ProcPtr; {address of provider code}
lsName: Ptr; {pointer to provider name}
lsStamp: OSType; {unique provider stamp}
lsRefCon: LongInt {for provider's use}
end;
LS_PROVIDER_PTR = ^LS_PROVIDER_ELEMENT;
The lsAddr field points to the provider routine. Providers are declared as follows:
procedure MyProvider (lsPB: LS_PBLOCKPTR;
lsElement: LS_PROVIDER_PTR);
When the provider is called, the LS_PARAMBLOCKREC pointed to by lsPB contains a code for the call being made, as well as all of the pertinent parameters. lsElement points to the provider's registered LS_PROVIDER_ELEMENT.
LS_PARAMBLOCKREC = record
qLink: Ptr;
qType: integer;
ioTrap: integer;
ioCmdAddr: Ptr;
ioCompletion: ProcPtr;
ioResult: integer;
ioNamePtr: Ptr;
ioVRefNum: integer;
ioRefNum: integer;
csCode: integer;
lsResult: LS_STATUS_CODE;
lsHandle: LS_HANDLE;
case integer of
1: (
lsPublisher: Ptr;
lsProduct: Ptr;
lsVersion: Ptr;
lsURequired: LongInt;
lsLogComm: Ptr;
lsChallenge: LS_CHALLENGE_PTR
lsTotUGranted: Ptr;
);
2: (
lsUConsumed: LongInt;
lsLogComm: Ptr;
);
3: (
lsUConsumed: LogInt;
lsUReserved: LongInt;
lsLogComm: Ptr;
lsChallenge: LS_CHALLENGE_PTR;
lsTotUGranted: Ptr;
);
4: (
lsInfo: LongInt;
lsInfoBuffer: Ptr;
lsBuffSize: Ptr;
lsActBuffSize: Ptr;
);
5: (
lsValue: LongInt;
lsBuffSize: LongInt;
lsBuffer: Ptr
);
end;
LS_PBLOCKPTR = ^LS_PARAMBLOCKREC;
The csCode field of a LS_PARAMBLOCKREC gives the reason that the provider was called. It can take on one of the following values, one for each of the six standard License Service API functions:
LS_REQUEST_CODE = 1;
LS_RELEASE_CODE = 2;
LS_UPDATE_CODE = 3;
LS_QUERYLICENSE_CODE = 4;
LS_GETMESSAGE_CODE = 5;
LS_FREEHANDLE_CODE = 6;
Other values for csCode should be ignored. This parameter block interface was chosen so that the provider can easily pass the parameter block on to a driver, which can then handle the actual License Service functions.
License Context Handles
On the Macintosh, an LS_HANDLE is always a pointer to an LS_HANDLE_REC. Note that the LS_HANDLE type should not be confused with the Memory Manager's Handle type. The LS_HANDLE_REC has the following format:
LS_HANDLE_REC = record
lhStamp: OSType;
lhData: array of byte
end;
LS_HANDLE = ^LS_HANDLE_REC;
The size and contents of the lhData array are specific to the provider, and are not interpreted by the license system management layer.
Provider support calls
When a provider wishes to register with the license system management layer, it first allocates an LS_PROVIDER_ELEMENT, fills in the last four fields with appropriate values, and then calls LSRegister(). LSRegister() is defined in the LSAPI.o library, which must be linked with the provider. LSRegister() is declared as follows:
function LSRegister (lsElement: LS_PROVIDER_PTR):LS_STATUS_CODE;
The routine a provider uses to unregister is declared as follows:
function LSRemove (lsElement: LS_PROVIDER_PTR):LS_STATUS_CODE;
A provider need register only once, and should only unregister if it is no longer available to the license system.
Provider example
The following incomplete example code illustrates how a provider registers itself and handles the License Service calls:
{ This procedure creates an LS_PROVIDER_ELEMENT }
{ and registers the provider. }
procedure RegisterMyProvider (myName: Ptr; myRefCon: LongInt);
const
myStamp = 'TEST';
var
myElem: LS_PROVIDER_PTR;
begin
{ allocate a provider element }
myElem := LS_PROVIDER_PTR(NewPtr(SizeOf(LS_PROVIDER_ELEMENT)));
if (myElem = nil) then
{ handle the error gracefully };
{ fill in the provider element }
myElem^.lsAddr := @MyProvider;
myElem^.lsName := myName;
myElem^.lsStamp := myStamp;
myElem^.lsRefCon := myRefCon;
err := LSRegister(myElem);
if (err <> LS_SUCCESS) then
{ handle the error gracefully }
end;
{ This is the main provider code, which handles all }
{ License Service calls from the management layer. }
procedure MyProvider (lsPB: LS_PBLOCKPTR;
lsElement: LS_PROVIDER_PTR);
begin
lsPB^.lsResult := LS_SUCCESS; { initialize lsResult }
case lsPB^.csCode of { which call has been made? }
LS_REQUEST_CODE:
...;
LS_RELEASE_CODE:
...;
LS_UPDATE_CODE:
...;
LS_QUERYLICENSE_CODE:
...;
LS_GETMESSAGE_CODE:
...;
otherwise
{ always ignore unknown csCode values }
end;
end;