Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

213 lines
6.5 KiB

/*
* Filename: Main.cpp
* Description:
* Author: chrisdar 07.17.02
*
* Tests support for CancelIPChangeNotify to cancel notififcations from TCP/IP.
* Also exercises notification calls in multiple worker threads (pool size
* controlled by NUM_THREAD).
*
* Each thread invokes an API method at random (selecting among the notification
* APIs in wlbsctrl.dll). At no time should the call fail due to the state of
* notifications in the dll. Thus multiple threads of control can use the
* notification API without fear of stomping on one another.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <process.h>
#include "wlbsctrl.h"
#include "winsock2.h"
/* The number of worker threads to create */
#define NUM_THREAD 8
/* The number of random numbers to generate */
#define NUM_RAND 100
/* Mnemonic for the 4 API methods */
#define CONN_UP 0
#define CONN_DOWN 1
#define CONN_RESET 2
#define CONN_CANCEL 3
/* Function pointers for notification APIs */
NLBNotificationConnectionUp pfnConnectionUp = NULL;
NLBNotificationConnectionDown pfnConnectionDown = NULL;
NLBNotificationConnectionReset pfnConnectionReset = NULL;
NLBNotificationCancelNotify pfnCancelNotify = NULL;
/* Set true when main thread wants worker threads to complete */
BOOL g_fexit = FALSE;
/* Array of handles to the worker threads */
HANDLE g_hThread[NUM_THREAD];
/* Couldn't get rand() to generate unique random numbers in worker threads. Resorted to generating an array of random numbers and cycling through it */
UINT uiRand[NUM_RAND];
/* Index of next random number to use. Shared by worker threads, so this is proctected by a critical section */
UINT uiIndex = 0;
/* Protects uiIndex */
CRITICAL_SECTION cs;
/* Only way I could get the thread id to each worker thread. Used only in dumped output so I know which thread is doing the work */
UINT tid[NUM_THREAD];
/* The function executed by the worker threads */
unsigned __stdcall rndm_notify(void* p)
{
DWORD dwStatus;
DWORD dwNLBStatus = 0;
/* Get my thread id */
DWORD dwtid = *((DWORD*) p);
while (!g_fexit)
{
Sleep(2000);
EnterCriticalSection(&cs);
UINT uiMethod = uiRand[uiIndex];
uiIndex = (uiIndex++)%NUM_RAND;
LeaveCriticalSection(&cs);
switch(uiMethod)
{
case CONN_UP:
dwStatus = (*pfnConnectionUp)(inet_addr("10.0.0.110"), htons(500), inet_addr("10.0.0.204"), htons(500), 50, &dwNLBStatus);
break;
case CONN_DOWN:
dwStatus = (*pfnConnectionDown)(inet_addr("10.0.0.110"), htons(500), inet_addr("10.0.0.204"), htons(500), 50, &dwNLBStatus);
break;
case CONN_RESET:
dwStatus = (*pfnConnectionReset)(inet_addr("10.0.0.110"), htons(500), inet_addr("10.0.0.204"), htons(500), 50, &dwNLBStatus);
break;
case CONN_CANCEL:
dwStatus = (*pfnCancelNotify)();
break;
default:
continue;
}
if (dwStatus != ERROR_SUCCESS)
{
wprintf(L"Thread %4d: notification %u failed with %d\n", dwtid, uiMethod, dwStatus);
}
else
{
wprintf(L"Thread %4d: notification %u succeeded\n", dwtid, uiMethod);
}
}
dwStatus = (*pfnCancelNotify)();
if (dwStatus == ERROR_SUCCESS)
{
wprintf(L"Thread %4d: tcp/ip notifications canceled without error\n");
}
else
{
wprintf(L"Thread %4d: canceling tcp/ip notifications failed with error %d\n", dwStatus);
}
wprintf(L"Thread %4d: exiting\n", dwtid);
return 0;
}
int __cdecl wmain (int argc, WCHAR ** argv) {
HINSTANCE hDLL = NULL;
int iRet = 0;
int i = 0;
DWORD dwStatus = 0;
ZeroMemory(g_hThread, sizeof(g_hThread));
InitializeCriticalSection(&cs);
srand( (unsigned)time( NULL ) );
for (i = 0; i < NUM_RAND; i++)
{
uiRand[i] = rand()*4/RAND_MAX;
}
hDLL = LoadLibrary(L"wlbsctrl.dll");
if (!hDLL) {
dwStatus = GetLastError();
wprintf(L"Unable to open wlbsctrl.dll... GetLastError() returned %u\n", dwStatus);
iRet = -1;
goto exit;
}
pfnConnectionUp = (NLBNotificationConnectionUp)GetProcAddress(hDLL, "WlbsConnectionUp");
pfnConnectionDown = (NLBNotificationConnectionDown)GetProcAddress(hDLL, "WlbsConnectionDown");
pfnConnectionReset = (NLBNotificationConnectionReset)GetProcAddress(hDLL, "WlbsConnectionReset");
pfnCancelNotify = (NLBNotificationCancelNotify)GetProcAddress(hDLL, "WlbsCancelConnectionNotify");
if (!pfnConnectionUp || !pfnConnectionDown || !pfnConnectionReset || !pfnCancelNotify) {
dwStatus = GetLastError();
wprintf(L"Unable to get procedure address... GetLastError() returned %u\n", dwStatus);
iRet = -2;
goto exit;
}
wprintf(L"Creating %u threads\n", NUM_THREAD);
for (i=0; i < NUM_THREAD; i++)
{
g_hThread[i] = (HANDLE) _beginthreadex(
NULL,
0,
rndm_notify,
&tid[i],
0,
&tid[i]
);
if (g_hThread[i] == 0)
{
wprintf(L"thread creation failed with error %d\n", errno);
iRet = -4;
goto exit;
}
Sleep(100);
}
wprintf(L"<return> to end threads and cancel\n");
(void)getchar();
g_fexit = TRUE;
dwStatus = WaitForMultipleObjects(NUM_THREAD, g_hThread, TRUE, INFINITE);
DWORD dwStatus2 = (*pfnCancelNotify)();
if (dwStatus2 == ERROR_SUCCESS)
{
wprintf(L"tcp/ip notifications canceled without error\n");
}
else
{
wprintf(L"canceling tcp/ip notifications failed with error %d\n", dwStatus2);
}
if (dwStatus != WAIT_OBJECT_0 + NUM_THREAD - 1)
{
wprintf(L"wait on threads failed with error %d\n", dwStatus);
iRet = -5;
goto exit;
}
exit:
if (hDLL != NULL) FreeLibrary(hDLL);
DeleteCriticalSection(&cs);
return iRet;
}