[This is preliminary documentation and subject to change.]
DWORD
APIENTRY
StartProtocol(
IN HANDLE hMgrNotifyEvent,
IN PSUPPORT_FUNCTIONS pSupportFunctions,
IN PVOID pvConfig
)
/*++
Routine Description
After the protocol has been registered, the IP Router Manager
calls this function to tell the protocol to start. Most of the
startup code is executed here.
Arguments
hMgrNotifyEvent Event to Set if the IP Router Manager needs to
be notified to take any action on our behalf
pSupportFunctions Some functions exported by IP Router Manager
pvConfig Our global configuration which was setup by our
setup/admin DLL
Return Value
NO_ERROR
--*/
{
WSADATA wsaData;
DWORD dwResult, dwThread;
HANDLE hThread;
BOOL bWinsockLoaded;
PSAMPLE_PROTOCOL_GLOBAL_INFO pGlobalInfo;
EnterProtocolApi();
TraceEnter("StartProtocol");
if(pvConfig == NULL)
{
Trace0(ERR,
"StartProtocol: Called with NULL config");
TraceLeave("StartProtocol");
ExitProtocolApi();
return ERROR_INVALID_PARAMETER;
}
pGlobalInfo = (PSAMPLE_PROTOCOL_GLOBAL_INFO)pvConfig;
if(!ValidateGlobalInfo(pGlobalInfo))
{
TraceLeave("StartProtocol");
ExitProtocolApi();
return ERROR_INVALID_DATA;
}
g_hPrivateHeap = NULL;
g_hRtmEvent = NULL;
g_hMgrNotifyEvent = NULL;
g_hRtmHandle = NULL;
g_hStopProtocolEvent = NULL;
g_hSocketEvent = NULL;
g_pmmStopMsg = NULL;
bWinsockLoaded = FALSE;
g_psfnSupportFunctions = pSupportFunctions;
do
{
InitializeCriticalSections();
//
// We need Winsock2.0 or better
//
dwResult = (DWORD)WSAStartup(MAKEWORD(2,0), &wsaData);
if(dwResult != 0)
{
Trace1(ERR,
"StartProtocol: Error %d starting WinSock.", dwResult);
LogErr0(WINSOCK_FAIL,
dwResult);
break;
}
bWinsockLoaded = TRUE;
dwResult = CreateHeaps();
if(dwResult != NO_ERROR)
{
break;
}
dwResult = CreateEvents();
if(dwResult != NO_ERROR)
{
break;
}
//
// The message that will be used to notify the stopping
// of this protocol. If we cant create this, we wont be
// able to stop
//
g_pmmStopMsg = HeapAlloc(g_hPrivateHeap,
0,
sizeof(MGR_MSG));
if(g_pmmStopMsg == NULL)
{
dwResult = GetLastError();
Trace1(ERR,
"StartProtocol: Couldnt allocate stop message. Error %d",
dwResult);
break;
}
//
// Register as an RTM client. We will not keep multiple routes
// to one destination so we set the flags to denote this
//
g_hRtmHandle = RtmRegisterClient(RTM_PROTOCOL_FAMILY_IP,
SAMPLE_PROTOCOL_ROUTE_ID,
g_hRtmEvent,
RTM_PROTOCOL_SINGLE_ROUTE);
if(g_hRtmHandle == NULL)
{
dwResult = GetLastError();
Trace1(ERR,
"StartProtocol: Error %d registering with RTM",
dwResult);
LogErr0(RTM_REGISTER_FAILED,
dwResult);
break;
}
//
// Create the main thread. This executes the MainThread()
// function
//
hThread = CreateThread(NULL, 0,
MainThread,
NULL,
0,
&dwThread);
if (hThread == NULL)
{
dwResult = GetLastError();
Trace1(ERR,
"StartProtocol: Error %d starting main thread",
dwResult);
LogErr0(CREATE_THREAD_FAILED,
dwResult);
break;
}
//
// We will never refer to the thread using the handle
// so close it and avoid a leak
//
CloseHandle(hThread);
}while(FALSE);
if(dwResult != NO_ERROR)
{
//
// Something bad happened
//
if(g_pmmStopMsg)
{
HeapFree(g_hPrivateHeap,
0,
g_pmmStopMsg);
}
CleanupProtocol(bWinsockLoaded);
}
else
{
g_hMgrNotifyEvent = hMgrNotifyEvent;
g_dwProtocolState = PROTOCOL_STATE_RUNNING;
}
TraceLeave("StartProtocol");
ExitProtocolApi();
return NO_ERROR;
}