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.

1562 lines
52 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. Protocol.cxx
  5. Abstract:
  6. Transport Protocol abstraction used mainly by PnP.
  7. The following is a brief description of the current RPC PnP mechanism:
  8. Whenever a non-local transport level object (a socket, or an address) is opened
  9. for a given protocol, it is added to the list of objects for the given protocol.
  10. This alllows all objects for a given protocol to be tracked down and closed if
  11. the protocol is unloaded. By the same token, objects closed are removed from
  12. the list of the given protocol.
  13. When a PnP notification arrives, the lower level transport code call into this PnP module
  14. to tell it that there may be a change of state. For each PnP protocol, the PnP code
  15. examines whether the protocol is active, and what was its last state. Depending of
  16. the outcome of this comparison, it will take appropriate action. Here's the finite
  17. state automaton with the transitions:
  18. Currently, RPC differentiates between four networking states of each protocol -
  19. protocol is not loaded, protocol is partially loaded (i.e. it is active, but
  20. does not have an address on it yet), it is fully loaded (or functional), and
  21. it is fully loaded and network address change monitoring is required. The
  22. fully loaded state with address change monitoring may be abbreviated to
  23. FunctionalMon for the purpose of this document.
  24. Note that Partially Loaded, and loaded without address are equivalent terms
  25. for the purpose of this module. Also, note that currently the networking
  26. code does not allow reloading of a protocol, so some of the code paths will
  27. never get exercised.
  28. RPC in turn maintains the following RPC (as opposed to networking) states:
  29. ProtocolNotLoaded
  30. ProtocolLoadedWithoutAddress
  31. ProtocolWasLoadedOrNeedsActivation
  32. ProtocolLoaded
  33. ProtocolWasLoadedOrNeedsActivationWithoutAddress
  34. ProtocolLoadedAndMonitored
  35. Depending on the last RPC state, and the new networking state, the following changes
  36. and state transitions are effected:
  37. If a PnP notification fails asynchronously, the completion port code will call into PnP
  38. code to try to resubmit the queries.
  39. Note that the threads on which overlapped WSAIoctl's are submitted are not protected.
  40. If a thread dies, the IO will fail, and the thread that picks the failure will resubmit
  41. the WSAIoctl. This strategy allows up to keep the thread pool smaller.
  42. Networking State Action
  43. RPC State
  44. ProtocolNotLoaded NotLoaded No-op
  45. PartiallyLoaded Submit a WSAIoctl to be notified
  46. when the protocol becomes
  47. functional.
  48. State = ProtocolLoadedWithoutAddress
  49. Functional State = ProtocolLoaded
  50. FunctionalMon Submit address change WSAIoctl.
  51. State = ProtocolLoadedAndMonitored
  52. ProtocolLoadedWithoutAddress NotLoaded Cancel WSAIoctl
  53. State = ProtocolNotLoaded
  54. PartiallyLoaded No-op
  55. Functional CancelWSAIoctl
  56. State = ProtocolLoaded
  57. FunctionalMon Submit address change WSAIoctl if necessary
  58. State = ProtocolLoadedAndMonitored
  59. ProtocolWasLoadedOrNeedsActivation NotLoaded No-op
  60. PartiallyLoaded Submit a WSAIoctl to be notified
  61. when the protocol becomes
  62. functional.
  63. State = ProtocolWasLoadedOrNeedsActivationWithoutAddress
  64. Functional Restart protocol
  65. State = ProtocolLoaded
  66. FunctionalMon Submit address change WSAIoctl.
  67. State = ProtocolLoadedAndMonitored
  68. ProtocolLoaded NotLoaded Unload protocol
  69. State = ProtocolWasLoadedOrNeedsActivation
  70. PartiallyLoaded Invalid
  71. Functional No-op
  72. FunctionalMon Invalid transition
  73. ProtocolWasLoadedOrNeedsActivationWithoutAddress
  74. NotLoaded Cancel WSAIoctl
  75. State = ProtocolWasLoadedOrNeedsActivation
  76. PartiallyLoaded No-op
  77. Functional Restart protocol
  78. State = ProtocolLoaded
  79. FunctionalMon Submit address change WSAIoctl.
  80. State = ProtocolLoadedAndMonitored
  81. ProtocolLoadedAndMonitored NotLoaded Cancel address change WSAIoctl
  82. Unload protocol
  83. State = ProtocolWasLoadedOrNeedsActivation
  84. PartiallyLoaded Resubmit address change WSAIoclt if necessary
  85. Functional Invalid transition
  86. FunctionalMon No-op
  87. ProtocolNeedToLoadWhenReady NotLoaded No-op
  88. PartiallyLoaded Submit a WSAIoctl to be notified
  89. when the protocol becomes
  90. functional.
  91. State = ProtocolNeedToLoadWhenReadyWithoutAddress
  92. Functional Restart protocol
  93. State = ProtocolLoaded
  94. FunctionalMon Submit address change WSAIoctl.
  95. State = ProtocolLoadedAndMonitored
  96. ProtocolNeedToLoadWhenReadyWithoutAddress
  97. NotLoaded Cancel WSAIoctl
  98. State = ProtocolNeedToLoadWhenReady
  99. PartiallyLoaded No-op
  100. Functional Restart protocol
  101. State = ProtocolLoaded
  102. FunctionalMon Submit address change WSAIoctl.
  103. State = ProtocolLoadedAndMonitored
  104. Author:
  105. Kamen Moutafov [KamenM]
  106. Revision History:
  107. KamenM 12/22/1998 Creation
  108. KamenM 03/05/1999 Adding state ProtocolLoadedAndMonitored and support for it.
  109. KamenM 07/17/2000 Adding support for ProtocolWasLoadedOrNeedsActivation/
  110. ProtocolWasLoadedOrNeedsActivationWithoutAddress
  111. --*/
  112. #include <precomp.hxx>
  113. #include <Protocol.hxx>
  114. void RPC_ENTRY NullAddressChangeFn( PVOID arg )
  115. {
  116. }
  117. RPC_ADDRESS_CHANGE_FN * AddressChangeFn = NullAddressChangeFn;
  118. #ifdef MAJOR_PNP_DEBUG
  119. const char *ProtocolStateNames[];
  120. #endif
  121. void TransportProtocol::DetectedAsFunctional(PROTOCOL_ID ProtocolId)
  122. {
  123. if (IsAddressChangeMonitoringOn(ProtocolId))
  124. {
  125. EnterCriticalSection(&AddressListLock);
  126. // monitor functional protocols for address change will
  127. // set the state
  128. MonitorFunctionalProtocolForAddressChange(ProtocolId);
  129. LeaveCriticalSection(&AddressListLock);
  130. }
  131. else
  132. {
  133. // we also need to take the critical section, and cancel any address change
  134. // notification (if any), to avoid race between a successful listen making
  135. // the protocol functional, and the address change notification completing
  136. EnterCriticalSection(&AddressListLock);
  137. CancelAddressChangeRequestIfNecessary(FALSE, ProtocolId);
  138. SetState(ProtocolLoaded, ProtocolId);
  139. LeaveCriticalSection(&AddressListLock);
  140. }
  141. }
  142. void TransportProtocol::HandleProtocolChange(IN WSAPROTOCOL_INFO *lpProtocolBuffer,
  143. IN int ProtocolCount,
  144. IN PROTOCOL_ID thisProtocolId)
  145. /*++
  146. Function Name: HandleProtocolChange
  147. Parameters:
  148. lpProtocolBuffer - an array of WSAPROTOCOL_INFO structures as returned by EnumProtocols
  149. ProtocolCount - the number of elements in the lpProtocolBuffer array
  150. thisProtocolId - the ID of the protocol for this object
  151. Description:
  152. This handles protocol state change for a particular protocol. The function is idempotent - it
  153. can be called many times safely, regardless of previous calls. It will turn into no-op if
  154. it is redundant.
  155. Returns:
  156. --*/
  157. {
  158. int i;
  159. BOOL fProtocolActive = FALSE;
  160. const WS_TRANS_INFO *pInfo;
  161. ASSERT(ProtocolCount >= 0);
  162. ASSERT(lpProtocolBuffer != NULL);
  163. ASSERT_TRANSPORT_PROTOCOL_STATE(thisProtocolId);
  164. if (
  165. #ifdef NETBIOS_ON
  166. (thisProtocolId == NBF) || (thisProtocolId == NBT) || (thisProtocolId == NBI) ||
  167. #endif
  168. #ifdef NCADG_MQ_ON
  169. (thisProtocolId == MSMQ) ||
  170. #endif
  171. (thisProtocolId == CDP)
  172. )
  173. return;
  174. if (IsTrailingProtocol(thisProtocolId))
  175. return;
  176. for (i = 0; i < ProtocolCount; i ++)
  177. {
  178. // if the enumerated protocol is the current protocol, break out of the loop
  179. if (MapProtocolId(lpProtocolBuffer[i].iProtocol, lpProtocolBuffer[i].iAddressFamily) == thisProtocolId)
  180. {
  181. fProtocolActive = TRUE;
  182. break;
  183. }
  184. }
  185. pInfo = &WsTransportTable[thisProtocolId];
  186. switch(State)
  187. {
  188. case ProtocolNotLoaded:
  189. case ProtocolLoadedWithoutAddress:
  190. // if the protocol was not loaded, but now it is active, attempt to verify
  191. // it is operational
  192. if (fProtocolActive)
  193. {
  194. #ifdef MAJOR_PNP_DEBUG
  195. if (State == ProtocolNotLoaded)
  196. {
  197. DbgPrint("Protocol %d was just loaded\n", thisProtocolId);
  198. }
  199. #endif
  200. // If the protocol is not fully functional, we will submit an address change
  201. // request to get notified when it does
  202. if (VerifyProtocolIsFunctional(thisProtocolId) == TRUE)
  203. {
  204. // we succeeded in changing the state of the protocol
  205. ASSERT((State == ProtocolLoaded) || (State == ProtocolLoadedAndMonitored));
  206. if (IsAddressChangeMonitoringOn(thisProtocolId))
  207. {
  208. if (FirewallTableNeedsUpdating())
  209. {
  210. DoFirewallUpdate();
  211. }
  212. // If the only reason we were monitoring this protocol
  213. // is to finish initializing the firewall table, then
  214. // we may not continue monitoring for address change if
  215. // the table has finished initializing after DoFirewallUpdate().
  216. if(IsAddressChangeMonitoringOn(thisProtocolId))
  217. {
  218. MonitorFunctionalProtocolForAddressChange(thisProtocolId);
  219. }
  220. if (IsAddressChangeFnDefined())
  221. {
  222. (*AddressChangeFn)((PVOID) State);
  223. }
  224. }
  225. }
  226. #ifdef MAJOR_PNP_DEBUG
  227. if (State == ProtocolLoadedWithoutAddress)
  228. {
  229. DbgPrint("Protocol %d was without an address\n", thisProtocolId);
  230. }
  231. #endif
  232. }
  233. else
  234. {
  235. if (State == ProtocolLoadedWithoutAddress)
  236. {
  237. // a protocol was removed without being fully initialized
  238. // cancel the pending query if any, and reset the state to not loaded
  239. CancelAddressChangeRequestIfNecessary(TRUE, thisProtocolId);
  240. SetState(ProtocolNotLoaded, thisProtocolId);
  241. #ifdef MAJOR_PNP_DEBUG
  242. DbgPrint("Protocol %d was removed without being fully initialized\n", thisProtocolId);
  243. #endif
  244. }
  245. // else - don't care. The protocol state is not loaded, and will remain so
  246. }
  247. break;
  248. case ProtocolWasLoadedOrNeedsActivation:
  249. case ProtocolWasLoadedOrNeedsActivationWithoutAddress:
  250. if (fProtocolActive)
  251. {
  252. // If the protocol is not fully functional, we will submit an address change
  253. // request to get notified when it does
  254. if (VerifyProtocolIsFunctional(thisProtocolId))
  255. {
  256. // if a protocol was loaded, and now is active, restart the addresses on it
  257. RestartProtocol(thisProtocolId);
  258. if (thisProtocolId == TCP)
  259. {
  260. GetTransportProtocol(HTTP)->RestartProtocol(HTTP);
  261. }
  262. // we succeeded in changing the state of the protocol
  263. ASSERT(State == ProtocolLoaded);
  264. if (IsAddressChangeMonitoringOn(thisProtocolId))
  265. {
  266. MonitorFunctionalProtocolForAddressChange(thisProtocolId);
  267. }
  268. }
  269. }
  270. else
  271. {
  272. // if the protocol was loaded, but it's not active, we don't care;
  273. // if it was trying to get an address, but then it was unloaded,
  274. // cancel the request
  275. if (State == ProtocolWasLoadedOrNeedsActivationWithoutAddress)
  276. {
  277. CancelAddressChangeRequestIfNecessary(TRUE, thisProtocolId);
  278. SetState(ProtocolWasLoadedOrNeedsActivation, thisProtocolId);
  279. #ifdef MAJOR_PNP_DEBUG
  280. DbgPrint("Protocol %d was removed without being fully initialized\n", thisProtocolId);
  281. #endif
  282. }
  283. }
  284. break;
  285. case ProtocolLoaded:
  286. ASSERT(IsAddressChangeMonitoringOn(thisProtocolId) == FALSE);
  287. // if the protocol was loaded, and it is active, we don't need to do anything;
  288. // if it was loaded, but is not active currently, we need to unload the protocol
  289. if (!fProtocolActive)
  290. {
  291. #ifdef MAJOR_PNP_DEBUG
  292. DbgPrint("Protocol %d was just unloaded\n", thisProtocolId);
  293. #endif
  294. UnloadProtocol(thisProtocolId);
  295. if (thisProtocolId == TCP)
  296. {
  297. GetTransportProtocol(HTTP)->UnloadProtocol(HTTP);
  298. }
  299. SetState(ProtocolWasLoadedOrNeedsActivation, thisProtocolId);
  300. }
  301. break;
  302. case ProtocolLoadedAndMonitored:
  303. // if it was loaded, but is not active currently, we need to unload the protocol
  304. if (!fProtocolActive)
  305. {
  306. #ifdef MAJOR_PNP_DEBUG
  307. DbgPrint("Protocol %d was just unloaded\n", thisProtocolId);
  308. #endif
  309. if (FirewallTableNeedsUpdating())
  310. {
  311. DoFirewallUpdate();
  312. }
  313. CancelAddressChangeRequestIfNecessary(TRUE, thisProtocolId);
  314. UnloadProtocol(thisProtocolId);
  315. if (thisProtocolId == TCP)
  316. {
  317. GetTransportProtocol(HTTP)->UnloadProtocol(HTTP);
  318. }
  319. SetState(ProtocolWasLoadedOrNeedsActivation, thisProtocolId);
  320. if (IsAddressChangeFnDefined())
  321. {
  322. (*AddressChangeFn)((PVOID) State);
  323. }
  324. }
  325. else
  326. {
  327. #ifdef MAJOR_PNP_DEBUG
  328. DbgPrint("Protocol %d is monitored and received event\n", thisProtocolId);
  329. #endif
  330. if (FirewallTableNeedsUpdating())
  331. {
  332. DoFirewallUpdate();
  333. }
  334. if (IsAddressChangeFnDefined())
  335. {
  336. (*AddressChangeFn)((PVOID) State);
  337. }
  338. }
  339. break;
  340. #if defined(DBG) || defined(_DEBUG)
  341. default:
  342. ASSERT(!"Invalid State");
  343. #endif
  344. }
  345. ASSERT_TRANSPORT_PROTOCOL_STATE(thisProtocolId);
  346. }
  347. void TransportProtocol::AddObjectToList(IN OUT BASE_ASYNC_OBJECT *pObj)
  348. /*++
  349. Function Name: AddObjectToList
  350. Parameters:
  351. pObj - the object to be added
  352. Description:
  353. Add the object to the list of transport objects for this protocol.
  354. Returns:
  355. --*/
  356. {
  357. EnterCriticalSection(&AddressListLock);
  358. RpcpfInsertHeadList(&ObjectList, &pObj->ObjectList);
  359. LeaveCriticalSection(&AddressListLock);
  360. }
  361. void TransportProtocol::RemoveObjectFromList(IN OUT BASE_ASYNC_OBJECT *pObj)
  362. /*++
  363. Function Name: RemoveObjectFromList
  364. Parameters:
  365. pObj - the object to be removed
  366. Description:
  367. Removes the object from the list of transport objects for this protocol.
  368. Returns:
  369. --*/
  370. {
  371. BASE_ASYNC_OBJECT *Prev, *Cur;
  372. Prev = NULL;
  373. EnterCriticalSection(&AddressListLock);
  374. RpcpfRemoveEntryList(&pObj->ObjectList);
  375. LeaveCriticalSection(&AddressListLock);
  376. }
  377. BOOL TransportProtocol::ResubmitQueriesIfNecessary(PROTOCOL_ID ProtocolId)
  378. /*++
  379. Function Name: ResubmitQueriesIfNecessary
  380. Parameters:
  381. ProtocolId - the ID of the current protocol
  382. Description:
  383. If there was a WSAIoctl pending that failed, it will be resubmitted.
  384. If this protocol was being monitored, try to restart monitoring if necessary
  385. Returns:
  386. FALSE if the WSAIoctl was not resubmitted successfully.
  387. TRUE if the WSAIoctl was resubmitted successfully, or there was no need to resubmit it.
  388. --*/
  389. {
  390. if (addressChangeSocket)
  391. {
  392. if ((addressChangeOverlapped.Internal != 0) && (addressChangeOverlapped.Internal != STATUS_PENDING))
  393. {
  394. if (SubmitAddressChangeQuery() == FALSE)
  395. return FALSE;
  396. }
  397. }
  398. if (State == ProtocolLoadedAndMonitored)
  399. {
  400. if (MonitorFunctionalProtocolForAddressChange(ProtocolId) == FALSE)
  401. return FALSE;
  402. }
  403. return TRUE;
  404. }
  405. PROTOCOL_ID
  406. MapProtocolId (
  407. IN UINT ProtocolId,
  408. IN UINT AddressFamily
  409. )
  410. /*++
  411. Function Name: MapProtocolId
  412. Parameters:
  413. ProtocolId - Winsock protocol ID
  414. AddressFamily - Winsock address family
  415. Description:
  416. Converts a Winsock Protocol ID to a RPC Transport protocol ID.
  417. Returns:
  418. The RPC Transport Protocol ID if successfull, or -1 if no mapping can be found
  419. --*/
  420. {
  421. unsigned id;
  422. for (id = 1; id < cWsTransportTable; id++)
  423. {
  424. if ((WsTransportTable[id].Protocol == (int) ProtocolId)
  425. && (WsTransportTable[id].AddressFamily == (int) AddressFamily))
  426. {
  427. return id;
  428. }
  429. }
  430. return -1;
  431. }
  432. BOOL TransportProtocol::HandlePnPStateChange(void)
  433. /*++
  434. Function Name: HandlePnPNotification
  435. Parameters:
  436. Description:
  437. Whenever a PnP notification (NewAddress) arrives, the completion port will direct it
  438. to this routine, which will handle all state management and all handling of the PnP
  439. notification.
  440. Returns:
  441. TRUE if the runtime should be notified that a protocol state change has occurred.
  442. FALSE if the run time should not be notified, or need not be notified that a
  443. protocol state change has occurred.
  444. --*/
  445. {
  446. int i;
  447. //
  448. // Enumerate the currently loaded protocols
  449. //
  450. WSAPROTOCOL_INFO *lpProtocolBuffer;
  451. DWORD dwBufferLength = 512;
  452. int ProtocolCount;
  453. PROTOCOL_ID ProtocolId;
  454. TransportProtocol *pCurrentProtocol;
  455. BOOL fRetVal;
  456. EnterCriticalSection(&AddressListLock);
  457. ASSERT(hWinsock2);
  458. while (1)
  459. {
  460. lpProtocolBuffer = (WSAPROTOCOL_INFO *) I_RpcAllocate(dwBufferLength);
  461. if (lpProtocolBuffer == 0)
  462. {
  463. fRetVal = FALSE;
  464. goto CleanupAndReturn;
  465. }
  466. ProtocolCount = WSAEnumProtocolsT(
  467. 0,
  468. lpProtocolBuffer,
  469. &dwBufferLength
  470. );
  471. if (ProtocolCount != SOCKET_ERROR)
  472. {
  473. break;
  474. }
  475. I_RpcFree(lpProtocolBuffer);
  476. if (GetLastError() != WSAENOBUFS)
  477. {
  478. fRetVal = FALSE;
  479. goto CleanupAndReturn;
  480. }
  481. }
  482. for (i = 1; i < MAX_PROTOCOLS; i++)
  483. {
  484. pCurrentProtocol = GetTransportProtocol(i);
  485. pCurrentProtocol->HandleProtocolChange(lpProtocolBuffer, ProtocolCount, i);
  486. }
  487. I_RpcFree(lpProtocolBuffer);
  488. fRetVal = g_NotifyRt;
  489. CleanupAndReturn:
  490. LeaveCriticalSection(&AddressListLock);
  491. #ifdef MAJOR_PNP_DEBUG
  492. DumpProtocolState();
  493. #endif
  494. return fRetVal;
  495. }
  496. BOOL TransportProtocol::ResubmitQueriesIfNecessary(void)
  497. /*++
  498. Function Name: ResubmitQueriesIfNecessary
  499. Parameters:
  500. Description:
  501. Iterates through all protocols and calls their ResubmitQueriesIfNecessary
  502. Returns:
  503. FALSE if at least one protocol needed to resubmit a query, but failed to do so
  504. TRUE otherwise
  505. --*/
  506. {
  507. int i;
  508. BOOL fAllResubmitsSucceeded = TRUE;
  509. TransportProtocol *pCurrentProtocol;
  510. #ifdef MAJOR_PNP_DEBUG
  511. DbgPrint("Resubmitting queries for process %d\n", GetCurrentProcessId());
  512. #endif
  513. EnterCriticalSection(&AddressListLock);
  514. for (i = 1; i < MAX_PROTOCOLS; i++)
  515. {
  516. pCurrentProtocol = GetTransportProtocol(i);
  517. if (!pCurrentProtocol->ResubmitQueriesIfNecessary(i))
  518. fAllResubmitsSucceeded = FALSE;
  519. }
  520. LeaveCriticalSection(&AddressListLock);
  521. return fAllResubmitsSucceeded;
  522. }
  523. void TransportProtocol::AddObjectToProtocolList(BASE_ASYNC_OBJECT *pObj)
  524. {
  525. GetTransportProtocol(pObj->id)->AddObjectToList(pObj);
  526. }
  527. #if defined(DBG) || defined(_DEBUG)
  528. void TransportProtocol::AssertProtocolListIntegrity(IN BASE_ASYNC_OBJECT *pObj)
  529. {
  530. GetTransportProtocol(pObj->id)->AssertListIntegrity(pObj->id);
  531. }
  532. #endif // DBG || _DEBUG
  533. void TransportProtocol::RemoveObjectFromProtocolList(IN OUT BASE_ASYNC_OBJECT *pObj)
  534. {
  535. // in some cases, we can legally have the id set to INVALID_PROTOCOL_ID
  536. // this happens when we have initialized the connection, but have failed
  537. // before calling Open on it, and then we attempt to destroy it
  538. if (pObj->id != INVALID_PROTOCOL_ID)
  539. {
  540. GetTransportProtocol(pObj->id)->RemoveObjectFromList(pObj);
  541. }
  542. }
  543. BOOL TransportProtocol::VerifyProtocolIsFunctional(IN PROTOCOL_ID ProtocolId)
  544. /*++
  545. Function Name: VerifyProtocolIsFunctional
  546. Parameters: ProtocolId - the protocol which we're attempting to verify as functional or not
  547. Description: Tries to find out the listening address for a loaded protocol. The address
  548. itself is not used anywhere. It just testifies that the protocol is fully operational.
  549. Depending on how far it gets with testing whether the protocol is operational,
  550. it will change the State to ProtocolLoaded, ProtocolLoadedWithoutAddress or
  551. ProtocolWasLoadedOrNeedsActivationWithoutAddress. It will return TRUE iff the state is moved to
  552. ProtocolLoaded.
  553. Returns: TRUE if the address was found and the protocol was fully operational
  554. FALSE if the address could not be found, and the protocol is not
  555. fully operational. Note that there are two subcases here. One is when
  556. the protocol is not operational (or we cannot confirm that for lack of
  557. resources for example) and it has no sign of becoming operational. The
  558. second is when the protocol is not operational, but there are chances of
  559. it becoming operational. This happens with protocols that take some
  560. time to initialize. In the second case, this function will arrange for
  561. a retry attempt by posting an async WSAIoctl request to the completion
  562. port. In the current code base, we don't differentiate between the two
  563. cases because we don't need to. We may need to do so in the future.
  564. --*/
  565. {
  566. ASSERT((State == ProtocolNotLoaded)
  567. || (State == ProtocolWasLoadedOrNeedsActivation)
  568. || (State == ProtocolLoadedWithoutAddress)
  569. || (State == ProtocolWasLoadedOrNeedsActivationWithoutAddress));
  570. ASSERT_TRANSPORT_PROTOCOL_STATE(ProtocolId);
  571. if (OpenAddressChangeRequestSocket(ProtocolId) == FALSE)
  572. goto AbortAndCleanup;
  573. // if the socket already has an address, skip further checks
  574. // NOTE: this check provides a fast way to check initialization state of
  575. // protocols that initialize quickly, but more importantly, it provides a
  576. // handling path for protocols that have submitted an address list change query
  577. // and now are getting back the result
  578. if (DoesAddressSocketHaveAddress())
  579. {
  580. #ifdef MAJOR_PNP_DEBUG
  581. DbgPrint("Protocol %d is functional (1)\n", ProtocolId);
  582. #endif
  583. CancelAddressChangeRequestIfNecessary(FALSE, ProtocolId);
  584. SetStateToLoadedAndMonitorProtocolIfNecessary(ProtocolId);
  585. ASSERT_TRANSPORT_PROTOCOL_STATE(ProtocolId);
  586. return TRUE;
  587. }
  588. // if there isn't a pending request, and there isn't a successful request (i.e. there is either
  589. // a failed request, or no request has been submitted so far)
  590. if ((addressChangeOverlapped.Internal != 0) && (addressChangeOverlapped.Internal != STATUS_PENDING))
  591. {
  592. #ifdef MAJOR_PNP_DEBUG
  593. DbgPrint("Submitting WSAIoclt for protocol %d\n", ProtocolId);
  594. #endif
  595. if (!SubmitAddressChangeQuery())
  596. goto AbortAndCleanup;
  597. }
  598. // check once more whether we have address - this takes care of the race where the
  599. // address did arrive between the time we checked for it in the beginning of this
  600. // function and the time we submitted the address change query
  601. if (DoesAddressSocketHaveAddress())
  602. {
  603. #ifdef MAJOR_PNP_DEBUG
  604. DbgPrint("Protocol %d is functional (2)\n", ProtocolId);
  605. #endif
  606. CancelAddressChangeRequestIfNecessary(FALSE, ProtocolId);
  607. SetStateToLoadedAndMonitorProtocolIfNecessary(ProtocolId);
  608. ASSERT_TRANSPORT_PROTOCOL_STATE(ProtocolId);
  609. return TRUE;
  610. }
  611. // regardless of whether we succeeded immediately or we are pending, advance the
  612. // state to ProtocolLoadedWithoutAddress and return not loaded. The completion at the
  613. // completion port will take care of the rest
  614. if (State == ProtocolWasLoadedOrNeedsActivation)
  615. SetState(ProtocolWasLoadedOrNeedsActivationWithoutAddress, ProtocolId);
  616. else if (State == ProtocolNotLoaded)
  617. SetState(ProtocolLoadedWithoutAddress, ProtocolId);
  618. #ifdef MAJOR_PNP_DEBUG
  619. else
  620. {
  621. DbgPrint("VerifyProtocolIsFunctional did not change state for protocol %d, state: %s\n", ProtocolId,
  622. ProtocolStateNames[State]);
  623. }
  624. #endif
  625. ASSERT_TRANSPORT_PROTOCOL_STATE(ProtocolId);
  626. return FALSE;
  627. AbortAndCleanup:
  628. // TRUE or FALSE for this argument doesn't matter here -
  629. // the operation has failed
  630. CancelAddressChangeRequestIfNecessary(FALSE, ProtocolId);
  631. ASSERT_TRANSPORT_PROTOCOL_STATE(ProtocolId);
  632. return FALSE;
  633. }
  634. BOOL TransportProtocol::DoesAddressSocketHaveAddress(void)
  635. /*++
  636. Function Name: DoesAddressSocketHaveAddress
  637. Parameters:
  638. Description:
  639. Checks if a valid address can be obtained for this protocol.
  640. Returns:
  641. TRUE - a valid address could be obtained for this protocol
  642. FALSE - otherwise
  643. --*/
  644. {
  645. DWORD byteRet = 0;
  646. char buf[40];
  647. ASSERT(addressChangeSocket != 0);
  648. if (WSAIoctl(addressChangeSocket, SIO_ADDRESS_LIST_QUERY,
  649. 0, 0, buf, sizeof(buf), &byteRet, NULL, NULL) == SOCKET_ERROR)
  650. {
  651. return FALSE;
  652. }
  653. // if the result has non-zero length ...
  654. if (byteRet != 0)
  655. {
  656. #if 0
  657. int i;
  658. DbgPrint("WSAIoctl returned:\n");
  659. for (i = 0; i < byteRet; i ++)
  660. {
  661. DbgPrint(" %X", (unsigned long) buf[i]);
  662. }
  663. DbgPrint("\nWSAIoctl with ADDRESS_LIST_QUERY returned addresses success\n");
  664. #endif
  665. // ... and the resulting value is non zero ...
  666. if (*(long *)buf != 0)
  667. {
  668. // ... we have managed to get the true address
  669. return TRUE;
  670. }
  671. }
  672. return FALSE;
  673. }
  674. void TransportProtocol::CancelAddressChangeRequestIfNecessary(BOOL fForceCancel, IN PROTOCOL_ID ProtocolId)
  675. /*++
  676. Function Name: CancelAddressChangeRequestIfNecessary
  677. Parameters:
  678. Description:
  679. If there's an active WSAIoctl on the protocol, cancel it by closing the socket.
  680. Returns:
  681. --*/
  682. {
  683. if (addressChangeSocket != 0)
  684. {
  685. // if the address change monitoring is off, or cancel is
  686. // forced, do the actual cancelling. That is, we don't
  687. // cancel if this is a monitored protocol and cancel is
  688. // optional
  689. if (!IsAddressChangeMonitoringOn(ProtocolId) || fForceCancel)
  690. {
  691. #ifdef MAJOR_PNP_DEBUG
  692. DbgPrint("Address change request cancelled\n");
  693. #endif
  694. closesocket(addressChangeSocket);
  695. addressChangeSocket = 0;
  696. addressChangeOverlapped.Internal = -1;
  697. }
  698. }
  699. }
  700. void TransportProtocol::RestartProtocol(PROTOCOL_ID ProtocolId)
  701. /*++
  702. Function Name: RestartProtocol
  703. Parameters:
  704. ProtocolId - the protocol to be restarted.
  705. Description:
  706. Restarts all addresses on this protocol.
  707. Returns:
  708. --*/
  709. {
  710. BASE_ASYNC_OBJECT *Obj;
  711. BOOL fAddressFound = 0;
  712. RPC_STATUS Status;
  713. LIST_ENTRY *CurrentEntry;
  714. VALIDATE(ProtocolId)
  715. {
  716. TCP,
  717. #ifdef SPX_ON
  718. SPX,
  719. #endif
  720. #ifdef APPLETALK_ON
  721. DSP,
  722. #endif
  723. HTTP,
  724. UDP,
  725. #ifdef IPX_ON
  726. IPX,
  727. #endif
  728. TCP_IPv6
  729. } END_VALIDATE;
  730. CurrentEntry = ObjectList.Flink;
  731. while(CurrentEntry != &ObjectList)
  732. {
  733. Obj = CONTAINING_RECORD(CurrentEntry, BASE_ASYNC_OBJECT, ObjectList);
  734. ASSERT(Obj->id == (int) ProtocolId);
  735. if (Obj->type & ADDRESS)
  736. {
  737. if (Obj->type & DATAGRAM)
  738. {
  739. Status = DG_ReactivateAddress((WS_DATAGRAM_ENDPOINT *) Obj);
  740. }
  741. else
  742. {
  743. Status = WS_ReactivateAddress((WS_ADDRESS *) Obj);
  744. }
  745. if (Status == RPC_S_OK)
  746. {
  747. fAddressFound = 1;
  748. COMMON_AddressManager((BASE_ADDRESS *) Obj);
  749. }
  750. }
  751. CurrentEntry = CurrentEntry->Flink;
  752. }
  753. if (fAddressFound)
  754. {
  755. COMMON_PostNonIoEvent(TRANSPORT, 0, NULL);
  756. }
  757. }
  758. void TransportProtocol::InitNewAddresses(PROTOCOL_ID ProtocolId)
  759. /*++
  760. Function Name: RestartProtocol
  761. Parameters:
  762. ProtocolId - the protocol for which the addresses are to be
  763. initialized.
  764. Description:
  765. Initializes transport address objects that listen on
  766. interfaces that were assigned addresses. Works for TCP only.
  767. Returns:
  768. --*/
  769. {
  770. BASE_ASYNC_OBJECT *Obj;
  771. WS_ADDRESS *WsAddr;
  772. BASE_ADDRESS *pSavedFirstAddress, *pSavedNextAddress;
  773. BOOL fAddressFound = FALSE;
  774. RPC_STATUS Status;
  775. LIST_ENTRY *CurrentEntry;
  776. ASSERT(ProtocolId == TCP);
  777. // For each new address in the firewall table, find tranport address
  778. // objects that have not been initialized and make them listen on
  779. // the net address. Make sure that a given transport address list
  780. // listens on all the available network addresses.
  781. // Go through the firewall table
  782. for (DWORD j = 0; j < pFirewallTable->NumAddresses; j++)
  783. {
  784. // Pick a newly-initialized and enabled address from the table.
  785. if (pFirewallTable->Entries[j].fNewAddress == FALSE
  786. || pFirewallTable->Entries[j].fEnabled == FALSE)
  787. {
  788. continue;
  789. }
  790. // Go through the list of transport addresses.
  791. CurrentEntry = ObjectList.Flink;
  792. while(CurrentEntry != &ObjectList)
  793. {
  794. Obj = CONTAINING_RECORD(CurrentEntry, BASE_ASYNC_OBJECT, ObjectList);
  795. ASSERT(Obj->id == (int) ProtocolId);
  796. WsAddr = (WS_ADDRESS *)Obj;
  797. #ifdef MAJOR_TRANS_DEBUG
  798. DbgPrint("RPC: TransportProtocol::InitNewAddresses: Processing address 0x%x.\n", WsAddr);
  799. #endif
  800. // Initialize the object if it is a TCP address that has not yet been initialized
  801. // and if the address list that it is a part of is not listening on all of the available
  802. // network addresses yet.
  803. if (Obj->type & ADDRESS
  804. && Obj->id == TCP
  805. && WsAddr->fAddressInitialized == FALSE
  806. && FirewallTableNumActiveEntries > ((WS_ADDRESS *)WsAddr->pFirstAddress)->NumActiveAddresses)
  807. {
  808. // Initialize the address from the firewall table entry.
  809. //
  810. // Note that we do not have to syncronize with the other users of
  811. // pFirewallTable since the only possible update would come from a PnP
  812. // notification and this function will be executing during a notification
  813. // after the table update. UseProtseq* path does not modify an initialized table
  814. // and can't race with this path.
  815. #ifdef MAJOR_TRANS_DEBUG
  816. DbgPrint("RPC: TransportProtocol::InitNewAddresses: Initializing address 0x%x from pFirewalTable entry with index 0x%x.\n", WsAddr, j);
  817. #endif
  818. WsAddr->ListenAddr.inetaddr.sin_addr.s_addr = pFirewallTable->Entries[j].Address;
  819. // Pass in fResetAddressListEntries = FALSE since the address is already in the list
  820. // and the fields have been initialized.
  821. Status = WS_ReactivateAddress(WsAddr, FALSE);
  822. #ifdef MAJOR_TRANS_DEBUG
  823. DbgPrint("RPC: TransportProtocol::InitNewAddresses: WS_ReactivateAddress for address 0x%x returned 0x%x.\n", WsAddr, Status);
  824. #endif
  825. if (Status == RPC_S_OK)
  826. {
  827. WsAddr->fAddressInitialized = TRUE;
  828. fAddressFound = TRUE;
  829. ((WS_ADDRESS *)WsAddr->pFirstAddress)->NumActiveAddresses++;
  830. COMMON_AddressManager((BASE_ADDRESS *) Obj);
  831. }
  832. // Re-build the address vector.
  833. Status = IP_BuildAddressVector(
  834. &(WsAddr->pFirstAddress->pAddressVector),
  835. 0, //OsfAddress->NICFlags,
  836. NULL, // Not listening on a specific address.
  837. (WS_ADDRESS *)WsAddr->pFirstAddress);
  838. // If we were not able to find an entry in the pFirewallTable to initialize this address,
  839. // there is nothing to do - wait for another address change event when the
  840. // NIC may finish initializing.
  841. //
  842. // Note that if an interface gets disabled, it may disapper from the pFirewallTable during
  843. // an update. In this case, we will remain with un-initialized transport address objects,
  844. // but there is nothing that we can do about this since the interface on which they should have
  845. // listened is not up.
  846. }
  847. CurrentEntry = CurrentEntry->Flink;
  848. }
  849. }
  850. if (fAddressFound)
  851. {
  852. COMMON_PostNonIoEvent(TRANSPORT, 0, NULL);
  853. }
  854. }
  855. void TransportProtocol::UnloadProtocol(PROTOCOL_ID ProtocolId)
  856. /*++
  857. Function Name: UnloadProtocol
  858. Parameters:
  859. ProtocolId - the protocol to be unloaded.
  860. Description:
  861. Walks the list of the protocol transport objects. Closes the connections, and removes the
  862. addresses from the list. Thus failing requests on addresses will not be retried.
  863. Returns:
  864. --*/
  865. {
  866. BASE_ASYNC_OBJECT *Obj;
  867. LIST_ENTRY *CurrentEntry;
  868. VALIDATE(ProtocolId)
  869. {
  870. TCP,
  871. #ifdef SPX_ON
  872. SPX,
  873. #endif
  874. #ifdef APPLETALK_ON
  875. DSP,
  876. #endif
  877. HTTP,
  878. UDP,
  879. #ifdef IPX_ON
  880. IPX,
  881. #endif
  882. TCP_IPv6,
  883. HTTPv2
  884. } END_VALIDATE;
  885. CurrentEntry = ObjectList.Flink;
  886. //
  887. // - Cleanup all the objects (ie: close the socket).
  888. // - Remove all objects other than address objects
  889. // from the list.
  890. //
  891. while(CurrentEntry != &ObjectList)
  892. {
  893. Obj = CONTAINING_RECORD(CurrentEntry, BASE_ASYNC_OBJECT, ObjectList);
  894. ASSERT(Obj->id == (int)ProtocolId);
  895. if (Obj->type & ADDRESS)
  896. {
  897. COMMON_RemoveAddress((BASE_ADDRESS *) Obj);
  898. }
  899. else
  900. {
  901. RpcpfRemoveEntryList(&Obj->ObjectList);
  902. if (ProtocolId != HTTPv2)
  903. WS_Abort(Obj);
  904. else
  905. HTTP_Abort(Obj);
  906. }
  907. CurrentEntry = CurrentEntry->Flink;
  908. }
  909. }
  910. BOOL TransportProtocol::SubmitAddressChangeQuery(void)
  911. /*++
  912. Function Name: SubmitAddressChangeQuery
  913. Parameters:
  914. Description:
  915. Submits an address change query (WSAIoctl)
  916. Returns:
  917. TRUE if the WSAIoctl was successfully posted.
  918. FALSE otherwise
  919. --*/
  920. {
  921. ASSERT(addressChangeSocket != 0);
  922. static DWORD dwBytesReturned;
  923. //
  924. // Post an address list change request
  925. //
  926. addressChangeOverlapped.hEvent = 0;
  927. addressChangeOverlapped.Offset = 0;
  928. addressChangeOverlapped.OffsetHigh = 0;
  929. addressChangeOverlapped.Internal = 0;
  930. // submit the address change request - it will always complete on the completion port
  931. // we don't care about the dwBytesReturned. The provider requires a valid address, or
  932. // it rejects the request
  933. if (WSAIoctl(addressChangeSocket, SIO_ADDRESS_LIST_CHANGE,
  934. 0, 0, 0, 0, &dwBytesReturned, &addressChangeOverlapped, 0) == SOCKET_ERROR)
  935. {
  936. if (WSAGetLastError() != ERROR_IO_PENDING)
  937. {
  938. #ifdef MAJOR_PNP_DEBUG
  939. DbgPrint("Submitting WSAIoclt failed with: %d\n", GetLastError());
  940. #endif
  941. return FALSE;
  942. }
  943. }
  944. return TRUE;
  945. }
  946. void TransportProtocol::SetState(TransportProtocolStates newState, PROTOCOL_ID ProtocolId)
  947. /*++
  948. Function Name: SetState
  949. Parameters:
  950. newState - the new state that the protocol needs to move to
  951. ProtocolId - the protocol number of this protocol
  952. Description:
  953. Sets the state of the protocol. Nobody should write the state directly, because
  954. protocol state mirroring will stop working.
  955. Returns:
  956. --*/
  957. {
  958. TransportProtocol *CurrentProtocol;
  959. #ifdef MAJOR_PNP_DEBUG
  960. DbgPrint("Protocol %d moved from state: %s to state: %s\n", ProtocolId, ProtocolStateNames[State],
  961. ProtocolStateNames[newState]);
  962. #endif
  963. // either the address change monitoring is not on for this protocol, or
  964. // the protocol doesn't move to loaded state, but not both
  965. ASSERT(!IsAddressChangeMonitoringOn(ProtocolId) || (newState != ProtocolLoaded));
  966. State = newState;
  967. if (ProtocolId == TCP)
  968. {
  969. // if a base protocols is moved into loaded and monitored, make sure
  970. // the trailing protocols doesn't follow it there. In such a case
  971. // the trailing protocol becomes only loaded
  972. if (newState == ProtocolLoadedAndMonitored)
  973. {
  974. GetTransportProtocol(HTTP)->State = ProtocolLoaded;
  975. }
  976. else
  977. {
  978. GetTransportProtocol(HTTP)->State = newState;
  979. }
  980. MirrorProtocolState(TCP_IPv6);
  981. }
  982. else if (ProtocolId == TCP_IPv6)
  983. {
  984. MirrorProtocolState(TCP);
  985. }
  986. }
  987. void TransportProtocol::SetStateToLoadedAndMonitorProtocolIfNecessary(PROTOCOL_ID ProtocolId)
  988. {
  989. if (IsAddressChangeMonitoringOn(ProtocolId))
  990. {
  991. // monitor functional protocols for address change will
  992. // set the state
  993. MonitorFunctionalProtocolForAddressChange(ProtocolId);
  994. }
  995. else
  996. SetState(ProtocolLoaded, ProtocolId);
  997. }
  998. RPC_STATUS InitTransportProtocols(void)
  999. /*++
  1000. Function Name: InitTransportProtocols
  1001. Parameters:
  1002. Description:
  1003. Initializes all transport level protocols. This function should be called before
  1004. any of the TransportProtocol functions.
  1005. Returns:
  1006. --*/
  1007. {
  1008. TransportProtocolArray = new TransportProtocol[MAX_PROTOCOLS];
  1009. if (TransportProtocolArray == NULL)
  1010. return (RPC_S_OUT_OF_MEMORY);
  1011. else
  1012. return RPC_S_OK;
  1013. }
  1014. #if defined(DBG) || defined(_DEBUG)
  1015. void TransportProtocol::AssertTransportProtocolState(void)
  1016. /*++
  1017. Function Name: AssertTransportProtocolState
  1018. Parameters:
  1019. Description:
  1020. Loops through all protocols and calls AssertState on them
  1021. Returns:
  1022. --*/
  1023. {
  1024. int i;
  1025. for (i = 1; i < MAX_PROTOCOLS; i ++)
  1026. {
  1027. GetTransportProtocol(i)->AssertState(i);
  1028. }
  1029. }
  1030. void TransportProtocol::AssertState(PROTOCOL_ID ProtocolId)
  1031. /*++
  1032. Function Name: AssertState
  1033. Parameters:
  1034. ProtocolId - the protocol number of the this protocol
  1035. Description:
  1036. Currently this includes that addressChangeSocket is set only in the *WithoutAddress states
  1037. and that all the objects in this protocol list are of the same protocol as this protocol.
  1038. Returns:
  1039. --*/
  1040. {
  1041. // make sure that the internal state of the object is consistent
  1042. ASSERT (State >= ProtocolNotLoaded);
  1043. ASSERT (State <= ProtocolLoadedAndMonitored);
  1044. if (IsTrailingProtocol(ProtocolId))
  1045. {
  1046. ASSERT(addressChangeSocket == 0);
  1047. }
  1048. else
  1049. {
  1050. // if we are in one of these states, there should be no address change request pending
  1051. if ((State == ProtocolNotLoaded)
  1052. || (State == ProtocolWasLoadedOrNeedsActivation)
  1053. || (State == ProtocolLoaded))
  1054. {
  1055. ASSERT(addressChangeSocket == 0);
  1056. }
  1057. else
  1058. {
  1059. // if we are in one of the else states, there must be address change request pending
  1060. ASSERT(addressChangeSocket != 0);
  1061. }
  1062. }
  1063. AssertListIntegrity(ProtocolId);
  1064. }
  1065. void
  1066. TransportProtocol::AssertListIntegrity (
  1067. IN PROTOCOL_ID ProtocolId
  1068. )
  1069. /*++
  1070. Routine Description:
  1071. Verifies the integrity of the protocol list by walking
  1072. through every entry and making sure it has the same (and
  1073. expected) protocol id.
  1074. Arguments:
  1075. ProtocolId - the protocol id of the current protocol
  1076. Return Value:
  1077. --*/
  1078. {
  1079. BASE_ASYNC_OBJECT *pObject;
  1080. LIST_ENTRY *CurrentEntry;
  1081. EnterCriticalSection(&AddressListLock);
  1082. // walk the object list and make sure every object is of the same protocol
  1083. CurrentEntry = ObjectList.Flink;
  1084. while (CurrentEntry != &ObjectList)
  1085. {
  1086. pObject = CONTAINING_RECORD(CurrentEntry, BASE_ASYNC_OBJECT, ObjectList);
  1087. ASSERT(pObject->id == ProtocolId);
  1088. CurrentEntry = CurrentEntry->Flink;
  1089. }
  1090. LeaveCriticalSection(&AddressListLock);
  1091. }
  1092. #endif
  1093. BOOL TransportProtocol::MonitorFunctionalProtocolForAddressChange(PROTOCOL_ID ProtocolId)
  1094. /*++
  1095. Function Name: MonitorFunctionalProtocolForAddressChange
  1096. Parameters:
  1097. ProtocolId - the protocol id of the current protocol
  1098. Description:
  1099. Makes sure that an already functional protocol is monitored for address change. This is done
  1100. by:
  1101. - if an address change socket does not exist, one is opened.
  1102. - if no address change WSAIoctl is pending on the socket, one is posted.
  1103. Returns:
  1104. TRUE if the posting of address change was successful
  1105. FALSE if it wasn't
  1106. --*/
  1107. {
  1108. BOOL bRetVal = FALSE;
  1109. // OpenAddressChangeRequestSocket will take care to check whether there's already
  1110. // a socket opened
  1111. if (OpenAddressChangeRequestSocket(ProtocolId) == FALSE)
  1112. goto Cleanup;
  1113. if (addressChangeOverlapped.Internal != STATUS_PENDING)
  1114. {
  1115. if (SubmitAddressChangeQuery() == FALSE)
  1116. goto Cleanup;
  1117. }
  1118. bRetVal = TRUE;
  1119. Cleanup:
  1120. if (State != ProtocolLoadedAndMonitored)
  1121. SetState(ProtocolLoadedAndMonitored, ProtocolId);
  1122. return bRetVal;
  1123. }
  1124. BOOL TransportProtocol::OpenAddressChangeRequestSocket(PROTOCOL_ID ProtocolId)
  1125. /*++
  1126. Function Name: OpenAddressChangeRequestSocket
  1127. Parameters:
  1128. ProtocolId - the protocol id of the current protocol
  1129. Description:
  1130. Makes sure that an address change request socket is opened.
  1131. Returns:
  1132. TRUE if the opening was successful
  1133. FALSE if it wasn't
  1134. --*/
  1135. {
  1136. const WS_TRANS_INFO *pInfo = &WsTransportTable[ProtocolId];
  1137. HANDLE h;
  1138. // we may end up with non-zero addressChangeSocket if this is an address change query
  1139. // request coming back to us. In this case we don't need to open up another socket
  1140. if (addressChangeSocket == 0)
  1141. {
  1142. ASSERT((State == ProtocolNotLoaded)
  1143. || (State == ProtocolWasLoadedOrNeedsActivation)
  1144. || (State == ProtocolLoaded));
  1145. //
  1146. // Create a socket
  1147. //
  1148. addressChangeSocket = WSASocketT(pInfo->AddressFamily,
  1149. pInfo->SocketType,
  1150. pInfo->Protocol,
  1151. 0,
  1152. 0,
  1153. WSA_FLAG_OVERLAPPED);
  1154. if (addressChangeSocket == INVALID_SOCKET)
  1155. {
  1156. //
  1157. // We should be able to at least open a socket on the protocol,
  1158. // if not we got a bogus notification or we're out of resources
  1159. addressChangeSocket = 0;
  1160. return FALSE;
  1161. }
  1162. //
  1163. // make the handle non-inheritable so it goes away when we close it.
  1164. //
  1165. if (FALSE == SetHandleInformation( (HANDLE) addressChangeSocket, HANDLE_FLAG_INHERIT, 0))
  1166. {
  1167. closesocket(addressChangeSocket);
  1168. addressChangeSocket = 0;
  1169. return FALSE;
  1170. }
  1171. // associate the socket with the completion port so that we get the notification there
  1172. h = CreateIoCompletionPort((HANDLE)addressChangeSocket,
  1173. RpcCompletionPort,
  1174. NewAddress,
  1175. 0);
  1176. if (h == 0)
  1177. {
  1178. closesocket(addressChangeSocket);
  1179. addressChangeSocket = 0;
  1180. return FALSE;
  1181. }
  1182. else if (RpcCompletionPort != h)
  1183. {
  1184. ASSERT(RpcCompletionPort == h);
  1185. CloseHandle(h);
  1186. closesocket(addressChangeSocket);
  1187. addressChangeSocket = 0;
  1188. return FALSE;
  1189. }
  1190. }
  1191. else
  1192. {
  1193. // we may have a protocol in state ProtocolNotLoaded, because we are just trying
  1194. // to bring it to loaded state
  1195. ASSERT((State == ProtocolLoadedWithoutAddress)
  1196. || (State == ProtocolWasLoadedOrNeedsActivationWithoutAddress)
  1197. || (State == ProtocolLoadedAndMonitored) || (State == ProtocolNotLoaded));
  1198. }
  1199. #ifdef MAJOR_PNP_DEBUG
  1200. DbgPrint("Socket was successfully opened for protocol %d\n", ProtocolId);
  1201. #endif
  1202. return TRUE;
  1203. }
  1204. void
  1205. TransportProtocol::MirrorProtocolState (
  1206. IN PROTOCOL_ID MirrorProtocolId
  1207. )
  1208. /*++
  1209. Function Name: MirrorProtocolState
  1210. Parameters:
  1211. MirrorProtocolId - the protocol which is mirrored
  1212. Description:
  1213. If this is one of the protocols in a dual stack configuration, change
  1214. the other protocol into appropriate state
  1215. Returns:
  1216. --*/
  1217. {
  1218. TransportProtocol *MirrorProtocol;
  1219. MirrorProtocol = GetTransportProtocol(MirrorProtocolId);
  1220. if ((State == ProtocolLoadedAndMonitored) || (State == ProtocolLoaded))
  1221. {
  1222. if (MirrorProtocol->State == ProtocolNotLoaded)
  1223. {
  1224. MirrorProtocol->SetState(ProtocolWasLoadedOrNeedsActivation, MirrorProtocolId);
  1225. }
  1226. else if (MirrorProtocol->State == ProtocolLoadedWithoutAddress)
  1227. {
  1228. MirrorProtocol->SetState(ProtocolWasLoadedOrNeedsActivationWithoutAddress, MirrorProtocolId);
  1229. }
  1230. }
  1231. }
  1232. #ifdef MAJOR_PNP_DEBUG
  1233. void TransportProtocol::DumpProtocolState(void)
  1234. /*++
  1235. Function Name: DumpProtocolState
  1236. Parameters:
  1237. Description:
  1238. Iterates through all protocol and calls their DumpProtocolState
  1239. Returns:
  1240. --*/
  1241. {
  1242. int i;
  1243. DbgPrint("Dumping protocol state for process %d\n", GetCurrentProcessId());
  1244. for (i = 1; i < MAX_PROTOCOLS; i ++)
  1245. {
  1246. GetTransportProtocol(i)->DumpProtocolState(i);
  1247. }
  1248. }
  1249. const char *ProtocolStateNames[] = {"ProtocolNotLoaded", "ProtocolLoadedWithoutAddress" ,
  1250. "ProtocolWasLoadedOrNeedsActivation", "ProtocolLoaded",
  1251. "ProtocolWasLoadedOrNeedsActivationWithoutAddress",
  1252. "ProtocolLoadedAndMonitored"};
  1253. void TransportProtocol::DumpProtocolState(PROTOCOL_ID ProtocolId)
  1254. /*++
  1255. Function Name: DumpProtocolState
  1256. Parameters:
  1257. ProtocolId - the protocol number for this protocol.
  1258. Description:
  1259. Dumps all significant information for this protcool on the debugger
  1260. Returns:
  1261. --*/
  1262. {
  1263. BASE_ASYNC_OBJECT *pCurrentObject;
  1264. LIST_ENTRY *pCurrentEntry = ObjectList.Flink;
  1265. int fFirstTime = TRUE;
  1266. const RPC_CHAR *Protseq;
  1267. if (TransportTable[ProtocolId].pInfo)
  1268. Protseq = TransportTable[ProtocolId].pInfo->ProtocolSequence;
  1269. else
  1270. Protseq = L"(null)";
  1271. DbgPrint("Protocol: %S\n", Protseq);
  1272. DbgPrint("State: %s, Addr Change Socket: %X, Addr Change Overlapped: %X\n",
  1273. ProtocolStateNames[State], addressChangeSocket, (ULONG_PTR)&addressChangeOverlapped);
  1274. while (pCurrentEntry != &ObjectList)
  1275. {
  1276. if (fFirstTime)
  1277. {
  1278. DbgPrint("Object List:\n");
  1279. fFirstTime = FALSE;
  1280. }
  1281. pCurrentObject = CONTAINING_RECORD(pCurrentEntry, BASE_ASYNC_OBJECT, ObjectList);
  1282. DbgPrint("\t%X\n", (ULONG_PTR)pCurrentObject);
  1283. pCurrentEntry = pCurrentEntry->Flink;
  1284. }
  1285. }
  1286. #endif
  1287. TransportProtocol *TransportProtocolArray;