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.

723 lines
24 KiB

  1. //****************************************************************************
  2. //
  3. // Microsoft Windows NT RIP
  4. //
  5. // Copyright 1995-96
  6. //
  7. //
  8. // Revision History
  9. //
  10. //
  11. // 3/12/95 Gurdeep Singh Pall Created
  12. //
  13. //
  14. // Description: General utility functions:
  15. //
  16. //****************************************************************************
  17. #include "pchrip.h"
  18. #pragma hdrstop
  19. DWORD LoadAddressSockets();
  20. DWORD OpenTcp();
  21. DWORD TCPSetInformationEx(LPVOID lpvInBuffer, LPDWORD lpdwInSize,
  22. LPVOID lpvOutBuffer, LPDWORD lpdwOutSize);
  23. DWORD TCPQueryInformationEx(LPVOID lpvInBuffer, LPDWORD lpdwInSize,
  24. LPVOID lpvOutBuffer, LPDWORD lpdwOutSize);
  25. //-------------------------------------------------------------------
  26. // Function: LogEntry
  27. // Parameters:
  28. // WORD wEventType type of event (ERROR, WARNING, etc)
  29. // DWORD dwMsgID ID of message string
  30. // WORD wNumStrings number of strings in lplpStrings
  31. // LPSTR *lplpStrings array of strings
  32. // DWORD dwErr error code
  33. //-------------------------------------------------------------------
  34. void LogEntry(WORD wEventType, DWORD dwMsgID, WORD wNumStrings,
  35. LPSTR *lplpStrings, DWORD dwErr) {
  36. DWORD dwSize;
  37. LPVOID lpvData;
  38. HANDLE hLog;
  39. PSID pSidUser = NULL;
  40. hLog = RegisterEventSource(NULL, RIP_SERVICE);
  41. dwSize = (dwErr == NO_ERROR) ? 0 : sizeof(dwErr);
  42. lpvData = (dwErr == NO_ERROR) ? NULL : (LPVOID)&dwErr;
  43. ReportEvent(hLog, wEventType, 0, dwMsgID, pSidUser,
  44. wNumStrings, dwSize, lplpStrings, lpvData);
  45. DeregisterEventSource(hLog);
  46. }
  47. //-------------------------------------------------------------------
  48. // Function: RipLogError
  49. // Parameters:
  50. // see LogEntry for parameter description
  51. //-------------------------------------------------------------------
  52. void RipLogError(DWORD dwMsgID, WORD wNumStrings,
  53. LPSTR *lplpStrings, DWORD dwErr) {
  54. DWORD dwLevel;
  55. dwLevel = g_params.dwLoggingLevel;
  56. if (dwLevel < LOGLEVEL_ERROR) { return; }
  57. LogEntry(EVENTLOG_ERROR_TYPE, dwMsgID, wNumStrings, lplpStrings, dwErr);
  58. }
  59. //-------------------------------------------------------------------
  60. // Function: LogWarning
  61. // Parameters:
  62. // see LogEntry for parameter description
  63. //-------------------------------------------------------------------
  64. void RipLogWarning(DWORD dwMsgID, WORD wNumStrings,
  65. LPSTR *lplpStrings, DWORD dwErr) {
  66. DWORD dwLevel;
  67. dwLevel = g_params.dwLoggingLevel;
  68. if (dwLevel < LOGLEVEL_WARNING) { return; }
  69. LogEntry(EVENTLOG_WARNING_TYPE, dwMsgID, wNumStrings, lplpStrings, dwErr);
  70. }
  71. //-------------------------------------------------------------------
  72. // Function: LogInformation
  73. // Parameters:
  74. // see LogEntry for parameter description
  75. //-------------------------------------------------------------------
  76. void RipLogInformation(DWORD dwMsgID, WORD wNumStrings,
  77. LPSTR *lplpStrings, DWORD dwErr) {
  78. DWORD dwLevel;
  79. dwLevel = g_params.dwLoggingLevel;
  80. if (dwLevel < LOGLEVEL_INFORMATION) { return; }
  81. LogEntry(EVENTLOG_INFORMATION_TYPE, dwMsgID,
  82. wNumStrings, lplpStrings, dwErr);
  83. }
  84. //-------------------------------------------------------------------
  85. // Function: Audit
  86. //-------------------------------------------------------------------
  87. VOID Audit(IN WORD wEventType, IN DWORD dwMessageId,
  88. IN WORD cNumberOfSubStrings, IN LPSTR *plpwsSubStrings) {
  89. HANDLE hLog;
  90. PSID pSidUser = NULL;
  91. // Audit enabled
  92. hLog = RegisterEventSourceA(NULL, RIP_SERVICE);
  93. ReportEventA(hLog, wEventType, 0, dwMessageId, pSidUser,
  94. cNumberOfSubStrings, 0, plpwsSubStrings, (PVOID)NULL);
  95. DeregisterEventSource( hLog );
  96. }
  97. //-------------------------------------------------------------------
  98. // Function: dbgprintf
  99. //-------------------------------------------------------------------
  100. VOID dbgprintf(LPSTR lpszFormat, ...) {
  101. va_list arglist;
  102. va_start(arglist, lpszFormat);
  103. TraceVprintf(g_dwTraceID, lpszFormat, arglist);
  104. va_end(arglist);
  105. }
  106. //-------------------------------------------------------------------
  107. // Function: InitializeAddressTable
  108. //
  109. // Assumes the address table is locked.
  110. //-------------------------------------------------------------------
  111. DWORD InitializeAddressTable(BOOL bFirstTime) {
  112. LPRIP_ADDRESS lpaddr, lpaddrend;
  113. LPRIP_ADDRESS_STATISTICS lpstats;
  114. DWORD dwErr, dwCount, *lpdw, *lpdwend;
  115. PMIB_IPADDRROW lpTable, lpiae, lpiaeend;
  116. // first close old sockets, if necessary
  117. if (!bFirstTime) {
  118. lpaddrend = g_ripcfg.lpAddrTable + g_ripcfg.dwAddrCount;
  119. for (lpaddr = g_ripcfg.lpAddrTable; lpaddr < lpaddrend; lpaddr++) {
  120. if (lpaddr->sock != INVALID_SOCKET) {
  121. closesocket(lpaddr->sock);
  122. lpaddr->sock = INVALID_SOCKET;
  123. }
  124. }
  125. }
  126. dwErr = GetIPAddressTable(&lpTable, &dwCount);
  127. if (dwErr != 0) { return dwErr; }
  128. if (dwCount > MAX_ADDRESS_COUNT) { dwCount = MAX_ADDRESS_COUNT; }
  129. lpaddr = g_ripcfg.lpAddrTable;
  130. lpstats = g_ripcfg.lpStatsTable->lpAddrStats;
  131. lpiaeend = lpTable + dwCount;
  132. g_ripcfg.dwAddrCount = dwCount;
  133. for (lpiae = lpTable; lpiae < lpiaeend; lpiae++) {
  134. if (!lpiae->dwAddr || IP_LOOPBACK_ADDR(lpiae->dwAddr)) {
  135. --g_ripcfg.dwAddrCount; continue;
  136. }
  137. lpaddr->dwIndex = lpiae->dwIndex;
  138. lpaddr->dwAddress = lpiae->dwAddr;
  139. lpaddr->dwNetmask = lpiae->dwMask;
  140. lpaddr->dwFlag = 0;
  141. lpdwend = (LPDWORD)(lpstats + 1);
  142. for (lpdw = (LPDWORD)lpstats; lpdw < lpdwend; lpdw++) {
  143. InterlockedExchange(lpdw, 0);
  144. }
  145. InterlockedExchange(&lpstats->dwAddress, lpaddr->dwAddress);
  146. lpaddr->lpstats = lpstats;
  147. lpstats++;
  148. lpaddr++;
  149. }
  150. FreeIPAddressTable(lpTable);
  151. // also update the stats address count
  152. InterlockedExchange(&g_ripcfg.lpStatsTable->dwAddrCount,
  153. g_ripcfg.dwAddrCount);
  154. // if no addresses, bail out now
  155. if (g_ripcfg.dwAddrCount == 0) {
  156. dbgprintf("no IP addresses available for routing");
  157. return NO_ERROR;
  158. }
  159. // open sockets for each interface we have, and set options on the sockets
  160. dwErr = LoadAddressSockets();
  161. return dwErr;
  162. }
  163. //-------------------------------------------------------------------
  164. // Function: InitializeStatsTable
  165. //
  166. // Creates a mapping of our statistics table in shareable memory
  167. // so interested processes can examine RIP's behavior.
  168. //-------------------------------------------------------------------
  169. DWORD InitializeStatsTable() {
  170. DWORD dwErr;
  171. g_ripcfg.lpStatsTable = NULL;
  172. // set up a pointer to the memory
  173. g_ripcfg.lpStatsTable = HeapAlloc(GetProcessHeap(), 0,
  174. sizeof(RIP_STATISTICS));
  175. if (g_ripcfg.lpStatsTable == NULL) {
  176. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  177. dbgprintf( "InitializeStatsTable failed with error %x\n", dwErr );
  178. RipLogError( RIPLOG_ADDR_ALLOC_FAILED, 0, NULL, dwErr );
  179. return dwErr;
  180. }
  181. ZeroMemory(g_ripcfg.lpStatsTable, sizeof(RIP_STATISTICS));
  182. return 0;
  183. }
  184. VOID CleanupStatsTable() {
  185. if (g_ripcfg.lpStatsTable != NULL) {
  186. InterlockedExchange(&g_ripcfg.lpStatsTable->dwAddrCount, 0);
  187. HeapFree(GetProcessHeap(), 0, g_ripcfg.lpStatsTable);
  188. g_ripcfg.lpStatsTable = NULL;
  189. }
  190. }
  191. //--------------------------------------------------------------------------
  192. // Function: LoadAddressSockets
  193. //
  194. // Opens, configures, and binds sockets for each address in the table
  195. //--------------------------------------------------------------------------
  196. DWORD LoadAddressSockets() {
  197. IN_ADDR addr;
  198. CHAR szAddress[24] = {0};
  199. CHAR *ppszArgs[] = { szAddress };
  200. CHAR *pszTemp;
  201. SOCKADDR_IN sinsock;
  202. DWORD dwOption, dwErr;
  203. LPRIP_ADDRESS lpaddr, lpend;
  204. struct ip_mreq imOption;
  205. lpend = g_ripcfg.lpAddrTable + g_ripcfg.dwAddrCount;
  206. for (lpaddr = g_ripcfg.lpAddrTable; lpaddr < lpend; lpaddr++) {
  207. if ((lpaddr->dwFlag & ADDRFLAG_DISABLED) != 0) {
  208. continue;
  209. }
  210. addr.s_addr = lpaddr->dwAddress;
  211. pszTemp = inet_ntoa(addr);
  212. if (pszTemp != NULL) {
  213. strcpy(szAddress, pszTemp);
  214. }
  215. lpaddr->sock = socket(AF_INET, SOCK_DGRAM, 0);
  216. if (lpaddr->sock == INVALID_SOCKET) {
  217. dwErr = WSAGetLastError();
  218. dbgprintf("error %d creating socket for address %s",
  219. dwErr, szAddress);
  220. RipLogError(RIPLOG_CREATESOCK_FAILED, 1, ppszArgs, dwErr);
  221. continue;
  222. }
  223. dwOption = 1;
  224. dwErr = setsockopt(lpaddr->sock, SOL_SOCKET, SO_BROADCAST,
  225. (LPBYTE)&dwOption, sizeof(dwOption));
  226. if (dwErr == SOCKET_ERROR) {
  227. dwErr = WSAGetLastError();
  228. dbgprintf("error %d enabling broadcast for address %s",
  229. dwErr, szAddress);
  230. RipLogError(RIPLOG_SET_BCAST_FAILED, 1, ppszArgs, dwErr);
  231. // this socket is useless if we can't broadcast on it
  232. closesocket(lpaddr->sock);
  233. lpaddr->sock = INVALID_SOCKET;
  234. continue;
  235. }
  236. dwOption = 1;
  237. dwErr = setsockopt(lpaddr->sock, SOL_SOCKET, SO_REUSEADDR,
  238. (LPBYTE)&dwOption, sizeof(dwOption));
  239. if (dwErr == SOCKET_ERROR) {
  240. dwErr = WSAGetLastError();
  241. dbgprintf("error %d enabling reuse of address %s",
  242. dwErr, szAddress);
  243. RipLogError(RIPLOG_SET_REUSE_FAILED, 1, ppszArgs, dwErr);
  244. }
  245. sinsock.sin_family = AF_INET;
  246. sinsock.sin_port = htons(RIP_PORT);
  247. sinsock.sin_addr.s_addr = lpaddr->dwAddress;
  248. dwErr = bind(lpaddr->sock, (LPSOCKADDR)&sinsock, sizeof(SOCKADDR_IN));
  249. if (dwErr == SOCKET_ERROR) {
  250. dwErr = WSAGetLastError();
  251. dbgprintf("error %d binding address %s to RIP port",
  252. dwErr, szAddress);
  253. RipLogError(RIPLOG_BINDSOCK_FAILED, 1, ppszArgs, dwErr);
  254. closesocket(lpaddr->sock);
  255. lpaddr->sock = INVALID_SOCKET;
  256. continue;
  257. }
  258. #if DBG
  259. dbgprintf( "socket %d bound to %s\n\n", lpaddr-> sock, inet_ntoa( *( (struct in_addr *) &(lpaddr-> dwAddress) ) ) );
  260. #endif
  261. //
  262. // enable multicasting also
  263. //
  264. sinsock.sin_addr.s_addr = lpaddr->dwAddress;
  265. dwErr = setsockopt(lpaddr->sock, IPPROTO_IP, IP_MULTICAST_IF,
  266. (PBYTE)&sinsock.sin_addr, sizeof(IN_ADDR));
  267. if (dwErr == SOCKET_ERROR) {
  268. dwErr = WSAGetLastError();
  269. dbgprintf("error %d setting interface %d (%s) as multicast",
  270. dwErr, lpaddr->dwIndex, szAddress);
  271. RipLogError(RIPLOG_SET_MCAST_IF_FAILED, 1, ppszArgs, dwErr);
  272. closesocket(lpaddr->sock);
  273. lpaddr->sock = INVALID_SOCKET;
  274. continue;
  275. }
  276. //
  277. // join the IPRIP multicast group
  278. //
  279. imOption.imr_multiaddr.s_addr = RIP_MULTIADDR;
  280. imOption.imr_interface.s_addr = lpaddr->dwAddress;
  281. dwErr = setsockopt(lpaddr->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
  282. (PBYTE)&imOption, sizeof(imOption));
  283. if (dwErr == SOCKET_ERROR) {
  284. dwErr = WSAGetLastError();
  285. dbgprintf("error %d enabling multicast on interface %d (%s)",
  286. dwErr, lpaddr->dwIndex, szAddress);
  287. RipLogError(RIPLOG_JOIN_GROUP_FAILED, 1, ppszArgs, dwErr);
  288. closesocket(lpaddr->sock);
  289. lpaddr->sock = INVALID_SOCKET;
  290. continue;
  291. }
  292. }
  293. return 0;
  294. }
  295. //--------------------------------------------------------------------------
  296. // Function: LoadRouteTable
  297. //
  298. // Get the transports routing table. This is called with firsttime set
  299. // to TRUE when RIP loads. After that it is called with firsttime set
  300. // to FALSE. Assumes the route table is locked.
  301. //--------------------------------------------------------------------------
  302. int LoadRouteTable(BOOL bFirstTime) {
  303. IN_ADDR addr;
  304. LPHASH_TABLE_ENTRY rt_entry;
  305. CHAR szDest[32] = {0};
  306. CHAR szNexthop[32] = {0};
  307. CHAR *pszTemp;
  308. DWORD dwRouteTimeout, dwErr, dwRouteCount;
  309. LPIPROUTE_ENTRY lpRouteEntryTable, lpentry, lpentend;
  310. dwErr = GetRouteTable(&lpRouteEntryTable, &dwRouteCount);
  311. if (dwErr != 0) {
  312. return dwErr;
  313. }
  314. dwRouteTimeout = g_params.dwRouteTimeout;
  315. // now prune unwanted entries, and add the others to our hash table.
  316. // we only load RIP, static, and SNMP routes, and for non-RIP routes
  317. // we set the timeout to 90 seconds,
  318. //
  319. lpentend = lpRouteEntryTable + dwRouteCount;
  320. for (lpentry = lpRouteEntryTable; lpentry < lpentend; lpentry++) {
  321. if (lpentry->ire_metric1 < METRIC_INFINITE &&
  322. (lpentry->ire_proto == IRE_PROTO_RIP ||
  323. lpentry->ire_proto == IRE_PROTO_LOCAL ||
  324. lpentry->ire_proto == IRE_PROTO_NETMGMT) &&
  325. !IP_LOOPBACK_ADDR(lpentry->ire_dest) &&
  326. !IP_LOOPBACK_ADDR(lpentry->ire_nexthop) &&
  327. !CLASSD_ADDR(lpentry->ire_dest) &&
  328. !CLASSE_ADDR(lpentry->ire_dest) &&
  329. !IsBroadcastAddress(lpentry->ire_dest) &&
  330. !IsDisabledLocalAddress(lpentry->ire_nexthop)) {
  331. rt_entry = GetRouteTableEntry(lpentry->ire_index,
  332. lpentry->ire_dest,
  333. lpentry->ire_mask);
  334. // If we hit low memory conditions, get out of the loop.
  335. //
  336. if (rt_entry == NULL) {
  337. dwErr = ERROR_OUTOFMEMORY;
  338. break;
  339. }
  340. // only update the route with information from
  341. // the system table if it is a route that was learnt
  342. // from the system table; this is so if it is a new route
  343. // or if it is an old static or SNMP-added route
  344. //
  345. if ((rt_entry->dwFlag & NEW_ENTRY) ||
  346. rt_entry->dwProtocol == IRE_PROTO_LOCAL ||
  347. rt_entry->dwProtocol == IRE_PROTO_NETMGMT) {
  348. // if the route is new and this isn't the first time
  349. // we have loaded the system routing table, set change flag
  350. //
  351. if (!bFirstTime && (rt_entry->dwFlag & NEW_ENTRY)) {
  352. rt_entry->dwFlag |= ROUTE_CHANGE;
  353. addr.s_addr = lpentry->ire_dest;
  354. pszTemp = inet_ntoa(addr);
  355. if (pszTemp != NULL) {
  356. strcpy(szDest, pszTemp);
  357. }
  358. addr.s_addr = lpentry->ire_nexthop;
  359. pszTemp = inet_ntoa(addr);
  360. if (pszTemp != NULL) {
  361. strcpy(szNexthop, pszTemp);
  362. }
  363. dbgprintf("new entry: dest=%s, nexthop=%s, "
  364. "metric=%d, protocol=%d", szDest, szNexthop,
  365. lpentry->ire_metric1, lpentry->ire_proto);
  366. }
  367. rt_entry->dwFlag &= ~NEW_ENTRY;
  368. // we need to reset all these parameters
  369. // because any of them may have changed since
  370. // the last time the system route table was loaded.
  371. //
  372. rt_entry->dwIndex = lpentry->ire_index;
  373. rt_entry->dwProtocol = lpentry->ire_proto;
  374. rt_entry->dwDestaddr = lpentry->ire_dest;
  375. rt_entry->dwNetmask = lpentry->ire_mask;
  376. rt_entry->dwNexthop = lpentry->ire_nexthop;
  377. rt_entry->dwMetric = lpentry->ire_metric1;
  378. if (rt_entry->dwProtocol == IRE_PROTO_RIP) {
  379. rt_entry->lTimeout = (LONG)dwRouteTimeout;
  380. }
  381. else {
  382. rt_entry->lTimeout = DEF_LOCALROUTETIMEOUT;
  383. }
  384. rt_entry->dwFlag &= ~GARBAGE_TIMER;
  385. rt_entry->dwFlag |= TIMEOUT_TIMER;
  386. // if our estimate is that this is a host route
  387. // and its mask tells us it is a host route
  388. // then we mark it as being a host route
  389. //
  390. if (IsHostAddress(rt_entry->dwDestaddr) &&
  391. rt_entry->dwNetmask == HOSTADDR_MASK) {
  392. rt_entry->dwFlag |= ROUTE_HOST;
  393. }
  394. }
  395. }
  396. }
  397. FreeRouteTable(lpRouteEntryTable);
  398. return dwErr;
  399. }
  400. //--------------------------------------------------------------------------
  401. // Function: UpdateSystemRouteTable
  402. //
  403. // Parameters:
  404. // LPHASH_TABLE_ENTRY rt_entry the entry to update
  405. // BOOL bAdd if true, the entry is added
  406. // otherwise, the entry is deleted
  407. //
  408. // Returns: DWORD:
  409. //
  410. //
  411. // Add a new route to the route table. Note: due to MIB's use of
  412. // the destination address as an instance number, and also due to
  413. // TCP/IP stack allowing multiple entries for a single destination,
  414. // an ambiguity can exist. If there is already an entry for this
  415. // destination. This will have the effect of changing the existing
  416. // entry, rather than creating a new one.
  417. // This function assumes the address table is locked.
  418. //--------------------------------------------------------------------------
  419. DWORD UpdateSystemRouteTable(LPHASH_TABLE_ENTRY rt_entry, BOOL bAdd) {
  420. IN_ADDR addr;
  421. DWORD dwErr, dwRouteType;
  422. // never delete or update a route which was not created by RIP
  423. if (rt_entry->dwProtocol != IRE_PROTO_RIP) {
  424. return 0;
  425. }
  426. if (bAdd) {
  427. dwRouteType = (IsLocalAddr(rt_entry->dwNexthop) ? IRE_TYPE_DIRECT
  428. : IRE_TYPE_INDIRECT);
  429. #if 0
  430. DbgPrintf(
  431. "AddRoute : Protocol %x, Index %x, dest addr %x, dest mask %x\n",
  432. rt_entry->dwProtocol, rt_entry->dwIndex, rt_entry->dwDestaddr, rt_entry->dwNetmask
  433. );
  434. DbgPrintf(
  435. "Next Hop %x, Metric %x\n\n", rt_entry->dwNexthop, rt_entry->dwMetric
  436. );
  437. #endif
  438. dwErr = AddRoute(rt_entry->dwProtocol, dwRouteType, rt_entry->dwIndex,
  439. rt_entry->dwDestaddr, rt_entry->dwNetmask,
  440. rt_entry->dwNexthop, rt_entry->dwMetric);
  441. }
  442. else {
  443. dwErr = DeleteRoute(rt_entry->dwIndex, rt_entry->dwDestaddr,
  444. rt_entry->dwNetmask, rt_entry->dwNexthop);
  445. }
  446. if (dwErr == STATUS_SUCCESS) {
  447. if (bAdd) {
  448. InterlockedIncrement(
  449. &g_ripcfg.lpStatsTable->dwRoutesAddedToSystemTable);
  450. }
  451. else {
  452. InterlockedIncrement(
  453. &g_ripcfg.lpStatsTable->dwRoutesDeletedFromSystemTable);
  454. }
  455. }
  456. else {
  457. if (bAdd) {
  458. dbgprintf("error %X adding route to system table", dwErr);
  459. RipLogError(RIPLOG_ADD_ROUTE_FAILED, 0, NULL, dwErr);
  460. InterlockedIncrement(
  461. &g_ripcfg.lpStatsTable->dwSystemAddRouteFailures);
  462. }
  463. else {
  464. dbgprintf("error %X deleting route from system table", dwErr);
  465. RipLogError(RIPLOG_DELETE_ROUTE_FAILED, 0, NULL, dwErr);
  466. InterlockedIncrement(
  467. &g_ripcfg.lpStatsTable->dwSystemDeleteRouteFailures);
  468. }
  469. }
  470. return dwErr;
  471. }
  472. #ifndef CHICAGO
  473. //------------------------------------------------------------------
  474. // Function: OpenTcp
  475. //
  476. // Parameters:
  477. // none.
  478. //
  479. // Opens the handle to the Tcpip driver.
  480. //------------------------------------------------------------------
  481. DWORD OpenTcp() {
  482. NTSTATUS status;
  483. UNICODE_STRING nameString;
  484. IO_STATUS_BLOCK ioStatusBlock;
  485. OBJECT_ATTRIBUTES objectAttributes;
  486. // Open the ip stack for setting routes and parps later.
  487. //
  488. // Open a Handle to the TCP driver.
  489. //
  490. RtlInitUnicodeString(&nameString, DD_TCP_DEVICE_NAME);
  491. InitializeObjectAttributes(&objectAttributes, &nameString,
  492. OBJ_CASE_INSENSITIVE, NULL, NULL);
  493. status = NtCreateFile(&g_ripcfg.hTCPDriver,
  494. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  495. &objectAttributes, &ioStatusBlock, NULL,
  496. FILE_ATTRIBUTE_NORMAL,
  497. FILE_SHARE_READ | FILE_SHARE_WRITE,
  498. FILE_OPEN_IF, 0, NULL, 0);
  499. return (status == STATUS_SUCCESS ? 0 : ERROR_OPEN_FAILED);
  500. }
  501. //---------------------------------------------------------------------
  502. // Function: TCPQueryInformationEx
  503. //
  504. // Parameters:
  505. // TDIObjectID *ID The TDI Object ID to query
  506. // void *Buffer buffer to contain the query results
  507. // LPDWORD *BufferSize pointer to the size of the buffer
  508. // filled in with the amount of data.
  509. // UCHAR *Context context value for the query. should
  510. // be zeroed for a new query. It will be
  511. // filled with context information for
  512. // linked enumeration queries.
  513. //
  514. // Returns:
  515. // An NTSTATUS value.
  516. //
  517. // This routine provides the interface to the TDI QueryInformationEx
  518. // facility of the TCP/IP stack on NT.
  519. //---------------------------------------------------------------------
  520. DWORD TCPQueryInformationEx(LPVOID lpvInBuffer, LPDWORD lpdwInSize,
  521. LPVOID lpvOutBuffer, LPDWORD lpdwOutSize) {
  522. NTSTATUS status;
  523. IO_STATUS_BLOCK isbStatusBlock;
  524. if (g_ripcfg.hTCPDriver == NULL) {
  525. OpenTcp();
  526. }
  527. status = NtDeviceIoControlFile(g_ripcfg.hTCPDriver, // Driver handle
  528. NULL, // Event
  529. NULL, // APC Routine
  530. NULL, // APC context
  531. &isbStatusBlock, // Status block
  532. IOCTL_TCP_QUERY_INFORMATION_EX, // Control
  533. lpvInBuffer, // Input buffer
  534. *lpdwInSize, // Input buffer size
  535. lpvOutBuffer, // Output buffer
  536. *lpdwOutSize); // Output buffer size
  537. if (status == STATUS_PENDING) {
  538. status = NtWaitForSingleObject(g_ripcfg.hTCPDriver, TRUE, NULL);
  539. status = isbStatusBlock.Status;
  540. }
  541. if (status != STATUS_SUCCESS) {
  542. *lpdwOutSize = 0;
  543. }
  544. else {
  545. *lpdwOutSize = (ULONG)isbStatusBlock.Information;
  546. }
  547. return status;
  548. }
  549. //---------------------------------------------------------------------------
  550. // Function: TCPSetInformationEx
  551. //
  552. // Parameters:
  553. //
  554. // TDIObjectID *ID the TDI Object ID to set
  555. // void *lpvBuffer data buffer containing the information
  556. // to be set
  557. // DWORD dwBufferSize the size of the data buffer.
  558. //
  559. // This routine provides the interface to the TDI SetInformationEx
  560. // facility of the TCP/IP stack on NT.
  561. //---------------------------------------------------------------------------
  562. DWORD TCPSetInformationEx(LPVOID lpvInBuffer, LPDWORD lpdwInSize,
  563. LPVOID lpvOutBuffer, LPDWORD lpdwOutSize) {
  564. NTSTATUS status;
  565. IO_STATUS_BLOCK isbStatusBlock;
  566. if (g_ripcfg.hTCPDriver == NULL) {
  567. OpenTcp();
  568. }
  569. status = NtDeviceIoControlFile(g_ripcfg.hTCPDriver, // Driver handle
  570. NULL, // Event
  571. NULL, // APC Routine
  572. NULL, // APC context
  573. &isbStatusBlock, // Status block
  574. IOCTL_TCP_SET_INFORMATION_EX, // Control
  575. lpvInBuffer, // Input buffer
  576. *lpdwInSize, // Input buffer size
  577. lpvOutBuffer, // Output buffer
  578. *lpdwOutSize); // Output buffer size
  579. if (status == STATUS_PENDING) {
  580. status = NtWaitForSingleObject(g_ripcfg.hTCPDriver, TRUE, NULL);
  581. status = isbStatusBlock.Status;
  582. }
  583. if (status != STATUS_SUCCESS) {
  584. *lpdwOutSize = 0;
  585. }
  586. else {
  587. *lpdwOutSize = (ULONG)isbStatusBlock.Information;
  588. }
  589. return status;
  590. }
  591. #endif