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.

1176 lines
32 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. loader.cxx
  5. Abstract:
  6. Configuration and loading of RPC transports
  7. Revision History:
  8. MarioGo 03-18-96 Cloned from parts of old common.c
  9. MarioGo 10-31-96 Async RPC
  10. --*/
  11. #include <precomp.hxx>
  12. #include <loader.hxx>
  13. #include <trans.hxx>
  14. #include <cotrans.hxx>
  15. #include <dgtrans.hxx>
  16. #include <selbinding.hxx>
  17. extern "C" {
  18. #include <iphlpapi.h>
  19. }
  20. // Globals - see loader.hxx
  21. DWORD gdwComputerNameLength = 0;
  22. RPC_CHAR gpstrComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  23. UINT gPostSize = CO_MIN_RECV;
  24. #ifdef _INTERNAL_RPC_BUILD_
  25. RPCLT_PDU_FILTER_FUNC gpfnFilter = NULL;
  26. #endif
  27. //
  28. // Used to convert numbers to hex strings
  29. //
  30. const RPC_CHAR HexDigits[] =
  31. {
  32. RPC_CONST_CHAR('0'),
  33. RPC_CONST_CHAR('1'),
  34. RPC_CONST_CHAR('2'),
  35. RPC_CONST_CHAR('3'),
  36. RPC_CONST_CHAR('4'),
  37. RPC_CONST_CHAR('5'),
  38. RPC_CONST_CHAR('6'),
  39. RPC_CONST_CHAR('7'),
  40. RPC_CONST_CHAR('8'),
  41. RPC_CONST_CHAR('9'),
  42. RPC_CONST_CHAR('A'),
  43. RPC_CONST_CHAR('B'),
  44. RPC_CONST_CHAR('C'),
  45. RPC_CONST_CHAR('D'),
  46. RPC_CONST_CHAR('E'),
  47. RPC_CONST_CHAR('F')
  48. };
  49. // WARNING: The order of these protocols must be consistent with the
  50. // definition of PROTOCOL_ID.
  51. const
  52. TRANSPORT_TABLE_ENTRY TransportTable[] = {
  53. {
  54. 0,
  55. 0,
  56. 0
  57. },
  58. // TCP/IP
  59. {
  60. TCP_TOWER_ID,
  61. IP_ADDRESS_ID,
  62. (RPC_TRANSPORT_INTERFACE)&TCP_TransportInterface
  63. },
  64. #ifdef SPX_ON
  65. // SPX
  66. {
  67. SPX_TOWER_ID,
  68. IPX_ADDRESS_ID,
  69. (RPC_TRANSPORT_INTERFACE)&SPX_TransportInterface
  70. },
  71. #else
  72. {
  73. 0,
  74. 0,
  75. NULL
  76. },
  77. #endif
  78. // Named pipes
  79. {
  80. NMP_TOWER_ID,
  81. UNC_ADDRESS_ID,
  82. (RPC_TRANSPORT_INTERFACE)&NMP_TransportInterface
  83. },
  84. #ifdef NETBIOS_ON
  85. // Netbeui
  86. {
  87. NB_TOWER_ID,
  88. NBF_ADDRESS_ID,
  89. (RPC_TRANSPORT_INTERFACE)&NBF_TransportInterface
  90. },
  91. // Netbios over TCP/IP
  92. {
  93. NB_TOWER_ID,
  94. IP_ADDRESS_ID,
  95. (RPC_TRANSPORT_INTERFACE)&NBT_TransportInterface
  96. },
  97. // Netbios over IPX
  98. {
  99. NB_TOWER_ID,
  100. IPX_ADDRESS_ID,
  101. (RPC_TRANSPORT_INTERFACE)&NBI_TransportInterface
  102. },
  103. #else
  104. // Netbeui
  105. {
  106. 0,
  107. 0,
  108. NULL
  109. },
  110. // Netbios over TCP/IP
  111. {
  112. 0,
  113. 0,
  114. NULL
  115. },
  116. // Netbios over IPX
  117. {
  118. 0,
  119. 0,
  120. NULL
  121. },
  122. #endif
  123. #ifdef APPLETALK_ON
  124. // Appletalk Datastream protocol
  125. {
  126. DSP_TOWER_ID,
  127. NBP_ADDRESS_ID,
  128. (RPC_TRANSPORT_INTERFACE)&DSP_TransportInterface
  129. },
  130. #else
  131. // Appletalk Datastream protocol
  132. {
  133. 0,
  134. 0,
  135. NULL
  136. },
  137. #endif
  138. // Banyan Vines SSP
  139. {
  140. 0,
  141. 0,
  142. NULL
  143. },
  144. // Hyper-Text Tranfer Protocol (HTTP)
  145. {
  146. HTTP_TOWER_ID,
  147. HTTP_ADDRESS_ID,
  148. (RPC_TRANSPORT_INTERFACE)&HTTP_TransportInterface
  149. },
  150. // UDP/IP
  151. {
  152. UDP_TOWER_ID,
  153. IP_ADDRESS_ID,
  154. (RPC_TRANSPORT_INTERFACE)&UDP_TransportInterface
  155. },
  156. #ifdef IPX_ON
  157. // IPX
  158. {
  159. IPX_TOWER_ID,
  160. IPX_ADDRESS_ID,
  161. (RPC_TRANSPORT_INTERFACE)&IPX_TransportInterface
  162. },
  163. #else
  164. // IPX
  165. {
  166. 0,
  167. 0,
  168. 0
  169. },
  170. #endif
  171. // CDP/UDP/IP
  172. {
  173. CDP_TOWER_ID,
  174. IP_ADDRESS_ID,
  175. (RPC_TRANSPORT_INTERFACE)&CDP_TransportInterface
  176. },
  177. #ifdef NCADG_MQ_ON
  178. // MSMQ (Falcon/RPC)
  179. {
  180. MQ_TOWER_ID,
  181. MQ_ADDRESS_ID,
  182. (RPC_TRANSPORT_INTERFACE)&MQ_TransportInterface
  183. },
  184. #else
  185. // MSMQ (Falcon/RPC)
  186. {
  187. 0,
  188. 0,
  189. NULL
  190. },
  191. #endif
  192. // TCP over IPv6
  193. {
  194. TCP_TOWER_ID,
  195. IP_ADDRESS_ID,
  196. (RPC_TRANSPORT_INTERFACE)&TCP_TransportInterface
  197. },
  198. // HTTP2 - same as HTTP in terms of contents.
  199. {
  200. HTTP_TOWER_ID,
  201. HTTP_ADDRESS_ID,
  202. (RPC_TRANSPORT_INTERFACE)&HTTP_TransportInterface
  203. }
  204. };
  205. const DWORD cTransportTable = sizeof(TransportTable)/sizeof(TRANSPORT_TABLE_ENTRY);
  206. inline
  207. BOOL CompareProtseqs(
  208. IN const CHAR *p1,
  209. IN const RPC_CHAR *p2)
  210. // Note: protseqs use only ANSI characters so this is ok.
  211. {
  212. while(*p1)
  213. {
  214. if (*p1 != *p2)
  215. {
  216. return FALSE;
  217. }
  218. p1++;
  219. p2++;
  220. }
  221. return(*p2 == 0);
  222. }
  223. PROTOCOL_ID
  224. MapProtseq(
  225. IN const RPC_CHAR *RpcProtocolSequence
  226. )
  227. {
  228. PROTOCOL_ID index;
  229. for(index = 1; index < cTransportTable; index++)
  230. {
  231. if (TransportTable[index].pInfo != NULL)
  232. {
  233. if (RpcpStringCompare(RpcProtocolSequence,
  234. TransportTable[index].pInfo->ProtocolSequence) == 0)
  235. {
  236. return(index);
  237. }
  238. }
  239. }
  240. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  241. DPFLTR_WARNING_LEVEL,
  242. RPCTRANS "Called with unknown protseq %S\n",
  243. RpcProtocolSequence));
  244. ASSERT(0);
  245. return(0);
  246. }
  247. PROTOCOL_ID
  248. MapProtseq(
  249. IN const CHAR *RpcProtocolSequence
  250. )
  251. {
  252. PROTOCOL_ID index;
  253. for(index = 1; index < cTransportTable; index++)
  254. {
  255. if (TransportTable[index].pInfo != NULL)
  256. {
  257. if (CompareProtseqs(RpcProtocolSequence,
  258. TransportTable[index].pInfo->ProtocolSequence))
  259. {
  260. return(index);
  261. }
  262. }
  263. }
  264. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  265. DPFLTR_WARNING_LEVEL,
  266. RPCTRANS "Called with unknown protseq %S\n",
  267. RpcProtocolSequence));
  268. ASSERT(0);
  269. return(0);
  270. }
  271. // NB: must be called before RpcCompletionPort is zeroed out, because it is used for comparison
  272. void FreeCompletionPortHashTable(void)
  273. {
  274. DWORD i;
  275. HANDLE hCurrentHandle;
  276. // walk through the table, not closing if there is next entry, and it is the same as this
  277. for (i = 0; i < gNumberOfProcessors * 2; i ++)
  278. {
  279. hCurrentHandle = RpcCompletionPorts[i];
  280. if (hCurrentHandle && (hCurrentHandle != RpcCompletionPort))
  281. {
  282. CloseHandle(hCurrentHandle);
  283. }
  284. }
  285. }
  286. HANDLE GetCompletionPortHandleForThread(void)
  287. {
  288. DWORD i;
  289. DWORD nMinLoad = (DWORD) -1;
  290. int nMinLoadIndex = -1;
  291. for (i = 0; i < gNumberOfProcessors * 2; i ++)
  292. {
  293. if ((DWORD)CompletionPortHandleLoads[i] < nMinLoad)
  294. {
  295. nMinLoadIndex = i;
  296. nMinLoad = CompletionPortHandleLoads[i];
  297. }
  298. }
  299. ASSERT (nMinLoadIndex >= 0);
  300. InterlockedIncrement(&CompletionPortHandleLoads[nMinLoadIndex]);
  301. ASSERT(RpcCompletionPorts[nMinLoadIndex] != 0);
  302. return RpcCompletionPorts[nMinLoadIndex];
  303. }
  304. void ReleaseCompletionPortHandleForThread(HANDLE h)
  305. {
  306. DWORD i;
  307. for (i = 0; i < gNumberOfProcessors * 2; i ++)
  308. {
  309. if (h == RpcCompletionPorts[i])
  310. {
  311. InterlockedDecrement((long *)&CompletionPortHandleLoads[i]);
  312. ASSERT(CompletionPortHandleLoads[i] >= 0);
  313. return;
  314. }
  315. }
  316. ASSERT(0);
  317. }
  318. //
  319. // The firewall table settings:
  320. //
  321. // DoFirewallInit() initializes and updates the data structure.
  322. //
  323. // Syncronization needs are:
  324. // - DoFirewallInit() is not thread-safe and should execute inside a critical section.
  325. // - Access to pFirewallTable should be syncronized against update in DoFirewallInit().
  326. //
  327. // The rules are:
  328. // - The table is initialized during the first UseProtseq*. Subsequent UseProtseq*'s will be noops for
  329. // the initialized table.
  330. // - Update happens on PnP notification. The table gets re-created and replaced during an address change.
  331. // - Access happens on PnP notification and on UseProtseq* path.
  332. // - Access on PnP notification happens after the update to the table. Since a UseProtseq* call must have
  333. // been already made, this path does not have to syncronize against modification by UseProtseq*. Since
  334. // we are doing an access after updating the table, and PnP state change occurs within a critical section,
  335. // access on PnP event does not have to syncronize with anyone.
  336. // - Therefore we only need to syncronize the access on UseProtseq* agains an update on address change.
  337. // The access thread will make a local copy inside a mutex and the update will modify table inside a mutex.
  338. //
  339. FIREWALL_INFO *pFirewallTable = 0;
  340. // Set to TRUE when all interfaces have addresses assigned
  341. // and the table does not have un-initialized addresses.
  342. // Untill all interfaces get addresses, we will monitor for
  343. // address change.
  344. BOOL fFirewallTableFullyInitialized = FALSE;
  345. // The number of interfaces that have addresses assigned.
  346. DWORD FirewallTableNumActiveEntries = 0;
  347. // Has the firewall table been initialized.
  348. // We are protected by the GlobalMutex when we are in DoFirewallInit, so this is OK
  349. BOOL fFirewallInited = FALSE;
  350. typedef DWORD (*PGETIPADDRTABLE)
  351. (
  352. OUT PMIB_IPADDRTABLE pIpAddrTable,
  353. IN OUT PDWORD pdwSize,
  354. IN BOOL bOrder
  355. );
  356. DWORD
  357. GetIpAddrTableHelper(
  358. OUT PMIB_IPADDRTABLE *ppIpAddrTable
  359. )
  360. {
  361. HMODULE hDll;
  362. PGETIPADDRTABLE pGetIpAddrTable = NULL;
  363. DWORD dwSize, dwStatus;
  364. hDll = LoadLibrary(RPC_CONST_SSTRING("iphlpapi.dll"));
  365. if (hDll == 0)
  366. {
  367. return FALSE;
  368. }
  369. pGetIpAddrTable = (PGETIPADDRTABLE)GetProcAddress(hDll, "GetIpAddrTable");
  370. if (pGetIpAddrTable == 0)
  371. {
  372. FreeLibrary(hDll);
  373. return FALSE;
  374. }
  375. // Query for the size
  376. *ppIpAddrTable = NULL;
  377. dwSize = 0;
  378. dwStatus = pGetIpAddrTable(*ppIpAddrTable,
  379. &dwSize,
  380. TRUE);
  381. if (dwStatus != ERROR_INSUFFICIENT_BUFFER)
  382. {
  383. VALIDATE(dwStatus)
  384. {
  385. ERROR_OUTOFMEMORY
  386. } END_VALIDATE;
  387. FreeLibrary(hDll);
  388. return FALSE;
  389. }
  390. *ppIpAddrTable = (PMIB_IPADDRTABLE) new char [dwSize];
  391. if (*ppIpAddrTable == NULL)
  392. {
  393. FreeLibrary(hDll);
  394. return FALSE;
  395. }
  396. // Get the interfaces for the machine
  397. dwStatus = pGetIpAddrTable(*ppIpAddrTable,
  398. &dwSize,
  399. TRUE);
  400. FreeLibrary(hDll);
  401. if (dwStatus != ERROR_SUCCESS)
  402. {
  403. ASSERT(0);
  404. delete [] *ppIpAddrTable;
  405. return FALSE;
  406. }
  407. return TRUE;
  408. }
  409. BOOL
  410. ConvertAndSaveHelper(
  411. IN VER_INDICES_SETTINGS *Settings,
  412. IN PMIB_IPADDRTABLE IpAddrTable
  413. )
  414. {
  415. DWORD IdxToSubnetCnt = 0;
  416. LPDWORD SubnetArray = NULL;
  417. DWORD dwStatus = ERROR_SUCCESS;
  418. SubnetArray = new DWORD[IpAddrTable->dwNumEntries];
  419. if (SubnetArray == NULL)
  420. {
  421. return FALSE;
  422. }
  423. for (DWORD idx = 0; idx < IpAddrTable->dwNumEntries; idx++)
  424. {
  425. PMIB_IPADDRROW pRow = &IpAddrTable->table[idx];
  426. for (DWORD idx2 = 0; idx2 < Settings->dwCount; idx2++)
  427. {
  428. DWORD dwDeviceIndex = pRow->dwIndex;
  429. if (dwDeviceIndex == Settings->dwIndices[idx2])
  430. {
  431. SubnetArray[IdxToSubnetCnt] = pRow->dwAddr & pRow->dwMask;
  432. IdxToSubnetCnt++;
  433. break;
  434. }
  435. }
  436. }
  437. // We have the subnets based off the index settings, commit them as subnet settings
  438. if (IdxToSubnetCnt == 0)
  439. {
  440. (void) DeleteSelectiveBinding();
  441. }
  442. else
  443. {
  444. dwStatus = SetSelectiveBindingSubnets(IdxToSubnetCnt, SubnetArray, TRUE);
  445. VALIDATE(dwStatus)
  446. {
  447. ERROR_SUCCESS,
  448. ERROR_OUTOFMEMORY,
  449. ERROR_ACCESS_DENIED
  450. } END_VALIDATE;
  451. }
  452. delete [] SubnetArray;
  453. return (dwStatus == ERROR_SUCCESS);
  454. }
  455. BOOL
  456. DoFirewallInit (
  457. )
  458. /*++
  459. Routine Description:
  460. Initializes the firewall address table.
  461. Arguments:
  462. Return Value:
  463. TRUE - Initialization suceeded and pFirewallTable has been initialized or updated.
  464. FALSE - Initialization has failed and the table is in the state
  465. it was in prior to the call.
  466. --*/
  467. {
  468. DWORD dwStatus = ERROR_SUCCESS;
  469. DWORD dwSize = 1;
  470. LPVOID lpSettings = NULL;
  471. SB_VER sbVer = SB_VER_UNKNOWN;
  472. PMIB_IPADDRTABLE pIpAddrTable = NULL;
  473. FIREWALL_INFO *pNewFirewallTable = 0;
  474. #ifdef MAJOR_TRANS_DEBUG
  475. DbgPrint("RPC: DoFirewallInit\n");
  476. #endif
  477. // If we already initialized, then just return success
  478. if (fFirewallInited)
  479. {
  480. return TRUE;
  481. }
  482. // We will return from this loop if there are unknown settings (return with failure), if there
  483. // are default settings (return with success), or if there is a failure converting the indicies settings
  484. // to subnet settings.
  485. // We will break from this loop only when we have read in subnet settings (which means they were there originially
  486. // or we read in index settings, wrote them back out as subnet settings and then read the new subnet settings in.
  487. for(;;)
  488. {
  489. // Retrieve the selective binding setting from the registry.
  490. dwStatus = GetSelectiveBindingSettings(&sbVer, &dwSize, &lpSettings);
  491. if (dwStatus != ERROR_SUCCESS)
  492. {
  493. VALIDATE(dwStatus)
  494. {
  495. ERROR_OUTOFMEMORY
  496. } END_VALIDATE;
  497. return FALSE;
  498. }
  499. switch (sbVer)
  500. {
  501. case SB_VER_UNKNOWN:
  502. //this means the selective binding settings are corrupt, fatal failure
  503. delete [] pIpAddrTable;
  504. return FALSE;
  505. case SB_VER_DEFAULT:
  506. // pFirewallTable == NULL in the beginning, so there is nothign to be done in that case.
  507. // If we have already initialized the table, we can't delete it now since folks
  508. // may have references to it. We will just ignore the new settings.
  509. fFirewallInited = TRUE;
  510. delete [] pIpAddrTable;
  511. delete lpSettings;
  512. return TRUE;
  513. case SB_VER_INDICES:
  514. // We need to convert this to subnet settings and commit it to the registry
  515. // Get the pIpAddrTable. Note: The pIpAddrTable may not be avaliable if the system
  516. // is being installed, we assume that if there are selective binding settings in the registry
  517. // then the pIpAddrTable is avaliable.
  518. if (!GetIpAddrTableHelper(&pIpAddrTable))
  519. {
  520. delete lpSettings;
  521. return FALSE;
  522. }
  523. if (!ConvertAndSaveHelper((VER_INDICES_SETTINGS *)lpSettings, pIpAddrTable))
  524. {
  525. delete [] pIpAddrTable;
  526. delete lpSettings;
  527. return FALSE;
  528. }
  529. delete [] lpSettings;
  530. continue;
  531. case SB_VER_SUBNETS:
  532. break;
  533. default:
  534. ASSERT(0);
  535. delete [] pIpAddrTable;
  536. return FALSE;
  537. }
  538. break;
  539. }
  540. ASSERT(sbVer == SB_VER_SUBNETS);
  541. ASSERT(lpSettings != NULL);
  542. // If we didn't retrieve the Ip Address Table, get it now. We would have already retrieved it if we originally read in
  543. // index format settings.
  544. if (pIpAddrTable == NULL)
  545. {
  546. if (!GetIpAddrTableHelper(&pIpAddrTable))
  547. {
  548. return FALSE;
  549. }
  550. }
  551. // Allocate the subnet table, for simplicity allocate enough space to fit all the interfaces on the system
  552. // and a flag for each interface. The array of addresses and flags will follow the FIREWALL_INFO structure
  553. // in memory.
  554. // We are using the following procedure to update pFirewallTable:
  555. // Req: If the function fails, pFirewallTable is unchanged.
  556. // Req: If the function suceeds, pFirewallTable is updated to the new copy atomically.
  557. // Rule: Work on a temp copy of the firewall table without touching the original.
  558. // Rule: On sucess update the original.
  559. pNewFirewallTable = (FIREWALL_INFO*) new char[sizeof(FIREWALL_INFO)
  560. + sizeof(FIREWALL_INFO_ENTRY) * (pIpAddrTable->dwNumEntries - 1)];
  561. if (pNewFirewallTable == NULL)
  562. {
  563. delete [] pIpAddrTable;
  564. delete [] lpSettings;
  565. return FALSE;
  566. }
  567. pNewFirewallTable->NumAddresses = pIpAddrTable->dwNumEntries;
  568. // Step through the interfaces, add enabled interfaces to our firewall table
  569. // for subnets: if admit list: if the interface & mask is in the list of subnets
  570. // it is enabled. for deny list, if it is a member of any of the subnets
  571. // then it not enabled
  572. VER_SUBNETS_SETTINGS *pSubnetSettings = (VER_SUBNETS_SETTINGS*) lpSettings;
  573. for (DWORD idx = 0; idx < pIpAddrTable->dwNumEntries; idx++)
  574. {
  575. PMIB_IPADDRROW pRow = &pIpAddrTable->table[idx];
  576. BOOL bEnabled = !(pSubnetSettings->bAdmit);
  577. pNewFirewallTable->Entries[idx].Address = pRow->dwAddr;
  578. for (DWORD idx2 = 0; idx2 < pSubnetSettings->dwCount; idx2++)
  579. {
  580. DWORD dwSubnet = pRow->dwAddr & pRow->dwMask;
  581. if (dwSubnet == pSubnetSettings->dwSubnets[idx2])
  582. {
  583. bEnabled = pSubnetSettings->bAdmit;
  584. break;
  585. }
  586. }
  587. if (pNewFirewallTable->Entries[idx].Address == 0x0100007F){
  588. // The loopback address must always be enabled, regardless
  589. // of the selective binding settings.
  590. pNewFirewallTable->Entries[idx].fEnabled = TRUE;
  591. }
  592. else {
  593. pNewFirewallTable->Entries[idx].fEnabled = bEnabled;
  594. }
  595. }
  596. // If some interfaces have not yet been initialized and do not have an address,
  597. // mark them as such with the flag.
  598. // Un-initialized interfaces will have a NULL address in the table. This
  599. // may happen if a DHCP address has not yet been assigned to the corresponding NIC.
  600. // If there are no un-initialized interfaces left, the table is now fully initialized
  601. // and we will set fFirewallTableFullyInitialized.
  602. fFirewallTableFullyInitialized = TRUE;
  603. FirewallTableNumActiveEntries = 0;
  604. for (DWORD i = 0; i < pNewFirewallTable->NumAddresses; i++)
  605. {
  606. if (pNewFirewallTable->Entries[i].Address == NULL)
  607. {
  608. pNewFirewallTable->Entries[i].fInitialized = FALSE;
  609. fFirewallTableFullyInitialized = FALSE;
  610. }
  611. else
  612. {
  613. pNewFirewallTable->Entries[i].fInitialized = TRUE;
  614. if (pNewFirewallTable->Entries[i].fEnabled == TRUE)
  615. {
  616. FirewallTableNumActiveEntries++;
  617. }
  618. }
  619. }
  620. #ifdef MAJOR_TRANS_DEBUG
  621. DbgPrint("RPC: DoFirewallInit: pNewFirewallTable = 0x%x pNewFirewallTable->NumAddresses = 0x%x\n",
  622. pNewFirewallTable,
  623. pNewFirewallTable->NumAddresses
  624. );
  625. for (DWORD i = 0; i < pNewFirewallTable->NumAddresses; i++)
  626. {
  627. DbgPrint("RPC: DoFirewallInit: pNewFirewallTable->Entries[0x%x]: Address = 0x%x fInitialized = 0x%x fEnabled = 0x%x fNewAddress = 0x%x\n",
  628. i,
  629. pNewFirewallTable->Entries[i].Address,
  630. pNewFirewallTable->Entries[i].fInitialized,
  631. pNewFirewallTable->Entries[i].fEnabled,
  632. pNewFirewallTable->Entries[i].fNewAddress,
  633. );
  634. }
  635. DbgPrint("RPC: DoFirewallInit: Initialized pNewFirewallTable:\n");
  636. #endif
  637. // Figure out which addresses in the table are new ones.
  638. for (DWORD i = 0; i < pNewFirewallTable->NumAddresses; i++)
  639. {
  640. // If this is a new table then all addresses are new ones.
  641. if (pFirewallTable == NULL)
  642. {
  643. pNewFirewallTable->Entries[i].fNewAddress = TRUE;
  644. }
  645. else
  646. {
  647. // If we are updating the table, see if the address appeared some place
  648. // in the old table.
  649. pNewFirewallTable->Entries[i].fNewAddress = TRUE;
  650. for (DWORD j = 0; j < pFirewallTable->NumAddresses; j++)
  651. {
  652. // If it does, then this entry is not a new one.
  653. if (pNewFirewallTable->Entries[i].Address == pFirewallTable->Entries[j].Address)
  654. {
  655. pNewFirewallTable->Entries[i].fNewAddress = FALSE;
  656. }
  657. }
  658. }
  659. }
  660. // We have completed the initialization of pNewFirewallTable.
  661. // Replace the old copy of the table with the new one.
  662. delete [] pFirewallTable;
  663. pFirewallTable = pNewFirewallTable;
  664. fFirewallInited = TRUE;
  665. delete [] pIpAddrTable;
  666. delete [] lpSettings;
  667. return TRUE;
  668. }
  669. void
  670. DoFirewallUpdate (
  671. )
  672. /*++
  673. Routine Description:
  674. Updates the firewall address table and any addresses that have not
  675. yet been initialized.
  676. This function is called on an address change PnP event.
  677. We re-load the firewall address table and then scan all transport addresses.
  678. We initialize and listen on the addresses that received an IP address.
  679. Arguments:
  680. None
  681. Return Value:
  682. None
  683. --*/
  684. {
  685. BOOL fRes;
  686. BOOL fFirewallInitedSaved;
  687. // We have received a PnP event that signals an address change.
  688. // Re-initialize the firewall address table since it may now
  689. // have addresses assigned to interfaces that previously were
  690. // uninitialized.
  691. // DoFirewallInit() is not thread safe so we will take the global mutex.
  692. RequestGlobalMutex();
  693. // Remember the current state of the table.
  694. fFirewallInitedSaved = fFirewallInited;
  695. // Force an update to the table.
  696. fFirewallInited = FALSE;
  697. fRes = DoFirewallInit();
  698. // If the update has failed, we will continue using the old table, so
  699. // restore the flag. The call should have left the table untouched.
  700. if (fFirewallInitedSaved && !fFirewallInited)
  701. {
  702. fFirewallInited = TRUE;
  703. }
  704. ClearGlobalMutex();
  705. // If we could not update the firewall table, bail out.
  706. // The table should remain with the original entries and
  707. // we will not listen on the new or modified addresses.
  708. if (!fRes)
  709. {
  710. #ifdef DBG
  711. DbgPrint("RPC: Could not update pFirewallTable. The server may not listen on some interfaces.\n");
  712. #endif
  713. return;
  714. }
  715. // Go through the list of the available transport addresses, initialize them,
  716. // and make them listen on the new network address.
  717. GetTransportProtocol(TCP)->InitNewAddresses(TCP);
  718. }
  719. FIREWALL_INFO *
  720. GetFirewallTableCopy (
  721. void
  722. )
  723. /*++
  724. Routine Description:
  725. Allocates and returns a copy of the firewall table.
  726. The caller must free the table after finishing using it.
  727. The function must be protected against racing with DoFirewallInit().
  728. The function must be called after the table has been initialized.
  729. Arguments:
  730. None
  731. Return Value:
  732. Pointer to a copy of the firewall table.
  733. --*/
  734. {
  735. FIREWALL_INFO *pCopyOfFirewallTable = NULL;
  736. DWORD size;
  737. ASSERT(fFirewallInited);
  738. if (pFirewallTable == NULL)
  739. {
  740. return NULL;
  741. }
  742. size = sizeof(FIREWALL_INFO) + sizeof(FIREWALL_INFO_ENTRY) * (pFirewallTable->NumAddresses - 1);
  743. pCopyOfFirewallTable = (FIREWALL_INFO*) new char[size];
  744. if (pCopyOfFirewallTable == NULL)
  745. {
  746. return NULL;
  747. }
  748. RpcpMemoryCopy(pCopyOfFirewallTable, pFirewallTable, size);
  749. return pCopyOfFirewallTable;
  750. }
  751. RPC_TRANSPORT_INTERFACE
  752. TransportLoad (
  753. IN const RPC_CHAR * RpcProtocolSequence
  754. )
  755. {
  756. static fLoaded = FALSE;
  757. RPC_STATUS RpcStatus;
  758. PROTOCOL_ID index;
  759. RPC_STATUS status;
  760. RPC_TRANSPORT_INTERFACE pInfo;
  761. if (fLoaded == FALSE)
  762. {
  763. RpcStatus = InitTransportProtocols();
  764. if (RpcStatus != RPC_S_OK)
  765. return NULL;
  766. //
  767. // Query the computer name - used by most protocols.
  768. //
  769. gdwComputerNameLength = sizeof(gpstrComputerName)/sizeof(RPC_CHAR);
  770. if (!GetComputerName((RPC_SCHAR *)gpstrComputerName, &gdwComputerNameLength))
  771. {
  772. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  773. DPFLTR_WARNING_LEVEL,
  774. "RPCTRANS: GetComputerNameW failed: %d\n",
  775. GetLastError()));
  776. return(0);
  777. }
  778. gdwComputerNameLength++; // Include the null in the count.
  779. // Create initial IO completion port. This saves us from a race
  780. // assigning the global io completion port.
  781. ASSERT(RpcCompletionPort == 0);
  782. RpcCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,
  783. 0,
  784. 0,
  785. 0); // PERF REVIEW
  786. if (RpcCompletionPort == 0)
  787. {
  788. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  789. DPFLTR_WARNING_LEVEL, RPCTRANS "Failed to create initial completion port: %d\n",
  790. GetLastError()));
  791. return(0);
  792. }
  793. InactiveRpcCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,
  794. 0,
  795. 0,
  796. MAXULONG); // PERF REVIEW
  797. if (InactiveRpcCompletionPort == 0)
  798. {
  799. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  800. DPFLTR_WARNING_LEVEL, RPCTRANS "Failed to create initial completion port: %d\n",
  801. GetLastError()));
  802. CloseHandle(RpcCompletionPort);
  803. RpcCompletionPort = 0;
  804. return(0);
  805. }
  806. HANDLE hCurrentCompletionPortHandle;
  807. DWORD i;
  808. BOOL fSuccess = TRUE;
  809. HANDLE hSourceProcessHandle = GetCurrentProcess();
  810. RpcCompletionPorts = new HANDLE[gNumberOfProcessors * 2];
  811. CompletionPortHandleLoads = new long[gNumberOfProcessors * 2];
  812. if ((RpcCompletionPorts == NULL) || (CompletionPortHandleLoads == NULL))
  813. {
  814. CloseHandle(RpcCompletionPort);
  815. RpcCompletionPort = 0;
  816. return 0;
  817. }
  818. for (i = 0; i < gNumberOfProcessors * 2; i ++)
  819. {
  820. RpcCompletionPorts[i] = 0;
  821. CompletionPortHandleLoads[i] = 0;
  822. }
  823. RpcCompletionPorts[0] = RpcCompletionPort;
  824. for (i = 1; i < gNumberOfProcessors * 2; i ++)
  825. {
  826. fSuccess = DuplicateHandle(hSourceProcessHandle, RpcCompletionPort,
  827. hSourceProcessHandle, &hCurrentCompletionPortHandle, 0, FALSE, DUPLICATE_SAME_ACCESS);
  828. if (!fSuccess)
  829. break;
  830. ASSERT(hCurrentCompletionPortHandle != 0);
  831. RpcCompletionPorts[i] = hCurrentCompletionPortHandle;
  832. }
  833. if (!fSuccess)
  834. {
  835. FreeCompletionPortHashTable();
  836. CloseHandle(RpcCompletionPort);
  837. RpcCompletionPort = 0;
  838. return 0;
  839. }
  840. //
  841. // Initalize locks, use Rtl* so we don't need to catch exception.
  842. //
  843. NTSTATUS NtStatus;
  844. NtStatus = RtlInitializeCriticalSectionAndSpinCount(&AddressListLock, PREALLOCATE_EVENT_MASK);
  845. if (!NT_SUCCESS(NtStatus))
  846. {
  847. FreeCompletionPortHashTable();
  848. CloseHandle(RpcCompletionPort);
  849. RpcCompletionPort = 0;
  850. return 0;
  851. }
  852. if (gBCacheMode == BCacheModeDirect)
  853. {
  854. // allocate minimum post size. This guarantees that buffer
  855. // will always be at the end.
  856. gPostSize = sizeof(CONN_RPC_HEADER);
  857. }
  858. fLoaded = TRUE;
  859. }
  860. index = MapProtseq(RpcProtocolSequence);
  861. if (!index)
  862. {
  863. return(0);
  864. }
  865. pInfo = 0;
  866. switch (index)
  867. {
  868. case NMP:
  869. pInfo = (RPC_TRANSPORT_INTERFACE) NMP_TransportLoad();
  870. break;
  871. #ifdef NETBIOS_ON
  872. case NBF:
  873. case NBT:
  874. case NBI:
  875. pInfo = (RPC_TRANSPORT_INTERFACE) NB_TransportLoad(index);
  876. break;
  877. #endif
  878. case TCP:
  879. #ifdef SPX_ON
  880. case SPX:
  881. #endif
  882. #ifdef APPLETALK_ON
  883. case DSP:
  884. #endif
  885. case HTTP:
  886. pInfo = (RPC_TRANSPORT_INTERFACE) WS_TransportLoad(index);
  887. break;
  888. #ifdef NCADG_MQ_ON
  889. case MSMQ:
  890. #endif
  891. case CDP:
  892. case UDP:
  893. #ifdef IPX_ON
  894. case IPX:
  895. #endif
  896. pInfo = (RPC_TRANSPORT_INTERFACE) DG_TransportLoad(index);
  897. break;
  898. }
  899. if (pInfo == 0)
  900. {
  901. #ifdef UNICODE
  902. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  903. DPFLTR_WARNING_LEVEL,
  904. RPCTRANS "Load of %S failed\n",
  905. RpcProtocolSequence));
  906. #else
  907. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  908. DPFLTR_WARNING_LEVEL,
  909. RPCTRANS "Load of %s failed\n",
  910. RpcProtocolSequence));
  911. #endif
  912. return(0);
  913. }
  914. // When running with corruption injection for the client receives,
  915. // we may overwrite the default transport interfaces with costom Avrf versions.
  916. CORRUPTION_ASSERT(pInfo == TransportTable[index].pInfo);
  917. return(pInfo);
  918. }
  919. void
  920. UnjoinCompletionPort (
  921. void
  922. )
  923. {
  924. DWORD NumberOfBytes;
  925. ULONG_PTR CompletionKey;
  926. LPOVERLAPPED Overlapped;
  927. BOOL b;
  928. // The kernel today doesn't have the functionality to
  929. // unjoin a thread from a completion port. Therefore
  930. // we fake unjoining by joining another completion port which has
  931. // unlimited concurrency called the inactive completion port.
  932. // Thus threads unjoined from the main completion port will not
  933. // affect its concurrency. One undesirable effect is that each
  934. // time a thread joined to the inactive completion port blocks,
  935. // it will try to wake up another thread, and there won't be any
  936. // there, which is a waste of CPU. Ideally, we should have had
  937. // a capability to set KTHREAD::Queue to NULL, but we don't
  938. b = GetQueuedCompletionStatus(InactiveRpcCompletionPort,
  939. &NumberOfBytes,
  940. &CompletionKey,
  941. &Overlapped,
  942. 0
  943. );
  944. // this operation should either timeout or fail - it should never
  945. // succeed. If it does, this means somebody has erroneously posted
  946. // an IO on the inactive completion port
  947. ASSERT(b == FALSE);
  948. }
  949. void RPC_CLIENT_IP_ADDRESS::ZeroOut (
  950. void
  951. )
  952. /*++
  953. Routine Description:
  954. Create an empty IP address.
  955. Arguments:
  956. Return Value:
  957. --*/
  958. {
  959. SOCKADDR_IN *EmptyAddr = (SOCKADDR_IN *) Data;
  960. EmptyAddr->sin_family = AF_INET;
  961. EmptyAddr->sin_addr.S_un.S_addr = 0;
  962. EmptyAddr->sin_port = 0;
  963. RpcpMemorySet(&EmptyAddr->sin_zero, 0, sizeof(EmptyAddr->sin_zero));
  964. DataSize = 0;
  965. }
  966. #ifdef _INTERNAL_RPC_BUILD_
  967. void
  968. I_RpcltDebugSetPDUFilter (
  969. IN RPCLT_PDU_FILTER_FUNC pfnFilter
  970. )
  971. {
  972. gpfnFilter = pfnFilter;
  973. }
  974. #endif