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

  1. /*
  2. * Filename: Main.cpp
  3. * Description:
  4. * Author: chrisdar 07.17.02
  5. *
  6. * Tests support for CancelIPChangeNotify to cancel notififcations from TCP/IP.
  7. * Also exercises notification calls in multiple worker threads (pool size
  8. * controlled by NUM_THREAD).
  9. *
  10. * Each thread invokes an API method at random (selecting among the notification
  11. * APIs in wlbsctrl.dll). At no time should the call fail due to the state of
  12. * notifications in the dll. Thus multiple threads of control can use the
  13. * notification API without fear of stomping on one another.
  14. */
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18. #include <time.h>
  19. #include <process.h>
  20. #include "wlbsctrl.h"
  21. #include "winsock2.h"
  22. /* The number of worker threads to create */
  23. #define NUM_THREAD 8
  24. /* The number of random numbers to generate */
  25. #define NUM_RAND 100
  26. /* Mnemonic for the 4 API methods */
  27. #define CONN_UP 0
  28. #define CONN_DOWN 1
  29. #define CONN_RESET 2
  30. #define CONN_CANCEL 3
  31. /* Function pointers for notification APIs */
  32. NLBNotificationConnectionUp pfnConnectionUp = NULL;
  33. NLBNotificationConnectionDown pfnConnectionDown = NULL;
  34. NLBNotificationConnectionReset pfnConnectionReset = NULL;
  35. NLBNotificationCancelNotify pfnCancelNotify = NULL;
  36. /* Set true when main thread wants worker threads to complete */
  37. BOOL g_fexit = FALSE;
  38. /* Array of handles to the worker threads */
  39. HANDLE g_hThread[NUM_THREAD];
  40. /* Couldn't get rand() to generate unique random numbers in worker threads. Resorted to generating an array of random numbers and cycling through it */
  41. UINT uiRand[NUM_RAND];
  42. /* Index of next random number to use. Shared by worker threads, so this is proctected by a critical section */
  43. UINT uiIndex = 0;
  44. /* Protects uiIndex */
  45. CRITICAL_SECTION cs;
  46. /* 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 */
  47. UINT tid[NUM_THREAD];
  48. /* The function executed by the worker threads */
  49. unsigned __stdcall rndm_notify(void* p)
  50. {
  51. DWORD dwStatus;
  52. DWORD dwNLBStatus = 0;
  53. /* Get my thread id */
  54. DWORD dwtid = *((DWORD*) p);
  55. while (!g_fexit)
  56. {
  57. Sleep(2000);
  58. EnterCriticalSection(&cs);
  59. UINT uiMethod = uiRand[uiIndex];
  60. uiIndex = (uiIndex++)%NUM_RAND;
  61. LeaveCriticalSection(&cs);
  62. switch(uiMethod)
  63. {
  64. case CONN_UP:
  65. dwStatus = (*pfnConnectionUp)(inet_addr("10.0.0.110"), htons(500), inet_addr("10.0.0.204"), htons(500), 50, &dwNLBStatus);
  66. break;
  67. case CONN_DOWN:
  68. dwStatus = (*pfnConnectionDown)(inet_addr("10.0.0.110"), htons(500), inet_addr("10.0.0.204"), htons(500), 50, &dwNLBStatus);
  69. break;
  70. case CONN_RESET:
  71. dwStatus = (*pfnConnectionReset)(inet_addr("10.0.0.110"), htons(500), inet_addr("10.0.0.204"), htons(500), 50, &dwNLBStatus);
  72. break;
  73. case CONN_CANCEL:
  74. dwStatus = (*pfnCancelNotify)();
  75. break;
  76. default:
  77. continue;
  78. }
  79. if (dwStatus != ERROR_SUCCESS)
  80. {
  81. wprintf(L"Thread %4d: notification %u failed with %d\n", dwtid, uiMethod, dwStatus);
  82. }
  83. else
  84. {
  85. wprintf(L"Thread %4d: notification %u succeeded\n", dwtid, uiMethod);
  86. }
  87. }
  88. dwStatus = (*pfnCancelNotify)();
  89. if (dwStatus == ERROR_SUCCESS)
  90. {
  91. wprintf(L"Thread %4d: tcp/ip notifications canceled without error\n");
  92. }
  93. else
  94. {
  95. wprintf(L"Thread %4d: canceling tcp/ip notifications failed with error %d\n", dwStatus);
  96. }
  97. wprintf(L"Thread %4d: exiting\n", dwtid);
  98. return 0;
  99. }
  100. int __cdecl wmain (int argc, WCHAR ** argv) {
  101. HINSTANCE hDLL = NULL;
  102. int iRet = 0;
  103. int i = 0;
  104. DWORD dwStatus = 0;
  105. ZeroMemory(g_hThread, sizeof(g_hThread));
  106. InitializeCriticalSection(&cs);
  107. srand( (unsigned)time( NULL ) );
  108. for (i = 0; i < NUM_RAND; i++)
  109. {
  110. uiRand[i] = rand()*4/RAND_MAX;
  111. }
  112. hDLL = LoadLibrary(L"wlbsctrl.dll");
  113. if (!hDLL) {
  114. dwStatus = GetLastError();
  115. wprintf(L"Unable to open wlbsctrl.dll... GetLastError() returned %u\n", dwStatus);
  116. iRet = -1;
  117. goto exit;
  118. }
  119. pfnConnectionUp = (NLBNotificationConnectionUp)GetProcAddress(hDLL, "WlbsConnectionUp");
  120. pfnConnectionDown = (NLBNotificationConnectionDown)GetProcAddress(hDLL, "WlbsConnectionDown");
  121. pfnConnectionReset = (NLBNotificationConnectionReset)GetProcAddress(hDLL, "WlbsConnectionReset");
  122. pfnCancelNotify = (NLBNotificationCancelNotify)GetProcAddress(hDLL, "WlbsCancelConnectionNotify");
  123. if (!pfnConnectionUp || !pfnConnectionDown || !pfnConnectionReset || !pfnCancelNotify) {
  124. dwStatus = GetLastError();
  125. wprintf(L"Unable to get procedure address... GetLastError() returned %u\n", dwStatus);
  126. iRet = -2;
  127. goto exit;
  128. }
  129. wprintf(L"Creating %u threads\n", NUM_THREAD);
  130. for (i=0; i < NUM_THREAD; i++)
  131. {
  132. g_hThread[i] = (HANDLE) _beginthreadex(
  133. NULL,
  134. 0,
  135. rndm_notify,
  136. &tid[i],
  137. 0,
  138. &tid[i]
  139. );
  140. if (g_hThread[i] == 0)
  141. {
  142. wprintf(L"thread creation failed with error %d\n", errno);
  143. iRet = -4;
  144. goto exit;
  145. }
  146. Sleep(100);
  147. }
  148. wprintf(L"<return> to end threads and cancel\n");
  149. (void)getchar();
  150. g_fexit = TRUE;
  151. dwStatus = WaitForMultipleObjects(NUM_THREAD, g_hThread, TRUE, INFINITE);
  152. DWORD dwStatus2 = (*pfnCancelNotify)();
  153. if (dwStatus2 == ERROR_SUCCESS)
  154. {
  155. wprintf(L"tcp/ip notifications canceled without error\n");
  156. }
  157. else
  158. {
  159. wprintf(L"canceling tcp/ip notifications failed with error %d\n", dwStatus2);
  160. }
  161. if (dwStatus != WAIT_OBJECT_0 + NUM_THREAD - 1)
  162. {
  163. wprintf(L"wait on threads failed with error %d\n", dwStatus);
  164. iRet = -5;
  165. goto exit;
  166. }
  167. exit:
  168. if (hDLL != NULL) FreeLibrary(hDLL);
  169. DeleteCriticalSection(&cs);
  170. return iRet;
  171. }