Implementing Startup
The first time a Resource Monitor creates an instance of a resource type, it calls the Startup entry point function in the appropriate resource DLL. The purpose of Startup is to allow the resource DLL and the Resource Monitor to exchange two important pieces of information:
- The Resource Monitor needs the addresses of the entry point functions for the resource type.
- The resource DLL needs addresses for the LogEvent and SetResourceStatus callback functions.
In addition, Startup indicates the version of the Resource API in use on the local node.
To implement Startup
- Recommended: Verify that the local version of the Resource API is compatible with your implementation.
- Required. Store the addresses of LogEvent and SetResourceStatus callback functions.
- Required. Return a function table for the specified resource type.
- Recommended. Take no more than 300 milliseconds to return a value.
Once a Resource Monitor has a function table for a resource type, it does not call Startup to create additional instances. A Resource Monitor will retain the function table for a resource type until all instances of the type assigned to the Resource Monitor have been deleted.
Resource DLLs that support multiple resource types typically define a single Startup entry point function for the entire DLL and take appropriate action based on the name of the resource type passed in by the Resource Monitor. However, you could instead create <Name>Startup functions for each <Name> resource type supported by your DLL, as described in Implementing DllMain.
Example
The following example illustrates a Startup routine in a resource DLL that supports two types, MyTypeAlpha and MyTypeBeta. For additional examples see Resource DLL Examples.
////////////////////////////////////////////////////////////////
DWORD WINAPI Startup( IN LPCWSTR pszResourceType,
IN DWORD nMinVersionSupported,
IN DWORD nMaxVersionSupported,
IN PSET_RESOURCE_STATUS_ROUTINE pfnSetResourceStatus,
IN PLOG_EVENT_ROUTINE pfnLogEvent,
OUT PCLRES_FUNCTION_TABLE *pFunctionTable )
{
DWORD nStatus;
if ( (nMinVersionSupported > CLRES_VERSION_V1_00)
|| (nMaxVersionSupported < CLRES_VERSION_V1_00) )
{
nStatus = ERROR_REVISION_MISMATCH;
}
else if( lstrcmpiW( pszResourceType, TYPE_NAME_ALPHA ) == 0 )
{
*pFunctionTable = &g_FTable_Alpha;
nStatus = ERROR_SUCCESS;
}
else if( lstrcmpiW( pszResourceType, TYPE_NAME_BETA ) == 0 )
{
*pFunctionTable = &g_FTable_Beta;
nStatus = ERROR_SUCCESS;
}
else
{
nStatus = ERROR_CLUSTER_RESNAME_NOT_FOUND;
}
if( nStatus == ERROR_SUCCESS )
{
g_pfnSetResourceStatus = pfnSetResourceStatus;
g_pfnLogEvent = pfnLogEvent;
}
return nStatus;
}