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.

6984 lines
221 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. Ntisol.h
  5. Abstract:
  6. This file contains the interface between the TDI interface on the top
  7. of NBT and the OS independent code. It takes the parameters out of the
  8. irps and puts in into procedure calls for the OS independent code (which
  9. is mostly in name.c).
  10. Author:
  11. Jim Stewart (Jimst) 10-2-92
  12. Revision History:
  13. Notes:
  14. The Nbt routines have been modified to include an additional parameter, i.e,
  15. the transport type. This transport type is used primarily to distinguish the
  16. NETBIOS over TCP/IP implementation from the Messaging Over TCP/IP implementation.
  17. The primary difference between the two being that the later uses the NETBT framing
  18. without the associated NETBIOS name registartion/resolution. It primarily uses
  19. DNS for name resolution. All the names that are registered for the new transport
  20. are local names and are not defended on the network.
  21. The primary usage is in conjuntion with an extended NETBIOS address type defined
  22. in tdi.h. The NETBIOS name resolution/registration traffic occurs in two phases.
  23. The first phase contains all the broadcast traffic that ensues during NETBIOS
  24. name registration. Subsequently the NETBT implementation queries the remote
  25. adapter status to choose the appropriate called name. This approach results in
  26. additional traffic for querying the remote adapter status. The new address type
  27. defined in tdi.h enables the client of netbt to supply the name to be used in
  28. NETBT session setup. This avoids the network traffic for querying the adapter
  29. status.
  30. The original design which has not been fully implemented involved exposing two
  31. device objects from the NetBt driver -- the NetBt device object which would be
  32. the full implementation of NETBIOS over TCP/IP and the MoTcp device object which
  33. would be the implementation of Messaging over TCP/IP. The MoTcp device object
  34. would use the same port address as NetBt and use the same session setup protocol
  35. to talk to remote machines running old NetBt drivers and machines running new
  36. NetBt drivers.
  37. The transport type variations combined with the address type changes present us
  38. with four different cases which need to be handled -- the NetBt transport being
  39. presented with a TDI_ADDRESS_NETBIOS_EX structure, the NetBt transport being
  40. prsented with a TDI_ADDRESS_NETBIOS structure and the same two cases for the
  41. MoTcp transport.
  42. --*/
  43. #include "precomp.h"
  44. #include "ntprocs.h"
  45. #include <ipinfo.h>
  46. #include <ntddtcp.h> // for IOCTL_TCP_SET_INFORMATION_EX
  47. #ifdef RASAUTODIAL
  48. #include <acd.h>
  49. #include <acdapi.h>
  50. #endif // RASAUTODIAL
  51. #include <tcpinfo.h>
  52. #include <tdiinfo.h>
  53. #include "ntisol.tmh"
  54. #if BACK_FILL
  55. #define SESSION_HDR_SIZE sizeof(tSESSIONHDR)
  56. #endif
  57. NTSTATUS
  58. SendCompletion(
  59. IN PDEVICE_OBJECT DeviceObject,
  60. IN PIRP Irp,
  61. IN PVOID Context
  62. );
  63. NTSTATUS
  64. NTSendCleanupConnection(
  65. IN tCONNECTELE *pConnEle,
  66. IN PVOID pCompletionRoutine,
  67. IN PVOID Context,
  68. IN PIRP pIrp);
  69. VOID
  70. DpcSendSession(
  71. IN PKDPC pDpc,
  72. IN PVOID Context,
  73. IN PVOID SystemArgument1,
  74. IN PVOID SystemArgument2
  75. );
  76. NBT_WORK_ITEM_CONTEXT *
  77. FindLmhSvcRequest(
  78. IN PDEVICE_OBJECT DeviceContext,
  79. IN PIRP pIrp,
  80. IN tLMHSVC_REQUESTS *pLmhRequest
  81. );
  82. NTSTATUS
  83. NbtCancelCancelRoutine(
  84. IN PIRP pIrp
  85. );
  86. #ifdef RASAUTODIAL
  87. extern ACD_DRIVER AcdDriverG;
  88. BOOLEAN
  89. NbtCancelPostConnect(
  90. IN PIRP pIrp
  91. );
  92. #endif // RASAUTODIAL
  93. NTSTATUS
  94. NbtQueryGetAddressInfo(
  95. IN PIO_STACK_LOCATION pIrpSp,
  96. OUT PVOID *ppBuffer,
  97. OUT ULONG *pSize
  98. );
  99. VOID
  100. NbtCancelConnect(
  101. IN PDEVICE_OBJECT pDeviceContext,
  102. IN PIRP pIrp
  103. );
  104. VOID
  105. NbtCancelReceive(
  106. IN PDEVICE_OBJECT DeviceContext,
  107. IN PIRP pIrp
  108. );
  109. NTSTATUS
  110. GetIpAddrs(
  111. IN tDEVICECONTEXT *pDeviceContext,
  112. IN PIRP pIrp
  113. );
  114. typedef struct
  115. {
  116. struct _DeviceContext *pDeviceContext;
  117. PIRP pClientIrp;
  118. PIRP pLocalIrp;
  119. tCONNECTELE *pConnEle;
  120. PTA_NETBT_INTERNAL_ADDRESS pTransportAddress;
  121. TDI_CONNECTION_INFORMATION LocalConnectionInformation;
  122. BOOLEAN ProcessingDone;
  123. TDI_ADDRESS_NETBIOS_UNICODE_EX *pUnicodeAddress; // First Readable buffer in the transport address list
  124. TDI_ADDRESS_NETBIOS_UNICODE_EX *pReturnBuffer; // First writable buffer in the transport address list
  125. LONG CurrIndex, NumberOfAddresses;
  126. LONG TaAddressLength, RemainingAddressLength;
  127. PUCHAR pTaAddress;
  128. } NBT_DELAYED_CONNECT_CONTEXT, *PNBT_DELAYED_CONNECT_CONTEXT;
  129. extern POBJECT_TYPE *IoFileObjectType;
  130. NTSTATUS
  131. InitDelayedNbtProcessConnect(
  132. IN PNBT_DELAYED_CONNECT_CONTEXT pDelConnCtx
  133. );
  134. HANDLE
  135. NbtOpenParametersRegistry(
  136. VOID
  137. );
  138. //******************* Pageable Routine Declarations ****************
  139. #ifdef ALLOC_PRAGMA
  140. #pragma CTEMakePageable(PAGE, NTOpenControl)
  141. #pragma CTEMakePageable(PAGE, NTOpenAddr)
  142. #pragma CTEMakePageable(PAGE, NTCloseAddress)
  143. #pragma CTEMakePageable(PAGE, NTOpenConnection)
  144. #pragma CTEMakePageable(PAGE, NTAssocAddress)
  145. #pragma CTEMakePageable(PAGE, NTCloseConnection)
  146. #pragma CTEMakePageable(PAGE, NTSetSharedAccess)
  147. #pragma CTEMakePageable(PAGE, NTCheckSharedAccess)
  148. #pragma CTEMakePageable(PAGE, NTCleanUpConnection)
  149. #pragma CTEMakePageable(PAGE, NTCleanUpAddress)
  150. #pragma CTEMakePageable(PAGE, NTDisAssociateAddress)
  151. #pragma CTEMakePageable(PAGE, NTListen)
  152. #pragma CTEMakePageable(PAGE, DelayedNbtProcessConnect)
  153. #pragma CTEMakePageable(PAGE, InitDelayedNbtProcessConnect)
  154. #pragma CTEMakePageable(PAGE, DispatchIoctls)
  155. #pragma CTEMakePageable(PAGE, NTSendDatagram)
  156. #pragma CTEMakePageable(PAGE, NTSetInformation)
  157. #pragma CTEMakePageable(PAGE, NTSetEventHandler)
  158. #pragma CTEMakePageable(PAGE, NbtOpenParametersRegistry)
  159. //
  160. // Should not be pageable since AFD can call us at raised Irql in case of AcceptEx.
  161. //
  162. // #pragma CTEMakePageable(PAGE, NTQueryInformation)
  163. #endif
  164. //******************* Pageable Routine Declarations ****************
  165. int check_unicode_string(IN PUNICODE_STRING str);
  166. //----------------------------------------------------------------------------
  167. NTSTATUS
  168. NTOpenControl(
  169. IN tDEVICECONTEXT *pDeviceContext,
  170. IN PIRP pIrp)
  171. /*++
  172. Routine Description:
  173. This Routine handles opening the control object, which represents the
  174. driver itself. For example QueryInformation uses the control object
  175. as the destination of the Query message.
  176. Arguments:
  177. pIrp - a ptr to an IRP
  178. Return Value:
  179. NTSTATUS - status of the request
  180. --*/
  181. {
  182. PIO_STACK_LOCATION pIrpSp;
  183. NTSTATUS status;
  184. CTEPagedCode();
  185. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  186. pIrpSp->FileObject->FsContext2 = (PVOID)(NBT_CONTROL_TYPE);
  187. // return a ptr the control endpoint
  188. pIrpSp->FileObject->FsContext = (PVOID)pNbtGlobConfig->pControlObj;
  189. //
  190. // the following call opens a control object with the transport below since
  191. // several of the query information calls are passed directly on to the
  192. // transport below.
  193. //
  194. if (!pDeviceContext->pControlFileObject)
  195. {
  196. status = NbtTdiOpenControl(pDeviceContext);
  197. }
  198. else
  199. status = STATUS_SUCCESS;
  200. return(status);
  201. }
  202. //----------------------------------------------------------------------------
  203. NTSTATUS
  204. NTOpenAddr(
  205. IN tDEVICECONTEXT *pDeviceContext,
  206. IN PIRP pIrp,
  207. IN PFILE_FULL_EA_INFORMATION ea)
  208. /*++
  209. Routine Description:
  210. This Routine handles converting an Open Address Request from an IRP to
  211. a procedure call so that NbtOpenAddress can be called in an OS independent
  212. manner.
  213. Arguments:
  214. pIrp - a ptr to an IRP
  215. Return Value:
  216. NTSTATUS - status of the request
  217. --*/
  218. {
  219. TDI_REQUEST Request;
  220. TA_ADDRESS *pAddress;
  221. int j;
  222. NTSTATUS status=STATUS_INVALID_ADDRESS_COMPONENT;
  223. ULONG BufferLength, MinBufferLength;
  224. TRANSPORT_ADDRESS UNALIGNED *pTransportAddr; // structure containing counted array of TA_ADDRESS
  225. CTEPagedCode();
  226. // make up the Request data structure from the IRP info
  227. Request.Handle.AddressHandle = NULL;
  228. //
  229. // Verify Minimum Buffer length!
  230. // Bug#: 120683
  231. //
  232. BufferLength = ea->EaValueLength;
  233. if (BufferLength < sizeof(TA_NETBIOS_ADDRESS))
  234. {
  235. IF_DBG(NBT_DEBUG_NETBIOS_EX)
  236. KdPrint(("Nbt.NTOpenAddr[1]: ...Rejecting Open Address request -- BufferLength<%d> < Min<%d>\n",
  237. BufferLength, sizeof(TA_NETBIOS_ADDRESS)));
  238. NbtTrace(NBT_TRACE_LOCALNAMES, ("Rejecting Open Address request -- BufferLength<%d> < Min<%d>",
  239. BufferLength, sizeof(TA_NETBIOS_ADDRESS)));
  240. return (status);
  241. }
  242. MinBufferLength = FIELD_OFFSET(TRANSPORT_ADDRESS,Address); // Set for Address[0]
  243. pTransportAddr = (PTRANSPORT_ADDRESS)&ea->EaName[ea->EaNameLength+1];
  244. pAddress = (TA_ADDRESS *) &pTransportAddr->Address[0]; // this includes the address type + the actual address
  245. //
  246. // The Transport Address information is packed as follows:
  247. // Field: Length:
  248. // ------ -------
  249. // TAAddressCount --> LONG
  250. //
  251. // Address[0].AddressLength --> USHORT
  252. // Address[0].AddressType --> USHORT
  253. // Address[0].Address.. --> Address[0].AddressLength
  254. //
  255. // Address[1].AddressLength --> USHORT
  256. // Address[1].AddressType --> USHORT
  257. // Address[1].Address.. --> Address[1].AddressLength
  258. // :
  259. //
  260. // loop through the addresses passed in until ONE is successfully used
  261. // *TODO* do we need this loop or can we just assume the name is at the start of the address buffer...
  262. // *TODO* does this need to handle multiple names??
  263. for (j=0; BufferLength >= MinBufferLength && j<pTransportAddr->TAAddressCount ;j++ )
  264. {
  265. //
  266. // do we have enough data to access the "AddressLength" field?
  267. //
  268. MinBufferLength += FIELD_OFFSET(TA_ADDRESS,Address);
  269. if (BufferLength < MinBufferLength) {
  270. return (status);
  271. }
  272. //
  273. // Now we can safely access AddressLength
  274. //
  275. MinBufferLength += pAddress->AddressLength;
  276. if (BufferLength < MinBufferLength) {
  277. return (status);
  278. }
  279. //
  280. // We support only 2 address types:
  281. //
  282. if (pAddress->AddressType == TDI_ADDRESS_TYPE_NETBIOS &&
  283. pAddress->AddressLength >= sizeof(TDI_ADDRESS_NETBIOS)) {
  284. status = STATUS_SUCCESS;
  285. break;
  286. } else if (pAddress->AddressType == TDI_ADDRESS_TYPE_NETBIOS_EX &&
  287. pAddress->AddressLength >= sizeof(TDI_ADDRESS_NETBIOS_EX)) {
  288. status = STATUS_SUCCESS;
  289. break;
  290. }
  291. IF_DBG(NBT_DEBUG_NETBIOS_EX)
  292. KdPrint(("Nbt.NTOpenAddr[2]: ...Rejecting Open Address request for AddressType=<%d>\n",
  293. pAddress->AddressType));
  294. //
  295. // Set pAddress to point to the next address
  296. //
  297. pAddress = (TA_ADDRESS *) ((PUCHAR)pAddress
  298. + FIELD_OFFSET(TA_ADDRESS,Address)
  299. + pAddress->AddressLength);
  300. }
  301. if (status == STATUS_SUCCESS) // We found a valid address type!
  302. {
  303. // call the non-NT specific function to open an address
  304. status = NbtOpenAddress(&Request,
  305. pAddress,
  306. pDeviceContext->IpAddress,
  307. pDeviceContext,
  308. (PVOID)pIrp);
  309. if (status != STATUS_SUCCESS) {
  310. NbtTrace(NBT_TRACE_NAMESRV, ("NbtOpenAddress returns %!status!", status));
  311. }
  312. }
  313. return(status);
  314. }
  315. //----------------------------------------------------------------------------
  316. NTSTATUS
  317. NTCloseAddress(
  318. IN tDEVICECONTEXT *pDeviceContext,
  319. IN PIRP pIrp)
  320. /*++
  321. Routine Description:
  322. This Routine handles converting a Close Address Request from an IRP to
  323. a procedure call so that NbtCloseAddress can be called in an OS independent
  324. manner.
  325. Arguments:
  326. pIrp - a ptr to an IRP
  327. Return Value:
  328. NTSTATUS - status of the request
  329. --*/
  330. {
  331. TDI_REQUEST Request;
  332. TDI_REQUEST_STATUS RequestStatus;
  333. PIO_STACK_LOCATION pIrpSp;
  334. NTSTATUS status;
  335. tCLIENTELE *pClientEle;
  336. CTEPagedCode();
  337. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  338. pClientEle = Request.Handle.ConnectionContext = pIrpSp->FileObject->FsContext;
  339. if (!NBT_VERIFY_HANDLE2 (pClientEle, NBT_VERIFY_CLIENT, NBT_VERIFY_CLIENT_DOWN))
  340. {
  341. ASSERTMSG ("Nbt.NTCloseAddress: ERROR - Invalid Address Handle\n", 0);
  342. return (STATUS_INVALID_HANDLE);
  343. }
  344. status = NbtCloseAddress (&Request, &RequestStatus, pDeviceContext, (PVOID)pIrp);
  345. NbtTrace(NBT_TRACE_NAMESRV, ("NbtCloseAddress returns %!status! for ClientEle=%p", status, pClientEle));
  346. return(status);
  347. }
  348. //----------------------------------------------------------------------------
  349. NTSTATUS
  350. NTOpenConnection(
  351. IN tDEVICECONTEXT *pDeviceContext,
  352. IN PIRP pIrp,
  353. IN PFILE_FULL_EA_INFORMATION ea)
  354. /*++
  355. Routine Description:
  356. This Routine handles converting an Open Connection Request from an IRP to
  357. a procedure call so that NbtOpenConnection can be called in an OS independent
  358. manner. The connection must be associated with an address before it
  359. can be used, except for in inbound call where the client returns the
  360. connection ID in the accept.
  361. Arguments:
  362. pIrp - a ptr to an IRP
  363. Return Value:
  364. NTSTATUS - status of the request
  365. --*/
  366. {
  367. TDI_REQUEST Request;
  368. PIO_STACK_LOCATION pIrpSp;
  369. CONNECTION_CONTEXT ConnectionContext;
  370. NTSTATUS status;
  371. PFILE_OBJECT pFileObject;
  372. ULONG BufferLength;
  373. tCONNECTELE *pConnEle;
  374. CTEPagedCode();
  375. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  376. // make up the Request data structure from the IRP info
  377. Request.Handle.ConnectionContext = NULL;
  378. //
  379. // Verify Minimum Buffer length!
  380. // Bug#: 120682
  381. //
  382. BufferLength = ea->EaValueLength;
  383. if (BufferLength < sizeof(CONNECTION_CONTEXT))
  384. {
  385. IF_DBG(NBT_DEBUG_NETBIOS_EX)
  386. KdPrint(("Nbt.NTOpenConnection: ERROR -- Open Connection request -- (BufferLength=%d < Min=%d)\n",
  387. BufferLength, sizeof(CONNECTION_CONTEXT)));
  388. ASSERT(0);
  389. return (STATUS_INVALID_ADDRESS_COMPONENT);
  390. }
  391. // the connection context value is stored in the string just after the
  392. // name "connectionContext", and it is most likely unaligned, so just
  393. // copy it out.( 4 bytes of copying ).
  394. CTEMemCopy(&ConnectionContext,
  395. (CONNECTION_CONTEXT)&ea->EaName[ea->EaNameLength+1],
  396. sizeof(CONNECTION_CONTEXT));
  397. // call the non-NT specific function to open an address
  398. status = NbtOpenConnection (&Request, ConnectionContext, pDeviceContext);
  399. pFileObject = pIrpSp->FileObject;
  400. if (!NT_SUCCESS(status))
  401. {
  402. pFileObject->FsContext = NULL;
  403. NbtTrace(NBT_TRACE_OUTBOUND, ("NbtOpenConnection returns %!status!", status));
  404. }
  405. else if (Request.Handle.ConnectionContext)
  406. {
  407. // fill the IRP with successful completion information so we can
  408. // find the connection object given the fileObject later.
  409. pConnEle = pFileObject->FsContext = Request.Handle.ConnectionContext;
  410. if (!NBT_VERIFY_HANDLE (pConnEle, NBT_VERIFY_CONNECTION))
  411. {
  412. ASSERTMSG ("Nbt.NTOpenConnection: ERROR - Invalid Connection Handle\n", 0);
  413. return (STATUS_UNSUCCESSFUL);
  414. }
  415. pFileObject->FsContext2 = (PVOID)(NBT_CONNECTION_TYPE);
  416. pConnEle->pClientFileObject = pFileObject;
  417. NbtTrace(NBT_TRACE_OUTBOUND, ("New connection %p", pConnEle));
  418. status = STATUS_SUCCESS;
  419. }
  420. return(status);
  421. }
  422. //----------------------------------------------------------------------------
  423. NTSTATUS
  424. NTAssocAddress(
  425. IN tDEVICECONTEXT *pDeviceContext,
  426. IN PIRP pIrp)
  427. /*++
  428. Routine Description:
  429. This Routine handles converting an Associate Address Request from an IRP to
  430. a procedure call so that NbtAssociateAddress can be called in an OS independent
  431. manner.
  432. Arguments:
  433. pIrp - a ptr to an IRP
  434. Return Value:
  435. NTSTATUS - status of the request
  436. --*/
  437. {
  438. TDI_REQUEST Request;
  439. PIO_STACK_LOCATION pIrpSp;
  440. PFILE_OBJECT fileObject;
  441. PTDI_REQUEST_KERNEL_ASSOCIATE parameters; // holds address handle
  442. NTSTATUS status;
  443. tCONNECTELE *pConnEle;
  444. tCLIENTELE *pClientEle;
  445. CTEPagedCode();
  446. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  447. pConnEle = Request.Handle.ConnectionContext = pIrpSp->FileObject->FsContext;
  448. if (!NBT_VERIFY_HANDLE (pConnEle, NBT_VERIFY_CONNECTION))
  449. {
  450. ASSERTMSG ("Nbt.NTAssocAddress: ERROR - Invalid Connection Handle\n", 0);
  451. return (STATUS_INVALID_HANDLE);
  452. }
  453. // the address handle is buried in the Irp...
  454. parameters = (PTDI_REQUEST_KERNEL_ASSOCIATE)&pIrpSp->Parameters;
  455. // now get a pointer to the file object, which points to the address
  456. // element by calling a kernel routine to convert this filehandle into
  457. // a file pointer.
  458. status = ObReferenceObjectByHandle (parameters->AddressHandle,
  459. FILE_READ_DATA,
  460. *IoFileObjectType,
  461. pIrp->RequestorMode,
  462. (PVOID *)&fileObject,
  463. NULL);
  464. IF_DBG(NBT_DEBUG_HANDLES)
  465. KdPrint (("\t ++<%x>====><%x>\tNTAssocAddress->ObReferenceObject, Status = <%x>\n", parameters->AddressHandle, fileObject, status));
  466. if ((NT_SUCCESS(status)) &&
  467. (fileObject->DeviceObject->DriverObject == NbtConfig.DriverObject) && // Bug# 202349
  468. NBT_VERIFY_HANDLE(((tDEVICECONTEXT*)fileObject->DeviceObject), NBT_VERIFY_DEVCONTEXT) && // Bug# 202349
  469. (PtrToUlong(fileObject->FsContext2) == TDI_TRANSPORT_ADDRESS_FILE))
  470. {
  471. pClientEle = fileObject->FsContext;
  472. if (NBT_VERIFY_HANDLE (pClientEle, NBT_VERIFY_CLIENT))
  473. {
  474. // call the non-NT specific function to associate the address with
  475. // the connection
  476. status = NbtAssociateAddress (&Request, pClientEle, (PVOID)pIrp);
  477. NbtTrace(NBT_TRACE_OUTBOUND, ("NbtAssociateAddress returns %!status!", status));
  478. }
  479. else
  480. {
  481. ASSERTMSG ("Nbt.NTAssocAddress: ERROR - Invalid Address Handle\n", 0);
  482. status = STATUS_INVALID_HANDLE;
  483. }
  484. // we are done with the file object, so release the reference
  485. ObDereferenceObject((PVOID)fileObject);
  486. return(status);
  487. }
  488. else
  489. {
  490. return(STATUS_INVALID_HANDLE);
  491. }
  492. }
  493. //----------------------------------------------------------------------------
  494. NTSTATUS
  495. NTCloseConnection(
  496. IN tDEVICECONTEXT *pDeviceContext,
  497. IN PIRP pIrp)
  498. /*++
  499. Routine Description:
  500. This Routine handles converting a Close Connection Request from an IRP to
  501. a procedure call so that NbtCloseConnection can be called in an OS independent
  502. manner.
  503. Arguments:
  504. pIrp - a ptr to an IRP
  505. Return Value:
  506. NTSTATUS - status of the request
  507. --*/
  508. {
  509. TDI_REQUEST Request;
  510. TDI_REQUEST_STATUS RequestStatus;
  511. PIO_STACK_LOCATION pIrpSp;
  512. NTSTATUS status;
  513. tCONNECTELE *pConnEle;
  514. CTEPagedCode();
  515. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  516. pConnEle = Request.Handle.ConnectionContext = pIrpSp->FileObject->FsContext;
  517. if (!NBT_VERIFY_HANDLE2 (pConnEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN))
  518. {
  519. ASSERTMSG ("Nbt.NTCloseConnection: ERROR - Invalid Connection Handle\n", 0);
  520. return (STATUS_INVALID_HANDLE);
  521. }
  522. status = NbtCloseConnection(
  523. &Request,
  524. &RequestStatus,
  525. pDeviceContext,
  526. (PVOID)pIrp);
  527. NbtTrace(NBT_TRACE_OUTBOUND, ("Close connection %p returns %!status!", pConnEle, status));
  528. return(status);
  529. }
  530. //----------------------------------------------------------------------------
  531. VOID
  532. NTSetFileObjectContexts(
  533. IN PIRP pIrp,
  534. IN PVOID FsContext,
  535. IN PVOID FsContext2)
  536. /*++
  537. Routine Description:
  538. This Routine handles fills in two context values in the Irp stack location,
  539. that has to be done in an OS-dependent manner. This routine is called
  540. from NbtOpenAddress() when a name is being registered on the network( i.e.
  541. as a result of OpenAddress).
  542. Arguments:
  543. pIrp - a ptr to an IRP
  544. Return Value:
  545. NTSTATUS - status of the request
  546. --*/
  547. {
  548. PIO_STACK_LOCATION pIrpSp;
  549. PFILE_OBJECT pFileObject;
  550. //
  551. // fill the IRP with context information so we can
  552. // find the address object given the fileObject later.
  553. //
  554. // This must be done here, rather than after the call to NbtOpenAddress
  555. // because that call can complete the Irp before it returns. Soooo,
  556. // in the complete routine for the Irp, if the completion code is not
  557. // good, it Nulls these two context values.
  558. //
  559. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  560. pFileObject = pIrpSp->FileObject;
  561. pFileObject->FsContext = FsContext;
  562. pFileObject->FsContext2 =FsContext2;
  563. }
  564. //----------------------------------------------------------------------------
  565. VOID
  566. NTClearFileObjectContext(
  567. IN PIRP pIrp
  568. )
  569. /*++
  570. Routine Description:
  571. This Routine clears the context value in the file object when an address
  572. object is closed.
  573. Arguments:
  574. pIrp - a ptr to an IRP
  575. Return Value:
  576. none
  577. --*/
  578. {
  579. PIO_STACK_LOCATION pIrpSp;
  580. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  581. CHECK_PTR(pIrpSp->FileObject);
  582. pIrpSp->FileObject->FsContext = NULL;
  583. }
  584. //----------------------------------------------------------------------------
  585. NTSTATUS
  586. NTSetSharedAccess(
  587. IN tDEVICECONTEXT *pDeviceContext,
  588. IN PIRP pIrp,
  589. IN tADDRESSELE *pAddress)
  590. /*++
  591. Routine Description:
  592. This Routine handles setting the shared access on the file object.
  593. Arguments:
  594. pIrp - a ptr to an IRP
  595. Return Value:
  596. NTSTATUS - status of the request
  597. --*/
  598. {
  599. PACCESS_STATE AccessState;
  600. ULONG DesiredAccess;
  601. PIO_STACK_LOCATION pIrpSp;
  602. NTSTATUS status;
  603. static GENERIC_MAPPING AddressGenericMapping = { READ_CONTROL, READ_CONTROL, READ_CONTROL, READ_CONTROL };
  604. CTEPagedCode();
  605. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  606. if ((pIrpSp->Parameters.Create.ShareAccess & FILE_SHARE_READ) ||
  607. (pIrpSp->Parameters.Create.ShareAccess & FILE_SHARE_WRITE))
  608. {
  609. DesiredAccess = (ULONG)FILE_SHARE_READ;
  610. }
  611. else
  612. {
  613. DesiredAccess = (ULONG)0;
  614. }
  615. IoSetShareAccess (FILE_READ_DATA, DesiredAccess, pIrpSp->FileObject, &pAddress->ShareAccess);
  616. // assign the security descriptor ( need to to do this with the spinlock
  617. // released because the descriptor is not mapped. Assign and CheckAccess
  618. // are synchronized using a Resource.
  619. AccessState = pIrpSp->Parameters.Create.SecurityContext->AccessState;
  620. status = SeAssignSecurity (NULL, // Parent Descriptor
  621. AccessState->SecurityDescriptor,
  622. &pAddress->SecurityDescriptor,
  623. FALSE, // is a directory
  624. &AccessState->SubjectSecurityContext,
  625. &AddressGenericMapping,
  626. NonPagedPool);
  627. if (!NT_SUCCESS(status))
  628. {
  629. IoRemoveShareAccess (pIrpSp->FileObject, &pAddress->ShareAccess);
  630. }
  631. return status;
  632. }
  633. //----------------------------------------------------------------------------
  634. NTSTATUS
  635. NTCheckSharedAccess(
  636. IN tDEVICECONTEXT *pDeviceContext,
  637. IN PIRP pIrp,
  638. IN tADDRESSELE *pAddress)
  639. /*++
  640. Routine Description:
  641. This Routine handles setting the shared access on the file object.
  642. Arguments:
  643. pIrp - a ptr to an IRP
  644. Return Value:
  645. NTSTATUS - status of the request
  646. --*/
  647. {
  648. PACCESS_STATE AccessState;
  649. ACCESS_MASK GrantedAccess;
  650. BOOLEAN AccessAllowed;
  651. ULONG DesiredAccess;
  652. PIO_STACK_LOCATION pIrpSp;
  653. BOOLEAN duplicate=FALSE;
  654. NTSTATUS status;
  655. ULONG DesiredShareAccess;
  656. static GENERIC_MAPPING AddressGenericMapping =
  657. { READ_CONTROL, READ_CONTROL, READ_CONTROL, READ_CONTROL };
  658. CTEPagedCode();
  659. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  660. if ((pIrpSp->Parameters.Create.ShareAccess & FILE_SHARE_READ) ||
  661. (pIrpSp->Parameters.Create.ShareAccess & FILE_SHARE_WRITE))
  662. DesiredAccess = (ULONG)FILE_SHARE_READ;
  663. else
  664. DesiredAccess = (ULONG)0;
  665. //
  666. // The address already exists. Check the ACL and see if we
  667. // can access it. If so, simply use this address as our address.
  668. //
  669. AccessState = pIrpSp->Parameters.Create.SecurityContext->AccessState;
  670. status = STATUS_SUCCESS;
  671. // *TODO* check that this routine is doing the right thing...
  672. //
  673. AccessAllowed = SeAccessCheck(
  674. pAddress->SecurityDescriptor,
  675. &AccessState->SubjectSecurityContext,
  676. FALSE, // tokens locked
  677. pIrpSp->Parameters.Create.SecurityContext->DesiredAccess,
  678. (ACCESS_MASK)0, // previously granted
  679. NULL, // privileges
  680. &AddressGenericMapping,
  681. pIrp->RequestorMode,
  682. &GrantedAccess,
  683. &status);
  684. // use the status from the IoCheckShareAccess as the return access
  685. // event if SeAccessCheck fails....
  686. //
  687. // Hmmm .... Compare DesiredAccess to GrantedAccess?
  688. //
  689. //
  690. // Now check that we can obtain the desired share
  691. // access. We use read access to control all access.
  692. //
  693. DesiredShareAccess = (ULONG)
  694. (((pIrpSp->Parameters.Create.ShareAccess & FILE_SHARE_READ) ||
  695. (pIrpSp->Parameters.Create.ShareAccess & FILE_SHARE_WRITE)) ?
  696. FILE_SHARE_READ : 0);
  697. //ACQUIRE_SPIN_LOCK (&pDeviceContext->SpinLock, &oldirql);
  698. status = IoCheckShareAccess(
  699. FILE_READ_DATA,
  700. DesiredAccess,
  701. pIrpSp->FileObject,
  702. &pAddress->ShareAccess,
  703. TRUE);
  704. return(status);
  705. }
  706. //----------------------------------------------------------------------------
  707. NTSTATUS
  708. NTCleanUpAddress(
  709. IN tDEVICECONTEXT *pDeviceContext,
  710. IN PIRP pIrp)
  711. /*++
  712. Routine Description:
  713. This Routine handles the first stage of releasing an address object.
  714. Arguments:
  715. pIrp - a ptr to an IRP
  716. Return Value:
  717. NTSTATUS - status of the request
  718. --*/
  719. {
  720. NTSTATUS status;
  721. tCLIENTELE *pClientEle;
  722. PIO_STACK_LOCATION pIrpSp;
  723. CTEPagedCode();
  724. IF_DBG(NBT_DEBUG_NAMESRV)
  725. KdPrint(("Nbt.NTCleanUpAddress: Cleanup Address Hit ***\n"));
  726. //
  727. // Disconnect any active connections, and for each connection that is not
  728. // in use, remove one from the free list to the transport below.
  729. //
  730. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  731. pClientEle = (tCLIENTELE *) pIrpSp->FileObject->FsContext;
  732. if (!NBT_VERIFY_HANDLE (pClientEle, NBT_VERIFY_CLIENT))
  733. {
  734. ASSERTMSG ("Nbt.NTCleanUpAddress: ERROR - Invalid Address Handle\n", 0);
  735. return (STATUS_INVALID_HANDLE);
  736. }
  737. CTEVerifyHandle(pClientEle,NBT_VERIFY_CLIENT,tCLIENTELE,&status);
  738. status = NbtCleanUpAddress(pClientEle,pDeviceContext);
  739. NbtTrace(NBT_TRACE_NAMESRV, ("Cleanup address %p returns %!status!", pClientEle, status));
  740. return(status);
  741. }
  742. //----------------------------------------------------------------------------
  743. NTSTATUS
  744. NTCleanUpConnection(
  745. IN tDEVICECONTEXT *pDeviceContext,
  746. IN PIRP pIrp)
  747. /*++
  748. Routine Description:
  749. This Routine handles running down a connection in preparation for a close
  750. that will come in next. NtClose hits this entry first, and then it hits
  751. the NTCloseConnection next. If the connection was outbound, then the
  752. address object must be closed as well as the connection. This routine
  753. mainly deals with the pLowerconn connection to the transport whereas
  754. NbtCloseConnection deals with closing pConnEle, the connection to the client.
  755. Arguments:
  756. pIrp - a ptr to an IRP
  757. Return Value:
  758. NTSTATUS - status of the request
  759. --*/
  760. {
  761. NTSTATUS status;
  762. PIO_STACK_LOCATION pIrpSp;
  763. tCONNECTELE *pConnEle;
  764. CTEPagedCode();
  765. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  766. pConnEle = (tCONNECTELE *) pIrpSp->FileObject->FsContext;
  767. if (!NBT_VERIFY_HANDLE2 (pConnEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN))
  768. {
  769. ASSERTMSG ("Nbt.NTCleanUpConnection: ERROR - Invalid Connection Handle\n", 0);
  770. return (STATUS_INVALID_HANDLE);
  771. }
  772. //CTEVerifyHandle(pConnEle,NBT_VERIFY_CONNECTION,tCONNECTELE,&status);
  773. IF_DBG(NBT_DEBUG_NAMESRV)
  774. KdPrint(("Nbt.NTCleanUpConnection: Cleanup Connection Hit state= %X\n",pConnEle->state));
  775. pConnEle->ConnectionCleanedUp = TRUE;
  776. status = NbtCleanUpConnection(pConnEle,pDeviceContext);
  777. ASSERT (status != STATUS_PENDING);
  778. NbtTrace(NBT_TRACE_NAMESRV, ("Cleanup connection %p returns %!status!", pConnEle, status));
  779. return(status);
  780. }
  781. //----------------------------------------------------------------------------
  782. NTSTATUS
  783. NTAccept(
  784. IN tDEVICECONTEXT *pDeviceContext,
  785. IN PIRP pIrp)
  786. /*++
  787. Routine Description:
  788. This Routine handles passing an accept for an inbound connect indication to
  789. the OS independent code.
  790. Arguments:
  791. pIrp - a ptr to an IRP
  792. Return Value:
  793. NTSTATUS - status of the request
  794. --*/
  795. {
  796. NTSTATUS status;
  797. TDI_REQUEST TdiRequest;
  798. PIO_STACK_LOCATION pIrpSp;
  799. PTDI_REQUEST_KERNEL_ACCEPT pRequest;
  800. tCONNECTELE *pConnEle;
  801. IF_DBG(NBT_DEBUG_NAMESRV)
  802. KdPrint(("Nbt.NTAccept: ** Got an Accept from the Client **\n"));
  803. // pull the junk out of the Irp and call the non-OS specific routine.
  804. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  805. // the Parameters value points to a Request structure...
  806. pRequest = (PTDI_REQUEST_KERNEL_ACCEPT)&pIrpSp->Parameters;
  807. // the pConnEle ptr was stored in the FsContext value when the connection
  808. // was initially created.
  809. pConnEle = TdiRequest.Handle.ConnectionContext = pIrpSp->FileObject->FsContext;
  810. if (!NBT_VERIFY_HANDLE2 (pConnEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN))
  811. {
  812. ASSERTMSG ("Nbt.NTAccept: ERROR - Invalid Connection Handle\n", 0);
  813. return (STATUS_INVALID_HANDLE);
  814. }
  815. status = NbtAccept(
  816. &TdiRequest,
  817. pRequest->RequestConnectionInformation,
  818. pRequest->ReturnConnectionInformation,
  819. pIrp);
  820. return(status);
  821. }
  822. //----------------------------------------------------------------------------
  823. NTSTATUS
  824. NTDisAssociateAddress(
  825. IN tDEVICECONTEXT *pDeviceContext,
  826. IN PIRP pIrp)
  827. /*++
  828. Routine Description:
  829. This Routine handles
  830. Arguments:
  831. pIrp - a ptr to an IRP
  832. Return Value:
  833. NTSTATUS - status of the request
  834. --*/
  835. {
  836. NTSTATUS status;
  837. TDI_REQUEST TdiRequest;
  838. PIO_STACK_LOCATION pIrpSp;
  839. PTDI_REQUEST_KERNEL_ACCEPT pRequest;
  840. tCONNECTELE *pConnEle;
  841. CTEPagedCode();
  842. // pull the junk out of the Irp and call the non-OS specific routine.
  843. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  844. // the Parameters value points to a Request structure...
  845. pRequest = (PTDI_REQUEST_KERNEL_ACCEPT)&pIrpSp->Parameters;
  846. // the pConnEle ptr was stored in the FsContext value when the connection
  847. // was initially created.
  848. pConnEle = TdiRequest.Handle.ConnectionContext = pIrpSp->FileObject->FsContext;
  849. if (!NBT_VERIFY_HANDLE2 (pConnEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN))
  850. {
  851. ASSERTMSG ("Nbt.NTCloseAddress: ERROR - Invalid Address Handle\n", 0);
  852. return (STATUS_INVALID_HANDLE);
  853. }
  854. status = NbtDisassociateAddress(&TdiRequest);
  855. return(status);
  856. }
  857. LONG
  858. NextTransportAddress(
  859. IN PNBT_DELAYED_CONNECT_CONTEXT pDelConnCtx
  860. )
  861. /*++
  862. Move the pointer to the next address.
  863. --*/
  864. {
  865. pDelConnCtx->RemainingAddressLength -= (pDelConnCtx->TaAddressLength + FIELD_OFFSET(TRANSPORT_ADDRESS,Address));
  866. pDelConnCtx->pTaAddress += pDelConnCtx->TaAddressLength + FIELD_OFFSET(TRANSPORT_ADDRESS,Address);
  867. RtlCopyMemory(&pDelConnCtx->TaAddressLength,
  868. (pDelConnCtx->pTaAddress+FIELD_OFFSET(TA_ADDRESS,AddressLength)), sizeof(USHORT));
  869. pDelConnCtx->CurrIndex++;
  870. /*
  871. * make sure we don't overrun the buffer
  872. */
  873. if(pDelConnCtx->RemainingAddressLength < (pDelConnCtx->TaAddressLength + FIELD_OFFSET(TRANSPORT_ADDRESS,Address))) {
  874. KdPrint(("netbt!NextTransportAddress: insufficient TaAddress buffer size\n"));
  875. pDelConnCtx->CurrIndex = pDelConnCtx->NumberOfAddresses;
  876. }
  877. return pDelConnCtx->CurrIndex;
  878. }
  879. NTSTATUS
  880. InitDelayedNbtProcessConnect(
  881. IN PNBT_DELAYED_CONNECT_CONTEXT pDelConnCtx
  882. )
  883. /*++
  884. Reset the NBT_DELAYED_CONNECT_CONTEXT
  885. Find the first readable unicode address and writable buffer. In compound address case, NetBT will first try
  886. to establish the connection using the first readable unicode address. If this fails, it will attempt to use
  887. OEM address, ie. only one readable unicode address is effective. If DNS name resolution is used, NetBT will
  888. return the result in the first writable buffer and update the NameBufferType to NBT_WRITTEN.
  889. --*/
  890. {
  891. PTDI_REQUEST_KERNEL pRequestKernel;
  892. PIO_STACK_LOCATION pIrpSp;
  893. PTRANSPORT_ADDRESS pRemoteAddress;
  894. PUCHAR pTaAddress;
  895. enum eNameBufferType NameBufferType, UnicodeAddressNameBufferType;
  896. NTSTATUS status;
  897. tCONNECTELE *pConnEle = NULL;
  898. CTEPagedCode();
  899. pIrpSp = IoGetCurrentIrpStackLocation(pDelConnCtx->pClientIrp);
  900. pRequestKernel = (PTDI_REQUEST_KERNEL) &pIrpSp->Parameters;
  901. pRemoteAddress = pRequestKernel->RequestConnectionInformation->RemoteAddress;
  902. pDelConnCtx->NumberOfAddresses = pRemoteAddress->TAAddressCount;
  903. pDelConnCtx->RemainingAddressLength = pRequestKernel->RequestConnectionInformation->RemoteAddressLength;
  904. pDelConnCtx->pTaAddress = (PCHAR)&pRemoteAddress->Address[0];
  905. RtlCopyMemory(&pDelConnCtx->TaAddressLength,
  906. (pDelConnCtx->pTaAddress+FIELD_OFFSET(TA_ADDRESS,AddressLength)), sizeof(USHORT));
  907. pDelConnCtx->CurrIndex = 0;
  908. /*
  909. * Find the first writable buffer and readable unicode address
  910. */
  911. pDelConnCtx->pReturnBuffer = NULL;
  912. pDelConnCtx->pUnicodeAddress = NULL;
  913. for (pDelConnCtx->CurrIndex = 0; pDelConnCtx->CurrIndex < pDelConnCtx->NumberOfAddresses;
  914. NextTransportAddress(pDelConnCtx)) {
  915. USHORT TaAddressType;
  916. RtlCopyMemory(&TaAddressType, (pDelConnCtx->pTaAddress+FIELD_OFFSET(TA_ADDRESS,AddressType)), sizeof(USHORT));
  917. if (TaAddressType != TDI_ADDRESS_TYPE_NETBIOS_UNICODE_EX) {
  918. continue;
  919. }
  920. RtlCopyMemory(&NameBufferType,
  921. pDelConnCtx->pTaAddress +
  922. FIELD_OFFSET(TA_ADDRESS,Address)+
  923. FIELD_OFFSET(TDI_ADDRESS_NETBIOS_UNICODE_EX,NameBufferType),
  924. sizeof(NameBufferType));
  925. if (NameBufferType != NBT_READONLY && NameBufferType != NBT_WRITEONLY &&
  926. NameBufferType != NBT_READWRITE && NameBufferType != NBT_WRITTEN) {
  927. return STATUS_INVALID_ADDRESS;
  928. }
  929. if (NameBufferType == NBT_READONLY || NameBufferType == NBT_READWRITE) {
  930. if (pDelConnCtx->pUnicodeAddress == NULL) {
  931. pDelConnCtx->pUnicodeAddress = (TDI_ADDRESS_NETBIOS_UNICODE_EX*)
  932. (pDelConnCtx->pTaAddress + FIELD_OFFSET(TA_ADDRESS,Address));
  933. UnicodeAddressNameBufferType = NameBufferType;
  934. }
  935. }
  936. if (NameBufferType == NBT_WRITEONLY) {
  937. pDelConnCtx->pReturnBuffer = (TDI_ADDRESS_NETBIOS_UNICODE_EX*)
  938. (pDelConnCtx->pTaAddress + FIELD_OFFSET(TA_ADDRESS,Address));
  939. break;
  940. }
  941. if (NameBufferType == NBT_READWRITE) {
  942. pDelConnCtx->pReturnBuffer = (TDI_ADDRESS_NETBIOS_UNICODE_EX*)
  943. (pDelConnCtx->pTaAddress + FIELD_OFFSET(TA_ADDRESS,Address));
  944. /*
  945. * Only when no WRITEONLY buffer is presented, can we use a READWRITE buffer. So continue searching.
  946. */
  947. }
  948. }
  949. pDelConnCtx->NumberOfAddresses = pRemoteAddress->TAAddressCount;
  950. pDelConnCtx->RemainingAddressLength = pRequestKernel->RequestConnectionInformation->RemoteAddressLength;
  951. pDelConnCtx->pTaAddress = (PCHAR)&pRemoteAddress->Address[0];
  952. RtlCopyMemory(&pDelConnCtx->TaAddressLength,
  953. (pDelConnCtx->pTaAddress+FIELD_OFFSET(TA_ADDRESS,AddressLength)), sizeof(USHORT));
  954. pDelConnCtx->CurrIndex = 0;
  955. /*
  956. * Setup the first local transport address
  957. */
  958. if (pDelConnCtx->pUnicodeAddress != NULL) {
  959. pTaAddress = ((PUCHAR)pDelConnCtx->pUnicodeAddress - FIELD_OFFSET(TA_ADDRESS,Address));
  960. } else {
  961. pTaAddress = pDelConnCtx->pTaAddress;
  962. }
  963. status = NewInternalAddressFromTransportAddress(
  964. (PTRANSPORT_ADDRESS) (pTaAddress-FIELD_OFFSET(TRANSPORT_ADDRESS,Address)),
  965. pDelConnCtx->RemainingAddressLength, &pDelConnCtx->pTransportAddress);
  966. if (status != STATUS_SUCCESS) {
  967. ASSERT(pDelConnCtx->pTransportAddress == NULL);
  968. return status;
  969. }
  970. if (pDelConnCtx->pUnicodeAddress == NULL || UnicodeAddressNameBufferType != NBT_READWRITE) {
  971. pDelConnCtx->pTransportAddress->Address[0].Address[0].pNetbiosUnicodeEX = pDelConnCtx->pReturnBuffer;
  972. }
  973. ASSERT(pDelConnCtx->pTransportAddress);
  974. pConnEle = pIrpSp->FileObject->FsContext;
  975. if (NULL == pConnEle || !NBT_VERIFY_HANDLE2 (pConnEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN)) {
  976. return STATUS_INVALID_HANDLE;
  977. }
  978. pDelConnCtx->pConnEle = pConnEle;
  979. NBT_REFERENCE_CONNECTION (pConnEle, REF_CONN_MULTIPLE_CONNECT); // so we don't delete the connection
  980. return STATUS_SUCCESS;
  981. }
  982. NTSTATUS
  983. NextDelayedNbtProcessConnect(
  984. IN PNBT_DELAYED_CONNECT_CONTEXT pDelConnCtx
  985. )
  986. /*++
  987. Move the pointer to the next address.
  988. --*/
  989. {
  990. USHORT TaAddressType;
  991. enum eNameBufferType NameBufferType;
  992. PTA_NETBT_INTERNAL_ADDRESS pTransportAddress = NULL;
  993. TDI_ADDRESS_NETBT_INTERNAL *pAddr;
  994. PIO_STACK_LOCATION pIrpSp;
  995. tCONNECTELE *pConnEle;
  996. NTSTATUS status;
  997. pIrpSp = IoGetCurrentIrpStackLocation(pDelConnCtx->pClientIrp);
  998. pConnEle = pIrpSp->FileObject->FsContext;
  999. ASSERT (pConnEle->pIrp == NULL);
  1000. ASSERT(pDelConnCtx->pTransportAddress);
  1001. status = STATUS_SUCCESS;
  1002. while(1) {
  1003. /*
  1004. * Free memory allocated in previous loop
  1005. */
  1006. if (pTransportAddress) {
  1007. DeleteInternalAddress(pTransportAddress);
  1008. pTransportAddress = NULL;
  1009. }
  1010. if (pDelConnCtx->pUnicodeAddress == NULL) {
  1011. NextTransportAddress(pDelConnCtx);
  1012. } else {
  1013. pDelConnCtx->pUnicodeAddress = NULL;
  1014. }
  1015. if (pDelConnCtx->CurrIndex >= pDelConnCtx->NumberOfAddresses) {
  1016. break;
  1017. }
  1018. /*
  1019. * Skip UNICODE address.
  1020. * UNICODE address is always done first, ie. just after InitDelayedNbtProcessConnect gets called.
  1021. */
  1022. RtlCopyMemory(&TaAddressType, (pDelConnCtx->pTaAddress+FIELD_OFFSET(TA_ADDRESS,AddressType)), sizeof(USHORT));
  1023. if (TaAddressType != TDI_ADDRESS_TYPE_NETBIOS && TaAddressType != TDI_ADDRESS_TYPE_NETBIOS_EX) {
  1024. continue;
  1025. }
  1026. /*
  1027. * Since we only do OEM address, we can safely call NewInternalAddressFromTransportAddress (this guy will
  1028. * call Rtl* to convert UNICODE to OEM in UNICODE address case so that we may hit bug check.)
  1029. */
  1030. status = NewInternalAddressFromTransportAddress(
  1031. (PTRANSPORT_ADDRESS) (pDelConnCtx->pTaAddress-FIELD_OFFSET(TRANSPORT_ADDRESS,Address)),
  1032. pDelConnCtx->RemainingAddressLength, &pTransportAddress);
  1033. if (status != STATUS_SUCCESS) {
  1034. ASSERT(pTransportAddress == NULL);
  1035. continue;
  1036. }
  1037. ASSERT(pTransportAddress);
  1038. pAddr = pTransportAddress->Address[0].Address;
  1039. /*
  1040. * Always attach a writable buffer in OEM address case
  1041. */
  1042. pAddr->pNetbiosUnicodeEX = pDelConnCtx->pReturnBuffer;
  1043. /*
  1044. * Skip any address which is same as previous one.
  1045. * Since the previous one fails, there is no point to use it again.
  1046. */
  1047. if (IsDeviceNetbiosless(pDelConnCtx->pDeviceContext) ||
  1048. (pDelConnCtx->pLocalIrp->IoStatus.Status == STATUS_HOST_UNREACHABLE)) {
  1049. OEM_STRING RemoteName, PreviouseRemoteName;
  1050. CTEMemCopy (&RemoteName, &pAddr->OEMRemoteName, sizeof(OEM_STRING));
  1051. CTEMemCopy (&PreviouseRemoteName,
  1052. &pDelConnCtx->pTransportAddress->Address[0].Address[0].OEMRemoteName, sizeof(OEM_STRING));
  1053. if ((RemoteName.Length) && (RemoteName.Length == PreviouseRemoteName.Length) &&
  1054. (CTEMemEqu (RemoteName.Buffer, PreviouseRemoteName.Buffer, RemoteName.Length))) {
  1055. IF_DBG(NBT_DEBUG_NETBIOS_EX)
  1056. KdPrint(("Nbt.DelayedNbtProcessConnect: Irp=<%x>, Names match!<%16.16s:%x>, Types=<%x:%x>\n",
  1057. pDelConnCtx->pClientIrp, pAddr->OEMRemoteName.Buffer, pAddr->OEMRemoteName.Buffer[15],
  1058. pAddr->AddressType, pDelConnCtx->pTransportAddress->Address[0].Address[0].AddressType));
  1059. continue;
  1060. }
  1061. }
  1062. if (pConnEle->RemoteNameDoesNotExistInDNS) {
  1063. IF_DBG(NBT_DEBUG_NETBIOS_EX)
  1064. KdPrint(("netbt!DelayedNbtProcessConnect: Skipping address type %lx length %lx\n"
  1065. "\t\tfor nonexistent name, pIrp %lx, pLocalIrp %lx\n",
  1066. TaAddressType, pDelConnCtx->TaAddressLength,
  1067. pDelConnCtx->pClientIrp, pDelConnCtx->pLocalIrp));
  1068. // If the address type is such that we rely on DNS name resolution and
  1069. // if a prior attempt failed, there is no point in reissuing the request.
  1070. // We can fail them without having to go on the NET.
  1071. if (TaAddressType == TDI_ADDRESS_TYPE_NETBIOS_EX) {
  1072. status = STATUS_BAD_NETWORK_PATH;
  1073. continue;
  1074. } else if (pDelConnCtx->TaAddressLength != TDI_ADDRESS_LENGTH_NETBIOS) {
  1075. ASSERT(TaAddressType == TDI_ADDRESS_TYPE_NETBIOS);
  1076. status = STATUS_INVALID_ADDRESS_COMPONENT;
  1077. continue;
  1078. }
  1079. }
  1080. IF_DBG(NBT_DEBUG_NETBIOS_EX)
  1081. KdPrint(("netbt!DelayedNbtProcessConnect: Sending local irp=%lx, %lx of %lx\n"
  1082. "\t\t\t\tTA=%lx Length=%lx\n",
  1083. pDelConnCtx->pLocalIrp, pDelConnCtx->CurrIndex+1, pDelConnCtx->NumberOfAddresses,
  1084. pDelConnCtx->pTaAddress, pDelConnCtx->TaAddressLength));
  1085. DeleteInternalAddress(pDelConnCtx->pTransportAddress);
  1086. pDelConnCtx->pTransportAddress = pTransportAddress;
  1087. pTransportAddress = NULL;
  1088. break;
  1089. }
  1090. if (pTransportAddress) {
  1091. DeleteInternalAddress(pTransportAddress);
  1092. pTransportAddress = NULL;
  1093. }
  1094. return status;
  1095. }
  1096. VOID
  1097. DoneDelayedNbtProcessConnect(
  1098. IN PNBT_DELAYED_CONNECT_CONTEXT pDelConnCtx,
  1099. NTSTATUS status
  1100. )
  1101. /*++
  1102. 1. Complete the client IRP
  1103. 2. Cleanup everything
  1104. --*/
  1105. {
  1106. tCONNECTELE *pConnEle = NULL;
  1107. ASSERT(pDelConnCtx->pLocalIrp);
  1108. ASSERT(pDelConnCtx->pClientIrp);
  1109. NbtCancelCancelRoutine(pDelConnCtx->pClientIrp);
  1110. pConnEle = pDelConnCtx->pConnEle;
  1111. NBT_DEREFERENCE_CONNECTION (pConnEle, REF_CONN_MULTIPLE_CONNECT); // so we don't delete the connection
  1112. ASSERT(status != STATUS_PENDING);
  1113. if (pDelConnCtx->pLocalIrp) {
  1114. IF_DBG(NBT_DEBUG_NETBIOS_EX)
  1115. KdPrint(("netbt!DoneDelayedNbtProcessConnect: Freeing Local Irp=<%x>\n", pDelConnCtx->pLocalIrp));
  1116. IoFreeIrp(pDelConnCtx->pLocalIrp);
  1117. }
  1118. if (pDelConnCtx->pTransportAddress) {
  1119. DeleteInternalAddress(pDelConnCtx->pTransportAddress);
  1120. }
  1121. IF_DBG(NBT_DEBUG_NETBIOS_EX)
  1122. KdPrint(("netbt!DoneDelayed...: Connect Complete, LocalIrp=<%x>, ClientIrp=<%x>, Status=<%x>\n",
  1123. pDelConnCtx->pLocalIrp, pDelConnCtx->pClientIrp, status));
  1124. NbtTrace(NBT_TRACE_OUTBOUND, ("Complete connection request pIrp=%p pLocalIrp=%p with %!status!",
  1125. pDelConnCtx->pClientIrp, pDelConnCtx->pLocalIrp, status));
  1126. NTIoComplete (pDelConnCtx->pClientIrp, status, 0);
  1127. pDelConnCtx->pLocalIrp = NULL;
  1128. pDelConnCtx->pClientIrp = NULL;
  1129. pDelConnCtx->pTransportAddress = NULL;
  1130. CTEFreeMem(pDelConnCtx);
  1131. }
  1132. //----------------------------------------------------------------------------
  1133. NTSTATUS
  1134. NbtpConnectCompletionRoutine(
  1135. PDEVICE_OBJECT pDeviceObject,
  1136. PIRP pIrp,
  1137. PVOID pCompletionContext
  1138. )
  1139. /*++
  1140. Routine Description:
  1141. This Routine is the completion routine for local IRPS that are generated
  1142. to handle compound transport addresses
  1143. Arguments:
  1144. pDeviceObject - the device object
  1145. pIrp - a ptr to an IRP
  1146. pCompletionContext - the completion context
  1147. Return Value:
  1148. NTSTATUS - status of the request
  1149. --*/
  1150. {
  1151. PNBT_DELAYED_CONNECT_CONTEXT pDelConnCtx;
  1152. NTSTATUS Status, Status2;
  1153. PIRP pLocalIrp;
  1154. tDEVICECONTEXT *pDeviceContext;
  1155. pDelConnCtx = pCompletionContext;
  1156. pDeviceContext = pDelConnCtx->pDeviceContext;
  1157. pLocalIrp = pDelConnCtx->pLocalIrp;
  1158. ASSERT (pIrp == pLocalIrp);
  1159. Status = pLocalIrp->IoStatus.Status;
  1160. ASSERT(Status != STATUS_PENDING);
  1161. NbtTrace(NBT_TRACE_OUTBOUND, ("pIrp %p: %!status! pParentIrp %p",
  1162. pIrp, Status, pDelConnCtx->pClientIrp));
  1163. pDelConnCtx->ProcessingDone = TRUE;
  1164. /*
  1165. * Let's move to next address
  1166. */
  1167. Status2 = NextDelayedNbtProcessConnect(pDelConnCtx);
  1168. /*
  1169. * Are we done
  1170. */
  1171. if (Status == STATUS_CANCELLED || Status == STATUS_SUCCESS || Status2 != STATUS_SUCCESS ||
  1172. pDelConnCtx->CurrIndex >= pDelConnCtx->NumberOfAddresses) {
  1173. if (Status2 != STATUS_SUCCESS) {
  1174. Status = Status2;
  1175. }
  1176. IF_DBG(NBT_DEBUG_NETBIOS_EX)
  1177. KdPrint(("Nbt.NbtpC...:==>Connect Complete, LocalIrp=<%x>, ClientIrp=<%x>, Status=<%x> <==\n",
  1178. pIrp,pDelConnCtx->pClientIrp, Status));
  1179. if (Status == STATUS_HOST_UNREACHABLE) {
  1180. Status = STATUS_BAD_NETWORK_PATH;
  1181. }
  1182. DoneDelayedNbtProcessConnect(pDelConnCtx, Status);
  1183. return STATUS_MORE_PROCESSING_REQUIRED;
  1184. }
  1185. /*
  1186. * Start worker thread to process the Connect request on the next address
  1187. */
  1188. IF_DBG(NBT_DEBUG_NETBIOS_EX)
  1189. KdPrint(("NbtpConnectCompletionRoutine: queuing worker item, local irp=%lx, previous status=%lx\n",
  1190. pIrp, Status));
  1191. if (STATUS_SUCCESS != NTQueueToWorkerThread(NULL, DelayedNbtProcessConnect,
  1192. NULL,
  1193. pDelConnCtx,
  1194. NULL,
  1195. pDeviceContext,
  1196. FALSE))
  1197. {
  1198. KdPrint(("Nbt.NbtpConnectCompletionRoutine: Failed to Enqueue Worker thread\n"));
  1199. DoneDelayedNbtProcessConnect(pDelConnCtx, STATUS_INSUFFICIENT_RESOURCES);
  1200. }
  1201. return STATUS_MORE_PROCESSING_REQUIRED;
  1202. }
  1203. //----------------------------------------------------------------------------
  1204. NTSTATUS
  1205. DelayedNbtProcessConnect(
  1206. IN tDGRAM_SEND_TRACKING *pUnused1,
  1207. IN PVOID pClientContext,
  1208. IN PVOID pUnused2,
  1209. IN tDEVICECONTEXT *pUnused3
  1210. )
  1211. /*++
  1212. Routine Description:
  1213. This Routine is the worker thread for processing Connect Requests.
  1214. Arguments:
  1215. pContext
  1216. Return Value:
  1217. NONE
  1218. --*/
  1219. {
  1220. PNBT_DELAYED_CONNECT_CONTEXT pDelConnCtx = NULL;
  1221. PIRP pIrp = NULL, pLocalIrp = NULL;
  1222. PIO_STACK_LOCATION pIrpSp = NULL;
  1223. tCONNECTELE *pConnEle = NULL;
  1224. NTSTATUS Status = STATUS_SUCCESS;
  1225. PTDI_REQUEST_KERNEL pRequestKernel = NULL;
  1226. CTEPagedCode();
  1227. pDelConnCtx = (PNBT_DELAYED_CONNECT_CONTEXT) pClientContext;
  1228. pIrp = pDelConnCtx->pClientIrp;
  1229. pLocalIrp = pDelConnCtx->pLocalIrp;
  1230. IF_DBG(NBT_DEBUG_NETBIOS_EX)
  1231. KdPrint(("netbt!DelayedNbtProcessConnect: Enter with local irp=%lx, %lx of %lx\n"
  1232. "\t\t\t\tTA=%lx Length=%lx\n",
  1233. pLocalIrp, pDelConnCtx->CurrIndex+1, pDelConnCtx->NumberOfAddresses,
  1234. pDelConnCtx->pTaAddress, pDelConnCtx->TaAddressLength));
  1235. pConnEle = pDelConnCtx->pConnEle;
  1236. if (!NBT_VERIFY_HANDLE2 (pConnEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN)) {
  1237. DbgPrint ("Nbt.DelayedNbtProcessConnect: ERROR - Invalid Connection Handle\n");
  1238. DoneDelayedNbtProcessConnect(pDelConnCtx,
  1239. (pDelConnCtx->ProcessingDone)? pLocalIrp->IoStatus.Status: STATUS_UNSUCCESSFUL);
  1240. return STATUS_UNSUCCESSFUL;
  1241. }
  1242. CHECK_PTR (pConnEle);
  1243. Status = STATUS_UNSUCCESSFUL;
  1244. /*
  1245. * Set the Cancel routine and ensure that the original IRP was not cancelled before continuing.
  1246. */
  1247. IF_DBG(NBT_DEBUG_NETBIOS_EX)
  1248. KdPrint (("Nbt.DelayedNbtProcessConnect: Setting Cancel=<NbtCancelConnect> for Irp:Device <%x:%x>\n",
  1249. pIrp, pDelConnCtx->pDeviceContext));
  1250. if (STATUS_CANCELLED == NTCheckSetCancelRoutine(pIrp, NbtCancelConnect, pDelConnCtx->pDeviceContext)) {
  1251. IF_DBG(NBT_DEBUG_NETBIOS_EX)
  1252. KdPrint(("Nbt.DelayedNbtProcessConnect: Irp <%x> was cancelled\n", pIrp));
  1253. pConnEle->pIrp = NULL;
  1254. DoneDelayedNbtProcessConnect(pDelConnCtx, STATUS_CANCELLED);
  1255. return STATUS_CANCELLED;
  1256. }
  1257. /*
  1258. * InitDelayedNbtProcessConnect/NextDelayedNbtProcessConnect has set up pDelConnCtx->pTransportAddress properly
  1259. */
  1260. ASSERT(pDelConnCtx->pTransportAddress);
  1261. pConnEle->AddressType = pDelConnCtx->pTransportAddress->Address[0].Address[0].AddressType;
  1262. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  1263. pRequestKernel = (PTDI_REQUEST_KERNEL) &pIrpSp->Parameters;
  1264. pDelConnCtx->LocalConnectionInformation = *(pRequestKernel->RequestConnectionInformation);
  1265. pDelConnCtx->LocalConnectionInformation.RemoteAddress = pDelConnCtx->pTransportAddress;
  1266. pDelConnCtx->LocalConnectionInformation.RemoteAddressLength = pDelConnCtx->pTransportAddress->Address[0].AddressLength;
  1267. //
  1268. // Save the thread info for debugging purposes!
  1269. //
  1270. pLocalIrp->Tail.Overlay.Thread = PsGetCurrentThread();
  1271. TdiBuildConnect (pLocalIrp,
  1272. &pDelConnCtx->pDeviceContext->DeviceObject,
  1273. pIrpSp->FileObject,
  1274. NbtpConnectCompletionRoutine,
  1275. pDelConnCtx,
  1276. pRequestKernel->RequestSpecific,
  1277. &pDelConnCtx->LocalConnectionInformation,
  1278. pRequestKernel->ReturnConnectionInformation);
  1279. Status = IoCallDriver(&pDelConnCtx->pDeviceContext->DeviceObject,pLocalIrp);
  1280. if (Status != STATUS_PENDING) {
  1281. IF_DBG(NBT_DEBUG_NETBIOS_EX)
  1282. KdPrint(("Nbt.DelayedNbtProcessConnect: IoCallDriver returned %lx for irp %lx (%lx)\n",
  1283. Status,pIrp,pLocalIrp));
  1284. // ASSERT(0);
  1285. }
  1286. return STATUS_PENDING;
  1287. }
  1288. //----------------------------------------------------------------------------
  1289. NTSTATUS
  1290. NTConnect(
  1291. IN tDEVICECONTEXT *pDeviceContext,
  1292. IN PIRP pIrp)
  1293. /*++
  1294. Routine Description:
  1295. This Routine handles calling the non OS specific code to open a session
  1296. connection to a destination.
  1297. Arguments:
  1298. pIrp - a ptr to an IRP
  1299. Return Value:
  1300. NTSTATUS - status of the request
  1301. --*/
  1302. {
  1303. PIO_STACK_LOCATION pIrpSp;
  1304. PTRANSPORT_ADDRESS pRemoteAddress;
  1305. PTDI_REQUEST_KERNEL pRequestKernel;
  1306. PIRP pLocalIrp;
  1307. PNBT_DELAYED_CONNECT_CONTEXT pDelConnCtx;
  1308. NTSTATUS Status;
  1309. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  1310. pRequestKernel = (PTDI_REQUEST_KERNEL)&pIrpSp->Parameters;
  1311. NbtTrace(NBT_TRACE_OUTBOUND, ("TDI_CONNECT pIrp %p", pIrp));
  1312. try
  1313. {
  1314. pRemoteAddress = pRequestKernel->RequestConnectionInformation->RemoteAddress;
  1315. if (pRequestKernel->RequestConnectionInformation->RemoteAddressLength < sizeof(TRANSPORT_ADDRESS)) {
  1316. return STATUS_INVALID_ADDRESS_COMPONENT;
  1317. }
  1318. }
  1319. except(EXCEPTION_EXECUTE_HANDLER)
  1320. {
  1321. KdPrint (("Nbt.NTConnect: Exception <0x%x> trying to access Connection info\n", GetExceptionCode()));
  1322. return STATUS_INVALID_ADDRESS_COMPONENT;
  1323. }
  1324. if (pIrpSp->CompletionRoutine != NbtpConnectCompletionRoutine) {
  1325. pDelConnCtx = NbtAllocMem(sizeof(NBT_DELAYED_CONNECT_CONTEXT),NBT_TAG('e'));
  1326. if (!pDelConnCtx) {
  1327. return(STATUS_INSUFFICIENT_RESOURCES);
  1328. }
  1329. CTEZeroMemory(pDelConnCtx, sizeof(NBT_DELAYED_CONNECT_CONTEXT));
  1330. pLocalIrp = IoAllocateIrp(pDeviceContext->DeviceObject.StackSize,FALSE);
  1331. if (!pLocalIrp) {
  1332. CTEFreeMem(pDelConnCtx);
  1333. return(STATUS_INSUFFICIENT_RESOURCES);
  1334. }
  1335. pDelConnCtx->pDeviceContext = pDeviceContext;
  1336. pDelConnCtx->pClientIrp = pIrp;
  1337. pDelConnCtx->pLocalIrp = pLocalIrp;
  1338. pDelConnCtx->pTransportAddress = NULL;
  1339. pDelConnCtx->ProcessingDone = FALSE;
  1340. Status = InitDelayedNbtProcessConnect(pDelConnCtx);
  1341. if (!NT_SUCCESS(Status)) {
  1342. CTEFreeMem(pDelConnCtx);
  1343. IoFreeIrp(pLocalIrp);
  1344. return Status;
  1345. }
  1346. NbtTrace(NBT_TRACE_OUTBOUND, ("Connection request pIrp=%p pLocalIrp=%p", pIrp, pLocalIrp));
  1347. //return (DelayedNbtProcessConnect (NULL, pDelConnCtx, NULL, NULL));
  1348. DelayedNbtProcessConnect (NULL, pDelConnCtx, NULL, NULL);
  1349. // Ignore the return from DelayedNbtProcessConnect and always return STATUS_PENDING;
  1350. // our client completion routine will take care of completing the IRP
  1351. // Otherwise, we will complete the IRP twice.
  1352. return STATUS_PENDING;
  1353. }
  1354. else
  1355. {
  1356. TDI_REQUEST Request;
  1357. tCONNECTELE *pConnEle;
  1358. // call the non-NT specific function to setup the connection
  1359. pConnEle = Request.Handle.ConnectionContext = pIrpSp->FileObject->FsContext;
  1360. if (!NBT_VERIFY_HANDLE2 (pConnEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN))
  1361. {
  1362. ASSERTMSG ("Nbt.NTConnect: ERROR - Invalid Connection Handle\n", 0);
  1363. return (STATUS_INVALID_HANDLE);
  1364. }
  1365. /*
  1366. * A user mode process may send us a faked request with a completion routine
  1367. * equal to NbtpConnectCompletionRoutine.
  1368. * Never let it pass through.
  1369. */
  1370. if (pIrp->RequestorMode != KernelMode) {
  1371. ASSERTMSG ("Nbt.NTConnect: ERROR - Invalid request\n", 0);
  1372. return (STATUS_INVALID_PARAMETER);
  1373. }
  1374. return NbtConnect(&Request,
  1375. pRequestKernel->RequestSpecific, // Ulong
  1376. pRequestKernel->RequestConnectionInformation,
  1377. pIrp);
  1378. }
  1379. }
  1380. //----------------------------------------------------------------------------
  1381. NTSTATUS
  1382. NTDisconnect(
  1383. IN tDEVICECONTEXT *pDeviceContext,
  1384. IN PIRP pIrp)
  1385. /*++
  1386. Routine Description:
  1387. This Routine handles calling the Non OS specific code to disconnect a
  1388. session.
  1389. Arguments:
  1390. pIrp - a ptr to an IRP
  1391. Return Value:
  1392. NTSTATUS - status of the request
  1393. --*/
  1394. {
  1395. TDI_REQUEST Request;
  1396. PIO_STACK_LOCATION pIrpSp;
  1397. NTSTATUS status;
  1398. PTDI_REQUEST_KERNEL pRequestKernel;
  1399. tCONNECTELE *pConnEle;
  1400. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  1401. pRequestKernel = (PTDI_REQUEST_KERNEL)&pIrpSp->Parameters;
  1402. pConnEle = Request.Handle.ConnectionContext = pIrpSp->FileObject->FsContext;
  1403. if (!NBT_VERIFY_HANDLE2 (pConnEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN))
  1404. {
  1405. ASSERTMSG ("Nbt.NTDisconnect: ERROR - Invalid Connection Handle\n", 0);
  1406. return (STATUS_INVALID_HANDLE);
  1407. }
  1408. // call the non-NT specific function to setup the connection
  1409. NbtTrace(NBT_TRACE_DISCONNECT, ("Client Disconnects %!NBTNAME!<%02x>",
  1410. pConnEle->RemoteName, (unsigned char)pConnEle->RemoteName[15]));
  1411. status = NbtDisconnect(
  1412. &Request,
  1413. pRequestKernel->RequestSpecific, // Large Integer
  1414. (ULONG) pRequestKernel->RequestFlags,
  1415. pRequestKernel->RequestConnectionInformation,
  1416. pRequestKernel->ReturnConnectionInformation,
  1417. pIrp
  1418. );
  1419. NbtTrace(NBT_TRACE_DISCONNECT, ("Client Disconnects status: %!status!", status));
  1420. return(status);
  1421. }
  1422. //----------------------------------------------------------------------------
  1423. NTSTATUS
  1424. NTListen(
  1425. IN tDEVICECONTEXT *pDeviceContext,
  1426. IN PIRP pIrp)
  1427. /*++
  1428. Routine Description:
  1429. This Routine handles
  1430. Arguments:
  1431. pIrp - a ptr to an IRP
  1432. Return Value:
  1433. NTSTATUS - status of the request
  1434. --*/
  1435. {
  1436. NTSTATUS status;
  1437. TDI_REQUEST Request;
  1438. PTDI_REQUEST_KERNEL pRequestKernel;
  1439. PIO_STACK_LOCATION pIrpSp;
  1440. tCONNECTELE *pConnEle;
  1441. CTEPagedCode();
  1442. IF_DBG(NBT_DEBUG_NAMESRV)
  1443. KdPrint(("Nbt.NTListen: Got a LISTEN !!! *****************\n"));
  1444. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  1445. pRequestKernel = (PTDI_REQUEST_KERNEL)&pIrpSp->Parameters;
  1446. pConnEle = Request.Handle.ConnectionContext = pIrpSp->FileObject->FsContext;
  1447. if (NBT_VERIFY_HANDLE2 (pConnEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN))
  1448. {
  1449. try
  1450. {
  1451. PCHAR pName;
  1452. ULONG lNameType;
  1453. ULONG NameLen;
  1454. // Initialize Request data (may be needed by Vxd)
  1455. Request.RequestNotifyObject = NULL;
  1456. Request.RequestContext = NULL;
  1457. // call the non-NT specific function to setup the connection
  1458. status = NbtListen (&Request,
  1459. (ULONG) pRequestKernel->RequestFlags, // Ulong
  1460. pRequestKernel->RequestConnectionInformation,
  1461. pRequestKernel->ReturnConnectionInformation,
  1462. pIrp);
  1463. }
  1464. except(EXCEPTION_EXECUTE_HANDLER)
  1465. {
  1466. KdPrint (("Nbt.NTListen: Exception <0x%x> trying to access buffer\n", GetExceptionCode()));
  1467. status = STATUS_INVALID_ADDRESS;
  1468. }
  1469. }
  1470. else
  1471. {
  1472. ASSERTMSG ("Nbt.NTListen: ERROR - Invalid Connection Handle\n", 0);
  1473. status = STATUS_INVALID_HANDLE; // Bug# 202340: Have to complete Irp here!
  1474. }
  1475. if (status != STATUS_PENDING)
  1476. {
  1477. NTIoComplete(pIrp,status,0);
  1478. }
  1479. return(status);
  1480. }
  1481. //----------------------------------------------------------------------------
  1482. NBT_WORK_ITEM_CONTEXT *
  1483. FindLmhSvcRequest(
  1484. IN PDEVICE_OBJECT DeviceContext,
  1485. IN PIRP pIrp,
  1486. IN tLMHSVC_REQUESTS *pLmhRequest
  1487. )
  1488. /*++
  1489. Routine Description:
  1490. This routine handles the cancelling a Query to LmHost, so that the client's
  1491. irp can be returned to the client. This cancellation is instigated
  1492. by the client (i.e. RDR).
  1493. Arguments:
  1494. Return Value:
  1495. The final status from the operation.
  1496. --*/
  1497. {
  1498. tDGRAM_SEND_TRACKING *pTracker;
  1499. NBT_WORK_ITEM_CONTEXT *Context;
  1500. BOOLEAN FoundIt = FALSE;
  1501. PLIST_ENTRY pHead;
  1502. PLIST_ENTRY pEntry;
  1503. if (pLmhRequest->ResolvingNow && pLmhRequest->Context)
  1504. {
  1505. // this is the session setup tracker
  1506. //
  1507. Context = (NBT_WORK_ITEM_CONTEXT *) pLmhRequest->Context;
  1508. pTracker = (tDGRAM_SEND_TRACKING *) Context->pClientContext;
  1509. if (pTracker->pClientIrp == pIrp)
  1510. {
  1511. pLmhRequest->Context = NULL;
  1512. FoundIt = TRUE;
  1513. }
  1514. }
  1515. else
  1516. {
  1517. //
  1518. // go through the list of Queued requests to find the correct one
  1519. // and cancel it
  1520. //
  1521. pHead = pEntry = &pLmhRequest->ToResolve;
  1522. while ((pEntry = pEntry->Flink) != pHead)
  1523. {
  1524. Context = CONTAINING_RECORD (pEntry,NBT_WORK_ITEM_CONTEXT,Linkage);
  1525. // this is the session setup tracker
  1526. //
  1527. pTracker = (tDGRAM_SEND_TRACKING *)Context->pClientContext;
  1528. if (pTracker->pClientIrp == pIrp)
  1529. {
  1530. RemoveEntryList(pEntry);
  1531. FoundIt = TRUE;
  1532. break;
  1533. }
  1534. }
  1535. }
  1536. return (FoundIt ? Context : NULL);
  1537. }
  1538. //----------------------------------------------------------------------------
  1539. NTSTATUS
  1540. QueryProviderCompletion(
  1541. IN PDEVICE_OBJECT DeviceContext,
  1542. IN PIRP Irp,
  1543. IN PVOID Context
  1544. )
  1545. /*++
  1546. Routine Description:
  1547. This routine handles the completion event when the Query Provider
  1548. Information completes. This routine must decrement the MaxDgramSize
  1549. and max send size by the respective NBT header sizes.
  1550. Arguments:
  1551. DeviceObject - unused.
  1552. Irp - Supplies Irp that the transport has finished processing.
  1553. Context - not used
  1554. Return Value:
  1555. The final status from the operation (success or an exception).
  1556. --*/
  1557. {
  1558. PTDI_PROVIDER_INFO pProvider;
  1559. ULONG HdrSize;
  1560. ULONG SubnetAddr;
  1561. ULONG ThisSubnetAddr;
  1562. PLIST_ENTRY pHead;
  1563. PLIST_ENTRY pEntry;
  1564. tDEVICECONTEXT *pDeviceContext;
  1565. tDEVICECONTEXT *pDevContext;
  1566. CTELockHandle OldIrq;
  1567. if (NT_SUCCESS(Irp->IoStatus.Status))
  1568. {
  1569. pDeviceContext = (tDEVICECONTEXT *)DeviceContext;
  1570. pProvider = (PTDI_PROVIDER_INFO)MmGetMdlVirtualAddress(Irp->MdlAddress);
  1571. //
  1572. // Set the correct service flags to indicate what Netbt supports.
  1573. //
  1574. pProvider->ServiceFlags = TDI_SERVICE_MESSAGE_MODE |
  1575. TDI_SERVICE_CONNECTION_MODE |
  1576. TDI_SERVICE_CONNECTIONLESS_MODE |
  1577. TDI_SERVICE_ERROR_FREE_DELIVERY |
  1578. TDI_SERVICE_BROADCAST_SUPPORTED |
  1579. TDI_SERVICE_MULTICAST_SUPPORTED |
  1580. TDI_SERVICE_DELAYED_ACCEPTANCE |
  1581. TDI_SERVICE_ROUTE_DIRECTED |
  1582. TDI_SERVICE_FORCE_ACCESS_CHECK;
  1583. pProvider->MinimumLookaheadData = 128;
  1584. if (pProvider->MaxSendSize > sizeof(tSESSIONHDR))
  1585. {
  1586. //
  1587. // Nbt has just a two byte + 1 bit session message length, so it
  1588. // can't have a send size larger than 1ffff
  1589. //
  1590. if (pProvider->MaxSendSize > (0x1FFFF + sizeof(tSESSIONHDR)))
  1591. {
  1592. pProvider->MaxSendSize = 0x1FFFF;
  1593. }
  1594. else
  1595. {
  1596. pProvider->MaxSendSize -= sizeof(tSESSIONHDR);
  1597. }
  1598. }
  1599. else
  1600. {
  1601. pProvider->MaxSendSize = 0;
  1602. }
  1603. // subtract the datagram hdr size and the scope size (times 2)
  1604. HdrSize = DGRAM_HDR_SIZE + (NbtConfig.ScopeLength << 1);
  1605. if ((!IsDeviceNetbiosless (pDeviceContext)) &&
  1606. (pProvider->MaxDatagramSize > HdrSize))
  1607. {
  1608. pProvider->MaxDatagramSize -= HdrSize;
  1609. if (pProvider->MaxDatagramSize > MAX_NBT_DGRAM_SIZE)
  1610. {
  1611. pProvider->MaxDatagramSize = MAX_NBT_DGRAM_SIZE;
  1612. }
  1613. }
  1614. else
  1615. {
  1616. pProvider->MaxDatagramSize = 0;
  1617. }
  1618. //
  1619. // We need to hold the JointLock before we traverse
  1620. // the list of Devices
  1621. //
  1622. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  1623. //
  1624. // Check if any of the adapters with the same subnet address have
  1625. // the PointtoPoint bit set - and if so set it in the response.
  1626. //
  1627. SubnetAddr = pDeviceContext->IpAddress & pDeviceContext->SubnetMask;
  1628. pEntry = pHead = &NbtConfig.DeviceContexts;
  1629. while ((pEntry = pEntry->Flink) != pHead)
  1630. {
  1631. pDevContext = CONTAINING_RECORD(pEntry,tDEVICECONTEXT,Linkage);
  1632. ThisSubnetAddr = pDevContext->IpAddress & pDevContext->SubnetMask;
  1633. if ((SubnetAddr == ThisSubnetAddr) &&
  1634. (pDevContext->IpInterfaceFlags & IP_INTFC_FLAG_P2P))
  1635. {
  1636. pProvider->ServiceFlags |= TDI_SERVICE_POINT_TO_POINT;
  1637. break;
  1638. }
  1639. }
  1640. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  1641. }
  1642. //
  1643. // Must return a non-error status otherwise the IO system will not copy
  1644. // back into the users buffer.
  1645. //
  1646. return(STATUS_SUCCESS);
  1647. }
  1648. //----------------------------------------------------------------------------
  1649. NTSTATUS
  1650. NTQueryInformation(
  1651. IN tDEVICECONTEXT *pDeviceContext,
  1652. IN PIRP pIrp)
  1653. /*++
  1654. Routine Description:
  1655. This Routine handles
  1656. Arguments:
  1657. pIrp - a ptr to an IRP
  1658. Return Value:
  1659. NTSTATUS - status of the request
  1660. --*/
  1661. {
  1662. PIO_STACK_LOCATION pIrpSp;
  1663. PTDI_REQUEST_KERNEL_QUERY_INFORMATION Query;
  1664. NTSTATUS status = STATUS_UNSUCCESSFUL;
  1665. NTSTATUS Locstatus;
  1666. PVOID pBuffer = NULL;
  1667. LONG Size ;
  1668. PTA_NETBIOS_ADDRESS BroadcastAddress;
  1669. ULONG AddressLength;
  1670. ULONG BytesCopied = 0;
  1671. PDEVICE_OBJECT pDeviceObject;
  1672. //
  1673. // Should not be pageable since AFD can call us at raised Irql in case of AcceptEx.
  1674. //
  1675. // CTEPagedCode();
  1676. if (pDeviceContext == pWinsDeviceContext)
  1677. {
  1678. NTIoComplete(pIrp, STATUS_INVALID_DEVICE_REQUEST, 0);
  1679. return (STATUS_INVALID_DEVICE_REQUEST);
  1680. }
  1681. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  1682. Query = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&pIrpSp->Parameters;
  1683. IF_DBG(NBT_DEBUG_NAMESRV)
  1684. KdPrint(("Nbt.NTQueryInformation: Query type = %X\n",Query->QueryType));
  1685. switch (Query->QueryType)
  1686. {
  1687. case TDI_QUERY_BROADCAST_ADDRESS:
  1688. {
  1689. // the broadcast address is the netbios name "*0000000..."
  1690. if ((!pIrp->MdlAddress) ||
  1691. (!(BroadcastAddress = (PTA_NETBIOS_ADDRESS)NbtAllocMem(sizeof(TA_NETBIOS_ADDRESS),NBT_TAG('b')))))
  1692. {
  1693. status = STATUS_INSUFFICIENT_RESOURCES;
  1694. break;
  1695. }
  1696. AddressLength = sizeof(TA_NETBIOS_ADDRESS);
  1697. BroadcastAddress->TAAddressCount = 1;
  1698. BroadcastAddress->Address[0].AddressLength = NETBIOS_NAME_SIZE +
  1699. sizeof(USHORT);
  1700. BroadcastAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
  1701. BroadcastAddress->Address[0].Address[0].NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_GROUP;
  1702. // the broadcast address to NetBios is "* 000000...", an * followed
  1703. // by 15 zeroes.
  1704. CTEZeroMemory(BroadcastAddress->Address[0].Address[0].NetbiosName,
  1705. NETBIOS_NAME_SIZE);
  1706. BroadcastAddress->Address[0].Address[0].NetbiosName[0] = '*';
  1707. status = TdiCopyBufferToMdl (
  1708. (PVOID)BroadcastAddress,
  1709. 0,
  1710. AddressLength,
  1711. pIrp->MdlAddress,
  1712. 0,
  1713. (PULONG)&pIrp->IoStatus.Information);
  1714. BytesCopied = (ULONG) pIrp->IoStatus.Information;
  1715. CTEMemFree((PVOID)BroadcastAddress);
  1716. break;
  1717. }
  1718. case TDI_QUERY_PROVIDER_INFO:
  1719. {
  1720. //
  1721. // Simply pass the Irp on by to the Transport, and let it
  1722. // fill in the provider info
  1723. //
  1724. if (!pDeviceContext->IpAddress)
  1725. {
  1726. status = STATUS_INVALID_DEVICE_STATE;
  1727. break;
  1728. }
  1729. if (StreamsStack)
  1730. {
  1731. TdiBuildQueryInformation(pIrp,
  1732. pDeviceContext->pFileObjects->pDgramDeviceObject,
  1733. pDeviceContext->pFileObjects->pDgramFileObject,
  1734. QueryProviderCompletion,
  1735. NULL,
  1736. TDI_QUERY_PROVIDER_INFO,
  1737. pIrp->MdlAddress);
  1738. }
  1739. else
  1740. {
  1741. TdiBuildQueryInformation(pIrp,
  1742. pDeviceContext->pControlDeviceObject,
  1743. pDeviceContext->pControlFileObject,
  1744. QueryProviderCompletion,
  1745. NULL,
  1746. TDI_QUERY_PROVIDER_INFO,
  1747. pIrp->MdlAddress);
  1748. }
  1749. CHECK_COMPLETION(pIrp);
  1750. status = IoCallDriver(pDeviceContext->pControlDeviceObject,pIrp);
  1751. //
  1752. // we must return the next drivers ret code back to the IO subsystem
  1753. //
  1754. return(status);
  1755. }
  1756. case TDI_QUERY_ADAPTER_STATUS:
  1757. {
  1758. if (!pIrp->MdlAddress)
  1759. {
  1760. break;
  1761. }
  1762. Size = MmGetMdlByteCount (pIrp->MdlAddress);
  1763. //
  1764. // check if it is a remote or local adapter status
  1765. //
  1766. if (Query->RequestConnectionInformation &&
  1767. Query->RequestConnectionInformation->RemoteAddress)
  1768. {
  1769. PCHAR pName;
  1770. ULONG lNameType;
  1771. ULONG NameLen;
  1772. tDGRAM_SEND_TRACKING *pTracker;
  1773. TDI_ADDRESS_NETBT_INTERNAL TdiAddr;
  1774. //
  1775. //
  1776. // in case the call results in a name query on the wire...
  1777. //
  1778. IoMarkIrpPending(pIrp);
  1779. status = STATUS_SUCCESS;
  1780. if (pIrp->RequestorMode != KernelMode) {
  1781. try
  1782. {
  1783. ProbeForRead(Query->RequestConnectionInformation->RemoteAddress,
  1784. Query->RequestConnectionInformation->RemoteAddressLength,
  1785. sizeof(BYTE));
  1786. } except(EXCEPTION_EXECUTE_HANDLER) {
  1787. status = STATUS_INVALID_PARAMETER;
  1788. }
  1789. }
  1790. if (NT_SUCCESS(status) && NT_SUCCESS (status = GetNetBiosNameFromTransportAddress(
  1791. (PTRANSPORT_ADDRESS) Query->RequestConnectionInformation->RemoteAddress,
  1792. Query->RequestConnectionInformation->RemoteAddressLength, &TdiAddr)))
  1793. {
  1794. pName = TdiAddr.OEMRemoteName.Buffer;
  1795. NameLen = TdiAddr.OEMRemoteName.Length;
  1796. lNameType = TdiAddr.NameType;
  1797. if ((lNameType == TDI_ADDRESS_NETBIOS_TYPE_UNIQUE) &&
  1798. (NameLen == NETBIOS_NAME_SIZE) &&
  1799. (NT_SUCCESS (status = GetTracker(&pTracker, NBT_TRACKER_ADAPTER_STATUS))))
  1800. {
  1801. pTracker->ClientContext = pIrp;
  1802. status = NbtSendNodeStatus (pDeviceContext,
  1803. pName,
  1804. NULL,
  1805. pTracker,
  1806. CopyNodeStatusResponseCompletion);
  1807. // only complete the irp (below) for failure status's
  1808. if (status == STATUS_PENDING)
  1809. {
  1810. return(status);
  1811. }
  1812. //
  1813. // We cannot have a Success status returned here!
  1814. //
  1815. if (status == STATUS_SUCCESS)
  1816. {
  1817. ASSERT (0);
  1818. status = STATUS_UNSUCCESSFUL;
  1819. }
  1820. FreeTracker (pTracker, RELINK_TRACKER);
  1821. }
  1822. else if (NT_SUCCESS(status))
  1823. {
  1824. status = STATUS_INVALID_PARAMETER; // The NameType or NameLen must be wrong!
  1825. }
  1826. }
  1827. // the request has been satisfied, so unmark the pending
  1828. // since we will return the irp below
  1829. //
  1830. pIrpSp->Control &= ~SL_PENDING_RETURNED;
  1831. }
  1832. else
  1833. {
  1834. // return an array of netbios names that are registered
  1835. status = NbtQueryAdapterStatus(pDeviceContext,
  1836. &pBuffer,
  1837. &Size,
  1838. NBT_LOCAL);
  1839. }
  1840. break;
  1841. }
  1842. case TDI_QUERY_CONNECTION_INFO:
  1843. {
  1844. tCONNECTELE *pConnectEle;
  1845. tLOWERCONNECTION *pLowerConn;
  1846. KIRQL OldIrq1, OldIrq2;
  1847. // pass to transport to get the current throughput, delay and
  1848. // reliability numbers
  1849. //
  1850. pConnectEle = (tCONNECTELE *)pIrpSp->FileObject->FsContext;
  1851. if (!NBT_VERIFY_HANDLE2 (pConnectEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN))
  1852. {
  1853. ASSERTMSG ("Nbt.NTQueryInformation: ERROR - Invalid Connection Handle\n", 0);
  1854. status = STATUS_INVALID_HANDLE;
  1855. break;
  1856. }
  1857. CTESpinLock(pConnectEle, OldIrq1);
  1858. pLowerConn = (tLOWERCONNECTION *)pConnectEle->pLowerConnId;
  1859. if (!NBT_VERIFY_HANDLE (pLowerConn, NBT_VERIFY_LOWERCONN))
  1860. {
  1861. status = STATUS_CONNECTION_INVALID;
  1862. CTESpinFree(pConnectEle, OldIrq1);
  1863. break;
  1864. }
  1865. CTESpinLock(pLowerConn, OldIrq2);
  1866. NBT_REFERENCE_LOWERCONN (pLowerConn, REF_LOWC_QUERY_INFO); // Bug # 212632
  1867. CTESpinFree(pLowerConn, OldIrq2);
  1868. CTESpinFree(pConnectEle, OldIrq1);
  1869. //
  1870. // Simply pass the Irp on by to the Transport, and let it
  1871. // fill in the info
  1872. //
  1873. pDeviceObject = IoGetRelatedDeviceObject( pLowerConn->pFileObject );
  1874. TdiBuildQueryInformation(pIrp,
  1875. pDeviceObject,
  1876. pLowerConn->pFileObject,
  1877. NULL, NULL,
  1878. TDI_QUERY_CONNECTION_INFO,
  1879. pIrp->MdlAddress);
  1880. status = IoCallDriver(pDeviceObject,pIrp);
  1881. NBT_DEREFERENCE_LOWERCONN (pLowerConn, REF_LOWC_QUERY_INFO, FALSE);
  1882. //
  1883. // we must return the next drivers ret code back to the IO subsystem
  1884. //
  1885. return(status);
  1886. }
  1887. case TDI_QUERY_FIND_NAME:
  1888. {
  1889. //
  1890. //
  1891. // in case the call results in a name query on the wire...
  1892. //
  1893. if (pIrp->MdlAddress)
  1894. {
  1895. //
  1896. // Verify the request address space
  1897. //
  1898. try
  1899. {
  1900. status = STATUS_INVALID_ADDRESS_COMPONENT;
  1901. if (pIrp->RequestorMode == KernelMode)
  1902. {
  1903. //
  1904. // Since the TdiBuildQueryInformation macro NULLs out the
  1905. // RequestConnectionInformation field, we need to dereference
  1906. // it under Try/Except to ensure that the caller has filled
  1907. // the fields in properly
  1908. //
  1909. PTRANSPORT_ADDRESS pRemoteAddress=Query->RequestConnectionInformation->RemoteAddress;
  1910. if ((Query->RequestConnectionInformation->RemoteAddressLength
  1911. < sizeof(TRANSPORT_ADDRESS)) ||
  1912. (pRemoteAddress->TAAddressCount < 1) ||
  1913. (pRemoteAddress->Address[0].AddressType != TDI_ADDRESS_TYPE_NETBIOS))
  1914. {
  1915. break;
  1916. }
  1917. }
  1918. else // User-mode client
  1919. {
  1920. ProbeForRead(Query->RequestConnectionInformation->RemoteAddress,
  1921. Query->RequestConnectionInformation->RemoteAddressLength,
  1922. sizeof(BYTE));
  1923. }
  1924. }
  1925. except(EXCEPTION_EXECUTE_HANDLER)
  1926. {
  1927. KdPrint (("Nbt.TDI_QUERY_FIND_NAME: Exception <0x%x> during Probe\n",
  1928. GetExceptionCode()));
  1929. break;
  1930. }
  1931. IoMarkIrpPending(pIrp);
  1932. status = NbtQueryFindName(Query->RequestConnectionInformation, pDeviceContext, pIrp, FALSE);
  1933. if (status == STATUS_PENDING)
  1934. {
  1935. return(status);
  1936. }
  1937. // the request has been satisfied, so unmark the pending
  1938. // since we will return the irp below
  1939. //
  1940. pIrpSp->Control &= ~SL_PENDING_RETURNED;
  1941. }
  1942. break;
  1943. }
  1944. case TDI_QUERY_ADDRESS_INFO:
  1945. {
  1946. if (pIrp->MdlAddress)
  1947. {
  1948. status = NbtQueryGetAddressInfo (pIrpSp, &pBuffer, &Size);
  1949. }
  1950. break;
  1951. }
  1952. case TDI_QUERY_SESSION_STATUS:
  1953. default:
  1954. {
  1955. IF_DBG(NBT_DEBUG_NAMESRV)
  1956. KdPrint(("Nbt Query Info NOT SUPPORTED = %X\n",Query->QueryType));
  1957. status = STATUS_NOT_SUPPORTED;
  1958. break;
  1959. }
  1960. } // switch
  1961. if (!NT_ERROR(status) && // allow buffer overflow to pass by
  1962. ((Query->QueryType == TDI_QUERY_ADAPTER_STATUS) ||
  1963. (Query->QueryType == TDI_QUERY_ADDRESS_INFO)))
  1964. {
  1965. status = TdiCopyBufferToMdl (pBuffer, 0, Size, pIrp->MdlAddress, 0, &BytesCopied);
  1966. CTEMemFree((PVOID)pBuffer);
  1967. }
  1968. //
  1969. // either Success or an Error
  1970. // so complete the irp
  1971. //
  1972. NTIoComplete(pIrp,status,BytesCopied);
  1973. return(status);
  1974. }
  1975. //----------------------------------------------------------------------------
  1976. NTSTATUS
  1977. NbtQueryGetAddressInfo(
  1978. IN PIO_STACK_LOCATION pIrpSp,
  1979. OUT PVOID *ppBuffer,
  1980. OUT ULONG *pSize
  1981. )
  1982. {
  1983. NTSTATUS status;
  1984. BOOLEAN IsGroup;
  1985. PLIST_ENTRY p;
  1986. tADDRESSELE *pAddressEle;
  1987. tNAMEADDR *pNameAddr;
  1988. tADDRESS_INFO *pAddressInfo;
  1989. tCLIENTELE *pClientEle;
  1990. tCONNECTELE *pConnectEle;
  1991. CTELockHandle OldIrq;
  1992. CTELockHandle OldIrq1;
  1993. PNBT_ADDRESS_PAIR_INFO pAddressPairInfo;
  1994. //
  1995. // We are not sure whether this is a ConnectionContext or a ClientContext!
  1996. //
  1997. pConnectEle = (tCONNECTELE *) pClientEle = pIrpSp->FileObject->FsContext;
  1998. if (NBT_VERIFY_HANDLE2 (pConnectEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN))
  1999. {
  2000. //
  2001. // We crashed here since the pLowerConn was NULL below.
  2002. // Check the state of the connection, since it is possible that the connection
  2003. // was aborted and the disconnect indicated, but this query came in before the client
  2004. // got the disconnect indication.
  2005. // If the state is idle (in case of TDI_DISCONNECT_ABORT) or DISCONNECTED
  2006. // (TDI_DISCONNECT_RELEASE), error out.
  2007. // Also check for NBT_ASSOCIATED.
  2008. //
  2009. // NOTE: If NbtOpenConnection is unable to allocate the lower conn block (say, if the session fileobj
  2010. // has not been created yet), the state will be still be IDLE, so we are covered here.
  2011. //
  2012. CTESpinLock(pConnectEle,OldIrq);
  2013. if (pConnectEle->Verify != NBT_VERIFY_CONNECTION)
  2014. {
  2015. CTESpinFree(pConnectEle,OldIrq);
  2016. return (STATUS_INVALID_HANDLE);
  2017. }
  2018. else if ((pConnectEle->state <= NBT_ASSOCIATED) || // includes NBT_IDLE
  2019. (pConnectEle->state == NBT_DISCONNECTED))
  2020. {
  2021. CTESpinFree(pConnectEle,OldIrq);
  2022. return (STATUS_CONNECTION_DISCONNECTED);
  2023. }
  2024. //
  2025. // A TdiQueryInformation() call requesting TDI_QUERY_ADDRESS_INFO
  2026. // on a connection. Fill in a TDI_ADDRESS_INFO containing both the
  2027. // NetBIOS address and the IP address of the remote. Some of the
  2028. // fields are fudged.
  2029. //
  2030. if (pAddressPairInfo = NbtAllocMem(sizeof (NBT_ADDRESS_PAIR_INFO), NBT_TAG('c')))
  2031. {
  2032. memset ( pAddressPairInfo, 0, sizeof(NBT_ADDRESS_PAIR_INFO) );
  2033. pAddressPairInfo->ActivityCount = 1;
  2034. pAddressPairInfo->AddressPair.TAAddressCount = 2;
  2035. pAddressPairInfo->AddressPair.AddressIP.AddressType = TDI_ADDRESS_TYPE_IP;
  2036. pAddressPairInfo->AddressPair.AddressIP.AddressLength = TDI_ADDRESS_LENGTH_IP;
  2037. pAddressPairInfo->AddressPair.AddressNetBIOS.AddressType = TDI_ADDRESS_TYPE_NETBIOS;
  2038. pAddressPairInfo->AddressPair.AddressNetBIOS.AddressLength = TDI_ADDRESS_LENGTH_NETBIOS;
  2039. pAddressPairInfo->AddressPair.AddressNetBIOS.Address.NetbiosNameType =
  2040. TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
  2041. memcpy( &pAddressPairInfo->AddressPair.AddressNetBIOS.Address.NetbiosName[0],
  2042. &pConnectEle->RemoteName[0],
  2043. NETBIOS_NAME_SIZE);
  2044. //
  2045. // Check for NULL (should not be NULL here since we check for states above).
  2046. //
  2047. if (pConnectEle->pLowerConnId)
  2048. {
  2049. pAddressPairInfo->AddressPair.AddressIP.Address.in_addr =
  2050. pConnectEle->pLowerConnId->SrcIpAddr;
  2051. *ppBuffer = (PVOID)pAddressPairInfo;
  2052. *pSize = sizeof(NBT_ADDRESS_PAIR_INFO);
  2053. status = STATUS_SUCCESS;
  2054. }
  2055. else
  2056. {
  2057. DbgPrint("pLowerConn NULL in pConnEle%lx, state: %lx\n", pConnectEle, pConnectEle->state);
  2058. CTEMemFree ((PVOID)pAddressPairInfo);
  2059. status = STATUS_CONNECTION_DISCONNECTED;
  2060. }
  2061. }
  2062. else
  2063. {
  2064. status = STATUS_INSUFFICIENT_RESOURCES;
  2065. }
  2066. CTESpinFree(pConnectEle,OldIrq);
  2067. }
  2068. else if (NBT_VERIFY_HANDLE2 (pClientEle, NBT_VERIFY_CLIENT, NBT_VERIFY_CLIENT_DOWN))
  2069. {
  2070. pAddressInfo = NbtAllocMem(sizeof(tADDRESS_INFO),NBT_TAG('c'));
  2071. if (pAddressInfo)
  2072. {
  2073. //
  2074. // count the clients attached to this address
  2075. // We need to spinlock the address element, which
  2076. // is why this routine is not pageable
  2077. //
  2078. pAddressInfo->ActivityCount = 0;
  2079. pAddressEle = pClientEle->pAddress;
  2080. //
  2081. // The Client can be removed from the AddressEle only under the JointLock,
  2082. // so we need to hold that while counting the Clients on htis address
  2083. //
  2084. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  2085. CTESpinLock(pAddressEle,OldIrq1);
  2086. for (p = pAddressEle->ClientHead.Flink; p != &pAddressEle->ClientHead; p = p->Flink)
  2087. {
  2088. ++pAddressInfo->ActivityCount;
  2089. }
  2090. CTESpinFree(pAddressEle,OldIrq1);
  2091. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  2092. pNameAddr = pAddressEle->pNameAddr;
  2093. IsGroup = (pNameAddr->NameTypeState & NAMETYPE_UNIQUE) ? FALSE : TRUE;
  2094. TdiBuildNetbiosAddress((PUCHAR)pNameAddr->Name, IsGroup, &pAddressInfo->NetbiosAddress);
  2095. *ppBuffer = (PVOID)pAddressInfo;
  2096. *pSize = sizeof(tADDRESS_INFO);
  2097. status = STATUS_SUCCESS;
  2098. }
  2099. else
  2100. {
  2101. status = STATUS_INSUFFICIENT_RESOURCES;
  2102. }
  2103. }
  2104. else // neither a client nor a connection context!
  2105. {
  2106. ASSERTMSG ("Nbt.NbtQueryGetAddressInfo: ERROR - Invalid Handle\n", 0);
  2107. return (STATUS_INVALID_HANDLE);
  2108. }
  2109. return status;
  2110. }
  2111. //----------------------------------------------------------------------------
  2112. NTSTATUS
  2113. NbtGetInterfaceInfo(
  2114. IN PIRP pIrp
  2115. )
  2116. /*++
  2117. Routine Description:
  2118. gets the interface to index mapping info
  2119. for all the interfaces
  2120. Arguments:
  2121. Irp - Pointer to I/O request packet to cancel.
  2122. IrpSp - pointer to current stack
  2123. Return Value:
  2124. NTSTATUS Indicates status success or failure
  2125. Notes:
  2126. Function does not pend.
  2127. --*/
  2128. {
  2129. NTSTATUS LocStatus, Status = STATUS_SUCCESS;
  2130. ULONG InfoBufferLen, MaxSize, i=0;
  2131. NETBT_INTERFACE_INFO *pInterfaceInfo;
  2132. KIRQL OldIrq;
  2133. PLIST_ENTRY pEntry,pHead;
  2134. tDEVICECONTEXT *pDeviceContext;
  2135. PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation (pIrp);
  2136. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  2137. IF_DBG(NBT_DEBUG_NAMESRV)
  2138. KdPrint(("Nbt.NbtGetInterfaceInfo: AdapterCount=<%x>\n", NbtConfig.AdapterCount));
  2139. InfoBufferLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  2140. MaxSize = (NbtConfig.AdapterCount+1)*sizeof(NETBT_ADAPTER_INDEX_MAP)+sizeof(ULONG);
  2141. if (MaxSize <= InfoBufferLen)
  2142. {
  2143. if (pInterfaceInfo = NbtAllocMem (MaxSize,NBT_TAG('P')))
  2144. {
  2145. pEntry = pHead = &NbtConfig.DeviceContexts;
  2146. while ((pEntry = pEntry->Flink) != pHead)
  2147. {
  2148. pDeviceContext = CONTAINING_RECORD(pEntry, tDEVICECONTEXT, Linkage);
  2149. CTEMemCopy (&pInterfaceInfo->Adapter[i].Name,
  2150. pDeviceContext->ExportName.Buffer,
  2151. pDeviceContext->ExportName.Length);
  2152. pInterfaceInfo->Adapter[i].Name[pDeviceContext->ExportName.Length/2] = 0;
  2153. pInterfaceInfo->Adapter[i].Index = i;
  2154. i++;
  2155. }
  2156. pInterfaceInfo->NumAdapters = i;
  2157. Status = TdiCopyBufferToMdl (pInterfaceInfo,
  2158. 0,
  2159. i*sizeof(NETBT_ADAPTER_INDEX_MAP)+sizeof(ULONG),
  2160. pIrp->MdlAddress,
  2161. 0,
  2162. (PULONG)&pIrp->IoStatus.Information);
  2163. CTEMemFree (pInterfaceInfo);
  2164. }
  2165. else
  2166. {
  2167. Status = STATUS_INSUFFICIENT_RESOURCES;
  2168. }
  2169. }
  2170. else
  2171. {
  2172. //KdPrint(("GetInterfaceInfo Buffer Overflow %x\n", pIrp));
  2173. //pIrp->IoStatus.Information = sizeof(ULONG);
  2174. Status = STATUS_BUFFER_OVERFLOW;
  2175. }
  2176. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  2177. //KdPrint(("GetInterfaceInfo exit status %x\n", Status));
  2178. return Status;
  2179. }
  2180. //----------------------------------------------------------------------------
  2181. NTSTATUS
  2182. NbtFlushEntryFromRemoteHashTable(
  2183. tNAME *pRemoteName
  2184. )
  2185. {
  2186. NTSTATUS status;
  2187. KIRQL OldIrq;
  2188. tNAMEADDR *pNameAddr = NULL;
  2189. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  2190. status = FindInHashTable (NbtConfig.pRemoteHashTbl, pRemoteName->Name, NbtConfig.pScope, &pNameAddr);
  2191. if (NT_SUCCESS (status))
  2192. {
  2193. if (pNameAddr->RefCount <= 1)
  2194. {
  2195. NBT_DEREFERENCE_NAMEADDR (pNameAddr, REF_NAME_REMOTE, TRUE);
  2196. }
  2197. else
  2198. {
  2199. status = STATUS_UNSUCCESSFUL;
  2200. }
  2201. }
  2202. else
  2203. {
  2204. status = STATUS_RESOURCE_NAME_NOT_FOUND;
  2205. }
  2206. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  2207. return (status);
  2208. }
  2209. //----------------------------------------------------------------------------
  2210. NTSTATUS
  2211. SetTcpInfo(
  2212. IN HANDLE FileHandle,
  2213. IN PVOID pInfoBuffer,
  2214. IN ULONG InfoBufferLength
  2215. )
  2216. {
  2217. IO_STATUS_BLOCK IoStatus;
  2218. HANDLE event;
  2219. BOOLEAN fAttached = FALSE;
  2220. NTSTATUS status;
  2221. CTEAttachFsp(&fAttached, REF_FSP_SET_TCP_INFO);
  2222. status = ZwCreateEvent (&event, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE);
  2223. if (NT_SUCCESS(status))
  2224. {
  2225. //
  2226. // Make the actual TDI call
  2227. //
  2228. IoStatus.Status = STATUS_SUCCESS;
  2229. status = ZwDeviceIoControlFile (FileHandle,
  2230. event,
  2231. NULL,
  2232. NULL,
  2233. &IoStatus,
  2234. IOCTL_TCP_SET_INFORMATION_EX,
  2235. pInfoBuffer,
  2236. InfoBufferLength,
  2237. NULL,
  2238. 0);
  2239. //
  2240. // If the call pended and we were supposed to wait for completion,
  2241. // then wait.
  2242. //
  2243. if (status == STATUS_PENDING)
  2244. {
  2245. status = NtWaitForSingleObject (event, FALSE, NULL);
  2246. ASSERT(status == STATUS_SUCCESS);
  2247. } else if (!NT_SUCCESS(status) && IoStatus.Status == STATUS_SUCCESS) {
  2248. //
  2249. // Set the IoStatus.Status if it hasn't been set so that we could
  2250. // return the correct status below.
  2251. //
  2252. IoStatus.Status = status;
  2253. }
  2254. status = ZwClose (event);
  2255. ASSERT (NT_SUCCESS(status));
  2256. status = IoStatus.Status;
  2257. }
  2258. CTEDetachFsp(fAttached, REF_FSP_SET_TCP_INFO);
  2259. return (status);
  2260. }
  2261. //----------------------------------------------------------------------------
  2262. NTSTATUS
  2263. NbtClientSetTcpInfo(
  2264. IN tCONNECTELE *pConnEle,
  2265. IN PVOID pInfoBuffer,
  2266. IN ULONG InfoBufferLength
  2267. )
  2268. /*++
  2269. Routine Description:
  2270. Sets the Tcp connection information as requested
  2271. by the client
  2272. Arguments:
  2273. pConnEle - NetBT's Connection object
  2274. pInfoBuffer - pointer to TCP_REQUEST_SET_INFORMATION_EX structure
  2275. pInfoBufferLength - length of pInfoBuffer
  2276. Return Value:
  2277. NTSTATUS Indicates status success or failure
  2278. Notes:
  2279. Function does not pend.
  2280. --*/
  2281. {
  2282. NTSTATUS status;
  2283. tLOWERCONNECTION *pLowerConn;
  2284. KIRQL OldIrq1, OldIrq2;
  2285. if (!NBT_VERIFY_HANDLE2 (pConnEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN))
  2286. {
  2287. return STATUS_INVALID_HANDLE;
  2288. }
  2289. CTESpinLock(pConnEle, OldIrq1);
  2290. if ((!NBT_VERIFY_HANDLE ((pLowerConn = pConnEle->pLowerConnId), NBT_VERIFY_LOWERCONN)) ||
  2291. (pLowerConn->RefCount > 500)) // if queued for WipeOutLowerConn
  2292. {
  2293. CTESpinFree(pConnEle, OldIrq1);
  2294. return STATUS_BAD_NETWORK_PATH;
  2295. }
  2296. CTESpinLock(pLowerConn, OldIrq2);
  2297. //
  2298. // We have verified that the lower connection is up -- reference it
  2299. // so that the FileObject does not get Dereferenced by some disconnect
  2300. // from the transport
  2301. //
  2302. NBT_REFERENCE_LOWERCONN (pLowerConn, REF_LOWC_SET_TCP_INFO);
  2303. CTESpinFree(pLowerConn, OldIrq2);
  2304. CTESpinFree(pConnEle, OldIrq1);
  2305. status = SetTcpInfo (pLowerConn->FileHandle, pInfoBuffer, InfoBufferLength);
  2306. NBT_DEREFERENCE_LOWERCONN (pLowerConn, REF_LOWC_SET_TCP_INFO, FALSE);
  2307. return (status);
  2308. }
  2309. //----------------------------------------------------------------------------
  2310. NTSTATUS
  2311. NbtSetTcpInfo(
  2312. IN HANDLE FileHandle,
  2313. IN ULONG ToiId,
  2314. IN ULONG ToiType,
  2315. IN ULONG InfoBufferValue
  2316. )
  2317. {
  2318. NTSTATUS Status;
  2319. ULONG BufferLength;
  2320. TCP_REQUEST_SET_INFORMATION_EX *pTcpInfo;
  2321. TCPSocketOption *pSockOption;
  2322. BufferLength = sizeof(TCP_REQUEST_SET_INFORMATION_EX) + sizeof(TCPSocketOption);
  2323. if (!(pTcpInfo = (TCP_REQUEST_SET_INFORMATION_EX *) NbtAllocMem (BufferLength,NBT_TAG2('22'))))
  2324. {
  2325. return (STATUS_INSUFFICIENT_RESOURCES);
  2326. }
  2327. CTEZeroMemory(pTcpInfo, BufferLength);
  2328. pSockOption = (TCPSocketOption *) (&pTcpInfo->Buffer[0]);
  2329. pTcpInfo->ID.toi_entity.tei_entity = CO_TL_ENTITY;
  2330. pTcpInfo->ID.toi_class = INFO_CLASS_PROTOCOL;
  2331. pTcpInfo->BufferSize = sizeof (TCPSocketOption);
  2332. //
  2333. // Set the Configured values
  2334. //
  2335. pTcpInfo->ID.toi_id = ToiId;
  2336. pTcpInfo->ID.toi_type = ToiType;
  2337. pSockOption->tso_value = InfoBufferValue;
  2338. Status = SetTcpInfo (FileHandle, pTcpInfo, BufferLength);
  2339. if (!NT_SUCCESS(Status))
  2340. {
  2341. KdPrint (("Nbt.NbtSetTcpInfo: SetTcpInfo FAILed <%x>, Id=<0x%x>, Type=<0x%x>, Value=<%x>\n",
  2342. Status, ToiId, ToiType, InfoBufferValue));
  2343. }
  2344. CTEMemFree (pTcpInfo);
  2345. return (Status);
  2346. }
  2347. //----------------------------------------------------------------------------
  2348. NTSTATUS
  2349. NbtSetSmbBindingInfo2(
  2350. IN tDEVICECONTEXT *pDeviceContext,
  2351. IN NETBT_SMB_BIND_REQUEST *pSmbRequest
  2352. )
  2353. {
  2354. ULONG i, Operation;
  2355. PLIST_ENTRY pEntry,pHead;
  2356. KIRQL OldIrq;
  2357. ULONG NumBindings = 0;
  2358. CTEULONGLONG AddedAdapterMask = 0;
  2359. CTEULONGLONG DeletedAdapterMask = 0;
  2360. CTEULONGLONG BindListAdapterMask = 0;
  2361. CTEULONGLONG OriginalMask;
  2362. tDEVICECONTEXT *pDeviceContextBind = NULL;
  2363. NTSTATUS LocNtStatus = STATUS_SUCCESS;
  2364. if (!IsDeviceNetbiosless (pDeviceContext)) {
  2365. return (STATUS_UNSUCCESSFUL);
  2366. }
  2367. if (NULL == pSmbRequest) {
  2368. return STATUS_INVALID_PARAMETER;
  2369. }
  2370. if (pSmbRequest->RequestType == SMB_SERVER) {
  2371. OriginalMask = NbtConfig.ServerMask;
  2372. } else if (pSmbRequest->RequestType == SMB_CLIENT) {
  2373. OriginalMask = NbtConfig.ClientMask;
  2374. } else {
  2375. ASSERT(0);
  2376. return STATUS_INVALID_PARAMETER;
  2377. }
  2378. if (pSmbRequest->MultiSZBindList)
  2379. {
  2380. NTSTATUS status;
  2381. tDEVICES *pBindings = NULL;
  2382. ULONG MaxBindings;
  2383. MaxBindings = NBT_MAXIMUM_BINDINGS;
  2384. while (MaxBindings < 5000) {
  2385. status = STATUS_INSUFFICIENT_RESOURCES;
  2386. MaxBindings *= 2;
  2387. pBindings = NbtAllocMem ((sizeof(tDEVICES)+MaxBindings*sizeof(UNICODE_STRING)), NBT_TAG2('26'));
  2388. if (pBindings == NULL) {
  2389. break;
  2390. }
  2391. NumBindings = 0;
  2392. status = NbtParseMultiSzEntries (pSmbRequest->MultiSZBindList, (PVOID)(-1), MaxBindings, pBindings, &NumBindings);
  2393. if (status != STATUS_BUFFER_OVERFLOW) {
  2394. break;
  2395. }
  2396. CTEMemFree (pBindings);
  2397. pBindings = NULL;
  2398. }
  2399. if (status != STATUS_SUCCESS) {
  2400. if (pBindings) { // NbtParseMultiSzEntries can return failure other than STATUS_BUFFER_OVERFLOW
  2401. CTEMemFree (pBindings);
  2402. }
  2403. KdPrint(("Nbt.NbtSetSmbBindingInfo[STATUS_INSUFFICIENT_RESOURCES]: MaxBindings = <%d>\n",
  2404. MaxBindings));
  2405. return status;
  2406. }
  2407. ASSERT(pBindings);
  2408. //
  2409. // First, get the complete list of all bindings
  2410. //
  2411. for (i=0; i<NumBindings; i++)
  2412. {
  2413. if (pDeviceContextBind = NbtFindAndReferenceDevice (&pBindings->Names[i], FALSE))
  2414. {
  2415. BindListAdapterMask |= pDeviceContextBind->AdapterMask;
  2416. NBT_DEREFERENCE_DEVICE (pDeviceContextBind, REF_DEV_FIND_REF, FALSE);
  2417. }
  2418. }
  2419. CTEMemFree (pBindings);
  2420. }
  2421. else if (pSmbRequest->pDeviceName)
  2422. {
  2423. KdPrint (("Nbt.NbtSetSmbBindingInfo[WARNING]: NULL MultiSZBindList string!\n"));
  2424. BindListAdapterMask = OriginalMask;
  2425. if (pDeviceContextBind = NbtFindAndReferenceDevice (pSmbRequest->pDeviceName, FALSE))
  2426. {
  2427. switch (pSmbRequest->PnPOpCode)
  2428. {
  2429. case (TDI_PNP_OP_ADD):
  2430. {
  2431. BindListAdapterMask |= pDeviceContextBind->AdapterMask;
  2432. break;
  2433. }
  2434. case (TDI_PNP_OP_DEL):
  2435. {
  2436. BindListAdapterMask &= (~pDeviceContextBind->AdapterMask);
  2437. break;
  2438. }
  2439. default:
  2440. {
  2441. break;
  2442. }
  2443. }
  2444. NBT_DEREFERENCE_DEVICE (pDeviceContextBind, REF_DEV_FIND_REF, FALSE);
  2445. }
  2446. else
  2447. {
  2448. return (STATUS_SUCCESS);
  2449. }
  2450. }
  2451. else
  2452. {
  2453. ASSERTMSG ("Nbt.NbtSetSmbBindingInfo[ERROE]: NULL MultiSZBindList and NULL pDeviceName!\n", 0);
  2454. return (STATUS_UNSUCCESSFUL);
  2455. }
  2456. IF_DBG(NBT_DEBUG_PNP_POWER)
  2457. KdPrint (("Nbt.NbtSetSmbBindingInfo: PnPOpCode=<%x>, Bindings=<%d>, BindMask=[%lx:%lx]==>[%lx:%lx]\n",
  2458. pSmbRequest->PnPOpCode, NumBindings, OriginalMask, BindListAdapterMask));
  2459. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  2460. // NetBT used to incrementally add interface to tcpip.
  2461. // However, for some reason, the list in tcpip and netbt
  2462. // may be different. To increase the reliability, I
  2463. // remove the incrementally adding.
  2464. //
  2465. // AddedAdapterMask = BindListAdapterMask & (~OriginalMask)
  2466. AddedAdapterMask = BindListAdapterMask; // Always add device
  2467. DeletedAdapterMask = OriginalMask & (~BindListAdapterMask); // Devices Removed
  2468. if ((!AddedAdapterMask) && (!DeletedAdapterMask))
  2469. {
  2470. //
  2471. // If there are no adapters to be added or deleted, just return
  2472. //
  2473. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  2474. return (STATUS_SUCCESS);
  2475. }
  2476. if (pSmbRequest->RequestType == SMB_SERVER) {
  2477. NbtConfig.ServerMask = BindListAdapterMask;
  2478. } else if (pSmbRequest->RequestType == SMB_CLIENT) {
  2479. NbtConfig.ClientMask = BindListAdapterMask;
  2480. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  2481. return STATUS_SUCCESS;
  2482. } else {
  2483. ASSERT(0);
  2484. }
  2485. pEntry = pHead = &NbtConfig.DeviceContexts;
  2486. while ((pEntry = pEntry->Flink) != pHead)
  2487. {
  2488. pDeviceContextBind = CONTAINING_RECORD(pEntry, tDEVICECONTEXT, Linkage);
  2489. if (pDeviceContext->IPInterfaceContext == (ULONG)-1) // For Cluster devices, etc
  2490. {
  2491. continue;
  2492. }
  2493. ASSERT(0 == (AddedAdapterMask & DeletedAdapterMask));
  2494. if (AddedAdapterMask & pDeviceContextBind->AdapterMask)
  2495. {
  2496. AddedAdapterMask &= ~(pDeviceContextBind->AdapterMask);
  2497. Operation = AO_OPTION_ADD_IFLIST;
  2498. }
  2499. else if (DeletedAdapterMask & pDeviceContextBind->AdapterMask)
  2500. {
  2501. DeletedAdapterMask &= ~(pDeviceContextBind->AdapterMask);
  2502. Operation = AO_OPTION_DEL_IFLIST;
  2503. }
  2504. else
  2505. {
  2506. continue;
  2507. }
  2508. NBT_REFERENCE_DEVICE (pDeviceContextBind, REF_DEV_FIND_REF, TRUE);
  2509. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  2510. IF_DBG(NBT_DEBUG_PNP_POWER)
  2511. KdPrint(("Nbt.NbtSetSmbBindingInfo: %sing Device=%wZ\n",
  2512. (Operation == AO_OPTION_ADD_IFLIST ? "ADD" : "REMOV"), &pDeviceContextBind->BindName));
  2513. //
  2514. // Set the Session port info
  2515. //
  2516. if (pDeviceContext->hSession)
  2517. {
  2518. LocNtStatus = NbtSetTcpInfo (pDeviceContext->hSession,
  2519. Operation,
  2520. INFO_TYPE_ADDRESS_OBJECT,
  2521. pDeviceContextBind->IPInterfaceContext);
  2522. if (!NT_SUCCESS(LocNtStatus)) {
  2523. NbtConfig.ServerMask &= ~(pDeviceContextBind->AdapterMask);
  2524. }
  2525. }
  2526. //
  2527. // Now, set the same for the Datagram port
  2528. //
  2529. if ((pDeviceContext->pFileObjects) &&
  2530. (pDeviceContext->pFileObjects->hDgram))
  2531. {
  2532. NbtSetTcpInfo (pDeviceContext->pFileObjects->hDgram,
  2533. Operation,
  2534. INFO_TYPE_ADDRESS_OBJECT,
  2535. pDeviceContextBind->IPInterfaceContext);
  2536. }
  2537. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  2538. NBT_DEREFERENCE_DEVICE (pDeviceContextBind, REF_DEV_FIND_REF, TRUE);
  2539. //
  2540. // Set to restart from the beginning
  2541. //
  2542. pEntry = &NbtConfig.DeviceContexts;
  2543. }
  2544. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  2545. return STATUS_SUCCESS;
  2546. }
  2547. //----------------------------------------------------------------------------
  2548. NTSTATUS
  2549. NbtSetSmbBindingInfo(
  2550. IN tDEVICECONTEXT *pDeviceContext,
  2551. IN PIRP pIrp,
  2552. IN PIO_STACK_LOCATION pIrpSp
  2553. )
  2554. {
  2555. NETBT_SMB_BIND_REQUEST *pSmbRequest = (PNETBT_SMB_BIND_REQUEST)pIrp->AssociatedIrp.SystemBuffer;
  2556. PWSTR pBindListCache = NULL;
  2557. PWSTR pBindList = NULL;
  2558. PWSTR pOldBindList = NULL;
  2559. PWSTR *pTarget = NULL;
  2560. ULONG uInputLength = 0;
  2561. ULONG uLength = 0;
  2562. NTSTATUS status = STATUS_SUCCESS;
  2563. tDEVICECONTEXT *pSavedSmbDevice = NULL;
  2564. KIRQL OldIrq = 0;
  2565. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  2566. if (pNbtSmbDevice && !gbDestroyingSmbDevice) {
  2567. pSavedSmbDevice = pNbtSmbDevice;
  2568. NBT_REFERENCE_DEVICE (pSavedSmbDevice, REF_DEV_SMB_BIND, TRUE);
  2569. }
  2570. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  2571. if (NULL == pSavedSmbDevice) {
  2572. status = STATUS_DEVICE_BUSY;
  2573. goto error;
  2574. }
  2575. uInputLength = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
  2576. if (!(IsDeviceNetbiosless (pDeviceContext)) ||
  2577. (!pSmbRequest) ||
  2578. (uInputLength < sizeof(NETBT_SMB_BIND_REQUEST)))
  2579. {
  2580. KdPrint(("Nbt.NbtSetSmbBindingInfo: ERROR: pSmbRequest=<%p>, pDevice=<%p>\n",
  2581. pSmbRequest, pDeviceContext));
  2582. status = STATUS_UNSUCCESSFUL;
  2583. goto error;
  2584. }
  2585. if (pIrp->RequestorMode != KernelMode) {
  2586. status = STATUS_ACCESS_DENIED;
  2587. goto error;
  2588. }
  2589. status = NbtSetSmbBindingInfo2 (pDeviceContext, pSmbRequest);
  2590. if (NT_SUCCESS(status) && pSmbRequest->MultiSZBindList) {
  2591. //
  2592. // Cache the binding info
  2593. //
  2594. pBindList = pSmbRequest->MultiSZBindList;
  2595. uInputLength = 0;
  2596. while (*pBindList) {
  2597. uLength = wcslen (pBindList) + 1;
  2598. uInputLength += uLength;
  2599. pBindList += uLength;
  2600. }
  2601. uInputLength++;
  2602. uInputLength *= sizeof(WCHAR);
  2603. pBindList = pSmbRequest->MultiSZBindList;
  2604. if (pSmbRequest->RequestType == SMB_SERVER) {
  2605. pTarget = &NbtConfig.pServerBindings;
  2606. } else if (pSmbRequest->RequestType == SMB_CLIENT) {
  2607. pTarget = &NbtConfig.pClientBindings;
  2608. } else {
  2609. ASSERT(0);
  2610. }
  2611. pBindListCache = NbtAllocMem (uInputLength, NBT_TAG2('27'));
  2612. if (NULL != pBindListCache) {
  2613. RtlCopyMemory (pBindListCache, pBindList, uInputLength);
  2614. pOldBindList = InterlockedExchangePointer (pTarget, pBindListCache);
  2615. //
  2616. // Free the old copy if any
  2617. //
  2618. if (NULL != pOldBindList) {
  2619. CTEFreeMem (pOldBindList);
  2620. pOldBindList = NULL;
  2621. }
  2622. }
  2623. }
  2624. error:
  2625. if (pSavedSmbDevice) {
  2626. NBT_DEREFERENCE_DEVICE (pSavedSmbDevice, REF_DEV_SMB_BIND, FALSE);
  2627. }
  2628. return status;
  2629. }
  2630. NTSTATUS
  2631. NbtEnableNetbiosSmb(
  2632. IN tDEVICECONTEXT *pDeviceContext,
  2633. IN PIRP pIrp,
  2634. IN PIO_STACK_LOCATION pIrpSp
  2635. )
  2636. {
  2637. NTSTATUS status = STATUS_SUCCESS;
  2638. if (pNbtSmbDevice) {
  2639. goto error;
  2640. }
  2641. pNbtSmbDevice = NbtCreateSmbDevice();
  2642. if (NULL == pNbtSmbDevice) {
  2643. status = STATUS_INSUFFICIENT_RESOURCES;
  2644. goto error;
  2645. }
  2646. NbtConfig.SMBDeviceEnabled = TRUE;
  2647. if (AddressCount > 0) {
  2648. NbtNotifyTdiClients (pNbtSmbDevice, NBT_TDI_REGISTER);
  2649. }
  2650. error:
  2651. return status;
  2652. }
  2653. VOID
  2654. NbtSleep(
  2655. ULONG TimeToSleep
  2656. )
  2657. {
  2658. KEVENT NeverTriggered = { 0 };
  2659. NTSTATUS status = STATUS_SUCCESS;
  2660. LARGE_INTEGER liTimeOut = { 0 };
  2661. liTimeOut.QuadPart = UInt32x32To64(TimeToSleep, 10000UL);
  2662. liTimeOut.QuadPart = -liTimeOut.QuadPart;
  2663. KeInitializeEvent(&NeverTriggered, NotificationEvent, FALSE);
  2664. status = KeWaitForSingleObject(
  2665. &NeverTriggered,
  2666. Executive,
  2667. KernelMode,
  2668. FALSE,
  2669. &liTimeOut
  2670. );
  2671. ASSERT (status == STATUS_TIMEOUT);
  2672. }
  2673. NTSTATUS
  2674. NbtDisableNetbiosSmb(
  2675. IN tDEVICECONTEXT *pDeviceContext,
  2676. IN PIRP pIrp,
  2677. IN PIO_STACK_LOCATION pIrpSp
  2678. )
  2679. {
  2680. NTSTATUS status = STATUS_SUCCESS;
  2681. KIRQL OldIrq = 0;
  2682. tDEVICECONTEXT *pSavedSmbDevice = NULL;
  2683. int i = 0;
  2684. if (NULL == pNbtSmbDevice) {
  2685. goto error;
  2686. }
  2687. //
  2688. // Prevent the pNbtSmbDevice from being used
  2689. //
  2690. // NetBT could access the pNbtSmbDevice in 2 scenarios:
  2691. // 1. referenced, but without holding the JointLock.
  2692. // 2. No reference but with JointLock held.
  2693. //
  2694. gbDestroyingSmbDevice = TRUE;
  2695. ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
  2696. //
  2697. // Wait for the refcount to become 1 for at most 8 second
  2698. //
  2699. for(i = 0; i < 8 && (*(volatile*)(&pNbtSmbDevice->RefCount) != 1); i++) {
  2700. NbtSleep(1000);
  2701. }
  2702. if (*(volatile*)(&pNbtSmbDevice->RefCount) != 1) {
  2703. gbDestroyingSmbDevice = FALSE;
  2704. status = STATUS_DEVICE_BUSY;
  2705. goto error;
  2706. }
  2707. //
  2708. // From now on, we're sure that scenario 1 couldn't
  2709. // happen any more.
  2710. //
  2711. //
  2712. // Set pNbtSmbDevice to NULL.
  2713. //
  2714. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  2715. pSavedSmbDevice = pNbtSmbDevice;
  2716. pNbtSmbDevice = NULL;
  2717. NbtConfig.SMBDeviceEnabled = FALSE;
  2718. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  2719. //
  2720. // From now on, we're sure that scenario 2 couldn't
  2721. // happen any more.
  2722. //
  2723. NbtNotifyTdiClients (pSavedSmbDevice, NBT_TDI_DEREGISTER);
  2724. status = NbtDestroyDevice (pSavedSmbDevice, TRUE);
  2725. KdPrint(("NbtDisableSmbDevice -- status=<%x>\n", status));
  2726. status = STATUS_SUCCESS;
  2727. gbDestroyingSmbDevice = FALSE;
  2728. error:
  2729. return status;
  2730. }
  2731. HANDLE
  2732. NbtOpenParametersRegistry(
  2733. VOID
  2734. )
  2735. {
  2736. HANDLE NbtConfigHandle = NULL;
  2737. HANDLE ParametersHandle = NULL;
  2738. NTSTATUS status = STATUS_SUCCESS;
  2739. OBJECT_ATTRIBUTES TmpObjectAttributes = { 0 };
  2740. ULONG Disposition = 0;
  2741. extern NTSTATUS NbtOpenRegistry(
  2742. IN HANDLE NbConfigHandle,
  2743. IN PWSTR String,
  2744. OUT PHANDLE pHandle
  2745. );
  2746. CTEPagedCode();
  2747. InitializeObjectAttributes (&TmpObjectAttributes,
  2748. &NbtConfig.pRegistry,
  2749. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  2750. NULL,
  2751. NULL
  2752. );
  2753. status = ZwCreateKey (&NbtConfigHandle,
  2754. KEY_READ,
  2755. &TmpObjectAttributes,
  2756. 0,
  2757. NULL,
  2758. 0,
  2759. &Disposition
  2760. );
  2761. if (!NT_SUCCESS(status)) {
  2762. goto error;
  2763. }
  2764. status = NbtOpenRegistry (NbtConfigHandle, L"Parameters", &ParametersHandle);
  2765. ZwClose(NbtConfigHandle);
  2766. error:
  2767. return ParametersHandle;
  2768. }
  2769. NTSTATUS
  2770. NbtEnableDisableNetbiosSmb(
  2771. IN tDEVICECONTEXT *pDeviceContext,
  2772. IN PIRP pIrp,
  2773. IN PIO_STACK_LOCATION pIrpSp
  2774. )
  2775. {
  2776. NTSTATUS status = STATUS_SUCCESS;
  2777. PDWORD pdwEnableSmb = (PDWORD)(pIrp->AssociatedIrp.SystemBuffer);
  2778. DWORD dwSMBDeviceEnabled = TRUE;
  2779. HANDLE hParm = NULL;
  2780. if (InterlockedIncrement(&gdwPendingEnableDisableSmbDevice) > 1) {
  2781. status = STATUS_DEVICE_BUSY;
  2782. goto error;
  2783. }
  2784. if (pIrp->RequestorMode != KernelMode) {
  2785. status = STATUS_ACCESS_DENIED;
  2786. goto error;
  2787. }
  2788. if (pDeviceContext == pNbtSmbDevice || KeGetCurrentIrql() != PASSIVE_LEVEL) {
  2789. status = STATUS_INVALID_PARAMETER;
  2790. goto error;
  2791. }
  2792. if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(DWORD)) {
  2793. status = STATUS_INVALID_PARAMETER;
  2794. goto error;
  2795. }
  2796. switch (*pdwEnableSmb) {
  2797. case NETBT_ENABLE_NETBIOS_SMB:
  2798. dwSMBDeviceEnabled = TRUE;
  2799. KdPrint(("Enable NetbiosSmb\n"));
  2800. NbtTrace(NBT_TRACE_PNP, ("Enable NetbiosSmb"));
  2801. break;
  2802. case NETBT_DISABLE_NETBIOS_SMB:
  2803. dwSMBDeviceEnabled = FALSE;
  2804. KdPrint(("Disable NetbiosSmb\n"));
  2805. NbtTrace(NBT_TRACE_PNP, ("Disable NetbiosSmb"));
  2806. break;
  2807. case NETBT_RESTORE_NETBIOS_SMB:
  2808. KdPrint(("Restore NetbiosSmb\n"));
  2809. NbtTrace(NBT_TRACE_PNP, ("Restore NetbiosSmb"));
  2810. hParm = NbtOpenParametersRegistry();
  2811. if (hParm == NULL) {
  2812. status = STATUS_UNSUCCESSFUL;
  2813. goto error;
  2814. }
  2815. dwSMBDeviceEnabled = CTEReadSingleIntParameter(hParm,
  2816. WS_SMB_DEVICE_ENABLED,
  2817. 1, // Enabled by default
  2818. 0);
  2819. ZwClose(hParm);
  2820. hParm = NULL;
  2821. break;
  2822. default:
  2823. status = STATUS_INVALID_PARAMETER;
  2824. goto error;
  2825. }
  2826. if (dwSMBDeviceEnabled) {
  2827. status = NbtEnableNetbiosSmb(pDeviceContext, pIrp, pIrpSp);
  2828. KdPrint(("NbtEanbleNetbiosSmb return 0x%08lx\n", status));
  2829. NbtTrace(NBT_TRACE_PNP, ("NbtEnableNetbiosSmb return %!status!", status));
  2830. } else {
  2831. status = NbtDisableNetbiosSmb(pDeviceContext, pIrp, pIrpSp);
  2832. KdPrint(("NbtDisableNetbiosSmb return 0x%08lx\n", status));
  2833. NbtTrace(NBT_TRACE_PNP, ("NbtDisableNetbiosSmb return %!status!", status));
  2834. }
  2835. error:
  2836. InterlockedDecrement(&gdwPendingEnableDisableSmbDevice);
  2837. return status;
  2838. }
  2839. //----------------------------------------------------------------------------
  2840. NTSTATUS
  2841. DispatchIoctls(
  2842. IN tDEVICECONTEXT *pDeviceContext,
  2843. IN PIRP pIrp,
  2844. IN PIO_STACK_LOCATION pIrpSp
  2845. )
  2846. /*++
  2847. Routine Description:
  2848. This Routine handles calling the OS independent routine depending on
  2849. the Ioctl passed in.
  2850. Arguments:
  2851. pIrp - a ptr to an IRP
  2852. Return Value:
  2853. NTSTATUS - status of the request
  2854. --*/
  2855. {
  2856. NTSTATUS status=STATUS_UNSUCCESSFUL;
  2857. ULONG ControlCode;
  2858. ULONG Size;
  2859. PVOID pBuffer;
  2860. ControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
  2861. NbtTrace(NBT_TRACE_IOCTL, ("pDeviceContext %p: pIrp %p, IOCTL 0x%08x function %d %Z",
  2862. pDeviceContext,
  2863. pIrp,
  2864. ControlCode,
  2865. (ControlCode >> 2) & 0xfff,
  2866. &pDeviceContext->BindName));
  2867. switch (ControlCode)
  2868. {
  2869. case IOCTL_NETBT_REREAD_REGISTRY:
  2870. {
  2871. //
  2872. // This function can be called from either IOCTL or PnP path.
  2873. // IOCTL path can be called from non-admin, which can be potentially
  2874. // exploited.
  2875. // Therefore pass FALSE to tell the NTReReadRegistry not to do
  2876. // name refreshing.
  2877. //
  2878. status = NTReReadRegistry(pDeviceContext, FALSE);
  2879. break;
  2880. }
  2881. case IOCTL_NETBT_ENABLE_EXTENDED_ADDR:
  2882. {
  2883. //
  2884. // Enable extended addressing - pass up IP addrs on Datagram Recvs.
  2885. //
  2886. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation (pIrp);
  2887. tCLIENTELE *pClientEle = (tCLIENTELE *)pIrpSp->FileObject->FsContext;
  2888. if (!NBT_VERIFY_HANDLE2 (pClientEle, NBT_VERIFY_CLIENT, NBT_VERIFY_CLIENT_DOWN))
  2889. {
  2890. //
  2891. // To make the stresser (devctl.exe) happy. [JRuan 12/18/2000]
  2892. //
  2893. // ASSERTMSG ("Nbt.DispatchIoctls: ERROR - Invalid Address Handle\n", 0);
  2894. status = STATUS_INVALID_HANDLE;
  2895. }
  2896. else if (pIrpSp->FileObject->FsContext2 != (PVOID)NBT_ADDRESS_TYPE)
  2897. {
  2898. status = STATUS_INVALID_ADDRESS;
  2899. }
  2900. else
  2901. {
  2902. pClientEle->ExtendedAddress = TRUE;
  2903. status = STATUS_SUCCESS;
  2904. }
  2905. break;
  2906. }
  2907. case IOCTL_NETBT_DISABLE_EXTENDED_ADDR:
  2908. {
  2909. //
  2910. // Disable extended addressing - dont pass up IP addrs on Datagram Recvs.
  2911. //
  2912. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation (pIrp);
  2913. tCLIENTELE *pClientEle = (tCLIENTELE *)pIrpSp->FileObject->FsContext;
  2914. if (!NBT_VERIFY_HANDLE2 (pClientEle, NBT_VERIFY_CLIENT, NBT_VERIFY_CLIENT_DOWN))
  2915. {
  2916. // ASSERTMSG ("Nbt.DispatchIoctls: ERROR - Invalid Address Handle\n", 0);
  2917. status = STATUS_INVALID_HANDLE;
  2918. }
  2919. else if (pIrpSp->FileObject->FsContext2 != (PVOID)NBT_ADDRESS_TYPE)
  2920. {
  2921. status = STATUS_INVALID_ADDRESS;
  2922. }
  2923. else
  2924. {
  2925. pClientEle->ExtendedAddress = FALSE;
  2926. status = STATUS_SUCCESS;
  2927. }
  2928. break;
  2929. }
  2930. case IOCTL_NETBT_GET_WINS_ADDR:
  2931. {
  2932. if ((pIrp->MdlAddress) &&
  2933. ((Size = MmGetMdlByteCount (pIrp->MdlAddress)) >= sizeof(tWINS_ADDRESSES)) &&
  2934. (pBuffer = (PVOID) MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority)))
  2935. {
  2936. status = STATUS_SUCCESS;
  2937. if (Size >= sizeof(tWINS_NODE_INFO))
  2938. {
  2939. tWINS_NODE_INFO UNALIGNED *pWinsBuffer = (tWINS_NODE_INFO *) pBuffer;
  2940. CTEMemCopy (&pWinsBuffer->AllNameServers,
  2941. pDeviceContext->lAllNameServers,
  2942. (sizeof(tIPADDRESS)*(2+MAX_NUM_OTHER_NAME_SERVERS)));
  2943. pWinsBuffer->NumOtherServers = pDeviceContext->lNumOtherServers;
  2944. pWinsBuffer->LastResponsive = pDeviceContext->lLastResponsive;
  2945. pWinsBuffer->NetbiosEnabled = pDeviceContext->NetbiosEnabled;
  2946. pWinsBuffer->NodeType = NodeType;
  2947. pIrp->IoStatus.Information = sizeof(tWINS_NODE_INFO);
  2948. }
  2949. else
  2950. {
  2951. tWINS_ADDRESSES UNALIGNED *pWinsBuffer = (tWINS_ADDRESSES *) pBuffer;
  2952. pWinsBuffer->PrimaryWinsServer = pDeviceContext->lNameServerAddress;
  2953. pWinsBuffer->BackupWinsServer = pDeviceContext->lBackupServer;
  2954. pIrp->IoStatus.Information = sizeof(tWINS_ADDRESSES);
  2955. }
  2956. }
  2957. break;
  2958. }
  2959. case IOCTL_NETBT_GET_IP_ADDRS:
  2960. {
  2961. status = GetIpAddrs (pDeviceContext, pIrp);
  2962. break;
  2963. }
  2964. case IOCTL_NETBT_GET_IP_SUBNET:
  2965. {
  2966. ULONG Length;
  2967. PULONG pIpAddr;
  2968. //
  2969. // return this devicecontext's ip address and all the other
  2970. // ip addrs after it.
  2971. //
  2972. if (pIrp->MdlAddress)
  2973. {
  2974. Length = MmGetMdlByteCount( pIrp->MdlAddress );
  2975. if (Length < 2*sizeof(ULONG))
  2976. {
  2977. status = STATUS_BUFFER_OVERFLOW;
  2978. }
  2979. else if (pIpAddr = (PULONG )MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority))
  2980. {
  2981. //
  2982. // Put this adapter first in the list
  2983. //
  2984. *((tIPADDRESS UNALIGNED *) pIpAddr) = pDeviceContext->AssignedIpAddress;
  2985. pIpAddr++;
  2986. *((tIPADDRESS UNALIGNED *) pIpAddr) = pDeviceContext->SubnetMask;
  2987. pIpAddr++;
  2988. if (Length >= 3*sizeof(ULONG))
  2989. {
  2990. *((tIPADDRESS UNALIGNED *) pIpAddr) = pDeviceContext->DeviceType;
  2991. }
  2992. status = STATUS_SUCCESS;
  2993. } else {
  2994. status = STATUS_INSUFFICIENT_RESOURCES;
  2995. }
  2996. }
  2997. break;
  2998. }
  2999. //
  3000. // The following Ioctl is used mainly by the Server service
  3001. //
  3002. case IOCTL_NETBT_SET_TCP_CONNECTION_INFO:
  3003. {
  3004. status = NbtClientSetTcpInfo ((tCONNECTELE *) pIrpSp->FileObject->FsContext,
  3005. pIrp->AssociatedIrp.SystemBuffer,
  3006. pIrpSp->Parameters.DeviceIoControl.InputBufferLength);
  3007. break;
  3008. }
  3009. //
  3010. // The following Ioctls are used mainly by NbtStat.exe for diagnostic purposes
  3011. //
  3012. case IOCTL_NETBT_GET_INTERFACE_INFO:
  3013. {
  3014. status = NbtGetInterfaceInfo (pIrp);
  3015. break;
  3016. }
  3017. case IOCTL_NETBT_PURGE_CACHE:
  3018. {
  3019. DelayedNbtResyncRemoteCache (NULL, NULL, NULL, NULL);
  3020. status = STATUS_SUCCESS;
  3021. break;
  3022. }
  3023. case IOCTL_NETBT_GET_CONNECTIONS:
  3024. {
  3025. if (pIrp->MdlAddress)
  3026. {
  3027. Size = MmGetMdlByteCount( pIrp->MdlAddress ) ;
  3028. // return an array of netbios names that are registered
  3029. status = NbtQueryConnectionList (pDeviceContext, &pBuffer, &Size);
  3030. }
  3031. break;
  3032. }
  3033. case IOCTL_NETBT_ADAPTER_STATUS:
  3034. {
  3035. if (pIrp->MdlAddress)
  3036. {
  3037. PIO_STACK_LOCATION pIrpSp;
  3038. tIPANDNAMEINFO *pIpAndNameInfo;
  3039. PCHAR pName;
  3040. ULONG lNameType;
  3041. ULONG NameLen;
  3042. ULONG IpAddrsList[2];
  3043. tIPADDRESS *pIpAddrs = NULL;
  3044. tDGRAM_SEND_TRACKING *pTracker;
  3045. //
  3046. // in case the call results in a name query on the wire...
  3047. //
  3048. IoMarkIrpPending(pIrp);
  3049. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  3050. pIpAndNameInfo = pIrp->AssociatedIrp.SystemBuffer;
  3051. NameLen = pIrpSp->Parameters.DeviceIoControl.InputBufferLength
  3052. - FIELD_OFFSET(tIPANDNAMEINFO,NetbiosAddress);
  3053. //
  3054. // Bug# 125288+120947: Make sure the data passed in + the Address type are good
  3055. //
  3056. if ((pIpAndNameInfo) &&
  3057. (pIrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(tIPANDNAMEINFO)))
  3058. {
  3059. TDI_ADDRESS_NETBT_INTERNAL TdiAddr;
  3060. // this routine gets a ptr to the netbios name out of the wierd
  3061. // TDI address syntax.
  3062. status = GetNetBiosNameFromTransportAddress(
  3063. (PTRANSPORT_ADDRESS) &pIpAndNameInfo->NetbiosAddress,
  3064. NameLen, &TdiAddr);
  3065. pName = TdiAddr.OEMRemoteName.Buffer;
  3066. NameLen = TdiAddr.OEMRemoteName.Length;
  3067. lNameType = TdiAddr.NameType;
  3068. }
  3069. if (NT_SUCCESS(status) &&
  3070. (lNameType == TDI_ADDRESS_NETBIOS_TYPE_UNIQUE) &&
  3071. (NameLen == NETBIOS_NAME_SIZE))
  3072. {
  3073. //
  3074. // Nbtstat sends down * in the first byte on Nbtstat -A <IP address>
  3075. // Make sure we let that case go ahead.
  3076. //
  3077. if (!pDeviceContext->NetbiosEnabled) {
  3078. status = STATUS_INVALID_DEVICE_STATE;
  3079. }
  3080. else if ((pName[0] == '*') && (pIpAndNameInfo->IpAddress == 0))
  3081. {
  3082. status = STATUS_BAD_NETWORK_PATH;
  3083. }
  3084. else if (NT_SUCCESS (status = GetTracker(&pTracker, NBT_TRACKER_ADAPTER_STATUS)))
  3085. {
  3086. if (pIpAndNameInfo->IpAddress)
  3087. {
  3088. IpAddrsList[0] = pIpAndNameInfo->IpAddress;
  3089. IpAddrsList[1] = 0;
  3090. pIpAddrs = IpAddrsList;
  3091. }
  3092. pTracker->ClientContext = pIrp;
  3093. status = NbtSendNodeStatus(pDeviceContext,
  3094. pName,
  3095. pIpAddrs,
  3096. pTracker,
  3097. CopyNodeStatusResponseCompletion);
  3098. // only complete the irp (below) for failure status's
  3099. if (status == STATUS_PENDING)
  3100. {
  3101. return(status);
  3102. }
  3103. //
  3104. // We cannot have a Success status returned here!
  3105. //
  3106. if (status == STATUS_SUCCESS)
  3107. {
  3108. ASSERT (0);
  3109. status = STATUS_UNSUCCESSFUL;
  3110. }
  3111. FreeTracker (pTracker, RELINK_TRACKER);
  3112. }
  3113. }
  3114. else if (NT_SUCCESS(status))
  3115. {
  3116. status = STATUS_INVALID_PARAMETER; // The NameType or NameLen must be wrong!
  3117. }
  3118. // the request has been satisfied, so unmark the pending
  3119. // since we will return the irp below
  3120. //
  3121. pIrpSp->Control &= ~SL_PENDING_RETURNED;
  3122. }
  3123. break;
  3124. }
  3125. case IOCTL_NETBT_GET_REMOTE_NAMES:
  3126. {
  3127. if (pIrp->MdlAddress)
  3128. {
  3129. Size = MmGetMdlByteCount( pIrp->MdlAddress ) ;
  3130. // return an array of netbios names that are registered
  3131. status = NbtQueryAdapterStatus(pDeviceContext, &pBuffer, &Size, NBT_REMOTE);
  3132. }
  3133. break;
  3134. }
  3135. case IOCTL_NETBT_GET_BCAST_NAMES:
  3136. {
  3137. if (pIrp->MdlAddress)
  3138. {
  3139. Size = MmGetMdlByteCount( pIrp->MdlAddress ) ;
  3140. // return an array of netbios names that are registered
  3141. status = NbtQueryBcastVsWins(pDeviceContext,&pBuffer,&Size);
  3142. }
  3143. break;
  3144. }
  3145. case IOCTL_NETBT_NAME_RELEASE_REFRESH:
  3146. {
  3147. status = ReRegisterLocalNames (NULL, TRUE);
  3148. break;
  3149. }
  3150. //
  3151. // The following Ioctls are used by the Cluster code
  3152. //
  3153. case IOCTL_NETBT_ADD_INTERFACE:
  3154. {
  3155. //
  3156. // Creates a dummy devicecontext which can be primed by the layer above
  3157. // with a DHCP address. This is to support multiple IP addresses per adapter
  3158. // for the Clusters group; but can be used by any module that needs support
  3159. // for more than one IP address per adapter. This private interface hides the
  3160. // devices thus created from the setup/regisrty and that is fine since the
  3161. // component (say, the clusters client) takes the responsibility for ensuring
  3162. // that the server (above us) comes to know of this new device.
  3163. //
  3164. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation (pIrp);
  3165. pBuffer = pIrp->AssociatedIrp.SystemBuffer;
  3166. Size = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  3167. //
  3168. // return the export string created.
  3169. //
  3170. status = NbtAddNewInterface(pIrp, pBuffer, Size);
  3171. IF_DBG(NBT_DEBUG_PNP_POWER)
  3172. KdPrint(("Nbt.DispatchIoctls: ADD_INTERFACE -- status=<%x>\n", status));
  3173. NTIoComplete(pIrp,status,(ULONG)-1);
  3174. return status;
  3175. }
  3176. case IOCTL_NETBT_DELETE_INTERFACE:
  3177. {
  3178. //
  3179. // Dereference this device for the Reference taken in the
  3180. // Dispatch routine so that the cleanup can proceed properly
  3181. //
  3182. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE);
  3183. if (pDeviceContext->DeviceType == NBT_DEVICE_CLUSTER)
  3184. {
  3185. //
  3186. // Delete the device this came down on..
  3187. //
  3188. status = NbtDestroyDevice (pDeviceContext, TRUE);
  3189. }
  3190. else
  3191. {
  3192. KdPrint(("Nbt.DispatchIoctls: ERROR: DELETE_INTERFACE <%x>, pDevice=<%p>\n",
  3193. status, pDeviceContext));
  3194. }
  3195. break;
  3196. }
  3197. case IOCTL_NETBT_QUERY_INTERFACE_INSTANCE:
  3198. {
  3199. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation (pIrp);
  3200. //
  3201. // Validate input/output buffer size
  3202. //
  3203. Size = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  3204. if (Size < sizeof(NETBT_ADD_DEL_IF))
  3205. {
  3206. // IF_DBG(NBT_DEBUG_PNP_POWER)
  3207. KdPrint(("Nbt.DispatchIoctls: QUERY_INTERFACE_INSTANCE: Output buffer too small\n"));
  3208. status = STATUS_INVALID_PARAMETER;
  3209. }
  3210. else
  3211. {
  3212. PNETBT_ADD_DEL_IF pAddDelIf = (PNETBT_ADD_DEL_IF)pIrp->AssociatedIrp.SystemBuffer;
  3213. status = STATUS_SUCCESS;
  3214. ASSERT(pDeviceContext->DeviceType == NBT_DEVICE_CLUSTER);
  3215. pAddDelIf->InstanceNumber = pDeviceContext->InstanceNumber;
  3216. pAddDelIf->Status = status;
  3217. pIrp->IoStatus.Information = sizeof(NETBT_ADD_DEL_IF);
  3218. NTIoComplete(pIrp,status,(ULONG)-1);
  3219. return status;
  3220. }
  3221. break;
  3222. }
  3223. case IOCTL_NETBT_NEW_IPADDRESS:
  3224. {
  3225. tNEW_IP_ADDRESS *pNewAddress = (tNEW_IP_ADDRESS *)pIrp->AssociatedIrp.SystemBuffer;
  3226. status = STATUS_UNSUCCESSFUL;
  3227. //
  3228. // Bug# 202320: Make sure the data passed in is valid
  3229. //
  3230. if ((pDeviceContext->DeviceType == NBT_DEVICE_CLUSTER) &&
  3231. (pNewAddress) &&
  3232. (pIrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(tNEW_IP_ADDRESS)))
  3233. {
  3234. KdPrint (("Nbt.DispatchIoctls: Calling NbtNewDhcpAddress on ClusterDevice <%x>!\n",
  3235. pDeviceContext));
  3236. pDeviceContext->AssignedIpAddress = ntohl (pNewAddress->IpAddress);
  3237. status = NbtNewDhcpAddress (pDeviceContext, pNewAddress->IpAddress, pNewAddress->SubnetMask);
  3238. ASSERT (pDeviceContext->AssignedIpAddress == pDeviceContext->IpAddress);
  3239. IF_DBG(NBT_DEBUG_PNP_POWER)
  3240. KdPrint (("Nbt.DispatchIoctls: NEW_IPADDRESS, status=<%x>, IP=<%x>, pDevice=<%p>\n",
  3241. status, pNewAddress->IpAddress, pDeviceContext));
  3242. }
  3243. else
  3244. {
  3245. KdPrint(("Nbt.DispatchIoctls: ERROR: NEW_IPADDRESS status=<%x>, pDevice=<%p>\n",
  3246. status, pDeviceContext));
  3247. }
  3248. break;
  3249. }
  3250. case IOCTL_NETBT_SET_WINS_ADDRESS:
  3251. {
  3252. //
  3253. // Sets the WINS addresses for a dynamic adapter
  3254. //
  3255. PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation (pIrp);
  3256. //
  3257. // Validate input/output buffer size
  3258. //
  3259. Size = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
  3260. if (Size < sizeof(NETBT_SET_WINS_ADDR))
  3261. {
  3262. // IF_DBG(NBT_DEBUG_PNP_POWER)
  3263. KdPrint(("NbtSetWinsAddr: Input buffer too small for struct\n"));
  3264. status = STATUS_INVALID_PARAMETER;
  3265. }
  3266. else if (pDeviceContext->DeviceType == NBT_DEVICE_CLUSTER)
  3267. {
  3268. PNETBT_SET_WINS_ADDR pSetWinsAddr = (PNETBT_SET_WINS_ADDR)pIrp->AssociatedIrp.SystemBuffer;
  3269. status = STATUS_SUCCESS;
  3270. pDeviceContext->lNameServerAddress = pSetWinsAddr->PrimaryWinsAddr;
  3271. pDeviceContext->lBackupServer = pSetWinsAddr->SecondaryWinsAddr;
  3272. pDeviceContext->SwitchedToBackup = 0;
  3273. pDeviceContext->RefreshToBackup = 0;
  3274. pSetWinsAddr->Status = status;
  3275. pIrp->IoStatus.Information = 0; // We are not copying any data to the Output buffers
  3276. NTIoComplete (pIrp,status,(ULONG)-1);
  3277. return status;
  3278. }
  3279. else
  3280. {
  3281. KdPrint(("Nbt.DispatchIoctls: ERROR: SET_WINS_ADDRESS <%x>, pDevice=<%p>\n",
  3282. status, pDeviceContext));
  3283. }
  3284. break;
  3285. }
  3286. //
  3287. // The following Ioctls are used by the LmHost Services Dll (lmhSvc.dll) to
  3288. // help NetBT ping addresses in user space or resolve names in Dns
  3289. //
  3290. case IOCTL_NETBT_DNS_NAME_RESOLVE:
  3291. {
  3292. if (pIrp->MdlAddress)
  3293. {
  3294. Size = MmGetMdlByteCount( pIrp->MdlAddress ) ;
  3295. if (Size < sizeof (tIPADDR_BUFFER_DNS))
  3296. {
  3297. // IF_DBG(NBT_DEBUG_PNP_POWER)
  3298. KdPrint(("Nbt.DnsNameResolve: Input buffer size=<%d> < tIPADDR_BUFFER_DNS=<%d>\n",
  3299. Size, sizeof (tIPADDR_BUFFER_DNS)));
  3300. status = STATUS_INVALID_PARAMETER;
  3301. }
  3302. else if (pBuffer = MmGetSystemAddressForMdlSafe (pIrp->MdlAddress, NormalPagePriority))
  3303. {
  3304. // return an array of netbios names that are registered
  3305. status = NtProcessLmHSvcIrp (pDeviceContext,pBuffer,Size,pIrp,NBT_RESOLVE_WITH_DNS);
  3306. return(status);
  3307. } else {
  3308. status = STATUS_INSUFFICIENT_RESOURCES;
  3309. }
  3310. }
  3311. break;
  3312. }
  3313. case IOCTL_NETBT_CHECK_IP_ADDR:
  3314. {
  3315. IF_DBG(NBT_DEBUG_NAMESRV)
  3316. KdPrint(("Ioctl Value is %X (IOCTL_NETBT_CHECK_IP_ADDR)\n",ControlCode));
  3317. if (pIrp->MdlAddress)
  3318. {
  3319. Size = MmGetMdlByteCount( pIrp->MdlAddress ) ;
  3320. if (Size < sizeof (tIPADDR_BUFFER_DNS))
  3321. {
  3322. // IF_DBG(NBT_DEBUG_PNP_POWER)
  3323. KdPrint(("Nbt.CheckIpAddr: Input buffer size=<%d> < tIPADDR_BUFFER_DNS=<%d>\n",
  3324. Size, sizeof (tIPADDR_BUFFER_DNS)));
  3325. status = STATUS_INVALID_PARAMETER;
  3326. }
  3327. else if (pBuffer = MmGetSystemAddressForMdlSafe (pIrp->MdlAddress, NormalPagePriority))
  3328. {
  3329. // return an array of netbios names that are registered
  3330. status = NtProcessLmHSvcIrp (pDeviceContext,pBuffer,Size,pIrp,NBT_PING_IP_ADDRS);
  3331. return(status);
  3332. } else {
  3333. status = STATUS_INSUFFICIENT_RESOURCES;
  3334. }
  3335. }
  3336. break;
  3337. }
  3338. //
  3339. // The following Ioctl is used by the DNS resolver to resolve names through Wins/Bcast
  3340. //
  3341. case IOCTL_NETBT_FIND_NAME:
  3342. {
  3343. tIPADDR_BUFFER *pIpAddrBuffer;
  3344. PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation (pIrp);
  3345. //
  3346. // in case the call results in a name query on the wire...
  3347. //
  3348. IoMarkIrpPending(pIrp);
  3349. //
  3350. // Bug# 120957: Make sure the data passed in + the Address type are good
  3351. // Bug# 234627: Verify non-NULL MdlAddress ptr
  3352. //
  3353. pIpAddrBuffer = pIrp->AssociatedIrp.SystemBuffer;
  3354. if ((pIrp->MdlAddress) && // to copy the data back!
  3355. (pIpAddrBuffer) &&
  3356. (pIrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(tIPADDR_BUFFER)))
  3357. {
  3358. status = NbtQueryFindName((PTDI_CONNECTION_INFORMATION)pIpAddrBuffer,
  3359. pDeviceContext,
  3360. pIrp,
  3361. TRUE);
  3362. }
  3363. if (status == STATUS_PENDING)
  3364. {
  3365. return(status);
  3366. }
  3367. // the request has been satisfied, so unmark the pending
  3368. // since we will return the irp below
  3369. //
  3370. pIrpSp->Control &= ~SL_PENDING_RETURNED;
  3371. break;
  3372. }
  3373. //
  3374. // The following Ioctls are used by the Wins server
  3375. //
  3376. case IOCTL_NETBT_WINS_RCV:
  3377. {
  3378. tWINS_INFO *pWins = pIrpSp->FileObject->FsContext;
  3379. if ((pDeviceContext == pWinsDeviceContext) &&
  3380. (NBT_VERIFY_HANDLE (pWins, NBT_VERIFY_WINS_ACTIVE)))
  3381. {
  3382. if (pIrp->MdlAddress)
  3383. {
  3384. status = RcvIrpFromWins(pIrp);
  3385. return(status);
  3386. }
  3387. }
  3388. else
  3389. {
  3390. status = STATUS_INVALID_HANDLE;
  3391. }
  3392. break;
  3393. }
  3394. case IOCTL_NETBT_WINS_SEND:
  3395. {
  3396. tWINS_INFO *pWins = pIrpSp->FileObject->FsContext;
  3397. BOOLEAN MustSend;
  3398. if ((pDeviceContext == pWinsDeviceContext) &&
  3399. (NBT_VERIFY_HANDLE (pWins, NBT_VERIFY_WINS_ACTIVE)))
  3400. {
  3401. if ((pIrp->MdlAddress) && !(IsListEmpty(&NbtConfig.DeviceContexts)))
  3402. {
  3403. status = WinsSendDatagram (pDeviceContext,pIrp,(MustSend = FALSE));
  3404. return(status);
  3405. }
  3406. }
  3407. else
  3408. {
  3409. status = STATUS_INVALID_HANDLE;
  3410. }
  3411. break;
  3412. }
  3413. case IOCTL_NETBT_WINS_SET_INFO:
  3414. {
  3415. tWINS_INFO *pWins = pIrpSp->FileObject->FsContext;
  3416. tWINS_SET_INFO *pWinsSetInfo = (tWINS_SET_INFO *) pIrp->AssociatedIrp.SystemBuffer;
  3417. if ((pDeviceContext == pWinsDeviceContext) &&
  3418. (NBT_VERIFY_HANDLE (pWins, NBT_VERIFY_WINS_ACTIVE)))
  3419. {
  3420. //
  3421. // Validate input/output buffer size
  3422. //
  3423. Size = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
  3424. if (Size >= sizeof(tWINS_SET_INFO))
  3425. {
  3426. status = WinsSetInformation (pWins, pWinsSetInfo);
  3427. }
  3428. else
  3429. {
  3430. IF_DBG(NBT_DEBUG_WINS)
  3431. KdPrint(("Nbt.DispatchIoctls[IOCTL_NETBT_WINS_SET_INFO]: Input buffer too small\n"));
  3432. status = STATUS_INVALID_PARAMETER;
  3433. }
  3434. }
  3435. else
  3436. {
  3437. status = STATUS_INVALID_HANDLE;
  3438. }
  3439. break;
  3440. }
  3441. //
  3442. // The following Ioctl is used by the Remote boot code
  3443. //
  3444. case IOCTL_NETBT_ADD_TO_REMOTE_TABLE:
  3445. {
  3446. tREMOTE_CACHE *pRemoteEntry = (tREMOTE_CACHE *) pIrp->AssociatedIrp.SystemBuffer;
  3447. PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation (pIrp);
  3448. //
  3449. // Validate input/output buffer size
  3450. //
  3451. Size = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
  3452. if (Size >= sizeof(tREMOTE_CACHE)) {
  3453. //
  3454. // We need only the name, IpAddress, name_flags, and Ttl fields
  3455. //
  3456. status = NbtAddEntryToRemoteHashTable (pDeviceContext,
  3457. NAME_RESOLVED_BY_CLIENT,
  3458. pRemoteEntry->name,
  3459. pRemoteEntry->IpAddress,
  3460. pRemoteEntry->Ttl,
  3461. pRemoteEntry->name_flags);
  3462. }
  3463. else
  3464. {
  3465. IF_DBG(NBT_DEBUG_PNP_POWER)
  3466. KdPrint(("Nbt.DispatchIoctls[IOCTL_NETBT_ADD_TO_REMOTE_TABLE]: Input buffer too small for struct\n"));
  3467. status = STATUS_BUFFER_TOO_SMALL;
  3468. }
  3469. break;
  3470. }
  3471. //
  3472. // The following Ioctl is used by DsGetDcName
  3473. //
  3474. case IOCTL_NETBT_REMOVE_FROM_REMOTE_TABLE:
  3475. {
  3476. tNAME *pRemoteName = (tNAME *) pIrp->AssociatedIrp.SystemBuffer;
  3477. PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation (pIrp);
  3478. //
  3479. // Validate input/output buffer size
  3480. //
  3481. Size = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
  3482. if (Size >= sizeof(tNAME))
  3483. {
  3484. //
  3485. // We need only the name
  3486. //
  3487. status = NbtFlushEntryFromRemoteHashTable (pRemoteName);
  3488. }
  3489. else
  3490. {
  3491. IF_DBG(NBT_DEBUG_PNP_POWER)
  3492. KdPrint(("Nbt.DispatchIoctls[IOCTL_NETBT_REMOVE_FROM_REMOTE_TABLE]: Input buffer too small\n"));
  3493. status = STATUS_INVALID_PARAMETER;
  3494. }
  3495. break;
  3496. }
  3497. //
  3498. // The following Ioctl is used by the Rdr/Srv to add/remove addresses from the SmbDevice
  3499. //
  3500. case IOCTL_NETBT_SET_SMBDEVICE_BIND_INFO:
  3501. {
  3502. ASSERT (NULL == pNbtSmbDevice || pDeviceContext == pNbtSmbDevice);
  3503. status = NbtSetSmbBindingInfo (pDeviceContext, pIrp, pIrpSp);
  3504. break;
  3505. }
  3506. case IOCTL_NETBT_ENABLE_DISABLE_NETBIOS_SMB:
  3507. //
  3508. // Private API for the new smb driver (smb.sys)
  3509. //
  3510. status = NbtEnableDisableNetbiosSmb(pDeviceContext, pIrp, pIrpSp);
  3511. break;
  3512. default:
  3513. {
  3514. status = STATUS_INVALID_PARAMETER;
  3515. break;
  3516. }
  3517. } // switch
  3518. NbtTrace(NBT_TRACE_IOCTL, ("pDeviceContext %p: pIrp %p %!status!",
  3519. pDeviceContext,
  3520. pIrp,
  3521. status
  3522. ));
  3523. //
  3524. // copy the reponse to the client's Mdl
  3525. //
  3526. if (!NT_ERROR(status) && // allow buffer overflow to pass by
  3527. ((ControlCode == IOCTL_NETBT_GET_REMOTE_NAMES) ||
  3528. (ControlCode == IOCTL_NETBT_GET_BCAST_NAMES) ||
  3529. (ControlCode == IOCTL_NETBT_GET_CONNECTIONS)) )
  3530. {
  3531. status = TdiCopyBufferToMdl (pBuffer, 0, Size, pIrp->MdlAddress, 0,
  3532. (PULONG) &pIrp->IoStatus.Information);
  3533. CTEMemFree((PVOID)pBuffer);
  3534. }
  3535. //
  3536. // either Success or an Error
  3537. // so complete the irp
  3538. //
  3539. NTIoComplete(pIrp,status,0);
  3540. return(status);
  3541. }
  3542. //----------------------------------------------------------------------------
  3543. NTSTATUS
  3544. GetIpAddrs(
  3545. IN tDEVICECONTEXT *pDeviceContext,
  3546. IN PIRP pIrp
  3547. )
  3548. /*++
  3549. Routine Description:
  3550. This routine performs the IOCTL_GET_IP_ADDRS function.
  3551. It is in its own routine because it is non paged.
  3552. Arguments:
  3553. pDeviceContext -
  3554. pIrp -
  3555. Return Value:
  3556. NTSTATUS -
  3557. --*/
  3558. {
  3559. ULONG Length;
  3560. PULONG pIpAddr;
  3561. PLIST_ENTRY pEntry,pHead;
  3562. tDEVICECONTEXT *pDevContext;
  3563. KIRQL OldIrq;
  3564. tIPADDRESS IpAddr;
  3565. //
  3566. // return this devicecontext's ip address and all the other
  3567. // ip addrs after it.
  3568. //
  3569. if (!pIrp->MdlAddress)
  3570. {
  3571. return STATUS_INVALID_PARAMETER;
  3572. }
  3573. else if ((Length = MmGetMdlByteCount (pIrp->MdlAddress)) < sizeof(ULONG))
  3574. {
  3575. return STATUS_BUFFER_TOO_SMALL;
  3576. }
  3577. else if (!(pIpAddr = (PULONG )MmGetSystemAddressForMdlSafe (pIrp->MdlAddress, NormalPagePriority)))
  3578. {
  3579. return STATUS_UNSUCCESSFUL;
  3580. }
  3581. //
  3582. // Put this adapter first in the list
  3583. // Don't include the smb device, its address is uninteresting
  3584. if (!IsDeviceNetbiosless (pDeviceContext))
  3585. {
  3586. *((tIPADDRESS UNALIGNED *) pIpAddr) = pDeviceContext->AssignedIpAddress;
  3587. pIpAddr++;
  3588. Length -= sizeof(ULONG);
  3589. }
  3590. // Return the others
  3591. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  3592. pEntry = pHead = &NbtConfig.DeviceContexts;
  3593. while ((pEntry = pEntry->Flink) != pHead)
  3594. {
  3595. if (Length < sizeof(ULONG))
  3596. {
  3597. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  3598. return STATUS_BUFFER_OVERFLOW;
  3599. }
  3600. pDevContext = CONTAINING_RECORD(pEntry, tDEVICECONTEXT, Linkage);
  3601. if ((pDevContext != pDeviceContext) &&
  3602. (pDevContext->AssignedIpAddress))
  3603. {
  3604. *((tIPADDRESS UNALIGNED *) pIpAddr) = pDevContext->AssignedIpAddress;
  3605. pIpAddr++;
  3606. Length -= sizeof(ULONG);
  3607. }
  3608. }
  3609. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  3610. //
  3611. // put a -1 address on the end
  3612. //
  3613. if (Length < sizeof(ULONG))
  3614. {
  3615. return STATUS_BUFFER_OVERFLOW;
  3616. }
  3617. IpAddr = -1;
  3618. *((tIPADDRESS UNALIGNED *) pIpAddr) = IpAddr;
  3619. return STATUS_SUCCESS;
  3620. } // GetIpAddrs
  3621. //----------------------------------------------------------------------------
  3622. NTSTATUS
  3623. NTReceive(
  3624. IN tDEVICECONTEXT *pDeviceContext,
  3625. IN PIRP pIrp
  3626. )
  3627. /*++
  3628. Routine Description:
  3629. This Routine handles Queuing a receive buffer on a connection or passing
  3630. the recieve buffer to the transport if there is outstanding data waiting
  3631. to be received on the connection.
  3632. Arguments:
  3633. pIrp - a ptr to an IRP
  3634. Return Value:
  3635. NTSTATUS - status of the request
  3636. --*/
  3637. {
  3638. NTSTATUS status=STATUS_UNSUCCESSFUL;
  3639. PIO_STACK_LOCATION pIrpSp;
  3640. tCONNECTELE *pConnEle;
  3641. KIRQL OldIrq, OldIrq1;
  3642. ULONG ToCopy;
  3643. ULONG ClientRcvLen;
  3644. tLOWERCONNECTION *pLowerConn;
  3645. ULONG RemainingPdu;
  3646. PTDI_REQUEST_KERNEL_RECEIVE pParams;
  3647. PTDI_REQUEST_KERNEL_RECEIVE pClientParams;
  3648. ULONG BytesCopied;
  3649. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  3650. pConnEle = pIrpSp->FileObject->FsContext;
  3651. if ((pConnEle) &&
  3652. (pConnEle->state == NBT_SESSION_UP))
  3653. {
  3654. CTESpinLock(pConnEle,OldIrq1);
  3655. PUSH_LOCATION(0x30);
  3656. if (!NBT_VERIFY_HANDLE2 (pConnEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN))
  3657. {
  3658. CTESpinFree(pConnEle,OldIrq1);
  3659. ASSERTMSG ("Nbt.NTReceive: ERROR - Invalid Connection Handle\n", 0);
  3660. status = STATUS_INVALID_HANDLE;
  3661. }
  3662. else if (pLowerConn = pConnEle->pLowerConnId)
  3663. {
  3664. status = STATUS_SUCCESS;
  3665. }
  3666. else
  3667. {
  3668. CTESpinFree(pConnEle,OldIrq1);
  3669. status = STATUS_REMOTE_DISCONNECT;
  3670. }
  3671. }
  3672. if (STATUS_SUCCESS != status)
  3673. {
  3674. PUSH_LOCATION(0x47);
  3675. //
  3676. // session in wrong state so reject the buffer posting
  3677. // complete the irp, since there must have been some sort of error
  3678. // to get to here
  3679. //
  3680. NTIoComplete(pIrp, status, 0);
  3681. return(status);
  3682. }
  3683. PUSH_LOCATION(0x31);
  3684. //
  3685. // We are already holding the ConnEle lock
  3686. CTESpinLock(pLowerConn,OldIrq);
  3687. if (pLowerConn->StateRcv != PARTIAL_RCV)
  3688. {
  3689. // **** Fast Path Code ****
  3690. //
  3691. // Queue this receive buffer on to the Rcv Head
  3692. //
  3693. InsertTailList(&pConnEle->RcvHead, &pIrp->Tail.Overlay.ListEntry);
  3694. status = NTCheckSetCancelRoutine(pIrp,(PVOID)NbtCancelReceive,pDeviceContext);
  3695. if (!NT_SUCCESS(status))
  3696. {
  3697. RemoveEntryList(&pIrp->Tail.Overlay.ListEntry);
  3698. CTESpinFree(pLowerConn,OldIrq);
  3699. CTESpinFree(pConnEle,OldIrq1);
  3700. NTIoComplete(pIrp,status,0);
  3701. return(status);
  3702. }
  3703. else
  3704. {
  3705. //
  3706. // if the irp is not cancelled, returning pending
  3707. //
  3708. CTESpinFree(pLowerConn,OldIrq);
  3709. CTESpinFree(pConnEle,OldIrq1);
  3710. return(STATUS_PENDING);
  3711. }
  3712. }
  3713. else
  3714. {
  3715. // ***** Partial Rcv - Data Still in Transport *****
  3716. BOOLEAN ZeroLengthSend;
  3717. PUSH_LOCATION(0x32);
  3718. IF_DBG(NBT_DEBUG_RCV)
  3719. KdPrint(("Nbt.NTReceive: A Rcv Buffer posted data in Xport,InXport= %X,InIndic %X RcvIndicated %X\n",
  3720. pConnEle->BytesInXport,pLowerConn->BytesInIndicate,
  3721. pConnEle->ReceiveIndicated));
  3722. // get the MDL chain length
  3723. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  3724. pClientParams = (PTDI_REQUEST_KERNEL_RECEIVE)&pIrpSp->Parameters;
  3725. // Reset the Irp pending flag
  3726. pIrpSp->Control &= ~SL_PENDING_RETURNED;
  3727. // fill in the next irp stack location with our completion routine.
  3728. pIrpSp = IoGetNextIrpStackLocation(pIrp);
  3729. pIrpSp->CompletionRoutine = CompletionRcv;
  3730. pIrpSp->Context = (PVOID)pConnEle->pLowerConnId;
  3731. pIrpSp->Flags = 0;
  3732. // set flags so the completion routine is always invoked.
  3733. pIrpSp->Control = SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR | SL_INVOKE_ON_CANCEL;
  3734. pIrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  3735. pIrpSp->MinorFunction = TDI_RECEIVE;
  3736. pIrpSp->DeviceObject = IoGetRelatedDeviceObject(pConnEle->pLowerConnId->pFileObject);
  3737. pIrpSp->FileObject = pConnEle->pLowerConnId->pFileObject;
  3738. pParams = (PTDI_REQUEST_KERNEL_RECEIVE)&pIrpSp->Parameters;
  3739. pParams->ReceiveFlags = pClientParams->ReceiveFlags;
  3740. // Since this irp is going to traverse through CompletionRcv, we
  3741. // need to set the following, since it undoes this stuff.
  3742. // This also prevents the LowerConn from being blown away before
  3743. // the irp has returned from the transport
  3744. //
  3745. NBT_REFERENCE_LOWERCONN (pLowerConn, REF_LOWC_RCV_HANDLER);
  3746. //
  3747. // pass the receive buffer directly to the transport, decrementing
  3748. // the number of receive bytes that have been indicated
  3749. //
  3750. ASSERT(pConnEle->TotalPcktLen >= pConnEle->BytesRcvd);
  3751. if (pClientParams->ReceiveLength > (pConnEle->TotalPcktLen - pConnEle->BytesRcvd))
  3752. {
  3753. pParams->ReceiveLength = pConnEle->TotalPcktLen - pConnEle->BytesRcvd;
  3754. }
  3755. else
  3756. {
  3757. pParams->ReceiveLength = pClientParams->ReceiveLength;
  3758. }
  3759. ClientRcvLen = pParams->ReceiveLength;
  3760. //
  3761. // Set the amount of data that we will receive so when the
  3762. // irp completes in completionRcv, we can fill in that
  3763. // info in the Irp
  3764. //
  3765. pConnEle->CurrentRcvLen = ClientRcvLen;
  3766. // if a zero length send occurs, then ReceiveIndicated is set
  3767. // to zero with the state set to RcvPartial. Or, the client may
  3768. // pass down an Irp with no MDL in it!!
  3769. //
  3770. if ((pConnEle->ReceiveIndicated == 0) || !pIrp->MdlAddress)
  3771. {
  3772. ZeroLengthSend = TRUE;
  3773. }
  3774. else
  3775. {
  3776. ZeroLengthSend = FALSE;
  3777. }
  3778. // calculate how many bytes are still remaining for the client.
  3779. if (pConnEle->ReceiveIndicated > ClientRcvLen)
  3780. {
  3781. PUSH_LOCATION(0x40);
  3782. pConnEle->ReceiveIndicated -= ClientRcvLen;
  3783. }
  3784. else
  3785. {
  3786. pConnEle->ReceiveIndicated = 0;
  3787. }
  3788. if (pLowerConn->BytesInIndicate || ZeroLengthSend)
  3789. {
  3790. PMDL Mdl;
  3791. PUSH_LOCATION(0x33);
  3792. if (ClientRcvLen > pLowerConn->BytesInIndicate)
  3793. {
  3794. ToCopy = pLowerConn->BytesInIndicate;
  3795. }
  3796. else
  3797. {
  3798. PUSH_LOCATION(0x41);
  3799. ToCopy = ClientRcvLen;
  3800. }
  3801. // copy data from the indicate buffer to the client's buffer,
  3802. // remembering that there is a session header in the indicate
  3803. // buffer at the start of it... so skip that. The
  3804. // client can pass down a null Mdl address for a zero length
  3805. // rcv so check for that.
  3806. //
  3807. if (Mdl = pIrp->MdlAddress)
  3808. {
  3809. TdiCopyBufferToMdl(MmGetMdlVirtualAddress(pLowerConn->pIndicateMdl),
  3810. 0, // src offset
  3811. ToCopy,
  3812. Mdl,
  3813. 0, // dest offset
  3814. &BytesCopied);
  3815. }
  3816. else
  3817. {
  3818. BytesCopied = 0;
  3819. }
  3820. // client's MDL is too short...
  3821. if (BytesCopied != ToCopy)
  3822. {
  3823. PUSH_LOCATION(0x42);
  3824. IF_DBG(NBT_DEBUG_INDICATEBUFF)
  3825. KdPrint(("Nbt:Receive Buffer too short for Indicate buff BytesCopied %X, ToCopy %X\n",
  3826. BytesCopied, ToCopy));
  3827. // ToCopy = BytesCopied;
  3828. // so the irp will be completed, below
  3829. ClientRcvLen = BytesCopied;
  3830. }
  3831. pLowerConn->BytesInIndicate -= (USHORT)BytesCopied;
  3832. // this case is only if the irp is full and should be returned
  3833. // now.
  3834. if (BytesCopied == ClientRcvLen)
  3835. {
  3836. PUSH_LOCATION(0x34);
  3837. // check if the indicate buffer is empty now. If not, then
  3838. // move the data forward to the start of the buffer.
  3839. //
  3840. if (pLowerConn->BytesInIndicate)
  3841. {
  3842. PUSH_LOCATION(0x43);
  3843. CopyToStartofIndicate(pLowerConn,BytesCopied);
  3844. }
  3845. //
  3846. // the irp is full so complete it
  3847. //
  3848. // the client MDL is full, so complete his irp
  3849. // CompletionRcv increments the number of bytes rcvd
  3850. // for this session pdu (pConnEle->BytesRcvd).
  3851. pIrp->IoStatus.Information = BytesCopied;
  3852. pIrp->IoStatus.Status = STATUS_SUCCESS;
  3853. // since we are completing it and TdiRcvHandler did not set the next
  3854. // one.
  3855. //
  3856. ASSERT(pIrp->CurrentLocation > 1);
  3857. IoSetNextIrpStackLocation(pIrp);
  3858. // we need to track how much of the client's MDL has filled
  3859. // up to know when to return it. CompletionRcv subtracts
  3860. // from this value as it receives bytes.
  3861. pConnEle->FreeBytesInMdl = ClientRcvLen;
  3862. pConnEle->CurrentRcvLen = ClientRcvLen;
  3863. CTESpinFree(pLowerConn,OldIrq);
  3864. CTESpinFree(pConnEle,OldIrq1);
  3865. IoCompleteRequest(pIrp,IO_NETWORK_INCREMENT);
  3866. return(STATUS_SUCCESS);
  3867. }
  3868. else
  3869. {
  3870. //
  3871. // clear the number of bytes in the indicate buffer since the client
  3872. // has taken more than the data left in the Indicate buffer
  3873. //
  3874. pLowerConn->BytesInIndicate = 0;
  3875. // decrement the client rcv len by the amount already put into the
  3876. // client Mdl
  3877. //
  3878. ClientRcvLen -= BytesCopied;
  3879. IF_DBG(NBT_DEBUG_RCV)
  3880. KdPrint(("Nbt: Pass Client Irp to Xport BytesinXport %X, ClientRcvLen %X\n",
  3881. pConnEle->BytesInXport,ClientRcvLen));
  3882. //
  3883. // Set the amount left inthe transport after this irp
  3884. // completes
  3885. if (pConnEle->BytesInXport < ClientRcvLen )
  3886. {
  3887. pConnEle->BytesInXport = 0;
  3888. }
  3889. else
  3890. {
  3891. pConnEle->BytesInXport -= ClientRcvLen;
  3892. }
  3893. // Adjust the number of bytes in the Mdl chain so far since the
  3894. // completion routine will only count the bytes filled in by the
  3895. // transport
  3896. pConnEle->BytesRcvd += BytesCopied;
  3897. // the client is going to take more data from the transport with
  3898. // this Irp. Set the new Rcv Length that accounts for the data just
  3899. // copied to the Irp.
  3900. //
  3901. pParams->ReceiveLength = ClientRcvLen;
  3902. IF_DBG(NBT_DEBUG_RCV)
  3903. KdPrint(("Nbt:ClientRcvLen = %X, LeftinXport= %X BytesCopied= %X %X\n",ClientRcvLen,
  3904. pConnEle->BytesInXport,BytesCopied,pLowerConn));
  3905. // set the state to this so we can undo the MDL footwork
  3906. // in completion rcv - since we have made a partial MDL and
  3907. // put that at the start of the chain.
  3908. //
  3909. SET_STATERCV_LOWER(pLowerConn, FILL_IRP, FillIrp);
  3910. // Note that the Irp Mdl address changes below
  3911. // when MakePartialMdl is called so this line cannot
  3912. // be moved to the common code below!!
  3913. pLowerConn->pMdl = pIrp->MdlAddress;
  3914. // setup the next MDL so we can create a partial mdl correctly
  3915. // in TdiReceiveHandler
  3916. //
  3917. pConnEle->pNextMdl = pIrp->MdlAddress;
  3918. // Build a partial Mdl to represent the client's Mdl chain since
  3919. // we have copied data to it, and the transport must copy
  3920. // more data to it after that data.
  3921. //
  3922. // Force the system to map and lock the user buffer
  3923. MmGetSystemAddressForMdlSafe (pIrp->MdlAddress, HighPagePriority);
  3924. MakePartialMdl(pConnEle,pIrp,BytesCopied);
  3925. // pass the Irp to the transport
  3926. //
  3927. //
  3928. IF_DBG(NBT_DEBUG_RCV)
  3929. KdPrint(("Nbt:Calling IoCallDriver\n"));
  3930. ASSERT(pIrp->CurrentLocation > 1);
  3931. }
  3932. }
  3933. else
  3934. {
  3935. PUSH_LOCATION(0x36);
  3936. IF_DBG(NBT_DEBUG_RCV)
  3937. KdPrint(("Nbt.NTReceive: Pass Irp To Xport Bytes in Xport %X, ClientRcvLen %X, RcvIndicated %X\n",
  3938. pConnEle->BytesInXport,ClientRcvLen,pConnEle->ReceiveIndicated));
  3939. //
  3940. // there are no bytes in the indicate buffer, so just pass the
  3941. // irp on down to the transport
  3942. //
  3943. //
  3944. // Decide the next state depending on whether the transport currently
  3945. // has enough data for this irp
  3946. //
  3947. if (pConnEle->BytesInXport < ClientRcvLen)
  3948. {
  3949. PUSH_LOCATION(0x37);
  3950. pConnEle->BytesInXport = 0;
  3951. //
  3952. // to get to here, the implication is that ReceiveIndicated
  3953. // equals zero too!! Since ReceiveInd cannot be more than
  3954. // BytesInXport, so we can change the state to fill irp without
  3955. // worrying about overwriting PartialRcv
  3956. //
  3957. SET_STATERCV_LOWER(pLowerConn, FILL_IRP, FillIrp);
  3958. // setup the next MDL so we can create a partial mdl correctly
  3959. // in TdiReceiveHandler
  3960. //
  3961. pConnEle->pNextMdl = pIrp->MdlAddress;
  3962. }
  3963. else
  3964. {
  3965. PUSH_LOCATION(0x38);
  3966. pConnEle->BytesInXport -= ClientRcvLen;
  3967. // set the state to this so we know what to do in completion rcv
  3968. //
  3969. if (pConnEle->ReceiveIndicated == 0)
  3970. {
  3971. PUSH_LOCATION(0x39);
  3972. SET_STATERCV_LOWER(pLowerConn, NORMAL, Normal);
  3973. }
  3974. }
  3975. //
  3976. // save the Irp so we can reconstruct things later
  3977. //
  3978. pLowerConn->pMdl = pIrp->MdlAddress;
  3979. }
  3980. // *** Common Code to passing irp to transport - when there is
  3981. // data in the indicate buffer and when there isn't
  3982. // keep track of data in MDL so we know when it is full
  3983. // and we need to return it to the user
  3984. //
  3985. pConnEle->FreeBytesInMdl = pParams->ReceiveLength;
  3986. // Force the system to map and lock the user buffer
  3987. MmGetSystemAddressForMdlSafe (pIrp->MdlAddress, HighPagePriority);
  3988. //
  3989. // Null the Irp since we are passing it to the transport.
  3990. //
  3991. pConnEle->pIrpRcv = NULL;
  3992. CTESpinFree(pLowerConn,OldIrq);
  3993. CTESpinFree(pConnEle,OldIrq1);
  3994. CHECK_COMPLETION(pIrp);
  3995. status = IoCallDriver(IoGetRelatedDeviceObject(pLowerConn->pFileObject),pIrp);
  3996. IF_DBG(NBT_DEBUG_RCV)
  3997. KdPrint(("Nbt.NTReceive: Returning=<%x>, IoStatus.Status=<%x>, IoStatus.Information=<%x>\n",
  3998. status, pIrp->IoStatus.Status, pIrp->IoStatus.Information));
  3999. }
  4000. return(status);
  4001. }
  4002. //----------------------------------------------------------------------------
  4003. NTSTATUS
  4004. NTReceiveDatagram(
  4005. IN tDEVICECONTEXT *pDeviceContext,
  4006. IN PIRP pIrp)
  4007. /*++
  4008. Routine Description:
  4009. This Routine handles receiving a datagram by passing the datagram rcv
  4010. buffer to the non-OS specific code.
  4011. Arguments:
  4012. pIrp - a ptr to an IRP
  4013. Return Value:
  4014. NTSTATUS - status of the request
  4015. --*/
  4016. {
  4017. NTSTATUS status;
  4018. PIO_STACK_LOCATION pIrpSp;
  4019. PTDI_REQUEST_KERNEL_RECEIVEDG pTdiRequest;
  4020. TDI_REQUEST Request;
  4021. ULONG ReceivedLength;
  4022. tCLIENTELE *pClientEle;
  4023. IF_DBG(NBT_DEBUG_RCV)
  4024. KdPrint(("Nbt: Got a Receive datagram that NBT was NOT \n"));
  4025. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  4026. pClientEle = (tCLIENTELE *)pIrpSp->FileObject->FsContext;
  4027. if (!NBT_VERIFY_HANDLE2 (pClientEle, NBT_VERIFY_CLIENT, NBT_VERIFY_CLIENT_DOWN))
  4028. {
  4029. ASSERTMSG ("Nbt.NTReceiveDatagram: ERROR - Invalid Address Handle\n", 0);
  4030. return (STATUS_INVALID_HANDLE);
  4031. }
  4032. // get the sending information out of the irp
  4033. pTdiRequest = (PTDI_REQUEST_KERNEL_RECEIVEDG)&pIrpSp->Parameters;
  4034. Request.Handle.AddressHandle = pClientEle;
  4035. status = NbtReceiveDatagram(
  4036. &Request,
  4037. pTdiRequest->ReceiveDatagramInformation,
  4038. pTdiRequest->ReturnDatagramInformation,
  4039. pTdiRequest->ReceiveLength,
  4040. &ReceivedLength,
  4041. (PVOID)pIrp->MdlAddress, // user data
  4042. (tDEVICECONTEXT *)pDeviceContext,
  4043. pIrp);
  4044. if (status != STATUS_PENDING)
  4045. {
  4046. NTIoComplete(pIrp,status,ReceivedLength);
  4047. }
  4048. return(status);
  4049. }
  4050. //----------------------------------------------------------------------------
  4051. NTSTATUS
  4052. NTSend(
  4053. IN tDEVICECONTEXT *pDeviceContext,
  4054. IN PIRP pIrp)
  4055. /*++
  4056. Routine Description:
  4057. This Routine handles sending session pdus across a connection. It is
  4058. all OS specific code.
  4059. Arguments:
  4060. pIrp - a ptr to an IRP
  4061. Return Value:
  4062. NTSTATUS - status of the request
  4063. --*/
  4064. {
  4065. PIO_STACK_LOCATION pIrpSp;
  4066. NTSTATUS status;
  4067. PTDI_REQUEST_KERNEL_SEND pTdiRequest;
  4068. PMDL pMdl;
  4069. PSINGLE_LIST_ENTRY pSingleListEntry;
  4070. tSESSIONHDR *pSessionHdr;
  4071. tCONNECTELE *pConnEle;
  4072. KIRQL OldIrq;
  4073. KIRQL OldIrq1;
  4074. PTDI_REQUEST_KERNEL_SEND pParams;
  4075. PFILE_OBJECT pFileObject;
  4076. tLOWERCONNECTION *pLowerConn;
  4077. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  4078. //
  4079. // This function could be called directly also while bypassing the
  4080. // Io subsystem, so we need to recheck the DeviceContext here
  4081. //
  4082. if (!NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE))
  4083. {
  4084. // IF_DBG(NBT_DEBUG_SEND)
  4085. KdPrint(("Nbt.NTSend: Invalid Device=<%x>\n", pDeviceContext));
  4086. status = STATUS_INVALID_DEVICE_STATE;
  4087. goto ErrorInvalidDevice;
  4088. }
  4089. // get the sending information out of the irp
  4090. pTdiRequest = (PTDI_REQUEST_KERNEL_SEND)&pIrpSp->Parameters;
  4091. pConnEle = (tCONNECTELE *)pIrpSp->FileObject->FsContext;
  4092. if (!NBT_VERIFY_HANDLE2 (pConnEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN))
  4093. {
  4094. ASSERTMSG ("Nbt.NTSend: ERROR - Invalid Connection Handle\n", 0);
  4095. status = STATUS_INVALID_HANDLE;
  4096. goto ErrorExit; // Irp has to be completed in this routine! Bug# 202340
  4097. }
  4098. CTESpinLock(pConnEle,OldIrq);
  4099. if (!(pLowerConn = pConnEle->pLowerConnId))
  4100. {
  4101. CTESpinFree(pConnEle,OldIrq);
  4102. IF_DBG(NBT_DEBUG_SEND)
  4103. KdPrint(("Nbt.NTSend: attempting send when LowerConn has been freed!\n"));
  4104. status = STATUS_INVALID_HANDLE;
  4105. goto ErrorExit; // to save on indent levels use a goto here
  4106. }
  4107. //
  4108. // make sure lowerconn stays valid until the irp is done
  4109. //
  4110. CTESpinLock(pLowerConn,OldIrq1);
  4111. NBT_REFERENCE_LOWERCONN (pLowerConn, REF_LOWC_SEND);
  4112. CTESpinFree(pLowerConn,OldIrq1);
  4113. // check the state of the connection
  4114. if (pConnEle->state == NBT_SESSION_UP)
  4115. {
  4116. //
  4117. // send the data on downward to tcp
  4118. // allocate an MDL to allow us to put the session hdr in first and then
  4119. // put the users buffer on after that, chained to the session hdr MDL.
  4120. //
  4121. #if BACK_FILL
  4122. {
  4123. PMDL SmbMdl;
  4124. SmbMdl = (PMDL)pIrp->MdlAddress;
  4125. // Check if network header type is set
  4126. // if yes, then we can back fill the nbt session header
  4127. if ((SmbMdl) && (SmbMdl->MdlFlags & MDL_NETWORK_HEADER))
  4128. {
  4129. pSessionHdr = (tSESSIONHDR *)((ULONG_PTR)SmbMdl->MappedSystemVa - SESSION_HDR_SIZE);
  4130. (ULONG_PTR)SmbMdl->MappedSystemVa -= SESSION_HDR_SIZE;
  4131. SmbMdl->ByteOffset -= SESSION_HDR_SIZE;
  4132. SmbMdl->ByteCount+= SESSION_HDR_SIZE;
  4133. pSessionHdr->UlongLength = htonl(pTdiRequest->SendLength);
  4134. IF_DBG(NBT_DEBUG_SEND)
  4135. KdPrint(("Nbt: Backfilled mdl %x %x\n", pSessionHdr, SmbMdl));
  4136. }
  4137. else
  4138. {
  4139. CTESpinLockAtDpc(&NbtConfig);
  4140. if (NbtConfig.SessionMdlFreeSingleList.Next)
  4141. {
  4142. pSingleListEntry = PopEntryList(&NbtConfig.SessionMdlFreeSingleList);
  4143. pMdl = CONTAINING_RECORD(pSingleListEntry,MDL,Next);
  4144. ASSERT ( MmGetMdlByteCount ( pMdl ) == sizeof ( tSESSIONHDR ) );
  4145. }
  4146. else
  4147. {
  4148. NbtGetMdl(&pMdl,eNBT_FREE_SESSION_MDLS);
  4149. if (!pMdl)
  4150. {
  4151. IF_DBG(NBT_DEBUG_SEND)
  4152. KdPrint(("Nbt:Unable to get an MDL for a session send!\n"));
  4153. status = STATUS_INSUFFICIENT_RESOURCES;
  4154. CTESpinFreeAtDpc(&NbtConfig);
  4155. CTESpinFree(pConnEle,OldIrq);
  4156. // to save on indent levels use a goto here
  4157. goto ErrorExit1;
  4158. }
  4159. }
  4160. CTESpinFreeAtDpc(&NbtConfig);
  4161. // get the session hdr address out of the MDL
  4162. pSessionHdr = (tSESSIONHDR *)MmGetMdlVirtualAddress(pMdl);
  4163. // the type of PDU is always a session message, since the session
  4164. // request is sent when the client issues a "connect" rather than a send
  4165. //
  4166. pSessionHdr->UlongLength = htonl(pTdiRequest->SendLength);
  4167. // get the device object and file object for the TCP transport underneath
  4168. // link the user buffer on the end of the session header Mdl on the Irp
  4169. //
  4170. pMdl->Next = pIrp->MdlAddress;
  4171. pIrp->MdlAddress = pMdl;
  4172. }
  4173. }
  4174. #else
  4175. CTESpinLockAtDpc(&NbtConfig);
  4176. if (NbtConfig.SessionMdlFreeSingleList.Next)
  4177. {
  4178. pSingleListEntry = PopEntryList(&NbtConfig.SessionMdlFreeSingleList);
  4179. pMdl = CONTAINING_RECORD(pSingleListEntry,MDL,Next);
  4180. ASSERT ( MmGetMdlByteCount ( pMdl ) == sizeof ( tSESSIONHDR ) );
  4181. }
  4182. else
  4183. {
  4184. NbtGetMdl(&pMdl,eNBT_FREE_SESSION_MDLS);
  4185. if (!pMdl)
  4186. {
  4187. IF_DBG(NBT_DEBUG_SEND)
  4188. KdPrint(("Nbt:Unable to get an MDL for a session send!\n"));
  4189. status = STATUS_INSUFFICIENT_RESOURCES;
  4190. CTESpinFreeAtDpc(&NbtConfig);
  4191. CTESpinFree(pConnEle,OldIrq);
  4192. // to save on indent levels use a goto here
  4193. goto ErrorExit1;
  4194. }
  4195. }
  4196. CTESpinFreeAtDpc(&NbtConfig);
  4197. // get the session hdr address out of the MDL
  4198. pSessionHdr = (tSESSIONHDR *)MmGetMdlVirtualAddress(pMdl);
  4199. // the type of PDU is always a session message, since the session
  4200. // request is sent when the client issues a "connect" rather than a send
  4201. //
  4202. pSessionHdr->UlongLength = htonl(pTdiRequest->SendLength);
  4203. // get the device object and file object for the TCP transport underneath
  4204. // link the user buffer on the end of the session header Mdl on the Irp
  4205. //
  4206. pMdl->Next = pIrp->MdlAddress;
  4207. pIrp->MdlAddress = pMdl;
  4208. #endif //BACK_FILL
  4209. pIrpSp = IoGetNextIrpStackLocation(pIrp);
  4210. pParams = (PTDI_REQUEST_KERNEL_SEND)&pIrpSp->Parameters;
  4211. pParams->SendFlags = pTdiRequest->SendFlags;
  4212. pParams->SendLength = pTdiRequest->SendLength + sizeof(tSESSIONHDR);
  4213. pIrpSp->CompletionRoutine = SendCompletion;
  4214. pIrpSp->Context = (PVOID)pLowerConn;
  4215. pIrpSp->Control = SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR | SL_INVOKE_ON_CANCEL;
  4216. pIrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  4217. pIrpSp->MinorFunction = TDI_SEND;
  4218. pFileObject = pLowerConn->pFileObject;
  4219. pLowerConn->BytesSent += pTdiRequest->SendLength;
  4220. pIrpSp->FileObject = pFileObject;
  4221. pIrpSp->DeviceObject = IoGetRelatedDeviceObject(pFileObject);
  4222. CTESpinFree(pConnEle,OldIrq);
  4223. CHECK_COMPLETION(pIrp);
  4224. #if FAST_DISP
  4225. //if we are all set to do fast path, do so now.
  4226. if (pLowerConn->FastSend)
  4227. {
  4228. IoSetNextIrpStackLocation(pIrp);
  4229. IF_DBG(NBT_DEBUG_SEND)
  4230. KdPrint(("Nbt.NTSend: Fasttdi path %x %x \n", pIrp, pIrpSp));
  4231. status = pLowerConn->FastSend (pIrp, pIrpSp);
  4232. }
  4233. else
  4234. {
  4235. status = IoCallDriver (IoGetRelatedDeviceObject (pFileObject), pIrp);
  4236. }
  4237. #else
  4238. status = IoCallDriver(IoGetRelatedDeviceObject(pFileObject),pIrp);
  4239. #endif
  4240. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE);
  4241. return(status);
  4242. } //correct state
  4243. CTESpinFree(pConnEle,OldIrq);
  4244. IF_DBG(NBT_DEBUG_SEND)
  4245. KdPrint(("Nbt:Invalid state for connection on an attempted send, %X\n",
  4246. pConnEle));
  4247. status = STATUS_INVALID_HANDLE;
  4248. ErrorExit1:
  4249. //
  4250. // Dereference pLowerConn->RefCount, referenced above.
  4251. //
  4252. NBT_DEREFERENCE_LOWERCONN (pLowerConn, REF_LOWC_SEND, FALSE);
  4253. ErrorExit:
  4254. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE);
  4255. ErrorInvalidDevice:
  4256. //
  4257. // Reset the Irp pending flag
  4258. //
  4259. pIrpSp->Control &= ~SL_PENDING_RETURNED;
  4260. //
  4261. // complete the irp, since there must have been some sort of error
  4262. // to get to here
  4263. //
  4264. NTIoComplete (pIrp, status, 0);
  4265. return(status);
  4266. }
  4267. //----------------------------------------------------------------------------
  4268. NTSTATUS
  4269. SendCompletion(
  4270. IN PDEVICE_OBJECT DeviceObject,
  4271. IN PIRP Irp,
  4272. IN PVOID Context
  4273. )
  4274. /*++
  4275. Routine Description:
  4276. This routine handles the completion event when the send completes with
  4277. the underlying transport. It must put the session hdr buffer back in
  4278. the correct free list and free the active q entry and put it back on
  4279. its free list.
  4280. Arguments:
  4281. DeviceObject - unused.
  4282. Irp - Supplies Irp that the transport has finished processing.
  4283. Context - Supplies the pConnectEle - the connection data structure
  4284. Return Value:
  4285. The final status from the operation (success or an exception).
  4286. --*/
  4287. {
  4288. PMDL pMdl;
  4289. tLOWERCONNECTION *pLowerConn;
  4290. //
  4291. // Do some checking to keep the Io system happy - propagate the pending
  4292. // bit up the irp stack frame.... if it was set by the driver below then
  4293. // it must be set by me
  4294. //
  4295. if (Irp->PendingReturned)
  4296. {
  4297. IoMarkIrpPending(Irp);
  4298. }
  4299. // put the MDL we back on its free list and put the clients mdl back on the Irp
  4300. // as it was before the send
  4301. pMdl = Irp->MdlAddress;
  4302. #if BACK_FILL
  4303. // If the header is back filled
  4304. // we should adjust the pointers back to where it was.
  4305. if (pMdl->MdlFlags & MDL_NETWORK_HEADER)
  4306. {
  4307. (ULONG_PTR)pMdl->MappedSystemVa += SESSION_HDR_SIZE;
  4308. pMdl->ByteOffset += SESSION_HDR_SIZE;
  4309. pMdl->ByteCount -= SESSION_HDR_SIZE;
  4310. IF_DBG(NBT_DEBUG_SEND)
  4311. KdPrint(("Nbt: Done with Backfilled mdl %x\n", pMdl));
  4312. }
  4313. else
  4314. {
  4315. Irp->MdlAddress = pMdl->Next;
  4316. ASSERT ( MmGetMdlByteCount ( pMdl ) == SESSION_HDR_SIZE );
  4317. #if DBG
  4318. IF_DBG(NBT_DEBUG_SEND)
  4319. {
  4320. PMDL pMdl1;
  4321. ULONG ulen1,ulen2,ulen3;
  4322. UCHAR uc;
  4323. tSESSIONHDR *pSessionHdr;
  4324. PSINGLE_LIST_ENTRY pSingleListEntry;
  4325. KIRQL OldIrq;
  4326. pSessionHdr = (tSESSIONHDR *)MmGetMdlVirtualAddress(pMdl);
  4327. ulen1 = htonl ( pSessionHdr->UlongLength );
  4328. for ( ulen2 = 0 , pMdl1 = pMdl ; ( pMdl1 = pMdl1->Next ) != NULL ; )
  4329. {
  4330. ulen3 = MmGetMdlByteCount ( pMdl1 );
  4331. ASSERT ( ulen3 > 0 );
  4332. uc = ( ( UCHAR * ) MmGetMdlVirtualAddress ( pMdl1 ) ) [ ulen3 - 1 ];
  4333. ulen2 += ulen3;
  4334. }
  4335. ASSERT ( ulen2 == ulen1 );
  4336. CTESpinLock(&NbtConfig,OldIrq);
  4337. for ( pSingleListEntry = &NbtConfig.SessionMdlFreeSingleList ;
  4338. ( pSingleListEntry = pSingleListEntry->Next ) != NULL ;
  4339. )
  4340. {
  4341. pMdl1 = CONTAINING_RECORD(pSingleListEntry,MDL,Next);
  4342. ASSERT ( pMdl1 != pMdl );
  4343. }
  4344. CTESpinFree(&NbtConfig,OldIrq);
  4345. }
  4346. #endif // DBG
  4347. ExInterlockedPushEntryList(&NbtConfig.SessionMdlFreeSingleList,
  4348. (PSINGLE_LIST_ENTRY)pMdl,
  4349. &NbtConfig.LockInfo.SpinLock);
  4350. }
  4351. #else
  4352. Irp->MdlAddress = pMdl->Next;
  4353. ASSERT ( MmGetMdlByteCount ( pMdl ) == sizeof ( tSESSIONHDR ) );
  4354. #if DBG
  4355. IF_DBG(NBT_DEBUG_SEND)
  4356. {
  4357. PMDL pMdl1;
  4358. ULONG ulen1,ulen2,ulen3;
  4359. UCHAR uc;
  4360. tSESSIONHDR *pSessionHdr;
  4361. PSINGLE_LIST_ENTRY pSingleListEntry;
  4362. KIRQL OldIrq;
  4363. pSessionHdr = (tSESSIONHDR *)MmGetMdlVirtualAddress(pMdl);
  4364. ulen1 = htonl ( pSessionHdr->UlongLength );
  4365. for ( ulen2 = 0 , pMdl1 = pMdl ; ( pMdl1 = pMdl1->Next ) != NULL ; )
  4366. {
  4367. ulen3 = MmGetMdlByteCount ( pMdl1 );
  4368. ASSERT ( ulen3 > 0 );
  4369. uc = ( ( UCHAR * ) MmGetMdlVirtualAddress ( pMdl1 ) ) [ ulen3 - 1 ];
  4370. ulen2 += ulen3;
  4371. }
  4372. ASSERT ( ulen2 == ulen1 );
  4373. CTESpinLock(&NbtConfig,OldIrq);
  4374. for ( pSingleListEntry = &NbtConfig.SessionMdlFreeSingleList ;
  4375. ( pSingleListEntry = pSingleListEntry->Next ) != NULL ;
  4376. )
  4377. {
  4378. pMdl1 = CONTAINING_RECORD(pSingleListEntry,MDL,Next);
  4379. ASSERT ( pMdl1 != pMdl );
  4380. }
  4381. CTESpinFree(&NbtConfig,OldIrq);
  4382. }
  4383. #endif // DBG
  4384. ExInterlockedPushEntryList(&NbtConfig.SessionMdlFreeSingleList,
  4385. (PSINGLE_LIST_ENTRY)pMdl,
  4386. &NbtConfig.LockInfo.SpinLock);
  4387. #endif //BACK_FILL
  4388. // fill in the sent size so that it substracts off the session header size
  4389. //
  4390. if (Irp->IoStatus.Information > sizeof(tSESSIONHDR))
  4391. {
  4392. Irp->IoStatus.Information -= sizeof(tSESSIONHDR);
  4393. }
  4394. else
  4395. {
  4396. // nothing was sent
  4397. Irp->IoStatus.Information = 0;
  4398. IF_DBG(NBT_DEBUG_SEND)
  4399. KdPrint(("Nbt:Zero Send Length for a session send!\n"));
  4400. }
  4401. //
  4402. // we incremented this before the send: deref it now
  4403. //
  4404. pLowerConn = (tLOWERCONNECTION *)Context;
  4405. ASSERT (NBT_VERIFY_HANDLE (pLowerConn, NBT_VERIFY_LOWERCONN));
  4406. NBT_DEREFERENCE_LOWERCONN (pLowerConn, REF_LOWC_SEND, FALSE);
  4407. return(STATUS_SUCCESS);
  4408. UNREFERENCED_PARAMETER( DeviceObject );
  4409. }
  4410. //----------------------------------------------------------------------------
  4411. NTSTATUS
  4412. NTSendDatagram(
  4413. IN tDEVICECONTEXT *pDeviceContext,
  4414. IN PIRP pIrp)
  4415. /*++
  4416. Routine Description:
  4417. This Routine handles sending a datagram down to the transport.
  4418. Arguments:
  4419. pIrp - a ptr to an IRP
  4420. Return Value:
  4421. NTSTATUS - status of the request
  4422. --*/
  4423. {
  4424. PIO_STACK_LOCATION pIrpSp;
  4425. NTSTATUS status;
  4426. LONG lSentLength;
  4427. TDI_REQUEST Request;
  4428. PTDI_REQUEST_KERNEL_SENDDG pTdiRequest;
  4429. tCLIENTELE *pClientEle;
  4430. CTEPagedCode();
  4431. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  4432. pClientEle = (tCLIENTELE *)pIrpSp->FileObject->FsContext;
  4433. if (!NBT_VERIFY_HANDLE2 (pClientEle, NBT_VERIFY_CLIENT, NBT_VERIFY_CLIENT_DOWN))
  4434. {
  4435. ASSERTMSG ("Nbt.SendDatagram: ERROR - Invalid Address Handle\n", 0);
  4436. return (STATUS_INVALID_HANDLE);
  4437. }
  4438. // CTEVerifyHandle(pClientEle,NBT_VERIFY_CLIENT,tCLIENTELE,&status);
  4439. // get the sending information out of the irp
  4440. pTdiRequest = (PTDI_REQUEST_KERNEL_SENDDG)&pIrpSp->Parameters;
  4441. Request.Handle.AddressHandle = pClientEle;
  4442. lSentLength = 0;
  4443. //
  4444. // Mark IRP pending here
  4445. //
  4446. IoMarkIrpPending(pIrp);
  4447. status = NbtSendDatagram (&Request,
  4448. pTdiRequest->SendDatagramInformation,
  4449. pTdiRequest->SendLength,
  4450. &lSentLength,
  4451. (PVOID)pIrp->MdlAddress, // user data
  4452. (tDEVICECONTEXT *)pDeviceContext,
  4453. pIrp);
  4454. if (status != STATUS_PENDING)
  4455. {
  4456. //
  4457. // either Success or an Error
  4458. //
  4459. NTIoComplete(pIrp,status,lSentLength);
  4460. }
  4461. //
  4462. // To make driver verifier and IO system happy, always return
  4463. // STATUS_PENDING for the request marked as PENDING
  4464. //
  4465. return STATUS_PENDING;
  4466. }
  4467. //----------------------------------------------------------------------------
  4468. NTSTATUS
  4469. NTSetInformation(
  4470. IN tDEVICECONTEXT *pDeviceContext,
  4471. IN PIRP pIrp)
  4472. /*++
  4473. Routine Description:
  4474. This Routine handles sets up event handlers that the client passes in.
  4475. Arguments:
  4476. pIrp - a ptr to an IRP
  4477. Return Value:
  4478. NTSTATUS - status of the request
  4479. --*/
  4480. {
  4481. // *TODO*
  4482. CTEPagedCode();
  4483. IF_DBG(NBT_DEBUG_NAMESRV)
  4484. KdPrint(("Nbt:************ Got a Set Information that was NOT expected *******\n"));
  4485. return(STATUS_SUCCESS);
  4486. }
  4487. //----------------------------------------------------------------------------
  4488. NTSTATUS
  4489. NTQueueToWorkerThread(
  4490. IN OUT NBT_WORK_ITEM_CONTEXT * pContext,
  4491. IN PVOID DelayedWorkerRoutine,
  4492. IN tDGRAM_SEND_TRACKING *pTracker,
  4493. IN PVOID pClientContext,
  4494. IN PVOID ClientCompletion,
  4495. IN tDEVICECONTEXT *pDeviceContext,
  4496. IN BOOLEAN fJointLockHeld
  4497. )
  4498. /*++
  4499. Routine Description:
  4500. This routine simply queues a request on an excutive worker thread
  4501. for later execution. Scanning the LmHosts file must be down this way.
  4502. Arguments:
  4503. pContext - the workitem context. If it is NULL, this function will
  4504. allocate one. Otherwise, it will use the pass in context.
  4505. pTracker - the tracker block for context
  4506. DelayedWorkerRoutine- the routine for the Workerthread to call
  4507. pDeviceContext - the device context which is this delayed event
  4508. pertains to. This could be NULL (meaning it's an event
  4509. pertaining to not any specific device context)
  4510. Return Value:
  4511. --*/
  4512. {
  4513. KIRQL OldIrq = 0;
  4514. if ((pDeviceContext) &&
  4515. (!NBT_REFERENCE_DEVICE(pDeviceContext, REF_DEV_WORKER, fJointLockHeld)))
  4516. {
  4517. // ASSERT(NULL == pContext);
  4518. return STATUS_INVALID_DEVICE_REQUEST;
  4519. }
  4520. #if 0
  4521. //
  4522. // Dont bother queuing a workitem if we're running
  4523. // in the same context of the work thread and we're
  4524. // at PASSIVE_LEVEL
  4525. //
  4526. if (KeGetCurrentThread() == NbtConfig.pWorkThread &&
  4527. KeGetCurrentIrql() == PASSIVE_LEVEL) {
  4528. KdPrint(("WorkItem: Fast Path\n"));
  4529. (*((PNBT_WORKER_THREAD_ROUTINE)DelayedWorkerRoutine))(
  4530. pTracker,
  4531. pClientContext,
  4532. ClientCompletion,
  4533. pDeviceContext
  4534. );
  4535. if (pDeviceContext) {
  4536. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_WORKER, fJointLockHeld);
  4537. }
  4538. return (STATUS_SUCCESS);
  4539. }
  4540. #endif
  4541. //
  4542. // Allocate a context if
  4543. // 1. the caller doesn't have one, or
  4544. // 2. the context is already in queue
  4545. // this is a bug in the caller. In this case,
  4546. // we try to recover from the failure.
  4547. //
  4548. if (NULL == pContext || pContext->bQueued) {
  4549. //
  4550. // ASSERT out if the caller is giving us a pContext
  4551. // which has already been in queue.
  4552. //
  4553. ASSERT(NULL == pContext);
  4554. pContext = (NBT_WORK_ITEM_CONTEXT *)NbtAllocMem(sizeof(NBT_WORK_ITEM_CONTEXT),NBT_TAG2('22'));
  4555. if (NULL == pContext) {
  4556. if (pDeviceContext) {
  4557. NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_WORKER, fJointLockHeld);
  4558. }
  4559. return (STATUS_INSUFFICIENT_RESOURCES);
  4560. }
  4561. pContext->bSpecialAlloc = TRUE;
  4562. pContext->bQueued = FALSE;
  4563. } else {
  4564. pContext->bSpecialAlloc = FALSE;
  4565. }
  4566. //
  4567. // From now on, we cannot fail
  4568. //
  4569. pContext->bQueued = TRUE;
  4570. pContext->pTracker = pTracker;
  4571. pContext->pClientContext = pClientContext;
  4572. pContext->ClientCompletion = ClientCompletion;
  4573. pContext->pDeviceContext = pDeviceContext;
  4574. pContext->WorkerRoutine = DelayedWorkerRoutine;
  4575. InitializeListHead(&pContext->Linkage);
  4576. CTESpinLock(&NbtConfig.WorkerQLock,OldIrq);
  4577. InsertTailList(&NbtConfig.WorkerQList, &pContext->Linkage);
  4578. InterlockedIncrement(&NbtConfig.NumWorkItemQueued);
  4579. if (!NbtConfig.Unloading &&
  4580. !InterlockedExchange(&NbtConfig.bSystemWorkThreadQueued, TRUE)) {
  4581. ExInitializeWorkItem(&NbtConfig.SystemWorkItem, NTExecuteWorker, &NbtConfig.SystemWorkItem);
  4582. ExQueueWorkItem(&NbtConfig.SystemWorkItem, CriticalWorkQueue);
  4583. }
  4584. CTESpinFree(&NbtConfig.WorkerQLock,OldIrq);
  4585. return (STATUS_SUCCESS);
  4586. }
  4587. //----------------------------------------------------------------------------
  4588. VOID
  4589. NTExecuteWorker(
  4590. IN PVOID pUnused
  4591. )
  4592. /*++
  4593. Routine Description:
  4594. This routine handles executing delayed requests at non-Dpc level. If
  4595. the Device is currently being unloaded, we let the Unload Handler
  4596. complete the request.
  4597. Arguments:
  4598. pUnused - Unused
  4599. Return Value:
  4600. none
  4601. --*/
  4602. {
  4603. NBT_WORK_ITEM_CONTEXT * pContext = NULL;
  4604. PNBT_WORKER_THREAD_ROUTINE pDelayedWorkerRoutine = NULL;
  4605. KIRQL OldIrq;
  4606. PLIST_ENTRY pEntry = NULL;
  4607. tDEVICECONTEXT * pDeviceContext = NULL;
  4608. BOOL bSpecialAlloc = FALSE;
  4609. CTESpinLock(&NbtConfig.WorkerQLock,OldIrq);
  4610. ASSERT(NULL == NbtConfig.pWorkThread);
  4611. NbtConfig.pWorkThread = KeGetCurrentThread();
  4612. while(!IsListEmpty(&NbtConfig.WorkerQList)) {
  4613. pEntry = RemoveHeadList(&NbtConfig.WorkerQList);
  4614. InterlockedDecrement(&NbtConfig.NumWorkItemQueued);
  4615. CTESpinFree(&NbtConfig.WorkerQLock,OldIrq);
  4616. pContext = CONTAINING_RECORD(pEntry, NBT_WORK_ITEM_CONTEXT, Linkage);
  4617. pContext->bQueued = FALSE;
  4618. pDelayedWorkerRoutine = (PNBT_WORKER_THREAD_ROUTINE)pContext->WorkerRoutine;
  4619. //
  4620. // Save the value because pContext can be freed by the worker routine
  4621. //
  4622. pDeviceContext = pContext->pDeviceContext;
  4623. bSpecialAlloc = pContext->bSpecialAlloc;
  4624. (*pDelayedWorkerRoutine) (pContext->pTracker,
  4625. pContext->pClientContext,
  4626. pContext->ClientCompletion,
  4627. pDeviceContext
  4628. );
  4629. //
  4630. // Use the saved copy after the delayed worker routine is called
  4631. //
  4632. if (bSpecialAlloc) {
  4633. CTEMemFree((PVOID) pContext);
  4634. }
  4635. pContext = NULL;
  4636. if (pDeviceContext) {
  4637. NBT_DEREFERENCE_DEVICE(pDeviceContext, REF_DEV_WORKER, FALSE);
  4638. }
  4639. CTESpinLock(&NbtConfig.WorkerQLock,OldIrq);
  4640. }
  4641. //
  4642. // set the flag to FALSE before releasing the spinlock
  4643. //
  4644. InterlockedExchange(&NbtConfig.bSystemWorkThreadQueued, FALSE);
  4645. NbtConfig.pWorkThread = NULL;
  4646. CTESpinFree(&NbtConfig.WorkerQLock,OldIrq);
  4647. }
  4648. //----------------------------------------------------------------------------
  4649. VOID
  4650. SecurityDelete(
  4651. IN PVOID pContext
  4652. )
  4653. /*++
  4654. Routine Description:
  4655. This routine handles deleting a security context at non-dpc level.
  4656. Arguments:
  4657. Return Value:
  4658. none
  4659. --*/
  4660. {
  4661. PSECURITY_CLIENT_CONTEXT pClientSecurity;
  4662. pClientSecurity = (PSECURITY_CLIENT_CONTEXT)((NBT_WORK_ITEM_CONTEXT *)pContext)->pClientContext;
  4663. SeDeleteClientSecurity(pClientSecurity);
  4664. CTEMemFree(pContext);
  4665. }
  4666. //----------------------------------------------------------------------------
  4667. NTSTATUS
  4668. NTSendSession(
  4669. IN tDGRAM_SEND_TRACKING *pTracker,
  4670. IN tLOWERCONNECTION *pLowerConn,
  4671. IN PVOID pCompletion
  4672. )
  4673. /*++
  4674. Routine Description:
  4675. This Routine handles seting up a DPC to send a session pdu so that the stack
  4676. does not get wound up in multiple sends for the keep alive timeout case.
  4677. Arguments:
  4678. pIrp - a ptr to an IRP
  4679. Return Value:
  4680. NTSTATUS - status of the request
  4681. --*/
  4682. {
  4683. PKDPC pDpc;
  4684. if (pDpc = NbtAllocMem(sizeof(KDPC),NBT_TAG('f')))
  4685. {
  4686. KeInitializeDpc(pDpc, DpcSendSession, (PVOID)pTracker);
  4687. KeInsertQueueDpc(pDpc,(PVOID)pLowerConn,pCompletion);
  4688. return (STATUS_SUCCESS);
  4689. }
  4690. return (STATUS_INSUFFICIENT_RESOURCES);
  4691. }
  4692. //----------------------------------------------------------------------------
  4693. VOID
  4694. DpcSendSession(
  4695. IN PKDPC pDpc,
  4696. IN PVOID Context,
  4697. IN PVOID SystemArgument1,
  4698. IN PVOID SystemArgument2
  4699. )
  4700. /*++
  4701. Routine Description:
  4702. This routine simply calls TcpSendSession from a Dpc started in
  4703. in NTSendSession (above).
  4704. Arguments:
  4705. Return Value:
  4706. --*/
  4707. {
  4708. CTEMemFree((PVOID)pDpc);
  4709. TcpSendSession((tDGRAM_SEND_TRACKING *)Context,
  4710. (tLOWERCONNECTION *)SystemArgument1,
  4711. (PVOID)SystemArgument2);
  4712. }
  4713. //----------------------------------------------------------------------------
  4714. NTSTATUS
  4715. NTSetEventHandler(
  4716. IN tDEVICECONTEXT *pDeviceContext,
  4717. IN PIRP pIrp)
  4718. /*++
  4719. Routine Description:
  4720. This Routine handles
  4721. Arguments:
  4722. pIrp - a ptr to an IRP
  4723. Return Value:
  4724. NTSTATUS - status of the request
  4725. --*/
  4726. {
  4727. PIO_STACK_LOCATION pIrpSp;
  4728. NTSTATUS status;
  4729. tCLIENTELE *pClientEle;
  4730. PTDI_REQUEST_KERNEL_SET_EVENT pKeSetEvent;
  4731. CTEPagedCode();
  4732. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  4733. pClientEle = pIrpSp->FileObject->FsContext;
  4734. if (!NBT_VERIFY_HANDLE2 (pClientEle, NBT_VERIFY_CLIENT, NBT_VERIFY_CLIENT_DOWN))
  4735. {
  4736. ASSERTMSG ("Nbt.NTSetEventHandler: ERROR - Invalid Address Handle\n", 0);
  4737. return (STATUS_INVALID_HANDLE);
  4738. }
  4739. pKeSetEvent = (PTDI_REQUEST_KERNEL_SET_EVENT)&pIrpSp->Parameters;
  4740. // call the not NT specific routine to setup the event handler in the
  4741. // nbt data structures
  4742. status = NbtSetEventHandler(
  4743. pClientEle,
  4744. pKeSetEvent->EventType,
  4745. pKeSetEvent->EventHandler,
  4746. pKeSetEvent->EventContext);
  4747. return(status);
  4748. }
  4749. //----------------------------------------------------------------------------
  4750. VOID
  4751. NTIoComplete(
  4752. IN PIRP pIrp,
  4753. IN NTSTATUS Status,
  4754. IN ULONG SentLength)
  4755. /*++
  4756. Routine Description:
  4757. This Routine handles calling the NT I/O system to complete an I/O.
  4758. Arguments:
  4759. status - a completion status for the Irp
  4760. Return Value:
  4761. NTSTATUS - status of the request
  4762. --*/
  4763. {
  4764. KIRQL OldIrq;
  4765. #if DBG
  4766. if (!NT_SUCCESS(Status))
  4767. {
  4768. IF_DBG(NBT_DEBUG_NAMESRV)
  4769. KdPrint(("Nbt.NTIoComplete: Returning Error status = %X\n",Status));
  4770. // ASSERTMSG("Nbt: Error Ret Code In IoComplete",0);
  4771. }
  4772. #endif
  4773. pIrp->IoStatus.Status = Status;
  4774. // use -1 as a flag to mean do not adjust the sent length since it is
  4775. // already set
  4776. if (SentLength != -1)
  4777. {
  4778. pIrp->IoStatus.Information = SentLength;
  4779. }
  4780. NbtTrace(NBT_TRACE_IOCTL, ("pIrp %p: %!status! Information %d",
  4781. pIrp, Status, (ULONG)(pIrp->IoStatus.Information)));
  4782. #if DBG
  4783. if ( (Status != STATUS_SUCCESS) &&
  4784. (Status != STATUS_PENDING) &&
  4785. (Status != STATUS_INVALID_DEVICE_REQUEST) &&
  4786. (Status != STATUS_INVALID_PARAMETER) &&
  4787. (Status != STATUS_IO_TIMEOUT) &&
  4788. (Status != STATUS_BUFFER_OVERFLOW) &&
  4789. (Status != STATUS_BUFFER_TOO_SMALL) &&
  4790. (Status != STATUS_INVALID_HANDLE) &&
  4791. (Status != STATUS_INSUFFICIENT_RESOURCES) &&
  4792. (Status != STATUS_CANCELLED) &&
  4793. (Status != STATUS_DUPLICATE_NAME) &&
  4794. (Status != STATUS_TOO_MANY_NAMES) &&
  4795. (Status != STATUS_TOO_MANY_SESSIONS) &&
  4796. (Status != STATUS_REMOTE_NOT_LISTENING) &&
  4797. (Status != STATUS_BAD_NETWORK_PATH) &&
  4798. (Status != STATUS_HOST_UNREACHABLE) &&
  4799. (Status != STATUS_CONNECTION_REFUSED) &&
  4800. (Status != STATUS_WORKING_SET_QUOTA) &&
  4801. (Status != STATUS_REMOTE_DISCONNECT) &&
  4802. (Status != STATUS_LOCAL_DISCONNECT) &&
  4803. (Status != STATUS_LINK_FAILED) &&
  4804. (Status != STATUS_SHARING_VIOLATION) &&
  4805. (Status != STATUS_UNSUCCESSFUL) &&
  4806. (Status != STATUS_ACCESS_VIOLATION) &&
  4807. #ifdef MULTIPLE_WINS
  4808. (Status != STATUS_NETWORK_UNREACHABLE) &&
  4809. #endif
  4810. (Status != STATUS_NONEXISTENT_EA_ENTRY) )
  4811. {
  4812. KdPrint(("Nbt.NTIoComplete: returning unusual status = %X\n",Status));
  4813. }
  4814. #endif
  4815. // set the Irps cancel routine to null or the system may bugcheck
  4816. // with a bug code of CANCEL_STATE_IN_COMPLETED_IRP
  4817. //
  4818. // refer to IoCancelIrp() ..\ntos\io\iosubs.c
  4819. //
  4820. IoAcquireCancelSpinLock(&OldIrq);
  4821. IoSetCancelRoutine(pIrp,NULL);
  4822. IoReleaseCancelSpinLock(OldIrq);
  4823. IoCompleteRequest(pIrp,IO_NETWORK_INCREMENT);
  4824. }
  4825. //----------------------------------------------------------------------------
  4826. // ***** ***** Cancel Utilities ***** *****
  4827. //----------------------------------------------------------------------------
  4828. NTSTATUS
  4829. NTGetIrpIfNotCancelled(
  4830. IN PIRP pIrp,
  4831. IN PIRP *ppIrpInStruct
  4832. )
  4833. /*++
  4834. Routine Description:
  4835. This Routine gets the IOCancelSpinLock to coordinate with cancelling
  4836. irps It then returns STATUS_SUCCESS. It also nulls the irp in the structure
  4837. pointed to by the second parameter - so that the irp cancel routine
  4838. will not also be called.
  4839. Arguments:
  4840. status - a completion status for the Irp
  4841. Return Value:
  4842. NTSTATUS - status of the request
  4843. --*/
  4844. {
  4845. KIRQL OldIrq;
  4846. NTSTATUS status;
  4847. IoAcquireCancelSpinLock(&OldIrq);
  4848. // this nulls the irp in the datastructure - i.e. pConnEle->pIrp = NULL
  4849. *ppIrpInStruct = NULL;
  4850. if (!pIrp->Cancel)
  4851. {
  4852. status = STATUS_SUCCESS;
  4853. }
  4854. else
  4855. {
  4856. status = STATUS_UNSUCCESSFUL;
  4857. }
  4858. IoSetCancelRoutine(pIrp,NULL);
  4859. IoReleaseCancelSpinLock(OldIrq);
  4860. return(status);
  4861. }
  4862. //----------------------------------------------------------------------------
  4863. NTSTATUS
  4864. NTCheckSetCancelRoutine(
  4865. IN PIRP pIrp,
  4866. IN PVOID CancelRoutine,
  4867. IN tDEVICECONTEXT *pDeviceContext
  4868. )
  4869. /*++
  4870. Routine Description:
  4871. This Routine sets the cancel routine for an Irp.
  4872. Arguments:
  4873. status - a completion status for the Irp
  4874. Return Value:
  4875. NTSTATUS - status of the request
  4876. --*/
  4877. {
  4878. NTSTATUS status;
  4879. //
  4880. // Check if the irp was cancelled yet and if not, then set the
  4881. // irp cancel routine.
  4882. //
  4883. IoAcquireCancelSpinLock(&pIrp->CancelIrql);
  4884. if (pIrp->Cancel)
  4885. {
  4886. pIrp->IoStatus.Status = STATUS_CANCELLED;
  4887. status = STATUS_CANCELLED;
  4888. }
  4889. else
  4890. {
  4891. // setup the cancel routine
  4892. IoMarkIrpPending(pIrp);
  4893. IoSetCancelRoutine(pIrp,CancelRoutine);
  4894. status = STATUS_SUCCESS;
  4895. }
  4896. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  4897. return(status);
  4898. }
  4899. //----------------------------------------------------------------------------
  4900. NTSTATUS
  4901. NbtSetCancelRoutine(
  4902. IN PIRP pIrp,
  4903. IN PVOID CancelRoutine,
  4904. IN tDEVICECONTEXT *pDeviceContext
  4905. )
  4906. /*++
  4907. Routine Description:
  4908. This Routine sets the cancel routine for an Irp.
  4909. Arguments:
  4910. status - a completion status for the Irp
  4911. Return Value:
  4912. NTSTATUS - status of the request
  4913. --*/
  4914. {
  4915. NTSTATUS status;
  4916. //
  4917. // Check if the irp was cancelled yet and if not, then set the
  4918. // irp cancel routine.
  4919. //
  4920. IoAcquireCancelSpinLock(&pIrp->CancelIrql);
  4921. if (pIrp->Cancel)
  4922. {
  4923. pIrp->IoStatus.Status = STATUS_CANCELLED;
  4924. status = STATUS_CANCELLED;
  4925. //
  4926. // Note the cancel spin lock is released by the Cancel routine
  4927. //
  4928. (*(PDRIVER_CANCEL)CancelRoutine)((PDEVICE_OBJECT)pDeviceContext,pIrp);
  4929. }
  4930. else
  4931. {
  4932. // setup the cancel routine and mark the irp pending
  4933. //
  4934. IoMarkIrpPending(pIrp);
  4935. IoSetCancelRoutine(pIrp,CancelRoutine);
  4936. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  4937. status = STATUS_SUCCESS;
  4938. }
  4939. return(status);
  4940. }
  4941. //----------------------------------------------------------------------------
  4942. VOID
  4943. NTClearContextCancel(
  4944. IN NBT_WORK_ITEM_CONTEXT *pContext
  4945. )
  4946. /*++
  4947. Routine Description:
  4948. This Routine sets the cancel routine for
  4949. ((tDGRAM_SEND_TRACKING *)(pContext->pClientContext))->pClientIrp
  4950. to NULL.
  4951. NbtConfig.JointLock should be held when this routine is called.
  4952. Arguments:
  4953. status - a completion status for the Irp
  4954. Return Value:
  4955. NTSTATUS - status of the request
  4956. --*/
  4957. {
  4958. NTSTATUS status;
  4959. status = NbtCancelCancelRoutine( ((tDGRAM_SEND_TRACKING *)(pContext->pClientContext))->pClientIrp );
  4960. ASSERT ( status != STATUS_CANCELLED );
  4961. }
  4962. //----------------------------------------------------------------------------
  4963. NTSTATUS
  4964. NbtCancelCancelRoutine(
  4965. IN PIRP pIrp
  4966. )
  4967. /*++
  4968. Routine Description:
  4969. This Routine sets the cancel routine for an Irp to NULL
  4970. Arguments:
  4971. status - a completion status for the Irp
  4972. Return Value:
  4973. NTSTATUS - status of the request
  4974. --*/
  4975. {
  4976. NTSTATUS status = STATUS_SUCCESS;
  4977. if ( pIrp )
  4978. {
  4979. //
  4980. // Check if the irp was cancelled yet and if not, then set the
  4981. // irp cancel routine.
  4982. //
  4983. IoAcquireCancelSpinLock(&pIrp->CancelIrql);
  4984. if (pIrp->Cancel)
  4985. {
  4986. status = STATUS_CANCELLED;
  4987. }
  4988. IoSetCancelRoutine(pIrp,NULL);
  4989. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  4990. }
  4991. return(status);
  4992. }
  4993. //----------------------------------------------------------------------------
  4994. // ***** ***** Cancel Routines ***** *****
  4995. //----------------------------------------------------------------------------
  4996. VOID
  4997. NbtCancelListen(
  4998. IN PDEVICE_OBJECT DeviceContext,
  4999. IN PIRP pIrp
  5000. )
  5001. /*++
  5002. Routine Description:
  5003. This routine handles the cancelling a listen Irp. It must release the
  5004. cancel spin lock before returning re: IoCancelIrp().
  5005. Arguments:
  5006. Return Value:
  5007. The final status from the operation.
  5008. --*/
  5009. {
  5010. tCONNECTELE *pConnEle;
  5011. tCLIENTELE *pClientEle;
  5012. KIRQL OldIrq;
  5013. PLIST_ENTRY pHead;
  5014. PLIST_ENTRY pEntry;
  5015. PIO_STACK_LOCATION pIrpSp;
  5016. tLISTENREQUESTS *pListenReq;
  5017. IF_DBG(NBT_DEBUG_NAMESRV)
  5018. KdPrint(("Nbt:Got a LISTEN Cancel !!! *****************\n"));
  5019. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  5020. pConnEle = (tCONNECTELE *)pIrpSp->FileObject->FsContext;
  5021. if ((!NBT_VERIFY_HANDLE2 (pConnEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN)) ||
  5022. (!NBT_VERIFY_HANDLE2 ((pClientEle = pConnEle->pClientEle), NBT_VERIFY_CLIENT,NBT_VERIFY_CLIENT_DOWN)))
  5023. {
  5024. ASSERTMSG ("Nbt.NbtCancelListen: ERROR - Invalid Connection Handle\n", 0);
  5025. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  5026. return;
  5027. }
  5028. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  5029. NbtTrace(NBT_TRACE_INBOUND, ("Cancel Listen Irp %p pConnEle %p ClientEle %p", pIrp, pConnEle, pClientEle));
  5030. // now search the client's listen queue looking for this connection
  5031. //
  5032. CTESpinLock(pClientEle,OldIrq);
  5033. pHead = &pClientEle->ListenHead;
  5034. pEntry = pHead->Flink;
  5035. while (pEntry != pHead)
  5036. {
  5037. pListenReq = CONTAINING_RECORD(pEntry,tLISTENREQUESTS,Linkage);
  5038. if ((pListenReq->pConnectEle == pConnEle) &&
  5039. (pListenReq->pIrp == pIrp))
  5040. {
  5041. RemoveEntryList(pEntry);
  5042. CTESpinFree(pClientEle,OldIrq);
  5043. // complete the irp
  5044. pIrp->IoStatus.Status = STATUS_CANCELLED;
  5045. IoCompleteRequest(pIrp,IO_NETWORK_INCREMENT);
  5046. CTEMemFree((PVOID)pListenReq);
  5047. return;
  5048. }
  5049. pEntry = pEntry->Flink;
  5050. }
  5051. CTESpinFree(pClientEle,OldIrq);
  5052. return;
  5053. }
  5054. //----------------------------------------------------------------------------
  5055. VOID
  5056. NbtCancelSession(
  5057. IN PDEVICE_OBJECT DeviceContext,
  5058. IN PIRP pIrp
  5059. )
  5060. /*++
  5061. Routine Description:
  5062. This routine handles the cancelling a connect Irp. It must release the
  5063. cancel spin lock before returning re: IoCancelIrp(). It is called when
  5064. the session setup pdu has been sent, and the state is still outbound.
  5065. The cancel routine is only setup when the timer is started to time
  5066. sending the session response pdu.
  5067. Arguments:
  5068. Return Value:
  5069. The final status from the operation.
  5070. --*/
  5071. {
  5072. tCONNECTELE *pConnEle;
  5073. KIRQL OldIrq;
  5074. PIO_STACK_LOCATION pIrpSp;
  5075. BOOLEAN DerefConnEle=FALSE;
  5076. tTIMERQENTRY *pTimer;
  5077. tDGRAM_SEND_TRACKING *pTracker;
  5078. COMPLETIONCLIENT pCompletion;
  5079. PVOID pContext;
  5080. IF_DBG(NBT_DEBUG_NAMESRV)
  5081. KdPrint(("Nbt.NbtCancelSession: Got a Cancel !!! *****************\n"));
  5082. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  5083. pConnEle = (tCONNECTELE *)pIrpSp->FileObject->FsContext;
  5084. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  5085. if (!NBT_VERIFY_HANDLE2 (pConnEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN))
  5086. {
  5087. ASSERTMSG ("Nbt.NbtCancelSession: ERROR - Invalid Connection Handle\n", 0);
  5088. return;
  5089. }
  5090. NbtTrace(NBT_TRACE_OUTBOUND, ("Cancel TDI_CONNECT pIrp %p ConnEle=%p LowerConn=%p, ClientEle=%p",
  5091. pIrp, pConnEle, pConnEle->pLowerConnId, pConnEle->pClientEle));
  5092. #ifdef RASAUTODIAL
  5093. //
  5094. // Cancel the automatic connection if one's
  5095. // in progress. If we don't find the
  5096. // connection block in the automatic
  5097. // connection driver, then it's already
  5098. // been completed.
  5099. //
  5100. if (pConnEle->fAutoConnecting)
  5101. {
  5102. if (!NbtCancelPostConnect(pIrp))
  5103. {
  5104. return;
  5105. }
  5106. }
  5107. #endif // RASAUTODIAL
  5108. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  5109. if ((!NBT_VERIFY_HANDLE2 (pConnEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN)) ||
  5110. (!(pConnEle->pIrp)) || // the irp could get completed while acquiring the lock
  5111. (!(pTracker = (tDGRAM_SEND_TRACKING *)pConnEle->pIrpRcv)))
  5112. {
  5113. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  5114. NbtTrace(NBT_TRACE_OUTBOUND, ("pIrp %p: no tracker", pIrp));
  5115. return;
  5116. }
  5117. pTracker->Flags |= TRACKER_CANCELLED;
  5118. if (pTimer = pTracker->pTimer) // check for SessionStartupTimeout
  5119. {
  5120. pTracker->pTimer = NULL;
  5121. //
  5122. // stop the timer and only continue if the timer was stopped before
  5123. // it expired
  5124. //
  5125. StopTimer(pTimer, &pCompletion, &pContext);
  5126. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  5127. NbtTrace(NBT_TRACE_OUTBOUND, ("pIrp %p: pCompletion %p", pIrp, pCompletion));
  5128. //
  5129. // pCompletion will be set if the timer had not expired
  5130. // We want to cause a forced timeout, so we will just call the
  5131. // timeout routine with STATUS_CANCELLED
  5132. //
  5133. if (pCompletion)
  5134. {
  5135. (*pCompletion) (pContext, STATUS_CANCELLED);
  5136. }
  5137. }
  5138. else if (pConnEle->state == NBT_SESSION_OUTBOUND)
  5139. {
  5140. //
  5141. // for some reason there is no timer, but the connection is still
  5142. // outbound, so call the timer completion routine to kill off
  5143. // the connection.
  5144. //
  5145. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  5146. NbtTrace(NBT_TRACE_OUTBOUND, ("pIrp %p", pIrp));
  5147. SessionStartupTimeout (pTracker, ULongToPtr(STATUS_CANCELLED), (PVOID)1);
  5148. }
  5149. else
  5150. {
  5151. //
  5152. // Free the lock
  5153. //
  5154. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  5155. }
  5156. return;
  5157. }
  5158. //----------------------------------------------------------------------------
  5159. VOID
  5160. NbtCancelConnect(
  5161. IN PDEVICE_OBJECT pDeviceContext,
  5162. IN PIRP pIrp
  5163. )
  5164. /*++
  5165. Routine Description:
  5166. This routine handles cancelling an NTConnect Irp - which has been
  5167. passed down by a client (e.g. net view). Typically, when the request
  5168. succeeds on another adapter, it will issue this cancel.
  5169. On receiving the cancel, if we are processing a Local IRP, we just
  5170. pass the cancel on to the Local Irp which will complete this Irp also
  5171. in its Completion Routine.
  5172. Arguments:
  5173. Return Value:
  5174. The final status from the operation.
  5175. --*/
  5176. {
  5177. PIO_STACK_LOCATION pIrpSp;
  5178. IN PIRP pLocalIrp;
  5179. tCONNECTELE *pConnEle;
  5180. IF_DBG(NBT_DEBUG_NAMESRV)
  5181. KdPrint(("Nbt:NbtCancelConnect ********** Got an Irp Cancel !!! **********\n"));
  5182. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  5183. pConnEle = pIrpSp->FileObject->FsContext;
  5184. if (!NBT_VERIFY_HANDLE2 (pConnEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN))
  5185. {
  5186. ASSERTMSG ("Nbt.NbtCancelConnect: ERROR - Invalid Connection Handle\n", 0);
  5187. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  5188. return;
  5189. }
  5190. NbtTrace(NBT_TRACE_OUTBOUND, ("Cancel Connect pIrp %p: pConnEle %p", pIrp, pConnEle));
  5191. if ((pConnEle) &&
  5192. (pLocalIrp = pConnEle->pIrp))
  5193. {
  5194. IF_DBG(NBT_DEBUG_NAMESRV)
  5195. KdPrint (("Nbt.NbtCancelConnect: pClientIrp=<%x>, pLocalIrp=<%x>, Device=<%x>, CancelR=<%x>\n",
  5196. pIrp, pLocalIrp, pDeviceContext, pLocalIrp->CancelRoutine));
  5197. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  5198. IoCancelIrp(pLocalIrp);
  5199. }
  5200. else
  5201. {
  5202. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  5203. }
  5204. return;
  5205. }
  5206. //----------------------------------------------------------------------------
  5207. VOID
  5208. NbtCancelReceive(
  5209. IN PDEVICE_OBJECT DeviceContext,
  5210. IN PIRP pIrp
  5211. )
  5212. /*++
  5213. Routine Description:
  5214. This routine handles the cancelling a listen Irp. It must release the
  5215. cancel spin lock before returning re: IoCancelIrp().
  5216. Arguments:
  5217. Return Value:
  5218. The final status from the operation.
  5219. --*/
  5220. {
  5221. tCONNECTELE *pConnEle;
  5222. tLOWERCONNECTION *pLowerConn;
  5223. KIRQL OldIrq;
  5224. KIRQL OldIrq1;
  5225. PLIST_ENTRY pHead;
  5226. PLIST_ENTRY pEntry;
  5227. PIO_STACK_LOCATION pIrpSp;
  5228. PIRP pRcvIrp;
  5229. IF_DBG(NBT_DEBUG_NAMESRV)
  5230. KdPrint(("Nbt.NbtCancelReceive: Got a Cancel !!! *****************\n"));
  5231. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  5232. pConnEle = (tCONNECTELE *)pIrpSp->FileObject->FsContext;
  5233. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  5234. if (!NBT_VERIFY_HANDLE2 (pConnEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN))
  5235. {
  5236. ASSERTMSG ("Nbt.NbtCancelReceive: ERROR - Invalid Connection Handle\n", 0);
  5237. return;
  5238. }
  5239. NbtTrace(NBT_TRACE_INBOUND, ("Cancel Receive Irp %p ConnEle=%p LowerConn=%p, ClientEle=%p",
  5240. pIrp, pConnEle, pConnEle->pLowerConnId, pConnEle->pClientEle));
  5241. CTESpinLock(&NbtConfig.JointLock,OldIrq1);
  5242. pLowerConn = pConnEle->pLowerConnId;
  5243. if (pLowerConn)
  5244. {
  5245. CTESpinLock(pLowerConn,OldIrq);
  5246. }
  5247. if (pConnEle->Verify == NBT_VERIFY_CONNECTION)
  5248. {
  5249. // now search the connection's receive queue looking for this Irp
  5250. //
  5251. pHead = &pConnEle->RcvHead;
  5252. pEntry = pHead->Flink;
  5253. while (pEntry != pHead)
  5254. {
  5255. pRcvIrp = CONTAINING_RECORD(pEntry,IRP,Tail.Overlay.ListEntry);
  5256. if (pRcvIrp == pIrp)
  5257. {
  5258. RemoveEntryList(pEntry);
  5259. // complete the irp
  5260. pIrp->IoStatus.Status = STATUS_CANCELLED;
  5261. if (pLowerConn)
  5262. {
  5263. CTESpinFree(pLowerConn,OldIrq);
  5264. }
  5265. CTESpinFree(&NbtConfig.JointLock,OldIrq1);
  5266. IoCompleteRequest(pIrp,IO_NETWORK_INCREMENT);
  5267. return;
  5268. }
  5269. pEntry = pEntry->Flink;
  5270. }
  5271. }
  5272. if (pLowerConn)
  5273. {
  5274. CTESpinFree(pLowerConn,OldIrq);
  5275. }
  5276. CTESpinFree(&NbtConfig.JointLock,OldIrq1);
  5277. return;
  5278. }
  5279. //----------------------------------------------------------------------------
  5280. VOID
  5281. NbtCancelRcvDgram(
  5282. IN PDEVICE_OBJECT DeviceContext,
  5283. IN PIRP pIrp
  5284. )
  5285. /*++
  5286. Routine Description:
  5287. This routine handles the cancelling a listen Irp. It must release the
  5288. cancel spin lock before returning re: IoCancelIrp().
  5289. Arguments:
  5290. Return Value:
  5291. The final status from the operation.
  5292. --*/
  5293. {
  5294. tCLIENTELE *pClientEle;
  5295. KIRQL OldIrq;
  5296. PLIST_ENTRY pHead;
  5297. PLIST_ENTRY pEntry;
  5298. PIO_STACK_LOCATION pIrpSp;
  5299. tRCVELE *pRcvEle;
  5300. IF_DBG(NBT_DEBUG_NAMESRV)
  5301. KdPrint(("Nbt.NbtCancelRcvDgram: Got a Cancel !!! *****************\n"));
  5302. //
  5303. // Need to acquire JointLock before Cancel lock!
  5304. // Bug#: 124405
  5305. //
  5306. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  5307. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  5308. IoAcquireCancelSpinLock(&pIrp->CancelIrql);
  5309. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  5310. pClientEle = (tCLIENTELE *)pIrpSp->FileObject->FsContext;
  5311. NbtTrace(NBT_TRACE_RECVDGRAM, ("Cancel RcvDgram Irp %p ClientEle=%p", pIrp, pClientEle));
  5312. if (NBT_VERIFY_HANDLE (pClientEle, NBT_VERIFY_CLIENT))
  5313. {
  5314. // now search the client's listen queue looking for this connection
  5315. //
  5316. pHead = &pClientEle->RcvDgramHead;
  5317. pEntry = pHead->Flink;
  5318. while (pEntry != pHead)
  5319. {
  5320. pRcvEle = CONTAINING_RECORD(pEntry,tRCVELE,Linkage);
  5321. if (pRcvEle->pIrp == pIrp)
  5322. {
  5323. RemoveEntryList(pEntry);
  5324. // complete the irp
  5325. pIrp->IoStatus.Status = STATUS_CANCELLED;
  5326. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  5327. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  5328. IoCompleteRequest(pIrp,IO_NETWORK_INCREMENT);
  5329. CTEMemFree((PVOID)pRcvEle);
  5330. return;
  5331. }
  5332. pEntry = pEntry->Flink;
  5333. }
  5334. }
  5335. else
  5336. {
  5337. ASSERTMSG ("Nbt.NbtCancelRcvDgram: ERROR - Invalid Address Handle\n", 0);
  5338. }
  5339. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  5340. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  5341. return;
  5342. }
  5343. //----------------------------------------------------------------------------
  5344. VOID
  5345. NbtCancelFindName(
  5346. IN PDEVICE_OBJECT DeviceContext,
  5347. IN PIRP pIrp
  5348. )
  5349. /*++
  5350. Routine Description:
  5351. This routine handles the cancelling a FindName Irp - which has
  5352. been passed down by a client (e.g. ping). Typically, when ping succeeds
  5353. on another adapter, it will issue this cancel.
  5354. On receiving the cancel, we stop any timer that is running in connection
  5355. with name query and then complete the irp with status_cancelled.
  5356. Arguments:
  5357. Return Value:
  5358. The final status from the operation.
  5359. --*/
  5360. {
  5361. tDGRAM_SEND_TRACKING *pTracker;
  5362. PIO_STACK_LOCATION pIrpSp;
  5363. IF_DBG(NBT_DEBUG_NAMESRV)
  5364. KdPrint(("Nbt.NbtCancelFindName: Got a Cancel !!! *****************\n"));
  5365. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  5366. pTracker = pIrpSp->Parameters.Others.Argument4;
  5367. NbtTrace(NBT_TRACE_NAMESRV, ("Cancel FindName Irp %p pTracker=%p", pIrp, pTracker));
  5368. //
  5369. // We want to ensure that the tracker supplied by FsContext
  5370. // is the right Tracker for this Irp
  5371. //
  5372. if (pTracker && (pIrp == pTracker->pClientIrp))
  5373. {
  5374. //
  5375. // if pClientIrp still valid, completion routine hasn't run yet: go ahead
  5376. // and complete the irp here
  5377. //
  5378. pIrpSp->Parameters.Others.Argument4 = NULL;
  5379. pTracker->pClientIrp = NULL;
  5380. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  5381. NTIoComplete(pIrp,STATUS_CANCELLED,(ULONG)-1);
  5382. } else
  5383. {
  5384. //
  5385. // the completion routine has run.
  5386. //
  5387. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  5388. }
  5389. return;
  5390. }
  5391. //----------------------------------------------------------------------------
  5392. VOID
  5393. NbtCancelLmhSvcIrp(
  5394. IN PDEVICE_OBJECT DeviceContext,
  5395. IN PIRP pIrp
  5396. )
  5397. /*++
  5398. Routine Description:
  5399. This routine handles the cancelling a DNS name query Irp or
  5400. the CheckIpAddrs Irp that is passed down to NBT from Lmhsvc
  5401. This routine will get the Resource Lock, and Null the Irp ptr in the
  5402. DnsQueries or CheckAddr structure (as approp) and then return the irp.
  5403. Arguments:
  5404. Return Value:
  5405. The final status from the operation.
  5406. --*/
  5407. {
  5408. tLMHSVC_REQUESTS *pLmhSvcRequest = NULL;
  5409. KIRQL OldIrq;
  5410. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  5411. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  5412. if (pIrp == CheckAddr.QueryIrp)
  5413. {
  5414. IF_DBG(NBT_DEBUG_NAMESRV)
  5415. KdPrint(("Nbt.NbtCancelLmhSvcIrp: Got a Cancel on CheckAddr Irp !!! *****************\n"));
  5416. NbtTrace(NBT_TRACE_NAMESRV, ("Cancel LmhSvc CheckAddr Irp %p", pIrp));
  5417. pLmhSvcRequest = &CheckAddr;
  5418. }
  5419. else if (pIrp == DnsQueries.QueryIrp)
  5420. {
  5421. IF_DBG(NBT_DEBUG_NAMESRV)
  5422. KdPrint(("Nbt.NbtCancelLmhSvcIrp: Got a Cancel on DnsQueries Irp !!! *****************\n"));
  5423. NbtTrace(NBT_TRACE_NAMESRV, ("Cancel LmhSvc DnsQueries Irp %p", pIrp));
  5424. pLmhSvcRequest = &DnsQueries;
  5425. }
  5426. if (pLmhSvcRequest)
  5427. {
  5428. pIrp->IoStatus.Status = STATUS_CANCELLED;
  5429. pLmhSvcRequest->QueryIrp = NULL;
  5430. pLmhSvcRequest->pIpAddrBuf = NULL;
  5431. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  5432. IoCompleteRequest(pIrp,IO_NETWORK_INCREMENT);
  5433. }
  5434. else
  5435. {
  5436. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  5437. }
  5438. return;
  5439. }
  5440. //----------------------------------------------------------------------------
  5441. VOID
  5442. NbtCancelDisconnectWait(
  5443. IN PDEVICE_OBJECT DeviceContext,
  5444. IN PIRP pIrp
  5445. )
  5446. /*++
  5447. Routine Description:
  5448. This routine handles the cancelling a Disconnect Wait Irp - which has
  5449. been passed down by a client so that when a disconnect occurs this
  5450. irp will complete and inform the client. The action here is to simply
  5451. complete the irp with status cancelled.
  5452. down to NBT from Lmhsvc, for the purpose of resolving a name with DNS.
  5453. Nbt will complete this irp each time it has a name to resolve with DNS.
  5454. This routine will get the Resource Lock, and Null the Irp ptr in the
  5455. DnsQueries structure and then return the irp.
  5456. Arguments:
  5457. Return Value:
  5458. The final status from the operation.
  5459. --*/
  5460. {
  5461. tCONNECTELE *pConnEle;
  5462. PIO_STACK_LOCATION pIrpSp;
  5463. CTELockHandle OldIrq;
  5464. IF_DBG(NBT_DEBUG_NAMESRV)
  5465. KdPrint(("Nbt:Got a Disc Wait Irp Cancel !!! *****************\n"));
  5466. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  5467. pConnEle = (tCONNECTELE *)pIrpSp->FileObject->FsContext;
  5468. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  5469. CTESpinLock(pConnEle,OldIrq);
  5470. if (!NBT_VERIFY_HANDLE2 (pConnEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN))
  5471. {
  5472. ASSERTMSG ("Nbt.NbtCancelDisconnectWait: ERROR - Invalid Connection Handle\n", 0);
  5473. pIrp->IoStatus.Status = STATUS_INVALID_HANDLE;
  5474. }
  5475. else if (pConnEle->pIrpClose == pIrp)
  5476. {
  5477. pConnEle->pIrpClose = NULL;
  5478. pIrp->IoStatus.Status = STATUS_CANCELLED;
  5479. }
  5480. CTESpinFree(pConnEle,OldIrq);
  5481. IoCompleteRequest(pIrp,IO_NETWORK_INCREMENT);
  5482. return;
  5483. }
  5484. //----------------------------------------------------------------------------
  5485. VOID
  5486. NbtCancelWaitForLmhSvcIrp(
  5487. IN PDEVICE_OBJECT DeviceContext,
  5488. IN PIRP pIrp
  5489. )
  5490. /*++
  5491. Routine Description:
  5492. This routine handles the cancelling a Query to DNS, so that the client's
  5493. irp can be returned to the client. This cancellation is instigated
  5494. by the client (i.e. RDR).
  5495. Arguments:
  5496. Return Value:
  5497. The final status from the operation.
  5498. --*/
  5499. {
  5500. BOOLEAN FoundIt = FALSE;
  5501. NBT_WORK_ITEM_CONTEXT *Context;
  5502. CTELockHandle OldIrq;
  5503. tDGRAM_SEND_TRACKING *pTracker;
  5504. PVOID pClientCompletion;
  5505. PVOID pClientContext;
  5506. PLIST_ENTRY pHead;
  5507. PLIST_ENTRY pEntry;
  5508. IF_DBG(NBT_DEBUG_NAMESRV)
  5509. KdPrint(("Nbt.NbtCancelWaitForLmhSvcIrp: Got a Cancel !!! *****************\n"));
  5510. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  5511. CTESpinLock(&NbtConfig.JointLock,OldIrq);
  5512. //
  5513. // First check the lmhost list, then the CheckAddr list, then the Dns list
  5514. //
  5515. if (!(Context = FindLmhSvcRequest (DeviceContext, pIrp, &LmHostQueries)))
  5516. {
  5517. if (!(Context = FindLmhSvcRequest (DeviceContext, pIrp, &CheckAddr)))
  5518. {
  5519. Context = FindLmhSvcRequest (DeviceContext, pIrp, &DnsQueries);
  5520. }
  5521. }
  5522. CTESpinFree(&NbtConfig.JointLock,OldIrq);
  5523. NbtTrace(NBT_TRACE_NAMESRV, ("Cancel WaitForLmhsvc Irp %p", pIrp));
  5524. //
  5525. // Now complete the clients request to return the irp to the client
  5526. //
  5527. if (Context)
  5528. {
  5529. //
  5530. // this is the name Query tracker
  5531. //
  5532. pTracker = Context->pTracker;
  5533. pClientCompletion = Context->ClientCompletion;
  5534. pClientContext = Context->pClientContext;
  5535. // for dns names (NameLen>16), pTracker would be NULL
  5536. if (pTracker)
  5537. {
  5538. // name did not resolve, so delete from table
  5539. SetNameState (pTracker->pNameAddr, NULL, FALSE);
  5540. NBT_DEREFERENCE_TRACKER(pTracker, FALSE);
  5541. }
  5542. //
  5543. // this should complete any name queries that are waiting on
  5544. // this first name query - i.e. queries to the resolving name
  5545. //
  5546. CompleteClientReq(pClientCompletion, pClientContext, STATUS_CANCELLED);
  5547. CTEMemFree(Context);
  5548. }
  5549. }
  5550. //----------------------------------------------------------------------------
  5551. VOID
  5552. NbtCancelDgramSend(
  5553. IN PDEVICE_OBJECT DeviceContext,
  5554. IN PIRP pIrp
  5555. )
  5556. /*++
  5557. Routine Description:
  5558. This routine handles the cancelling of a Datagram Send. The action here is to simply
  5559. complete the irp with status cancelled.
  5560. This routine will Null the Irp ptr in the Tracker structure (if available) so that
  5561. SendDgramContinue does not find it.
  5562. Arguments:
  5563. Return Value:
  5564. The final status from the operation.
  5565. --*/
  5566. {
  5567. tDGRAM_SEND_TRACKING *pTracker;
  5568. PIO_STACK_LOCATION pIrpSp;
  5569. CTELockHandle OldIrq;
  5570. IF_DBG(NBT_DEBUG_NAMESRV)
  5571. KdPrint(("Nbt.NbtCancelDgramSend: Got a DatagramSend Irp Cancel !!! *****************\n"));
  5572. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  5573. pTracker = pIrpSp->Parameters.Others.Argument4;
  5574. NbtTrace(NBT_TRACE_SENDDGRAM, ("Cancel SendDgram Irp %p", pIrp));
  5575. if ((NBT_VERIFY_HANDLE (pTracker, NBT_VERIFY_TRACKER)) &&
  5576. (pTracker->pClientIrp == pIrp))
  5577. {
  5578. pTracker->pClientIrp = NULL;
  5579. pIrpSp->Parameters.Others.Argument4 = NULL;
  5580. pIrp->IoStatus.Status = STATUS_CANCELLED;
  5581. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  5582. NTIoComplete(pIrp,STATUS_CANCELLED,(ULONG)-1);
  5583. }
  5584. else
  5585. {
  5586. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  5587. }
  5588. return;
  5589. }
  5590. int
  5591. check_unicode_string(IN PUNICODE_STRING str)
  5592. {
  5593. try {
  5594. ProbeForRead(str, sizeof (UNICODE_STRING), sizeof(BYTE));
  5595. if ((str->MaximumLength <= 0) || (str->Length <= 0) || (str->Length >= str->MaximumLength)) {
  5596. return (-1);
  5597. }
  5598. ProbeForRead(str->Buffer, str->MaximumLength, sizeof(WCHAR));
  5599. ASSERT((str->Length&1) == 0);
  5600. if (str->Buffer[str->Length/sizeof(WCHAR)]) {
  5601. return (-1);
  5602. }
  5603. return 0;
  5604. } except(EXCEPTION_EXECUTE_HANDLER) {
  5605. KdPrint (("Nbt.check_unicode_string: Exception <0x%x> trying to access unicode string 0x%x\n",
  5606. GetExceptionCode(), str));
  5607. return (-1);
  5608. }
  5609. }