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.

645 lines
19 KiB

  1. /*++
  2. Copyright (c) 1989-2001 Microsoft Corporation
  3. Module Name:
  4. dns.c
  5. Abstract:
  6. This module implements a simple DNSv6 resolver
  7. Author:
  8. Jiandong Ruan
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #include "dns.tmh"
  13. VOID
  14. SmbDnsTimeout(
  15. PKDPC Dpc,
  16. PSMB_GETHOST_CONTEXT Context,
  17. PVOID Unused1,
  18. PVOID Unused2
  19. );
  20. PIRP __inline
  21. SmbDnsPopResolver(
  22. VOID
  23. )
  24. {
  25. PIRP Irp;
  26. ASSERT(Dns.ResolverNumber >= 0);
  27. if (Dns.ResolverNumber <= 0) {
  28. return NULL;
  29. }
  30. Dns.ResolverNumber--;
  31. Irp = Dns.ResolverList[Dns.ResolverNumber];
  32. Dns.ResolverList[Dns.ResolverNumber] = NULL;
  33. SmbTrace(SMB_TRACE_DNS, ("remove DNS Irp %p, # of resolvers=%d", Irp, Dns.ResolverNumber));
  34. SmbPrint(SMB_TRACE_DNS, ("remove DNS Irp %p, # of resolvers=%d\n", Irp, Dns.ResolverNumber));
  35. ASSERT(Irp != NULL);
  36. return Irp;
  37. }
  38. NTSTATUS __inline
  39. SmbDnsPushResolver(
  40. PIRP Irp
  41. )
  42. {
  43. ASSERT(SmbCfg.DnsMaxResolver >= 1 && SmbCfg.DnsMaxResolver <= DNS_MAX_RESOLVER);
  44. if (Dns.ResolverNumber >= SmbCfg.DnsMaxResolver) {
  45. return STATUS_QUOTA_EXCEEDED;
  46. }
  47. ASSERT(IsListEmpty(&Dns.WaitingServerList));
  48. IoMarkIrpPending(Irp);
  49. Dns.ResolverList[Dns.ResolverNumber] = Irp;
  50. Dns.ResolverNumber++;
  51. SmbTrace(SMB_TRACE_DNS, ("queue DNS Irp %p, # of resolvers=%d", Irp, Dns.ResolverNumber));
  52. SmbPrint(SMB_TRACE_DNS, ("queue DNS Irp %p, # of resolvers=%d\n", Irp, Dns.ResolverNumber));
  53. return STATUS_SUCCESS;
  54. }
  55. NTSTATUS
  56. SmbInitDnsResolver(
  57. VOID
  58. )
  59. {
  60. PAGED_CODE();
  61. RtlZeroMemory(&Dns, sizeof(Dns));
  62. KeInitializeSpinLock(&Dns.Lock);
  63. InitializeListHead(&Dns.WaitingServerList);
  64. InitializeListHead(&Dns.BeingServedList);
  65. Dns.NextId = 1;
  66. return STATUS_SUCCESS;
  67. }
  68. VOID
  69. SmbShutdownDnsResolver(
  70. VOID
  71. )
  72. {
  73. LONG i;
  74. PIRP Irp;
  75. KIRQL Irql;
  76. SMB_ACQUIRE_SPINLOCK(&Dns, Irql);
  77. while (Irp = SmbDnsPopResolver()) {
  78. SMB_RELEASE_SPINLOCK_DPC(&Dns);
  79. Irp->IoStatus.Status = STATUS_SYSTEM_SHUTDOWN;
  80. Irp->IoStatus.Information = 0;
  81. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  82. SMB_ACQUIRE_SPINLOCK_DPC(&Dns);
  83. }
  84. SMB_RELEASE_SPINLOCK(&Dns, Irql);
  85. }
  86. VOID
  87. SmbPassupDnsRequest(
  88. IN PUNICODE_STRING Name,
  89. IN PSMB_GETHOST_CONTEXT Context,
  90. IN PIRP DnsIrp,
  91. IN KIRQL Irql
  92. )
  93. {
  94. PSMB_DNS_BUFFER DnsBuffer;
  95. //
  96. // Spinlock should be held
  97. //
  98. ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
  99. InsertTailList(&Dns.BeingServedList, &Context->Linkage);
  100. DnsBuffer = (PSMB_DNS_BUFFER)MmGetSystemAddressForMdlSafe(DnsIrp->MdlAddress, HighPagePriority);
  101. ASSERT(DnsBuffer);
  102. Context->Id = DnsBuffer->Id = Dns.NextId++;
  103. if (0 == Dns.NextId) {
  104. Dns.NextId = 1;
  105. }
  106. SmbTrace(SMB_TRACE_DNS, ("pass up DNS request: Irp %p, # of resolvers=%d", DnsIrp, Dns.ResolverNumber));
  107. SmbPrint(SMB_TRACE_DNS, ("pass up DNS request: Irp %p, # of resolvers=%d\n", DnsIrp, Dns.ResolverNumber));
  108. ASSERT(Name->Length <= sizeof(DnsBuffer->Name));
  109. RtlCopyMemory(DnsBuffer->Name, Name->Buffer, Name->Length);
  110. DnsBuffer->Name[Name->Length/sizeof(WCHAR)] = L'\0';
  111. DnsBuffer->NameLen = (Name->Length/sizeof(WCHAR)) + 1;
  112. DnsBuffer->Resolved = FALSE;
  113. DnsBuffer->IpAddrsNum = 0;
  114. DnsBuffer->RequestType = 0;
  115. if (SmbCfg.Tcp6Available) {
  116. DnsBuffer->RequestType |= SMB_DNS_AAAA;
  117. if (SmbCfg.bIPv6EnableOutboundGlobal) {
  118. DnsBuffer->RequestType |= SMB_DNS_AAAA_GLOBAL;
  119. }
  120. }
  121. if (SmbCfg.Tcp4Available) {
  122. DnsBuffer->RequestType |= SMB_DNS_A;
  123. }
  124. SMB_RELEASE_SPINLOCK(&Dns, Irql);
  125. DnsIrp->IoStatus.Status = STATUS_SUCCESS;
  126. DnsIrp->IoStatus.Information = sizeof(DnsBuffer[0]);
  127. IoCompleteRequest(DnsIrp, IO_NETWORK_INCREMENT);
  128. }
  129. VOID
  130. SmbCancelConnectAtDns(
  131. IN PDEVICE_OBJECT Device,
  132. IN PIRP Irp
  133. );
  134. BOOL
  135. LookupLocalName(
  136. IN PUNICODE_STRING Name,
  137. IN PSMB_IP_ADDRESS ipaddr
  138. )
  139. /*++
  140. Routine Description:
  141. Lookup the name in local client list. If it is found,
  142. return a loopback IP address in ipaddr.
  143. TO BE FINISHED.
  144. Arguments:
  145. Return Value:
  146. TRUE if it is found
  147. --*/
  148. {
  149. OEM_STRING oemName;
  150. CHAR NbName[NETBIOS_NAME_SIZE+1];
  151. KIRQL Irql;
  152. NTSTATUS status;
  153. PLIST_ENTRY entry;
  154. PSMB_CLIENT_ELEMENT client;
  155. BOOL found = FALSE;
  156. PAGED_CODE();
  157. if (Name->Length > NETBIOS_NAME_SIZE * sizeof(WCHAR)) {
  158. return FALSE;
  159. }
  160. oemName.Buffer = NbName;
  161. oemName.MaximumLength = NETBIOS_NAME_SIZE + 1;
  162. status = RtlUpcaseUnicodeStringToOemString(&oemName, Name, FALSE);
  163. if (!NT_SUCCESS(status)) {
  164. return FALSE;
  165. }
  166. if (oemName.Length > NETBIOS_NAME_SIZE) {
  167. return FALSE;
  168. }
  169. ASSERT(oemName.Buffer == NbName);
  170. //
  171. // Pad the name with SPACEs
  172. //
  173. if (oemName.Length < NETBIOS_NAME_SIZE) {
  174. RtlFillMemory(oemName.Buffer + oemName.Length, NETBIOS_NAME_SIZE - oemName.Length, ' ');
  175. oemName.Length = NETBIOS_NAME_SIZE;
  176. }
  177. ASSERT(oemName.Length == NETBIOS_NAME_SIZE);
  178. found = FALSE;
  179. SMB_ACQUIRE_SPINLOCK(SmbCfg.SmbDeviceObject, Irql);
  180. entry = SmbCfg.SmbDeviceObject->ClientList.Flink;
  181. while (entry != &SmbCfg.SmbDeviceObject->ClientList) {
  182. client = CONTAINING_RECORD(entry, SMB_CLIENT_ELEMENT, Linkage);
  183. if (RtlEqualMemory(client->EndpointName, oemName.Buffer, oemName.Length)) {
  184. found = TRUE;
  185. }
  186. entry = entry->Flink;
  187. }
  188. SMB_RELEASE_SPINLOCK(SmbCfg.SmbDeviceObject, Irql);
  189. if (found) {
  190. if (IsTcp6Available()) {
  191. ipaddr->sin_family = SMB_AF_INET6;
  192. ip6addr_getloopback(&ipaddr->ip6);
  193. hton_ip6addr(&ipaddr->ip6);
  194. } else {
  195. ipaddr->sin_family = SMB_AF_INET;
  196. ipaddr->ip4.sin4_addr = htonl(INADDR_ANY);
  197. }
  198. }
  199. return found;
  200. }
  201. void SmbAsyncGetHostByName(
  202. IN PUNICODE_STRING Name,
  203. IN PSMB_GETHOST_CONTEXT Context
  204. )
  205. {
  206. KIRQL Irql, CancelIrql;
  207. PIRP DnsIrp = NULL, ClientIrp = NULL;
  208. PAGED_CODE();
  209. SmbPrint(SMB_TRACE_CALL, ("SmbAsyncGetHostByName %Z\n", Name));
  210. SmbAsyncStartTimer((PSMB_ASYNC_CONTEXT)Context, (PKDEFERRED_ROUTINE)SmbDnsTimeout);
  211. if (inet_addr6W(Name->Buffer, &Context->ipaddr[0].ip6)) {
  212. Context->ipaddr_num = 1;
  213. Context->ipaddr[0].sin_family = SMB_AF_INET6;
  214. Context->status = STATUS_SUCCESS;
  215. Context->FQDN.Length = 0;
  216. Context->FQDN.Buffer[0] = 0;
  217. SmbAsyncCompleteRequest((PSMB_ASYNC_CONTEXT)Context);
  218. return;
  219. }
  220. Context->ipaddr[0].ip4.sin4_addr = inet_addrW(Name->Buffer);
  221. if (Context->ipaddr[0].ip4.sin4_addr != 0 && Context->ipaddr[0].ip4.sin4_addr != (ULONG)(-1)) {
  222. Context->ipaddr_num = 1;
  223. Context->ipaddr[0].sin_family = SMB_AF_INET;
  224. Context->status = STATUS_SUCCESS;
  225. Context->FQDN.Length = 0;
  226. Context->FQDN.Buffer[0] = 0;
  227. SmbAsyncCompleteRequest((PSMB_ASYNC_CONTEXT)Context);
  228. return;
  229. }
  230. if (LookupLocalName(Name, &Context->ipaddr[0])) {
  231. Context->ipaddr_num = 1;
  232. Context->status = STATUS_SUCCESS;
  233. Context->FQDN.Length = 0;
  234. Context->FQDN.Buffer[0] = 0;
  235. SmbAsyncCompleteRequest((PSMB_ASYNC_CONTEXT)Context);
  236. return;
  237. }
  238. //
  239. // The name is too long
  240. //
  241. if (Name->Length + sizeof(WCHAR) > Context->FQDN.MaximumLength) {
  242. Context->status = STATUS_INVALID_PARAMETER;
  243. SmbAsyncCompleteRequest((PSMB_ASYNC_CONTEXT)Context);
  244. return;
  245. }
  246. //
  247. // It is not a IP address string, go to DNS resolver, to be implemented
  248. //
  249. ClientIrp = ((PSMB_CONNECT)Context->ClientContext)->PendingIRPs[SMB_PENDING_CONNECT];
  250. ASSERT(ClientIrp);
  251. SMB_ACQUIRE_SPINLOCK(&Dns, Irql);
  252. IoAcquireCancelSpinLock(&CancelIrql);
  253. if (ClientIrp->Cancel) {
  254. IoReleaseCancelSpinLock(CancelIrql);
  255. SMB_RELEASE_SPINLOCK(&Dns, Irql);
  256. //
  257. // Already cancelled
  258. //
  259. Context->status = STATUS_CANCELLED;
  260. SmbAsyncCompleteRequest((PSMB_ASYNC_CONTEXT)Context);
  261. return;
  262. }
  263. IoSetCancelRoutine(ClientIrp, SmbCancelConnectAtDns);
  264. DnsIrp = SmbDnsPopResolver();
  265. if (NULL == DnsIrp) {
  266. RtlCopyMemory(Context->FQDN.Buffer, Name->Buffer, Name->Length);
  267. Context->FQDN.Length = Name->Length;
  268. Context->FQDN.Buffer[Name->Length/sizeof(WCHAR)] = L'\0';
  269. InsertTailList(&Dns.WaitingServerList, &Context->Linkage);
  270. IoReleaseCancelSpinLock(CancelIrql);
  271. SMB_RELEASE_SPINLOCK(&Dns, Irql);
  272. return;
  273. }
  274. IoSetCancelRoutine(DnsIrp, NULL);
  275. IoReleaseCancelSpinLock(CancelIrql);
  276. //
  277. // This guy will complete the Irp and release the spinlock!!!
  278. //
  279. SmbPassupDnsRequest(Name, Context, DnsIrp, Irql);
  280. }
  281. VOID
  282. SmbCancelDns(
  283. IN PDEVICE_OBJECT Device,
  284. IN PIRP Irp
  285. )
  286. {
  287. KIRQL Irql;
  288. LONG i;
  289. BOOL Found = FALSE;
  290. //
  291. // Avoid deadlock, we need to release the spinlock first
  292. //
  293. SmbTrace(SMB_TRACE_DNS, ("Cancel DNS Irp %p", Irp));
  294. SmbPrint(SMB_TRACE_DNS, ("Cancel DNS Irp %p\n", Irp));
  295. IoSetCancelRoutine(Irp, NULL);
  296. IoReleaseCancelSpinLock(Irp->CancelIrql);
  297. //
  298. // After the cancel spinlock is released, the IRP can be completed
  299. // Check if it is still in our pending list
  300. //
  301. SMB_ACQUIRE_SPINLOCK(&Dns, Irql);
  302. for (i = 0; i < Dns.ResolverNumber; i++) {
  303. if (Dns.ResolverList[i] == Irp) {
  304. Dns.ResolverNumber--;
  305. Dns.ResolverList[i] = Dns.ResolverList[Dns.ResolverNumber];
  306. Dns.ResolverList[Dns.ResolverNumber] = NULL;
  307. Found = TRUE;
  308. break;
  309. }
  310. }
  311. SMB_RELEASE_SPINLOCK(&Dns, Irql);
  312. if (Found) {
  313. Irp->IoStatus.Status = STATUS_CANCELLED;
  314. Irp->IoStatus.Information = 0;
  315. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  316. SmbTrace(SMB_TRACE_DNS, ("Complete Cancel DNS Irp %p", Irp));
  317. SmbPrint(SMB_TRACE_DNS, ("Complete Cancel DNS Irp %p\n", Irp));
  318. }
  319. }
  320. PSMB_GETHOST_CONTEXT
  321. SmbDnsLookupGethostCtx(
  322. PLIST_ENTRY queue,
  323. PIRP Irp
  324. )
  325. {
  326. PLIST_ENTRY entry;
  327. PIRP ClientIrp;
  328. PSMB_GETHOST_CONTEXT Context;
  329. //
  330. // Spinlock should be held
  331. //
  332. ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
  333. entry = queue->Flink;
  334. while (entry != queue) {
  335. Context = CONTAINING_RECORD(entry, SMB_GETHOST_CONTEXT, Linkage);
  336. ClientIrp = ((PSMB_CONNECT)Context->ClientContext)->PendingIRPs[SMB_PENDING_CONNECT];
  337. if (ClientIrp == Irp) {
  338. return Context;
  339. }
  340. entry = entry->Flink;
  341. }
  342. return NULL;
  343. }
  344. VOID
  345. SmbCancelConnectAtDns(
  346. IN PDEVICE_OBJECT Device,
  347. IN PIRP Irp
  348. )
  349. {
  350. PSMB_GETHOST_CONTEXT Context;
  351. KIRQL Irql;
  352. //
  353. // Avoid deadlock, we need to release the spinlock first
  354. //
  355. SmbTrace(SMB_TRACE_OUTBOUND, ("Cancel Connect Irp %p", Irp));
  356. SmbPrint(SMB_TRACE_OUTBOUND, ("Cancel Connect Irp %p\n", Irp));
  357. IoSetCancelRoutine(Irp, NULL);
  358. IoReleaseCancelSpinLock(Irp->CancelIrql);
  359. SMB_ACQUIRE_SPINLOCK(&Dns, Irql);
  360. Context = SmbDnsLookupGethostCtx(&Dns.BeingServedList, Irp);
  361. if (NULL == Context) {
  362. Context = SmbDnsLookupGethostCtx(&Dns.WaitingServerList, Irp);
  363. }
  364. if (NULL == Context) {
  365. SMB_RELEASE_SPINLOCK(&Dns, Irql);
  366. //
  367. // This could happen. The DNS name resolution request could completed just before
  368. // we acquire the spinlock Dns.Lock
  369. //
  370. // This ASSERT can be removed after we investigates one such case.
  371. //
  372. // ASSERT(0); Hit in the 04/03/2001 stress
  373. SmbTrace(SMB_TRACE_OUTBOUND, ("Internal error: Cancel Connect Irp %p", Irp));
  374. SmbPrint(SMB_TRACE_OUTBOUND, ("Internal error: Cancel Connect Irp %p\n", Irp));
  375. return;
  376. }
  377. RemoveEntryList(&Context->Linkage);
  378. InitializeListHead(&Context->Linkage);
  379. SMB_RELEASE_SPINLOCK(&Dns, Irql);
  380. Context->status = STATUS_CANCELLED;
  381. SmbAsyncCompleteRequest((PSMB_ASYNC_CONTEXT)Context);
  382. }
  383. VOID
  384. SmbDnsTimeout(
  385. PKDPC Dpc,
  386. PSMB_GETHOST_CONTEXT Context,
  387. PVOID Unused1,
  388. PVOID Unused2
  389. )
  390. {
  391. KIRQL Irql;
  392. BOOL Found;
  393. //
  394. // Be careful on the operations on the Context before we're sure it
  395. // is still in the linked list.
  396. // It could be completed and freed.
  397. //
  398. SMB_ACQUIRE_SPINLOCK(&Dns, Irql);
  399. //
  400. // Note: &Context->Linkage is safe since it doesn't access the
  401. // storage allocated for Context!!!
  402. //
  403. Found = EntryIsInList(&Dns.BeingServedList, &Context->Linkage);
  404. if (!Found) {
  405. Found = EntryIsInList(&Dns.WaitingServerList, &Context->Linkage);
  406. }
  407. if (Found) {
  408. //
  409. // We're safe
  410. //
  411. RemoveEntryList(&Context->Linkage);
  412. InitializeListHead(&Context->Linkage);
  413. }
  414. SMB_RELEASE_SPINLOCK(&Dns, Irql);
  415. if (Found) {
  416. Context->status = STATUS_BAD_NETWORK_PATH;
  417. SmbAsyncCompleteRequest((PSMB_ASYNC_CONTEXT)Context);
  418. }
  419. }
  420. NTSTATUS
  421. SmbNewResolver(
  422. PSMB_DEVICE Device,
  423. PIRP Irp
  424. )
  425. {
  426. KIRQL Irql, CancelIrql;
  427. NTSTATUS status;
  428. PIO_STACK_LOCATION IrpSp;
  429. ULONG Size;
  430. PSMB_DNS_BUFFER DnsBuffer;
  431. PLIST_ENTRY entry;
  432. PSMB_GETHOST_CONTEXT Context;
  433. PIRP ClientIrp;
  434. if (NULL == Irp->MdlAddress) {
  435. return STATUS_INVALID_PARAMETER;
  436. }
  437. Size = MmGetMdlByteCount(Irp->MdlAddress);
  438. if (Size < sizeof(SMB_DNS_BUFFER)) {
  439. return STATUS_INVALID_PARAMETER;
  440. }
  441. DnsBuffer = (PSMB_DNS_BUFFER)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
  442. if (NULL == DnsBuffer) {
  443. return STATUS_INSUFFICIENT_RESOURCES;
  444. }
  445. SMB_ACQUIRE_SPINLOCK(&Dns, Irql);
  446. if (!IsListEmpty(&Dns.BeingServedList) && DnsBuffer->Id) {
  447. //
  448. // Complete the pending DNS request being served by this resolver
  449. //
  450. entry = Dns.BeingServedList.Flink;
  451. while (entry != &Dns.BeingServedList) {
  452. Context = CONTAINING_RECORD(entry, SMB_GETHOST_CONTEXT, Linkage);
  453. if (Context->Id == DnsBuffer->Id) {
  454. break;
  455. }
  456. entry = entry->Flink;
  457. }
  458. if (entry != &Dns.BeingServedList) {
  459. RemoveEntryList(&Context->Linkage);
  460. InitializeListHead(&Context->Linkage);
  461. SMB_RELEASE_SPINLOCK(&Dns, Irql);
  462. ClientIrp = ((PSMB_CONNECT)Context->ClientContext)->PendingIRPs[SMB_PENDING_CONNECT];
  463. ASSERT(ClientIrp);
  464. IoAcquireCancelSpinLock(&CancelIrql);
  465. IoSetCancelRoutine(ClientIrp, NULL);
  466. IoReleaseCancelSpinLock(CancelIrql);
  467. if (ClientIrp->Cancel) {
  468. Context->status = STATUS_CANCELLED;
  469. } else {
  470. if (DnsBuffer->Resolved) {
  471. USHORT BytesToCopy;
  472. Context->status = STATUS_SUCCESS;
  473. Context->ipaddr_num = DnsBuffer->IpAddrsNum;
  474. if (Context->ipaddr_num > SMB_MAX_IPADDRS_PER_HOST) {
  475. ASSERT (0);
  476. Context->ipaddr_num = SMB_MAX_IPADDRS_PER_HOST;
  477. }
  478. RtlCopyMemory (Context->ipaddr, DnsBuffer->IpAddrsList,
  479. Context->ipaddr_num * sizeof(Context->ipaddr[0]));
  480. if (DnsBuffer->NameLen) {
  481. //
  482. // Return the FQDN to RDR
  483. //
  484. Context->pUnicodeAddress->NameBufferType = NBT_WRITTEN;
  485. BytesToCopy = (USHORT)DnsBuffer->NameLen * sizeof(WCHAR);
  486. if (BytesToCopy > Context->pUnicodeAddress->RemoteName.MaximumLength) {
  487. BytesToCopy = Context->pUnicodeAddress->RemoteName.MaximumLength - sizeof(WCHAR);
  488. }
  489. RtlCopyMemory(Context->pUnicodeAddress->RemoteName.Buffer,
  490. DnsBuffer->Name, BytesToCopy);
  491. Context->pUnicodeAddress->RemoteName.Buffer[BytesToCopy/sizeof(WCHAR)] = L'\0';
  492. Context->pUnicodeAddress->RemoteName.Length = BytesToCopy;
  493. }
  494. } else {
  495. Context->status = STATUS_BAD_NETWORK_PATH;
  496. }
  497. }
  498. //
  499. // Is it better to start another thread?
  500. // Risk: if the connection setup is stucked in tcpip,
  501. // this thread won't be able to serve other DNS requests
  502. //
  503. SmbAsyncCompleteRequest((PSMB_ASYNC_CONTEXT)Context);
  504. SMB_ACQUIRE_SPINLOCK(&Dns, Irql);
  505. }
  506. }
  507. if (IsListEmpty(&Dns.WaitingServerList)) {
  508. //
  509. // We need to queue the IRP, setup the cancel routine.
  510. //
  511. IoAcquireCancelSpinLock(&CancelIrql);
  512. if (Irp->Cancel) {
  513. IoReleaseCancelSpinLock(CancelIrql);
  514. SMB_RELEASE_SPINLOCK(&Dns, Irql);
  515. SmbTrace(SMB_TRACE_DNS, ("DNS Irp %p is cancelled", Irp));
  516. SmbPrint(SMB_TRACE_DNS, ("DNS Irp %p is cancelled\n", Irp));
  517. return STATUS_CANCELLED;
  518. }
  519. IoSetCancelRoutine(Irp, SmbCancelDns);
  520. IoReleaseCancelSpinLock(CancelIrql);
  521. status = SmbDnsPushResolver(Irp);
  522. if (NT_SUCCESS(status)) {
  523. status = STATUS_PENDING;
  524. } else {
  525. IoAcquireCancelSpinLock(&CancelIrql);
  526. IoSetCancelRoutine(Irp, NULL);
  527. IoReleaseCancelSpinLock(CancelIrql);
  528. }
  529. SMB_RELEASE_SPINLOCK(&Dns, Irql);
  530. return status;
  531. }
  532. //
  533. // We have another guy to be served
  534. //
  535. Context = CONTAINING_RECORD(Dns.WaitingServerList.Flink, SMB_GETHOST_CONTEXT, Linkage);
  536. RemoveEntryList(&Context->Linkage);
  537. InitializeListHead(&Context->Linkage);
  538. IoMarkIrpPending(Irp);
  539. //
  540. // This guy will complete the Irp and release the spinlock!!!
  541. //
  542. SmbPassupDnsRequest(&Context->FQDN, Context, Irp, Irql);
  543. //
  544. // Avoid double completion
  545. //
  546. return STATUS_PENDING;
  547. }