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.

784 lines
21 KiB

  1. //============================================================================
  2. // Copyright (c) 1994-95, Microsoft Corp.
  3. //
  4. // File: routetab.c
  5. //
  6. // History:
  7. // t-abolag 6/20/95 Adapted from RIP code.
  8. //
  9. // Contains API entries for the Routing Table functions
  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 <malloc.h>
  24. #include <io.h>
  25. #include <winsvc.h>
  26. #include "ipinfo.h"
  27. #include "llinfo.h"
  28. #include "ntddtcp.h"
  29. #include "tdiinfo.h"
  30. #include "routetab.h"
  31. #include "rtdefs.h"
  32. #include <assert.h>
  33. #ifdef CHICAGO
  34. #include <wscntl.h>
  35. LPWSCONTROL pWsControl = NULL;
  36. HANDLE hWsock = NULL;
  37. #endif
  38. GLOBAL_STRUCT g_rtCfg;
  39. DWORD
  40. APIENTRY
  41. GetIfEntry(
  42. IN DWORD dwIfIndex,
  43. OUT LPIF_ENTRY lpIfEntry
  44. )
  45. {
  46. DWORD dwErr;
  47. LPIF_ENTRY lpIf, lpIfEnd;
  48. if (lpIfEntry == NULL) {
  49. return ERROR_INVALID_PARAMETER;
  50. }
  51. RT_LOCK();
  52. dwErr = ERROR_INVALID_PARAMETER;
  53. lpIfEnd = g_rtCfg.lpIfTable + g_rtCfg.dwIfCount;
  54. for (lpIf = g_rtCfg.lpIfTable; lpIf < lpIfEnd; lpIf++) {
  55. if (lpIf->ife_index == dwIfIndex) {
  56. CopyMemory(lpIfEntry, lpIf, sizeof(IF_ENTRY));
  57. dwErr = 0;
  58. break;
  59. }
  60. }
  61. RT_UNLOCK();
  62. return dwErr;
  63. }
  64. DWORD
  65. APIENTRY
  66. GetIPAddressTable(
  67. OUT LPIPADDRESS_ENTRY *lplpAddrTable,
  68. OUT LPDWORD lpdwAddrCount
  69. )
  70. {
  71. DWORD dwErr, dwCount;
  72. LPIPADDRESS_ENTRY lpAddresses;
  73. if (lpdwAddrCount == NULL || lplpAddrTable == NULL) {
  74. return ERROR_INVALID_PARAMETER;
  75. }
  76. RT_LOCK();
  77. dwCount = g_rtCfg.dwIPAddressCount;
  78. lpAddresses = (LPIPADDRESS_ENTRY)HeapAlloc(
  79. GetProcessHeap(), 0,
  80. dwCount * sizeof(IPADDRESS_ENTRY)
  81. );
  82. if (lpAddresses == NULL) {
  83. *lpdwAddrCount = 0;
  84. *lplpAddrTable = NULL;
  85. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  86. }
  87. else {
  88. CopyMemory(lpAddresses, g_rtCfg.lpIPAddressTable,
  89. dwCount * sizeof(IPADDRESS_ENTRY));
  90. *lpdwAddrCount = dwCount;
  91. *lplpAddrTable = lpAddresses;
  92. dwErr = 0;
  93. }
  94. RT_UNLOCK();
  95. return dwErr;
  96. }
  97. DWORD
  98. APIENTRY
  99. ReloadIPAddressTable(
  100. OUT LPIPADDRESS_ENTRY *lplpAddrTable,
  101. OUT LPDWORD lpdwAddrCount
  102. )
  103. {
  104. DWORD dwErr, dwCount;
  105. LPIPADDRESS_ENTRY lpAddresses;
  106. if (lpdwAddrCount == NULL || lplpAddrTable == NULL) {
  107. return ERROR_INVALID_PARAMETER;
  108. }
  109. do
  110. {
  111. RT_LOCK();
  112. if (g_rtCfg.lpIfTable != NULL) {
  113. HeapFree(GetProcessHeap(), 0, g_rtCfg.lpIfTable);
  114. g_rtCfg.lpIfTable = NULL;
  115. }
  116. if (g_rtCfg.lpIPAddressTable != NULL) {
  117. HeapFree(GetProcessHeap(), 0, g_rtCfg.lpIPAddressTable);
  118. g_rtCfg.lpIPAddressTable = NULL;
  119. }
  120. //
  121. // reload the tables
  122. //
  123. dwErr = RTGetTables(
  124. &g_rtCfg.lpIfTable, &g_rtCfg.dwIfCount,
  125. &g_rtCfg.lpIPAddressTable, &g_rtCfg.dwIPAddressCount
  126. );
  127. if (dwErr != 0) {
  128. RT_UNLOCK();
  129. break;
  130. }
  131. dwCount = g_rtCfg.dwIPAddressCount;
  132. lpAddresses = (LPIPADDRESS_ENTRY)HeapAlloc(
  133. GetProcessHeap(), 0,
  134. dwCount * sizeof(IPADDRESS_ENTRY)
  135. );
  136. if (lpAddresses == NULL) {
  137. *lpdwAddrCount = 0;
  138. *lplpAddrTable = NULL;
  139. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  140. }
  141. else {
  142. CopyMemory(lpAddresses, g_rtCfg.lpIPAddressTable,
  143. dwCount * sizeof(IPADDRESS_ENTRY));
  144. *lpdwAddrCount = dwCount;
  145. *lplpAddrTable = lpAddresses;
  146. dwErr = 0;
  147. }
  148. RT_UNLOCK();
  149. } while (FALSE);
  150. return dwErr;
  151. }
  152. /*
  153. *------------------------------------------------------------------
  154. * Function: FreeIPAddressTable
  155. *
  156. * Parameters:
  157. * LPIPADDRESS_ENTRY
  158. * lpAddrTable the address table to be freed.
  159. *
  160. * This function frees the memory allocated for an address table.
  161. * It returns 0 if successful and non-zero otherwise.
  162. *------------------------------------------------------------------
  163. */
  164. DWORD
  165. APIENTRY
  166. FreeIPAddressTable(
  167. IN LPIPADDRESS_ENTRY lpAddrTable
  168. )
  169. {
  170. if (lpAddrTable != NULL) {
  171. HeapFree(GetProcessHeap(), 0, lpAddrTable);
  172. return 0;
  173. }
  174. else {
  175. return ERROR_INVALID_PARAMETER;
  176. }
  177. }
  178. /*
  179. *------------------------------------------------------------------
  180. * Function: GetRouteTable
  181. *
  182. * Parameters:
  183. * LPIPROUTE_ENTRY
  184. * *lplpRouteTable pointer to an LPIPROUTE_ENTRY
  185. * which receives the routing table
  186. * LPDWORD lpdwRouteCount pointer to a DWORD which receives
  187. * the number of routing entries
  188. *
  189. * This function allocates and fills in an array of routing table
  190. * entries from the Tcpip driver. It also sets the number of
  191. * entries in the array in the DWORD pointed to by lpdwRouteCount.
  192. *
  193. * In the IPROUTE_ENTRY structure, the only metric used by
  194. * the Tcpip stack is IPROUTE_ENTRY.ire_metric1; the other metric
  195. * fields should be ignored.
  196. *
  197. * Call FreeRouteTable to free the memory allocated for the
  198. * routing table.
  199. *
  200. * It returns 0 if successful and non-zero otherwise
  201. *------------------------------------------------------------------
  202. */
  203. DWORD
  204. APIENTRY
  205. GetRouteTable(
  206. OUT LPIPROUTE_ENTRY *lplpRouteTable,
  207. OUT LPDWORD lpdwRouteCount
  208. )
  209. {
  210. ULONG_PTR *lpContext;
  211. IPSNMPInfo ipsiInfo;
  212. TDIObjectID *lpObject;
  213. DWORD dwRouteCount;
  214. LPIPROUTE_ENTRY lpRouteEntryTable;
  215. DWORD dwErr, dwInSize, dwOutSize;
  216. TCP_REQUEST_QUERY_INFORMATION_EX trqiBuffer;
  217. // first get route count
  218. dwInSize = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  219. dwOutSize = sizeof(IPSNMPInfo);
  220. lpContext = trqiBuffer.Context;
  221. ZeroMemory(lpContext, CONTEXT_SIZE);
  222. lpObject = &trqiBuffer.ID;
  223. lpObject->toi_id = IP_MIB_STATS_ID;
  224. lpObject->toi_type = INFO_TYPE_PROVIDER;
  225. lpObject->toi_class = INFO_CLASS_PROTOCOL;
  226. lpObject->toi_entity.tei_entity = CL_NL_ENTITY;
  227. lpObject->toi_entity.tei_instance = 0;
  228. RT_LOCK();
  229. dwErr = TCPQueryInformationEx(&trqiBuffer, &dwInSize,
  230. &ipsiInfo, &dwOutSize);
  231. RT_UNLOCK();
  232. if (dwErr != NO_ERROR || ipsiInfo.ipsi_numroutes == 0) {
  233. return dwErr;
  234. }
  235. dwRouteCount = ipsiInfo.ipsi_numroutes;
  236. // now get route table
  237. dwInSize = sizeof(TCP_REQUEST_QUERY_INFORMATION_EX);
  238. dwOutSize = dwRouteCount * sizeof(IPROUTE_ENTRY);
  239. lpRouteEntryTable = HeapAlloc(GetProcessHeap(), 0, dwOutSize);
  240. lpObject->toi_id = IP_MIB_RTTABLE_ENTRY_ID;
  241. lpObject->toi_class = INFO_CLASS_PROTOCOL;
  242. lpObject->toi_type = INFO_TYPE_PROVIDER;
  243. lpObject->toi_entity.tei_entity = CL_NL_ENTITY;
  244. lpObject->toi_entity.tei_instance = 0;
  245. RT_LOCK();
  246. dwErr = TCPQueryInformationEx(&trqiBuffer, &dwInSize,
  247. lpRouteEntryTable, &dwOutSize);
  248. RT_UNLOCK();
  249. if (dwErr != NO_ERROR) {
  250. HeapFree(GetProcessHeap(), 0, lpRouteEntryTable);
  251. return dwErr;
  252. }
  253. *lpdwRouteCount = dwRouteCount;
  254. *lplpRouteTable = lpRouteEntryTable;
  255. return 0;
  256. }
  257. /*
  258. *------------------------------------------------------------------
  259. * Function: FreeRouteTable
  260. *
  261. * Parameters:
  262. * LPIPROUTE_ENTRY
  263. * lpRouteTable the routing table to be freed.
  264. *
  265. * This function frees the memory allocated for a routing table.
  266. * It returns 0 if successful and non-zero otherwise.
  267. *------------------------------------------------------------------
  268. */
  269. DWORD
  270. APIENTRY
  271. FreeRouteTable(
  272. IN LPIPROUTE_ENTRY lpRouteTable
  273. )
  274. {
  275. if (lpRouteTable != NULL) {
  276. HeapFree(GetProcessHeap(), 0, lpRouteTable);
  277. return 0;
  278. }
  279. else {
  280. return ERROR_INVALID_PARAMETER;
  281. }
  282. }
  283. /*
  284. *------------------------------------------------------------------
  285. * Function: SetAddrChangeNotifyEvent
  286. *
  287. * Parameters:
  288. * HANDLE hEvent the event to be signalled if the
  289. * IP address of a local interface changes
  290. *
  291. * This function sets the event to be signalled if any IP address
  292. * for any interfaces is changed either via DHCP client activity
  293. * or manually in the Network Control Panel. This notification is
  294. * optional.
  295. *
  296. * Returns 0 if successful, non-zero otherwise.
  297. *------------------------------------------------------------------
  298. */
  299. DWORD
  300. APIENTRY
  301. SetAddrChangeNotifyEvent(
  302. HANDLE hEvent
  303. )
  304. {
  305. RT_LOCK();
  306. g_rtCfg.hUserNotifyEvent = hEvent;
  307. RT_UNLOCK();
  308. return 0;
  309. }
  310. DWORD UpdateRoute(DWORD dwProtocol, DWORD dwType, DWORD dwIndex,
  311. DWORD dwDestVal, DWORD dwMaskVal, DWORD dwGateVal,
  312. DWORD dwMetric, BOOL bAddRoute)
  313. {
  314. TDIObjectID *lpObject;
  315. IPRouteEntry *lpentry;
  316. DWORD dwErr, dwInSize, dwOutSize;
  317. TCP_REQUEST_SET_INFORMATION_EX *lptrsiBuffer;
  318. BYTE buffer[sizeof(TCP_REQUEST_SET_INFORMATION_EX) + sizeof(IPRouteEntry)];
  319. lptrsiBuffer = (TCP_REQUEST_SET_INFORMATION_EX *)buffer;
  320. lptrsiBuffer->BufferSize = sizeof(IPRouteEntry);
  321. lpObject = &lptrsiBuffer->ID;
  322. lpObject->toi_id = IP_MIB_RTTABLE_ENTRY_ID;
  323. lpObject->toi_type = INFO_TYPE_PROVIDER;
  324. lpObject->toi_class = INFO_CLASS_PROTOCOL;
  325. lpObject->toi_entity.tei_entity = CL_NL_ENTITY;
  326. lpObject->toi_entity.tei_instance = 0;
  327. lpentry = (IPRouteEntry *)lptrsiBuffer->Buffer;
  328. lpentry->ire_dest = dwDestVal;
  329. lpentry->ire_mask = dwMaskVal;
  330. lpentry->ire_index = dwIndex;
  331. lpentry->ire_metric1 = dwMetric;
  332. lpentry->ire_metric2 =
  333. lpentry->ire_metric3 =
  334. lpentry->ire_metric4 =
  335. lpentry->ire_metric5 = IRE_METRIC_UNUSED;
  336. lpentry->ire_nexthop = dwGateVal;
  337. lpentry->ire_type = (bAddRoute ? dwType : IRE_TYPE_INVALID);
  338. lpentry->ire_proto = dwProtocol;
  339. lpentry->ire_age = 0;
  340. dwOutSize = 0;
  341. dwInSize = sizeof(TCP_REQUEST_SET_INFORMATION_EX) +
  342. sizeof(IPRouteEntry) - 1;
  343. RT_LOCK();
  344. dwErr = TCPSetInformationEx((LPVOID)lptrsiBuffer, &dwInSize,
  345. NULL, &dwOutSize);
  346. RT_UNLOCK();
  347. return dwErr;
  348. }
  349. /*
  350. *------------------------------------------------------------------
  351. * Function: AddRoute
  352. *
  353. * Parameters:
  354. * DWORD dwProtocol protocol of specified route
  355. * DWORD dwType type of specified route
  356. * DWORD dwDestVal destination IP addr (network order)
  357. * DWORD dwMaskVal destination subnet mask, or zero
  358. * if no subnet (network order)
  359. * DWORD dwGateVal next hop IP addr (network order)
  360. * DWORD dwMetric metric
  361. *
  362. * This function adds a new route (or updates an existing route)
  363. * for the specified protocol, on the specified interface.
  364. * (See above for values which can be used as protocol numbers,
  365. * as well as values which can be used as route entry types.)
  366. *
  367. * Returns 0 if successful, non-zero otherwise.
  368. *------------------------------------------------------------------
  369. */
  370. DWORD
  371. APIENTRY
  372. AddRoute(
  373. IN DWORD dwProtocol,
  374. IN DWORD dwType,
  375. IN DWORD dwIndex,
  376. IN DWORD dwDestVal,
  377. IN DWORD dwMaskVal,
  378. IN DWORD dwGateVal,
  379. IN DWORD dwMetric
  380. )
  381. {
  382. return UpdateRoute(dwProtocol, dwType, dwIndex, dwDestVal,
  383. dwMaskVal, dwGateVal, dwMetric, TRUE);
  384. }
  385. /*
  386. *------------------------------------------------------------------
  387. * Function: DeleteRoute
  388. *
  389. * Parameters:
  390. * DWORD dwIndex index of interface to delete from
  391. * DWORD dwDestVal destination IP addr (network order)
  392. * DWORD dwMaskVal subnet mask (network order)
  393. * DWORD dwGateVal next hop IP addr (network order)
  394. *
  395. * This function deletes a route for the specified protocol.
  396. * See comments for AddRoute() for information on the use of
  397. * the argument dwMaskVal.
  398. *
  399. * Returns 0 if successful, non-zero otherwise.
  400. *------------------------------------------------------------------
  401. */
  402. DWORD
  403. APIENTRY
  404. DeleteRoute(
  405. IN DWORD dwIndex,
  406. IN DWORD dwDestVal,
  407. IN DWORD dwMaskVal,
  408. IN DWORD dwGateVal
  409. )
  410. {
  411. return UpdateRoute(IRE_PROTO_OTHER, IRE_TYPE_INVALID, dwIndex, dwDestVal,
  412. dwMaskVal, dwGateVal, IRE_METRIC_UNUSED, FALSE);
  413. }
  414. /*
  415. *------------------------------------------------------------------
  416. * Function: RefreshAddresses
  417. *
  418. * Parameters:
  419. *
  420. * This function is added for RSVP
  421. *
  422. * This function prods this code into refreshing its address tables with
  423. * the IP stack, just as if it had received a DHCP event notification.
  424. * This is needed because address change notifications coming through winsock
  425. * can arrive before the DHCP event has been set, which would normally cause
  426. * routetab to refresh its addresses.s
  427. *
  428. * Returns 0 if successful, non-zero otherwise.
  429. *------------------------------------------------------------------
  430. */
  431. DWORD
  432. APIENTRY
  433. RefreshAddresses(
  434. )
  435. {
  436. DWORD Error;
  437. Error = RTGetTables( &g_rtCfg.lpIfTable, &g_rtCfg.dwIfCount,
  438. &g_rtCfg.lpIPAddressTable, &g_rtCfg.dwIPAddressCount );
  439. return( Error );
  440. }
  441. //------------------------------------------------------------------
  442. // Function: OpenTcp
  443. //
  444. // Parameters:
  445. // none.
  446. //
  447. // Opens the handle to the Tcpip driver.
  448. //------------------------------------------------------------------
  449. DWORD OpenTcp()
  450. {
  451. #ifdef CHICAGO
  452. WSADATA wsaData;
  453. hWsock = LoadLibrary(TEXT("wsock32.dll"));
  454. if(! hWsock ){
  455. DEBUG_PRINT(("RTStartup: can't load wsock32.dll, %d\n",
  456. GetLastError()));
  457. DEBUG_PRINT(("OpenTcp: !hWsock\n"));
  458. return 1;
  459. }
  460. pWsControl = (LPWSCONTROL) GetProcAddress(hWsock, "WsControl");
  461. if (! pWsControl ){
  462. DEBUG_PRINT((
  463. "RTStartup: GetProcAddress(wsock32,WsControl) failed %d\n",
  464. GetLastError()));
  465. return 1;
  466. }
  467. if (WSAStartup(MAKEWORD(1, 1), &wsaData)) {
  468. DEBUG_PRINT((
  469. "RTStartup: error %d initializing Windows Sockets.",
  470. WSAGetLastError()));
  471. return 1;
  472. }
  473. return 0;
  474. #else
  475. NTSTATUS status;
  476. UNICODE_STRING nameString;
  477. IO_STATUS_BLOCK ioStatusBlock;
  478. OBJECT_ATTRIBUTES objectAttributes;
  479. // Open the ip stack for setting routes and parps later.
  480. //
  481. // Open a Handle to the TCP driver.
  482. //
  483. RtlInitUnicodeString(&nameString, DD_TCP_DEVICE_NAME);
  484. InitializeObjectAttributes(&objectAttributes, &nameString,
  485. OBJ_CASE_INSENSITIVE, NULL, NULL);
  486. status = NtCreateFile(&g_rtCfg.hTCPHandle,
  487. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  488. &objectAttributes, &ioStatusBlock, NULL,
  489. FILE_ATTRIBUTE_NORMAL,
  490. FILE_SHARE_READ | FILE_SHARE_WRITE,
  491. FILE_OPEN_IF, 0, NULL, 0);
  492. return (status == STATUS_SUCCESS ? 0 : ERROR_OPEN_FAILED);
  493. #endif
  494. }
  495. //---------------------------------------------------------------------
  496. // Function: TCPQueryInformationEx
  497. //
  498. // Parameters:
  499. // TDIObjectID *ID The TDI Object ID to query
  500. // void *Buffer buffer to contain the query results
  501. // LPDWORD *BufferSize pointer to the size of the buffer
  502. // filled in with the amount of data.
  503. // UCHAR *Context context value for the query. should
  504. // be zeroed for a new query. It will be
  505. // filled with context information for
  506. // linked enumeration queries.
  507. //
  508. // Returns:
  509. // An NTSTATUS value.
  510. //
  511. // This routine provides the interface to the TDI QueryInformationEx
  512. // facility of the TCP/IP stack on NT.
  513. //---------------------------------------------------------------------
  514. DWORD TCPQueryInformationEx(LPVOID lpvInBuffer, LPDWORD lpdwInSize,
  515. LPVOID lpvOutBuffer, LPDWORD lpdwOutSize)
  516. {
  517. #ifdef CHICAGO
  518. DWORD result;
  519. if( ! pWsControl )
  520. OpenTcp();
  521. if( ! pWsControl ){
  522. DEBUG_PRINT(("TCPQueryInformationEx: !pWsControl.\n"));
  523. return 0;
  524. }
  525. assert( pWsControl );
  526. result = (
  527. (*pWsControl)(
  528. IPPROTO_TCP,
  529. WSCNTL_TCPIP_QUERY_INFO,
  530. lpvInBuffer, // InBuf,
  531. lpdwInSize , // InBufLen,
  532. lpvOutBuffer, // OutBuf,
  533. lpdwOutSize // OutBufLen
  534. ) );
  535. return result;
  536. #else
  537. NTSTATUS status;
  538. IO_STATUS_BLOCK isbStatusBlock;
  539. if (g_rtCfg.hTCPHandle == NULL) {
  540. OpenTcp();
  541. }
  542. status = NtDeviceIoControlFile(g_rtCfg.hTCPHandle, // Driver handle
  543. NULL, // Event
  544. NULL, // APC Routine
  545. NULL, // APC context
  546. &isbStatusBlock, // Status block
  547. IOCTL_TCP_QUERY_INFORMATION_EX, // Control
  548. lpvInBuffer, // Input buffer
  549. *lpdwInSize, // Input buffer size
  550. lpvOutBuffer, // Output buffer
  551. *lpdwOutSize); // Output buffer size
  552. if (status == STATUS_PENDING) {
  553. status = NtWaitForSingleObject(g_rtCfg.hTCPHandle, TRUE, NULL);
  554. status = isbStatusBlock.Status;
  555. }
  556. if (status != STATUS_SUCCESS) {
  557. *lpdwOutSize = 0;
  558. }
  559. else {
  560. *lpdwOutSize = (ULONG)isbStatusBlock.Information;
  561. }
  562. return status;
  563. #endif
  564. }
  565. //---------------------------------------------------------------------------
  566. // Function: TCPSetInformationEx
  567. //
  568. // Parameters:
  569. //
  570. // TDIObjectID *ID the TDI Object ID to set
  571. // void *lpvBuffer data buffer containing the information
  572. // to be set
  573. // DWORD dwBufferSize the size of the data buffer.
  574. //
  575. // This routine provides the interface to the TDI SetInformationEx
  576. // facility of the TCP/IP stack on NT.
  577. //---------------------------------------------------------------------------
  578. DWORD TCPSetInformationEx(LPVOID lpvInBuffer, LPDWORD lpdwInSize,
  579. LPVOID lpvOutBuffer, LPDWORD lpdwOutSize)
  580. {
  581. #ifdef CHICAGO
  582. DWORD result;
  583. if( ! pWsControl )
  584. OpenTcp();
  585. if( ! pWsControl ){
  586. DEBUG_PRINT(("TCPSetInformationEx: !pWsControl \n"));
  587. return 0;
  588. }
  589. assert( pWsControl );
  590. result = (
  591. (*pWsControl)(
  592. IPPROTO_TCP,
  593. WSCNTL_TCPIP_SET_INFO,
  594. lpvInBuffer, // InBuf,
  595. lpdwInSize, // InBufLen,
  596. lpvOutBuffer, // OutBuf,
  597. lpdwOutSize // OutBufLen
  598. ) );
  599. return result;
  600. #else
  601. NTSTATUS status;
  602. IO_STATUS_BLOCK isbStatusBlock;
  603. if (g_rtCfg.hTCPHandle == NULL) {
  604. OpenTcp();
  605. }
  606. status = NtDeviceIoControlFile(g_rtCfg.hTCPHandle, // Driver handle
  607. NULL, // Event
  608. NULL, // APC Routine
  609. NULL, // APC context
  610. &isbStatusBlock, // Status block
  611. IOCTL_TCP_SET_INFORMATION_EX, // Control
  612. lpvInBuffer, // Input buffer
  613. *lpdwInSize, // Input buffer size
  614. lpvOutBuffer, // Output buffer
  615. *lpdwOutSize); // Output buffer size
  616. if (status == STATUS_PENDING) {
  617. status = NtWaitForSingleObject(g_rtCfg.hTCPHandle, TRUE, NULL);
  618. status = isbStatusBlock.Status;
  619. }
  620. if (status != STATUS_SUCCESS) {
  621. *lpdwOutSize = 0;
  622. }
  623. else {
  624. *lpdwOutSize = (ULONG)isbStatusBlock.Information;
  625. }
  626. return status;
  627. #endif
  628. }
  629.