|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1989-1993 Microsoft Corporation
4:
5: Module Name:
6:
7: connect.c
8:
9: Abstract:
10:
11: This module contains code which performs the following TDI services:
12:
13: o TdiAccept
14: o TdiListen
15: o TdiConnect
16: o TdiDisconnect
17: o TdiAssociateAddress
18: o TdiDisassociateAddress
19: o OpenConnection
20: o CloseConnection
21:
22: Environment:
23:
24: Kernel mode
25:
26: Revision History:
27:
28: --*/
29:
30: #include "st.h"
31:
32:
33: NTSTATUS
34: StTdiAccept(
35: IN PIRP Irp
36: )
37:
38: /*++
39:
40: Routine Description:
41:
42: This routine performs the TdiAccept request for the transport provider.
43:
44: Arguments:
45:
46: Irp - Pointer to the I/O Request Packet for this request.
47:
48: Return Value:
49:
50: NTSTATUS - status of operation.
51:
52: --*/
53:
54: {
55: PTP_CONNECTION connection;
56: PIO_STACK_LOCATION irpSp;
57: KIRQL oldirql;
58: NTSTATUS status;
59:
60: //
61: // Get the connection this is associated with; if there is none, get out.
62: //
63:
64: irpSp = IoGetCurrentIrpStackLocation (Irp);
65:
66: connection = irpSp->FileObject->FsContext;
67:
68: //
69: // This adds a connection reference if successful.
70: //
71:
72: status = StVerifyConnectionObject (connection);
73:
74: if (!NT_SUCCESS (status)) {
75: return status;
76: }
77:
78: //
79: // just set the connection flags to allow reads and writes to proceed.
80: //
81:
82: ACQUIRE_SPIN_LOCK (&connection->SpinLock, &oldirql);
83:
84: //
85: // Turn off the stopping flag for this connection.
86: //
87:
88: connection->Flags &= ~CONNECTION_FLAGS_STOPPING;
89: connection->Status = STATUS_PENDING;
90:
91: connection->Flags2 |= CONNECTION_FLAGS2_ACCEPTED;
92:
93:
94: if (connection->AddressFile->ConnectIndicationInProgress) {
95: connection->Flags2 |= CONNECTION_FLAGS2_INDICATING;
96: }
97:
98: if ((connection->Flags2 & CONNECTION_FLAGS2_WAIT_ACCEPT) != 0) {
99:
100: //
101: // We previously completed a listen, now the user is
102: // coming back with an accept, Set this flag to allow
103: // the connection to proceed.
104: //
105:
106: connection->Flags |= CONNECTION_FLAGS_READY;
107:
108: INCREMENT_COUNTER (connection->Provider, OpenConnections);
109:
110: //
111: // Set this flag to enable disconnect indications; once
112: // the client has accepted he expects those.
113: //
114:
115: connection->Flags2 &= ~CONNECTION_FLAGS2_WAIT_ACCEPT;
116: connection->Flags2 |= CONNECTION_FLAGS2_REQ_COMPLETED;
117:
118: StReferenceConnection("Pended listen completed", connection);
119:
120: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql);
121:
122: } else {
123:
124: //
125: // This accept is being called at some point before
126: // the link is up; directly from the connection handler
127: // or at some point slightly later.
128: //
129:
130: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql);
131:
132: }
133:
134: StDereferenceConnection ("Temp TdiAccept", connection);
135:
136: return STATUS_SUCCESS;
137:
138: } /* StTdiAccept */
139:
140:
141: NTSTATUS
142: StTdiAssociateAddress(
143: IN PIRP Irp
144: )
145:
146: /*++
147:
148: Routine Description:
149:
150: This routine performs the association of the connection and the address for
151: the user.
152:
153: Arguments:
154:
155: Irp - Pointer to the I/O Request Packet for this request.
156:
157: Return Value:
158:
159: NTSTATUS - status of operation.
160:
161: --*/
162:
163: {
164: NTSTATUS status;
165: PFILE_OBJECT fileObject;
166: PTP_ADDRESS_FILE addressFile;
167: PTP_ADDRESS oldAddress;
168: PTP_CONNECTION connection;
169: PIO_STACK_LOCATION irpSp;
170: PTDI_REQUEST_KERNEL_ASSOCIATE parameters;
171: PDEVICE_CONTEXT deviceContext;
172:
173: KIRQL oldirql, oldirql2;
174:
175: irpSp = IoGetCurrentIrpStackLocation (Irp);
176:
177: //
178: // verify that the operation is taking place on a connection. At the same
179: // time we do this, we reference the connection. This ensures it does not
180: // get removed out from under us. Note also that we do the connection
181: // lookup within a try/except clause, thus protecting ourselves against
182: // really bogus handles
183: //
184:
185: connection = irpSp->FileObject->FsContext;
186: status = StVerifyConnectionObject (connection);
187: if (!NT_SUCCESS (status)) {
188: return status;
189: }
190:
191:
192: //
193: // Make sure this connection is ready to be associated.
194: //
195:
196: oldAddress = (PTP_ADDRESS)NULL;
197:
198: ACQUIRE_SPIN_LOCK (&connection->SpinLock, &oldirql2);
199:
200: if ((connection->Flags2 & CONNECTION_FLAGS2_ASSOCIATED) &&
201: ((connection->Flags2 & CONNECTION_FLAGS2_DISASSOCIATED) == 0)) {
202:
203: //
204: // The connection is already associated with
205: // an active connection...bad!
206: //
207:
208: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql2);
209: StDereferenceConnection ("Temp Ref Associate", connection);
210:
211: return STATUS_INVALID_CONNECTION;
212:
213: } else {
214:
215: //
216: // See if there is an old association hanging around...
217: // this happens if the connection has been disassociated,
218: // but not closed.
219: //
220:
221: if (connection->Flags2 & CONNECTION_FLAGS2_DISASSOCIATED) {
222:
223: //
224: // Save this; since it is non-null this address
225: // will be dereferenced after the connection
226: // spinlock is released.
227: //
228:
229: oldAddress = connection->AddressFile->Address;
230:
231: //
232: // Remove the old association.
233: //
234:
235: connection->Flags2 &= ~CONNECTION_FLAGS2_ASSOCIATED;
236: RemoveEntryList (&connection->AddressList);
237: RemoveEntryList (&connection->AddressFileList);
238: InitializeListHead (&connection->AddressList);
239: InitializeListHead (&connection->AddressFileList);
240: connection->AddressFile = NULL;
241:
242: }
243:
244: }
245:
246: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql2);
247:
248: //
249: // If we removed an old association, dereference the
250: // address.
251: //
252:
253: if (oldAddress != (PTP_ADDRESS)NULL) {
254:
255: StDereferenceAddress("Removed old association", oldAddress);
256:
257: }
258:
259:
260: deviceContext = connection->Provider;
261:
262: parameters = (PTDI_REQUEST_KERNEL_ASSOCIATE)&irpSp->Parameters;
263:
264: //
265: // get a pointer to the address File Object, which points us to the
266: // transport's address object, which is where we want to put the
267: // connection.
268: //
269:
270: status = ObReferenceObjectByHandle (
271: parameters->AddressHandle,
272: 0L,
273: 0,
274: KernelMode,
275: (PVOID *) &fileObject,
276: NULL);
277:
278: if (NT_SUCCESS(status)) {
279:
280: //
281: // we might have one of our address objects; verify that.
282: //
283:
284: addressFile = fileObject->FsContext;
285:
286: if (NT_SUCCESS (StVerifyAddressObject (addressFile))) {
287:
288: //
289: // have an address and connection object. Add the connection to the
290: // address object database. Also add the connection to the address
291: // file object db (used primarily for cleaning up). Reference the
292: // address to account for one more reason for it staying open.
293: //
294:
295: ACQUIRE_SPIN_LOCK (&addressFile->Address->SpinLock, &oldirql);
296: if ((addressFile->Address->Flags & ADDRESS_FLAGS_STOPPING) == 0) {
297:
298: ACQUIRE_SPIN_LOCK (&connection->SpinLock, &oldirql2);
299:
300: if ((connection->Flags2 & CONNECTION_FLAGS2_CLOSING) == 0) {
301:
302: StReferenceAddress (
303: "Connection associated",
304: addressFile->Address);
305:
306: InsertTailList (
307: &addressFile->Address->ConnectionDatabase,
308: &connection->AddressList);
309:
310: InsertTailList (
311: &addressFile->ConnectionDatabase,
312: &connection->AddressFileList);
313:
314: connection->AddressFile = addressFile;
315: connection->Flags2 |= CONNECTION_FLAGS2_ASSOCIATED;
316: connection->Flags2 &= ~CONNECTION_FLAGS2_DISASSOCIATED;
317:
318: if (addressFile->ConnectIndicationInProgress) {
319: connection->Flags2 |= CONNECTION_FLAGS2_INDICATING;
320: }
321:
322: status = STATUS_SUCCESS;
323:
324: } else {
325:
326: //
327: // The connection is closing, stop the
328: // association.
329: //
330:
331: status = STATUS_INVALID_CONNECTION;
332:
333: }
334:
335: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql2);
336:
337: } else {
338:
339: status = STATUS_INVALID_HANDLE;
340: }
341:
342: RELEASE_SPIN_LOCK (&addressFile->Address->SpinLock, oldirql);
343:
344: StDereferenceAddress ("Temp associate", addressFile->Address);
345:
346: } else {
347:
348: status = STATUS_INVALID_HANDLE;
349: }
350:
351: //
352: // Note that we don't keep a reference to this file object around.
353: // That's because the IO subsystem manages the object for us; we simply
354: // want to keep the association. We only use this association when the
355: // IO subsystem has asked us to close one of the file object, and then
356: // we simply remove the association.
357: //
358:
359: ObDereferenceObject (fileObject);
360:
361: } else {
362: status = STATUS_INVALID_HANDLE;
363: }
364:
365: StDereferenceConnection ("Temp Ref Associate", connection);
366:
367: return status;
368:
369: } /* TdiAssociateAddress */
370:
371:
372: NTSTATUS
373: StTdiDisassociateAddress(
374: IN PIRP Irp
375: )
376: /*++
377:
378: Routine Description:
379:
380: This routine performs the disassociation of the connection and the address
381: for the user. If the connection has not been stopped, it will be stopped
382: here.
383:
384: Arguments:
385:
386: Irp - Pointer to the I/O Request Packet for this request.
387:
388: Return Value:
389:
390: NTSTATUS - status of operation.
391:
392: --*/
393:
394: {
395:
396: KIRQL oldirql;
397: PIO_STACK_LOCATION irpSp;
398: PTP_CONNECTION connection;
399: NTSTATUS status;
400:
401: irpSp = IoGetCurrentIrpStackLocation (Irp);
402:
403: connection = irpSp->FileObject->FsContext;
404:
405: //
406: // If successful this adds a reference.
407: //
408:
409: status = StVerifyConnectionObject (connection);
410:
411: if (!NT_SUCCESS (status)) {
412: return status;
413: }
414:
415: ACQUIRE_SPIN_LOCK (&connection->SpinLock, &oldirql);
416: if ((connection->Flags & CONNECTION_FLAGS_STOPPING) == 0) {
417: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql);
418: StStopConnection (connection, STATUS_LOCAL_DISCONNECT);
419:
420: } else {
421: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql);
422: }
423:
424: //
425: // and now we disassociate the address. This only removes
426: // the appropriate reference for the connection, the
427: // actually disassociation will be done later.
428: //
429: // The DISASSOCIATED flag is used to make sure that
430: // only one person removes this reference.
431: //
432:
433: ACQUIRE_SPIN_LOCK (&connection->SpinLock, &oldirql);
434: if ((connection->Flags2 & CONNECTION_FLAGS2_ASSOCIATED) &&
435: ((connection->Flags2 & CONNECTION_FLAGS2_DISASSOCIATED) == 0)) {
436: connection->Flags2 |= CONNECTION_FLAGS2_DISASSOCIATED;
437: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql);
438: } else {
439: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql);
440: }
441:
442: StDereferenceConnection ("Temp use in Associate", connection);
443:
444: return STATUS_SUCCESS;
445:
446: } /* TdiDisassociateAddress */
447:
448:
449: NTSTATUS
450: StTdiConnect(
451: IN PIRP Irp
452: )
453:
454: /*++
455:
456: Routine Description:
457:
458: This routine performs the TdiConnect request for the transport provider.
459:
460: Arguments:
461:
462: Irp - Pointer to the I/O Request Packet for this request.
463:
464: Return Value:
465:
466: NTSTATUS - status of operation.
467:
468: --*/
469:
470: {
471: NTSTATUS status;
472: PTP_CONNECTION connection;
473: PSTRING GeneralBroadcastSourceRoute = NULL; // BUGBUG: define this later.
474: LARGE_INTEGER timeout = {0,0};
475: KIRQL oldirql, cancelirql;
476: PTP_REQUEST tpRequest;
477: PIO_STACK_LOCATION irpSp;
478: PTDI_REQUEST_KERNEL parameters;
479: PTA_NETBIOS_ADDRESS RemoteAddress;
480: ULONG RemoteAddressLength;
481:
482: //
483: // is the file object a connection?
484: //
485:
486: irpSp = IoGetCurrentIrpStackLocation (Irp);
487: connection = irpSp->FileObject->FsContext;
488:
489: //
490: // If successful this adds a reference.
491: //
492:
493: status = StVerifyConnectionObject (connection);
494:
495: if (!NT_SUCCESS (status)) {
496: return status;
497: }
498:
499: parameters = (PTDI_REQUEST_KERNEL)(&irpSp->Parameters);
500:
501: //
502: // fix up the timeout if required; no connect request should take more
503: // than 15 seconds if there is someone out there. We'll assume that's
504: // what the user wanted if they specify -1 as the timer length.
505: //
506:
507: if (parameters->RequestSpecific != NULL) {
508: if ((((PLARGE_INTEGER)(parameters->RequestSpecific))->LowPart == -1) &&
509: (((PLARGE_INTEGER)(parameters->RequestSpecific))->HighPart == -1)) {
510:
511: timeout.LowPart = (ULONG)(-TDI_TIMEOUT_CONNECT * 10000000L); // n * 10 ** 7 => 100ns units
512: if (timeout.LowPart != 0) {
513: timeout.HighPart = -1L;
514: } else {
515: timeout.HighPart = 0;
516: }
517:
518: } else {
519:
520: timeout.LowPart = ((PLARGE_INTEGER)(parameters->RequestSpecific))->LowPart;
521: timeout.HighPart = ((PLARGE_INTEGER)(parameters->RequestSpecific))->HighPart;
522: }
523: }
524:
525: //
526: // Check that the remote is a Netbios address.
527: //
528:
529: RemoteAddress = (PTA_NETBIOS_ADDRESS)
530: (parameters->RequestConnectionInformation->RemoteAddress);
531:
532: if (RemoteAddress->Address[0].AddressType != TDI_ADDRESS_TYPE_NETBIOS) {
533:
534: StDereferenceConnection ("Not Netbios", connection);
535: return STATUS_BAD_NETWORK_PATH; // don't even try to find it.
536:
537: }
538:
539: //
540: // copy the called address someplace we can use it.
541: //
542:
543: RemoteAddressLength = parameters->RequestConnectionInformation->RemoteAddressLength;
544:
545: if (RemoteAddressLength > sizeof(TA_NETBIOS_ADDRESS)) {
546: RemoteAddressLength = sizeof(TA_NETBIOS_ADDRESS);
547: }
548:
549: RtlCopyMemory(
550: connection->CalledAddress.NetbiosName,
551: RemoteAddress->Address[0].Address[0].NetbiosName,
552: 16);
553:
554: //
555: // We need a request object to keep track of this TDI request.
556: // Attach this request to the new connection object.
557: //
558:
559: status = StCreateRequest (
560: Irp, // IRP for this request.
561: connection, // context.
562: REQUEST_FLAGS_CONNECTION, // partial flags.
563: NULL,
564: 0,
565: timeout,
566: &tpRequest);
567:
568: if (!NT_SUCCESS (status)) { // couldn't make the request.
569: StDereferenceConnection ("Throw away", connection);
570: return status; // return with failure.
571: } else {
572:
573: // Reference the connection since StDestroyRequest derefs it.
574:
575: StReferenceConnection("For connect request", connection);
576:
577: tpRequest->Owner = ConnectionType;
578: IoAcquireCancelSpinLock (&cancelirql);
579: ACQUIRE_SPIN_LOCK (&connection->SpinLock,&oldirql);
580: if ((connection->Flags & CONNECTION_FLAGS_STOPPING) != 0) {
581: RELEASE_SPIN_LOCK (&connection->SpinLock,oldirql);
582: IoReleaseCancelSpinLock (cancelirql);
583: StCompleteRequest (
584: tpRequest,
585: connection->Status,
586: 0);
587: StDereferenceConnection("Temporary Use 1", connection);
588: return STATUS_PENDING;
589: } else {
590: InsertTailList (&connection->InProgressRequest,&tpRequest->Linkage);
591:
592: connection->Flags |= CONNECTION_FLAGS_CONNECTOR; // we're the initiator.
593:
594: connection->Flags &= ~CONNECTION_FLAGS_STOPPING;
595: connection->Status = STATUS_PENDING;
596:
597: connection->Flags2 &= ~CONNECTION_FLAGS2_INDICATING;
598: RELEASE_SPIN_LOCK (&connection->SpinLock,oldirql);
599:
600: //
601: // Check if the IRP has been cancelled.
602: //
603:
604: if (Irp->Cancel) {
605: Irp->CancelIrql = cancelirql;
606: StCancelConnection((PDEVICE_OBJECT)(connection->Provider), Irp);
607: StDereferenceConnection ("IRP cancelled", connection); // release lookup hold.
608: return STATUS_PENDING;
609: }
610:
611: Irp->CancelRoutine = StCancelConnection;
612: IoReleaseCancelSpinLock(cancelirql);
613:
614: }
615: }
616:
617: status = StSendConnect (
618: connection);
619:
620: if (!NT_SUCCESS(status)) { // can't send the name request
621: StStopConnection (connection, status);
622: StDereferenceConnection("Temporary Use 2", connection);
623:
624: //
625: // Note that this return status isn't really a lie. We are waiting
626: // for the connection to run down.
627: //
628:
629: return STATUS_PENDING;
630: }
631:
632:
633: StDereferenceConnection("Temporary Use 3", connection);
634:
635: return STATUS_PENDING; // things are started.
636:
637: } /* TdiConnect */
638:
639:
640: NTSTATUS
641: StTdiDisconnect(
642: IN PIRP Irp
643: )
644:
645: /*++
646:
647: Routine Description:
648:
649: This routine performs the TdiDisconnect request for the transport provider.
650:
651: Arguments:
652:
653: Irp - Pointer to the I/O Request Packet for this request.
654:
655: Return Value:
656:
657: NTSTATUS - status of operation.
658:
659: --*/
660:
661: {
662: PTP_CONNECTION connection;
663: LARGE_INTEGER timeout;
664: PIO_STACK_LOCATION irpSp;
665: PTDI_REQUEST_KERNEL parameters;
666: KIRQL oldirql;
667: NTSTATUS status;
668:
669:
670: irpSp = IoGetCurrentIrpStackLocation (Irp);
671:
672: connection = irpSp->FileObject->FsContext;
673:
674: //
675: // If successful this adds a reference.
676: //
677:
678: status = StVerifyConnectionObject (connection);
679: if (!NT_SUCCESS (status)) {
680: return status;
681: }
682:
683:
684: ACQUIRE_SPIN_LOCK (&connection->SpinLock, &oldirql);
685:
686: //
687: // if the connection is currently stopping, there's no reason to blow
688: // it away...
689: //
690:
691: if ((connection->Flags & CONNECTION_FLAGS_STOPPING) != 0) {
692:
693: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql);
694: StDereferenceConnection ("Ignoring disconnect", connection); // release our lookup reference.
695: return connection->Status;
696:
697: } else {
698: connection->Flags2 &= ~ (CONNECTION_FLAGS2_ACCEPTED |
699: CONNECTION_FLAGS2_PRE_ACCEPT |
700: CONNECTION_FLAGS2_WAIT_ACCEPT);
701: connection->Flags2 |= CONNECTION_FLAGS2_DISCONNECT;
702:
703: //
704: // Set this flag so the disconnect IRP is completed.
705: //
706: // BUGBUG: If the connection goes down before we can
707: // call StStopConnection with STATUS_LOCAL_DISCONNECT,
708: // the disconnect IRP won't get completed.
709: //
710:
711: connection->Flags2 |= CONNECTION_FLAGS2_REQ_COMPLETED;
712:
713: connection->DisconnectIrp = Irp;
714: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql);
715: }
716:
717: //
718: // fix up the timeout if required; no disconnect request should take very
719: // long. However, the user can cause the timeout to not happen if they
720: // desire that.
721: //
722:
723: parameters = (PTDI_REQUEST_KERNEL)(&irpSp->Parameters);
724:
725: //
726: // fix up the timeout if required; no disconnect request should take more
727: // than 15 seconds. We'll assume that's what the user wanted if they
728: // specify -1 as the timer.
729: //
730:
731: if (parameters->RequestSpecific != NULL) {
732: if ((((PLARGE_INTEGER)(parameters->RequestSpecific))->LowPart == -1) &&
733: (((PLARGE_INTEGER)(parameters->RequestSpecific))->HighPart == -1)) {
734:
735: timeout.LowPart = (ULONG)(-TDI_TIMEOUT_DISCONNECT * 10000000L); // n * 10 ** 7 => 100ns units
736: if (timeout.LowPart != 0) {
737: timeout.HighPart = -1L;
738: } else {
739: timeout.HighPart = 0;
740: }
741:
742: } else {
743: timeout.LowPart = ((PLARGE_INTEGER)(parameters->RequestSpecific))->LowPart;
744: timeout.HighPart = ((PLARGE_INTEGER)(parameters->RequestSpecific))->HighPart;
745: }
746: }
747:
748: //
749: // Now the reason for the disconnect
750: //
751:
752: if ((ULONG)(parameters->RequestFlags) & (ULONG)TDI_DISCONNECT_RELEASE) {
753: connection->Flags |= CONNECTION_FLAGS_DESTROY;
754: } else if ((ULONG)(parameters->RequestFlags) & (ULONG)TDI_DISCONNECT_ABORT) {
755: connection->Flags |= CONNECTION_FLAGS_ABORT;
756: } else if ((ULONG)(parameters->RequestFlags) & (ULONG)TDI_DISCONNECT_WAIT) {
757: connection->Flags |= CONNECTION_FLAGS_ORDREL;
758: }
759:
760: //
761: // This will get passed to IoCompleteRequest during TdiDestroyConnection
762: //
763:
764: StStopConnection (connection, STATUS_LOCAL_DISCONNECT); // starts the abort sequence.
765: StDereferenceConnection ("Disconnecting", connection); // release our lookup reference.
766:
767: //
768: // This request will be completed by TdiDestroyConnection once
769: // the connection reference count drops to 0.
770: //
771:
772: return STATUS_PENDING;
773: } /* TdiDisconnect */
774:
775:
776: NTSTATUS
777: StTdiListen(
778: IN PIRP Irp
779: )
780:
781: /*++
782:
783: Routine Description:
784:
785: This routine performs the TdiListen request for the transport provider.
786:
787: Arguments:
788:
789: Irp - Pointer to the I/O Request Packet for this request.
790:
791: Return Value:
792:
793: NTSTATUS - status of operation.
794:
795: --*/
796:
797: {
798: NTSTATUS status;
799: PTP_CONNECTION connection;
800: LARGE_INTEGER timeout = {0,0};
801: KIRQL oldirql, cancelirql;
802: PTP_REQUEST tpRequest;
803: PIO_STACK_LOCATION irpSp;
804: PTDI_REQUEST_KERNEL_LISTEN parameters;
805:
806: //
807: // validate this connection
808:
809: irpSp = IoGetCurrentIrpStackLocation (Irp);
810:
811: connection = irpSp->FileObject->FsContext;
812:
813: //
814: // If successful this adds a reference.
815: //
816:
817: status = StVerifyConnectionObject (connection);
818:
819: if (!NT_SUCCESS (status)) {
820: return status;
821: }
822:
823: parameters = (PTDI_REQUEST_KERNEL_LISTEN)&irpSp->Parameters;
824:
825: //
826: // We need a request object to keep track of this TDI request.
827: // Attach this request to the new connection object.
828: //
829:
830: status = StCreateRequest (
831: Irp, // IRP for this request.
832: connection, // context.
833: REQUEST_FLAGS_CONNECTION, // partial flags.
834: NULL,
835: 0,
836: timeout, // timeout value (can be 0).
837: &tpRequest);
838:
839:
840: if (!NT_SUCCESS (status)) { // couldn't make the request.
841:
842: StDereferenceConnection ("For create", connection);
843: return status; // return with failure.
844: }
845:
846: // Reference the connection since StDestroyRequest derefs it.
847:
848: IoAcquireCancelSpinLock (&cancelirql);
849: ACQUIRE_SPIN_LOCK (&connection->SpinLock, &oldirql);
850: tpRequest->Owner = ConnectionType;
851:
852: StReferenceConnection("For listen request", connection);
853:
854: if ((connection->Flags & CONNECTION_FLAGS_STOPPING) != 0) {
855:
856: RELEASE_SPIN_LOCK (&connection->SpinLock,oldirql);
857: IoReleaseCancelSpinLock(cancelirql);
858:
859: StCompleteRequest (
860: tpRequest,
861: connection->Status,
862: 0);
863: StDereferenceConnection("Temp create", connection);
864: return STATUS_PENDING;
865:
866: } else {
867:
868: InsertTailList (&connection->InProgressRequest,&tpRequest->Linkage);
869: connection->Flags |= CONNECTION_FLAGS_LISTENER | // we're the passive one.
870: CONNECTION_FLAGS_WAIT_LISTEN; // waiting for a connect
871: connection->Flags2 &= ~CONNECTION_FLAGS2_INDICATING;
872: connection->Flags &= ~CONNECTION_FLAGS_STOPPING;
873: connection->Status = STATUS_PENDING;
874:
875: //
876: // If TDI_QUERY_ACCEPT is not set, then we set PRE_ACCEPT to
877: // indicate that when the listen completes we do not have to
878: // wait for a TDI_ACCEPT to continue.
879: //
880:
881: if ((parameters->RequestFlags & TDI_QUERY_ACCEPT) == 0) {
882: connection->Flags2 |= CONNECTION_FLAGS2_PRE_ACCEPT;
883: }
884:
885: RELEASE_SPIN_LOCK (&connection->SpinLock,oldirql);
886:
887: //
888: // Check if the IRP has been cancelled.
889: //
890:
891: if (Irp->Cancel) {
892: Irp->CancelIrql = cancelirql;
893: StCancelConnection((PDEVICE_OBJECT)(connection->Provider), Irp);
894: StDereferenceConnection ("IRP cancelled", connection); // release lookup hold.
895: return STATUS_PENDING;
896: }
897:
898: Irp->CancelRoutine = StCancelConnection;
899: IoReleaseCancelSpinLock(cancelirql);
900:
901: }
902:
903: //
904: // Wait for an incoming NAME_QUERY frame. The remainder of the
905: // connectionless protocol to set up a connection is processed
906: // in the NAME_QUERY frame handler.
907: //
908:
909: StDereferenceConnection("Temp create", connection);
910:
911: return STATUS_PENDING; // things are started.
912: } /* TdiListen */
913:
914:
915: NTSTATUS
916: StOpenConnection (
917: IN PDEVICE_OBJECT DeviceObject,
918: IN PIRP Irp,
919: IN PIO_STACK_LOCATION IrpSp
920: )
921:
922: /*++
923:
924: Routine Description:
925:
926: This routine is called to open a connection. Note that the connection that
927: is open is of little use until associated with an address; until then,
928: the only thing that can be done with it is close it.
929:
930: Arguments:
931:
932: DeviceObject - Pointer to the device object for this driver.
933:
934: Irp - Pointer to the request packet representing the I/O request.
935:
936: IrpSp - Pointer to current IRP stack frame.
937:
938: Return Value:
939:
940: The function value is the status of the operation.
941:
942: --*/
943:
944: {
945: PDEVICE_CONTEXT DeviceContext;
946: NTSTATUS status;
947: PTP_CONNECTION connection;
948: PFILE_FULL_EA_INFORMATION ea;
949:
950: UNREFERENCED_PARAMETER (Irp);
951:
952: DeviceContext = (PDEVICE_CONTEXT)DeviceObject;
953:
954: //
955: // First, try to make a connection object to represent this pending
956: // connection. Then fill in the relevant fields.
957: // In addition to the creation, if successful StCreateConnection
958: // will create a second reference which is removed once the request
959: // references the connection, or if the function exits before that.
960:
961: status = StCreateConnection (DeviceContext, &connection);
962: if (!NT_SUCCESS (status)) {
963: return status; // sorry, we couldn't make one.
964: }
965:
966: //
967: // set the connection context so we can connect the user to this data
968: // structure
969: //
970:
971: ea = (PFILE_FULL_EA_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
972: RtlCopyMemory (
973: &connection->Context,
974: &ea->EaName[ea->EaNameLength+1],
975: sizeof (PVOID));
976:
977: //
978: // let file object point at connection and connection at file object
979: //
980:
981: IrpSp->FileObject->FsContext = (PVOID)connection;
982: IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONNECTION_FILE;
983: connection->FileObject = IrpSp->FileObject;
984:
985: return status;
986:
987: } /* StOpenConnection */
988:
989:
990: NTSTATUS
991: StCloseConnection (
992: IN PDEVICE_OBJECT DeviceObject,
993: IN PIRP Irp,
994: IN PIO_STACK_LOCATION IrpSp
995: )
996:
997: /*++
998:
999: Routine Description:
1000:
1001: This routine is called to close a connection. There may be actions in
1002: progress on this connection, so we note the closing IRP, mark the
1003: connection as closing, and complete it somewhere down the road (when all
1004: references have been removed).
1005:
1006: Arguments:
1007:
1008: DeviceObject - Pointer to the device object for this driver.
1009:
1010: Irp - Pointer to the request packet representing the I/O request.
1011:
1012: IrpSp - Pointer to current IRP stack frame.
1013:
1014: Return Value:
1015:
1016: The function value is the status of the operation.
1017:
1018: --*/
1019:
1020: {
1021: NTSTATUS status;
1022: KIRQL oldirql;
1023: PTP_CONNECTION connection;
1024:
1025: UNREFERENCED_PARAMETER (DeviceObject);
1026: UNREFERENCED_PARAMETER (Irp);
1027:
1028: //
1029: // is the file object a connection?
1030: //
1031:
1032: connection = IrpSp->FileObject->FsContext;
1033:
1034:
1035: //
1036: // We duplicate the code from VerifyConnectionObject,
1037: // although we don't actually call that since it does
1038: // a reference, which we don't want (to avoid bouncing
1039: // the reference count up from 0 if this is a dead
1040: // link).
1041: //
1042:
1043: try {
1044:
1045: if ((connection->Size == sizeof (TP_CONNECTION)) &&
1046: (connection->Type == ST_CONNECTION_SIGNATURE)) {
1047:
1048: ACQUIRE_SPIN_LOCK (&connection->SpinLock, &oldirql);
1049:
1050: if ((connection->Flags2 & CONNECTION_FLAGS2_CLOSING) == 0) {
1051:
1052: status = STATUS_SUCCESS;
1053:
1054: } else {
1055:
1056: status = STATUS_INVALID_CONNECTION;
1057: }
1058:
1059: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql);
1060:
1061: } else {
1062:
1063: status = STATUS_INVALID_CONNECTION;
1064: }
1065:
1066: } except(EXCEPTION_EXECUTE_HANDLER) {
1067:
1068: return GetExceptionCode();
1069: }
1070:
1071: if (!NT_SUCCESS (status)) {
1072: return status;
1073: }
1074:
1075: //
1076: // We recognize it; is it closing already?
1077: //
1078:
1079: ACQUIRE_SPIN_LOCK (&connection->SpinLock, &oldirql);
1080:
1081: if ((connection->Flags2 & CONNECTION_FLAGS2_CLOSING) != 0) {
1082: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql);
1083: StDereferenceConnection("Temp Close", connection);
1084: return STATUS_INVALID_CONNECTION;
1085: }
1086:
1087: connection->Flags2 |= CONNECTION_FLAGS2_CLOSING;
1088:
1089: //
1090: // if there is activity on the connection, tear it down.
1091: //
1092:
1093: if ((connection->Flags & CONNECTION_FLAGS_STOPPING) == 0) {
1094: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql);
1095: StStopConnection (connection, STATUS_LOCAL_DISCONNECT);
1096: ACQUIRE_SPIN_LOCK (&connection->SpinLock, &oldirql);
1097: }
1098:
1099: //
1100: // If the connection is still associated, disassociate it.
1101: //
1102:
1103: if ((connection->Flags2 & CONNECTION_FLAGS2_ASSOCIATED) &&
1104: ((connection->Flags2 & CONNECTION_FLAGS2_DISASSOCIATED) == 0)) {
1105: connection->Flags2 |= CONNECTION_FLAGS2_DISASSOCIATED;
1106: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql);
1107: } else {
1108: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql);
1109: }
1110:
1111:
1112: //
1113: // Save this to complete the IRP later.
1114: //
1115:
1116: connection->CloseIrp = Irp;
1117:
1118: //
1119: // make it impossible to use this connection from the file object
1120: //
1121:
1122: IrpSp->FileObject->FsContext = NULL;
1123: IrpSp->FileObject->FsContext2 = NULL;
1124: connection->FileObject = NULL;
1125:
1126: //
1127: // dereference for the creation. Note that this dereference
1128: // here won't have any effect until the regular reference count
1129: // hits zero.
1130: //
1131:
1132: StDereferenceConnectionSpecial (" Closing Connection", connection);
1133:
1134: return STATUS_PENDING;
1135:
1136: } /* StCloseConnection */
1137:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.