Source code of Windows XP (NT5)
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.

356 lines
7.4 KiB

  1. //==========================================================================
  2. // Copyright (c) 1995, Microsoft Corporation
  3. //
  4. // File: entry.c
  5. //
  6. // History:
  7. // t-abolag 06-21-95 Created.
  8. //
  9. // entry point for Routing Table API set
  10. //==========================================================================
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <time.h>
  14. #include <ctype.h>
  15. #ifndef CHICAGO
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. #endif
  20. #include <windows.h>
  21. #include <winsock.h>
  22. #include <string.h>
  23. #include <errno.h>
  24. #include <process.h>
  25. #include <malloc.h>
  26. #include <io.h>
  27. #include <winsvc.h>
  28. #include "ipinfo.h"
  29. #include "llinfo.h"
  30. #include "ntddtcp.h"
  31. #include "tdiinfo.h"
  32. #include "dhcpcapi.h"
  33. #include "routetab.h"
  34. #include "rtdefs.h"
  35. BOOL
  36. WINAPI
  37. LIBMAIN(
  38. IN HINSTANCE hInstance,
  39. IN DWORD dwReason,
  40. IN LPVOID lpvUnused
  41. )
  42. {
  43. BOOL bError = TRUE;
  44. switch(dwReason) {
  45. case DLL_PROCESS_ATTACH: {
  46. DEBUG_PRINT(("LIBMAIN: DLL_PROCESS_ATTACH\n"));
  47. //
  48. // we have no per-thread initialization,
  49. // so disable DLL_THREAD_{ATTACH,DETACH} calls
  50. //
  51. DisableThreadLibraryCalls(hInstance);
  52. //
  53. // initialize globals and background thread
  54. //
  55. bError = RTStartup((HMODULE)hInstance);
  56. break;
  57. }
  58. case DLL_PROCESS_DETACH: {
  59. //
  60. // if the background thread is around, tell it to clean up;
  61. // otherwise clean up ourselves
  62. //
  63. bError = RTShutdown((HMODULE)hInstance);
  64. break;
  65. }
  66. }
  67. DEBUG_PRINT(("LIBMAIN: <= %d\n", bError ));
  68. return bError;
  69. }
  70. //----------------------------------------------------------------------------
  71. // Function: RTStartup
  72. //
  73. // Handles initialization for DLL-wide data
  74. //----------------------------------------------------------------------------
  75. BOOL
  76. RTStartup(
  77. HMODULE hmodule
  78. )
  79. {
  80. HANDLE hThread;
  81. DWORD dwErr, dwThread;
  82. SECURITY_ATTRIBUTES saAttr;
  83. SECURITY_DESCRIPTOR sdDesc;
  84. CHAR szModule[MAX_PATH + 1];
  85. g_prtcfg = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*g_prtcfg));
  86. if (g_prtcfg == NULL){
  87. DEBUG_PRINT(("RTStartup: !HeapAlloc \n"));
  88. return FALSE;
  89. }
  90. do {
  91. //
  92. // We do a loadlibrary to increment the reference count
  93. // on this library, so that when the library is unloaded
  94. // by the application, our address-space doesn't disappear.
  95. // Instead, we signal the thread and then we cleanup
  96. // and call FreeLibraryAndExitThread to unload the DLL completely
  97. //
  98. GetModuleFileName(hmodule, szModule, MAX_PATH);
  99. hmodule = LoadLibrary(szModule);
  100. if (!hmodule) {
  101. DEBUG_PRINT(("RTStartup: !loadlibrary %s\n", szModule ));
  102. return FALSE;
  103. }
  104. //
  105. // Create the event signalled to tell the update thread to exit
  106. //
  107. g_rtCfg.hUpdateThreadExit = CreateEvent(NULL, FALSE, FALSE, NULL);
  108. if (g_rtCfg.hUpdateThreadExit == NULL) {
  109. DEBUG_PRINT(("RTStartup: !CreateEvent \n"));
  110. break;
  111. }
  112. //
  113. // Create the mutex which protects our tables
  114. //
  115. g_rtCfg.hRTMutex = CreateMutex(NULL, FALSE, NULL);
  116. if (g_rtCfg.hRTMutex == NULL) { break; }
  117. //
  118. // Load interface table now before any API functions are called
  119. //
  120. dwErr = RTGetTables(
  121. &g_rtCfg.lpIfTable, &g_rtCfg.dwIfCount,
  122. &g_rtCfg.lpIPAddressTable, &g_rtCfg.dwIPAddressCount
  123. );
  124. if (dwErr != 0) {
  125. DEBUG_PRINT(("RTStartup: !RTGetTables \n"));
  126. break;
  127. }
  128. //
  129. // Try to create the DHCP event in case DHCP service or DHCP API
  130. // has not created it; use the security attributes struct
  131. // because DHCP will. Omitting this code will cause DHCP
  132. // to fail to open the event if the interfaces are statically
  133. // configured (in which case the DHCP client would not be running);
  134. //
  135. #if (WINVER >= 0x500)
  136. g_rtCfg.hDHCPEvent = DhcpOpenGlobalEvent();
  137. #else
  138. saAttr.nLength = sizeof(saAttr);
  139. saAttr.bInheritHandle = FALSE;
  140. InitializeSecurityDescriptor(&sdDesc, SECURITY_DESCRIPTOR_REVISION);
  141. if (SetSecurityDescriptorDacl(&sdDesc, TRUE, NULL, FALSE)) {
  142. saAttr.lpSecurityDescriptor = &sdDesc;
  143. }
  144. else {
  145. saAttr.lpSecurityDescriptor = NULL;
  146. }
  147. g_rtCfg.hDHCPEvent =
  148. CreateEvent(&saAttr, TRUE, FALSE, STR_DHCPNEWIPADDR);
  149. #endif
  150. if (g_rtCfg.hDHCPEvent != NULL) {
  151. //
  152. // Start up the thread which updates the interface table
  153. // if IP addresses are changed
  154. //
  155. hThread = CreateThread(
  156. NULL, 0, (LPTHREAD_START_ROUTINE)RTUpdateThread,
  157. (LPVOID)hmodule, 0, &dwThread
  158. );
  159. if (hThread == NULL) {
  160. DEBUG_PRINT(("RTStartup: !CreateThread \n"));
  161. break;
  162. }
  163. g_rtCfg.dwUpdateThreadStarted = 1;
  164. CloseHandle(hThread);
  165. }
  166. return TRUE;
  167. } while(FALSE);
  168. //
  169. // If we reach here, something went wrong;
  170. // clean up and decrement the DLL reference count.
  171. //
  172. RTCleanUp();
  173. if (hmodule) {
  174. FreeLibrary(hmodule);
  175. }
  176. return FALSE;
  177. }
  178. //----------------------------------------------------------------------------
  179. // Function: RTShutdown
  180. //
  181. // Handles DLL-unload-time cleanup.
  182. //----------------------------------------------------------------------------
  183. BOOL
  184. RTShutdown(
  185. HMODULE hmodule
  186. )
  187. {
  188. //
  189. // If the background thread exists, allow it to clean up;
  190. // otherwise, handle cleanup ourselves.
  191. //
  192. if (g_rtCfg.dwUpdateThreadStarted) {
  193. //
  194. // Tell the thread to exit
  195. //
  196. SetEvent(g_rtCfg.hUpdateThreadExit);
  197. }
  198. else {
  199. //
  200. // Do the cleanup ourselves
  201. //
  202. RTCleanUp();
  203. FreeLibrary(hmodule);
  204. }
  205. return TRUE;
  206. }
  207. //----------------------------------------------------------------------------
  208. // Function: RTCleanUp
  209. //
  210. // This is called to free up resources used by the DLL.
  211. //----------------------------------------------------------------------------
  212. VOID
  213. RTCleanUp(
  214. )
  215. {
  216. //
  217. // Free memory for the interface table
  218. //
  219. if (g_rtCfg.lpIfTable != NULL) {
  220. HeapFree(GetProcessHeap(), 0, g_rtCfg.lpIfTable);
  221. }
  222. //
  223. // Free memory for the address table
  224. //
  225. if (g_rtCfg.lpIPAddressTable != NULL) {
  226. HeapFree(GetProcessHeap(), 0, g_rtCfg.lpIPAddressTable);
  227. }
  228. //
  229. // Close the event on which we receive IP-address-change notifications
  230. //
  231. if (g_rtCfg.hDHCPEvent != NULL) { CloseHandle(g_rtCfg.hDHCPEvent); }
  232. //
  233. // Close the mutex protecting our tables
  234. //
  235. if (g_rtCfg.hRTMutex != NULL) { CloseHandle(g_rtCfg.hRTMutex); }
  236. //
  237. // Close the handle signalled to tell the update-thread to exit
  238. //
  239. if (g_rtCfg.hUpdateThreadExit != NULL) {
  240. CloseHandle(g_rtCfg.hUpdateThreadExit);
  241. }
  242. //
  243. // Close our handle to the TCP/IP driver
  244. //
  245. if (g_rtCfg.hTCPHandle != NULL) { CloseHandle(g_rtCfg.hTCPHandle); }
  246. HeapFree(GetProcessHeap(), 0, g_prtcfg);
  247. }