|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1989-1993 Microsoft Corporation
4:
5: Module Name:
6:
7: address.c
8:
9: Abstract:
10:
11: This module contains code which implements the TP_ADDRESS object.
12: Routines are provided to create, destroy, reference, and dereference,
13: transport address objects.
14:
15: Environment:
16:
17: Kernel mode
18:
19: Revision History:
20:
21: --*/
22:
23: #include "st.h"
24:
25:
26: //
27: // Map all generic accesses to the same one.
28: //
29:
30: STATIC GENERIC_MAPPING AddressGenericMapping =
31: { READ_CONTROL, READ_CONTROL, READ_CONTROL, READ_CONTROL };
32:
33:
34: NTSTATUS
35: StOpenAddress(
36: IN PDEVICE_OBJECT DeviceObject,
37: IN PIRP Irp,
38: IN PIO_STACK_LOCATION IrpSp
39: )
40:
41: /*++
42:
43: Routine Description:
44:
45: This routine opens a file that points to an existing address object, or, if
46: the object doesn't exist, creates it (note that creation of the address
47: object includes registering the address, and may take many seconds to
48: complete, depending upon system configuration).
49:
50: If the address already exists, and it has an ACL associated with it, the
51: ACL is checked for access rights before allowing creation of the address.
52:
53: Arguments:
54:
55: DeviceObject - pointer to the device object describing the ST transport.
56:
57: Irp - a pointer to the Irp used for the creation of the address.
58:
59: IrpSp - a pointer to the Irp stack location.
60:
61: Return Value:
62:
63: NTSTATUS - status of operation.
64:
65: --*/
66:
67: {
68: PDEVICE_CONTEXT DeviceContext;
69: NTSTATUS status;
70: PTP_ADDRESS address;
71: PTP_ADDRESS_FILE addressFile;
72: PST_NETBIOS_ADDRESS networkName; // Network name string.
73: PFILE_FULL_EA_INFORMATION ea;
74: TRANSPORT_ADDRESS UNALIGNED *name;
75: TA_ADDRESS UNALIGNED *addressName;
76: TDI_ADDRESS_NETBIOS UNALIGNED *netbiosName;
77: ULONG DesiredShareAccess;
78: KIRQL oldirql;
79: PACCESS_STATE AccessState;
80: ACCESS_MASK GrantedAccess;
81: BOOLEAN AccessAllowed;
82: int i;
83: BOOLEAN found = FALSE;
84:
85: DeviceContext = (PDEVICE_CONTEXT)DeviceObject;
86:
87: //
88: // The network name is in the EA, passed in AssociatedIrp.SystemBuffer
89: //
90:
91: ea = (PFILE_FULL_EA_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
92: if (ea == NULL) {
93: StPrint1("OpenAddress: IRP %lx has no EA\n", Irp);
94: return STATUS_NONEXISTENT_EA_ENTRY;
95: }
96:
97: //
98: // this may be a valid name; parse the name from the EA and use it if OK.
99: //
100:
101: name = (PTRANSPORT_ADDRESS)&ea->EaName[ea->EaNameLength+1];
102: addressName = (PTA_ADDRESS)&name->Address[0];
103:
104: //
105: // The name can be passed with multiple entries; we'll take and use only
106: // the first one.
107: //
108:
109: for (i=0;i<name->TAAddressCount;i++) {
110: if (addressName->AddressType == TDI_ADDRESS_TYPE_NETBIOS) {
111: if (addressName->AddressLength != 0) {
112: netbiosName = (PTDI_ADDRESS_NETBIOS)&addressName->Address[0];
113: networkName = (PST_NETBIOS_ADDRESS)ExAllocatePool (
114: NonPagedPool,
115: sizeof (ST_NETBIOS_ADDRESS));
116: if (networkName == NULL) {
117: PANIC ("StOpenAddress: PANIC! could not allocate networkName!\n");
118: StWriteResourceErrorLog (DeviceContext, sizeof(TA_NETBIOS_ADDRESS), 1);
119: return STATUS_INSUFFICIENT_RESOURCES;
120: }
121:
122: //
123: // get the name to local storage
124: //
125:
126: if ((netbiosName->NetbiosNameType == TDI_ADDRESS_NETBIOS_TYPE_GROUP) ||
127: (netbiosName->NetbiosNameType == TDI_ADDRESS_NETBIOS_TYPE_QUICK_GROUP)) {
128: networkName->NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_GROUP;
129: } else {
130: networkName->NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
131: }
132: RtlCopyMemory (networkName->NetbiosName, netbiosName->NetbiosName, 16);
133:
134: found = TRUE;
135: } else {
136: networkName = NULL;
137: found = TRUE;
138: }
139:
140: break;
141:
142: } else {
143:
144: addressName = (PTA_ADDRESS)(addressName->Address +
145: addressName->AddressLength);
146:
147: }
148:
149: }
150:
151: if (!found) {
152: StPrint1("OpenAddress: IRP %lx has no NETBIOS address\n", Irp);
153: return STATUS_NONEXISTENT_EA_ENTRY;
154: }
155:
156: //
157: // get an address file structure to represent this address.
158: //
159:
160: status = StCreateAddressFile (DeviceContext, &addressFile);
161:
162: if (!NT_SUCCESS (status)) {
163: return status;
164: }
165:
166: //
167: // See if this address is already established. This call automatically
168: // increments the reference count on the address so that it won't disappear
169: // from underneath us after this call but before we have a chance to use it.
170: //
171: // To ensure that we don't create two address objects for the
172: // same address, we hold the device context AddressResource until
173: // we have found the address or created a new one.
174: //
175:
176: ExAcquireResourceExclusive (&DeviceContext->AddressResource, TRUE);
177:
178: ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
179:
180: address = StLookupAddress (DeviceContext, networkName);
181:
182: if (address == NULL) {
183:
184: RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
185:
186: //
187: // This address doesn't exist. Create it, and start the process of
188: // registering it.
189: //
190:
191: status = StCreateAddress (
192: DeviceContext,
193: networkName,
194: &address);
195:
196: if (NT_SUCCESS (status)) {
197:
198: //
199: // Initialize the shared access now. We use read access
200: // to control all access.
201: //
202:
203: DesiredShareAccess = (ULONG)
204: (((IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_READ) ||
205: (IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_WRITE)) ?
206: FILE_SHARE_READ : 0);
207:
208: IoSetShareAccess(
209: FILE_READ_DATA,
210: DesiredShareAccess,
211: IrpSp->FileObject,
212: &address->ShareAccess);
213:
214:
215: //
216: // Assign the security descriptor (need to do this with
217: // the spinlock released because the descriptor is not
218: // mapped. BUGBUG: Need to synchronize Assign and Access).
219: //
220:
221: AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
222:
223: status = SeAssignSecurity(
224: NULL, // parent descriptor
225: AccessState->SecurityDescriptor,
226: &address->SecurityDescriptor,
227: FALSE, // is directory
228: &AccessState->SubjectSecurityContext,
229: &AddressGenericMapping,
230: NonPagedPool);
231:
232: if (!NT_SUCCESS(status)) {
233:
234: //
235: // Error, return status.
236: //
237:
238: IoRemoveShareAccess (IrpSp->FileObject, &address->ShareAccess);
239: ExReleaseResource (&DeviceContext->AddressResource);
240: StDereferenceAddress ("Device context stopping", address);
241: StDereferenceAddressFile (addressFile);
242: return status;
243:
244: }
245:
246: ExReleaseResource (&DeviceContext->AddressResource);
247:
248: //
249: // if the adapter isn't ready, we can't do any of this; get out
250: //
251:
252: if (DeviceContext->State == DEVICECONTEXT_STATE_STOPPING) {
253: StDereferenceAddress ("Device context stopping", address);
254: StDereferenceAddressFile (addressFile);
255: status = STATUS_DEVICE_NOT_READY;
256:
257: } else {
258:
259: IrpSp->FileObject->FsContext = (PVOID)addressFile;
260: IrpSp->FileObject->FsContext2 =
261: (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
262: addressFile->FileObject = IrpSp->FileObject;
263: addressFile->Irp = Irp;
264: addressFile->Address = address;
265:
266: ACQUIRE_SPIN_LOCK (&address->SpinLock, &oldirql);
267: InsertTailList (&address->AddressFileDatabase, &addressFile->Linkage);
268: RELEASE_SPIN_LOCK (&address->SpinLock, oldirql);
269:
270:
271: //
272: // Begin address registration unless this is the broadcast
273: // address (which is a "fake" address with no corresponding
274: // Netbios address) or the reserved address, which we know
275: // is unique since it is based on the adapter address.
276: //
277:
278: if ((networkName != NULL) &&
279: (RtlCompareMemory (networkName->NetbiosName,
280: DeviceContext->ReservedNetBIOSAddress,
281: NETBIOS_NAME_LENGTH) < NETBIOS_NAME_LENGTH)) {
282:
283: StRegisterAddress (address); // begin address registration.
284: status = STATUS_PENDING;
285:
286: } else {
287:
288: address->Flags &= ~ADDRESS_FLAGS_NEEDS_REG;
289: addressFile->Irp = NULL;
290: addressFile->State = ADDRESSFILE_STATE_OPEN;
291: status = STATUS_SUCCESS;
292:
293: }
294:
295: }
296:
297: } else {
298:
299: ExReleaseResource (&DeviceContext->AddressResource);
300:
301: //
302: // If the address could not be created, and is not in the process of
303: // being created, then we can't open up an address.
304: //
305:
306: if (networkName != NULL) {
307: ExFreePool (networkName);
308: }
309:
310: StDereferenceAddressFile (addressFile);
311:
312: }
313:
314: } else {
315:
316: RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
317:
318: //
319: // The address already exists. Check the ACL and see if we
320: // can access it. If so, simply use this address as our address.
321: //
322:
323: AccessState = IrpSp->Parameters.Create.SecurityContext->AccessState;
324:
325: AccessAllowed = SeAccessCheck(
326: address->SecurityDescriptor,
327: &AccessState->SubjectSecurityContext,
328: FALSE, // tokens locked
329: IrpSp->Parameters.Create.SecurityContext->DesiredAccess,
330: (ACCESS_MASK)0, // previously granted
331: NULL, // privileges
332: &AddressGenericMapping,
333: Irp->RequestorMode,
334: &GrantedAccess,
335: &status);
336:
337: if (AccessAllowed) {
338:
339: //
340: // Access was successful, make sure Status is right.
341: //
342:
343: status = STATUS_SUCCESS;
344:
345: //
346: // Check that the name is of the correct type (unique vs. group)
347: // We don't need to check this for the broadcast address.
348: //
349:
350: if (networkName != NULL) {
351: if (address->NetworkName->NetbiosNameType !=
352: networkName->NetbiosNameType) {
353:
354: status = STATUS_DUPLICATE_NAME;
355:
356: }
357: }
358:
359: }
360:
361:
362: if (!NT_SUCCESS (status)) {
363:
364: ExReleaseResource (&DeviceContext->AddressResource);
365:
366: StDereferenceAddressFile (addressFile);
367:
368: } else {
369:
370: //
371: // Now check that we can obtain the desired share
372: // access. We use read access to control all access.
373: //
374:
375: DesiredShareAccess = (ULONG)
376: (((IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_READ) ||
377: (IrpSp->Parameters.Create.ShareAccess & FILE_SHARE_WRITE)) ?
378: FILE_SHARE_READ : 0);
379:
380: status = IoCheckShareAccess(
381: FILE_READ_DATA,
382: DesiredShareAccess,
383: IrpSp->FileObject,
384: &address->ShareAccess,
385: TRUE);
386:
387: if (!NT_SUCCESS (status)) {
388:
389: ExReleaseResource (&DeviceContext->AddressResource);
390:
391: StDereferenceAddressFile (addressFile);
392:
393: } else {
394:
395: ExReleaseResource (&DeviceContext->AddressResource);
396:
397: ACQUIRE_SPIN_LOCK (&address->SpinLock, &oldirql);
398:
399: //
400: // now, if the address registered, we simply return success after
401: // pointing the file object at the address file (which points to
402: // the address). If the address registration is pending, we mark
403: // the registration pending and let the registration completion
404: // routine complete the open. If the address is bad, we simply
405: // fail the open.
406: //
407:
408: if ((address->Flags &
409: (ADDRESS_FLAGS_CONFLICT |
410: ADDRESS_FLAGS_REGISTERING |
411: ADDRESS_FLAGS_DEREGISTERING |
412: ADDRESS_FLAGS_DUPLICATE_NAME |
413: ADDRESS_FLAGS_NEEDS_REG |
414: ADDRESS_FLAGS_STOPPING |
415: ADDRESS_FLAGS_BAD_ADDRESS |
416: ADDRESS_FLAGS_CLOSED)) == 0) {
417:
418: InsertTailList (
419: &address->AddressFileDatabase,
420: &addressFile->Linkage);
421:
422: addressFile->Irp = NULL;
423: addressFile->Address = address;
424: addressFile->FileObject = IrpSp->FileObject;
425: addressFile->State = ADDRESSFILE_STATE_OPEN;
426:
427: StReferenceAddress("open ready", address);
428:
429: IrpSp->FileObject->FsContext = (PVOID)addressFile;
430: IrpSp->FileObject->FsContext2 =
431: (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
432:
433: RELEASE_SPIN_LOCK (&address->SpinLock, oldirql);
434:
435: status = STATUS_SUCCESS;
436:
437: } else {
438:
439: //
440: // if the address is still registering, make the open pending.
441: //
442:
443: if ((address->Flags & (ADDRESS_FLAGS_REGISTERING | ADDRESS_FLAGS_NEEDS_REG)) != 0) {
444:
445: InsertTailList (
446: &address->AddressFileDatabase,
447: &addressFile->Linkage);
448:
449: addressFile->Irp = Irp;
450: addressFile->Address = address;
451: addressFile->FileObject = IrpSp->FileObject;
452:
453: StReferenceAddress("open registering", address);
454:
455: IrpSp->FileObject->FsContext = (PVOID)addressFile;
456: IrpSp->FileObject->FsContext2 =
457: (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
458:
459: RELEASE_SPIN_LOCK (&address->SpinLock, oldirql);
460:
461: status = STATUS_PENDING;
462:
463: } else {
464:
465: RELEASE_SPIN_LOCK (&address->SpinLock, oldirql);
466:
467: StDereferenceAddressFile (addressFile);
468:
469: status = STATUS_DRIVER_INTERNAL_ERROR;
470:
471: }
472: }
473: }
474: }
475:
476: //
477: // Remove the reference from StLookupAddress.
478: //
479:
480: StDereferenceAddress ("Done opening", address);
481: }
482:
483: return status;
484: } /* StOpenAddress */
485:
486:
487: VOID
488: StAllocateAddress(
489: IN PDEVICE_CONTEXT DeviceContext,
490: OUT PTP_ADDRESS *TransportAddress
491: )
492:
493: /*++
494:
495: Routine Description:
496:
497: This routine allocates storage for a transport address. Some minimal
498: initialization is done on the address.
499:
500: NOTE: This routine is called with the device context spinlock
501: held, or at such a time as synchronization is unnecessary.
502:
503: Arguments:
504:
505: DeviceContext - Pointer to the device context (which is really just
506: the device object with its extension) to be associated with the
507: address.
508:
509: Address - Pointer to a place where this routine will return a pointer
510: to a transport address structure. Returns NULL if no storage
511: can be allocated.
512:
513: Return Value:
514:
515: None.
516:
517: --*/
518:
519: {
520: PTP_ADDRESS Address;
521: PSEND_PACKET_TAG SendTag;
522:
523: if ((DeviceContext->MemoryLimit != 0) &&
524: ((DeviceContext->MemoryUsage + sizeof(TP_ADDRESS)) >
525: DeviceContext->MemoryLimit)) {
526: PANIC("ST: Could not allocate address: limit\n");
527: StWriteResourceErrorLog (DeviceContext, sizeof(TP_ADDRESS), 101);
528: *TransportAddress = NULL;
529: return;
530: }
531:
532: Address = (PTP_ADDRESS)ExAllocatePool (NonPagedPool, sizeof (TP_ADDRESS));
533: if (Address == NULL) {
534: PANIC("ST: Could not allocate address: no pool\n");
535: StWriteResourceErrorLog (DeviceContext, sizeof(TP_ADDRESS), 201);
536: *TransportAddress = NULL;
537: return;
538: }
539: RtlZeroMemory (Address, sizeof(TP_ADDRESS));
540:
541: DeviceContext->MemoryUsage += sizeof(TP_ADDRESS);
542: ++DeviceContext->AddressAllocated;
543:
544: StAllocateSendPacket (DeviceContext, &(Address->Packet));
545: if (Address->Packet == NULL) {
546: ExFreePool (Address);
547: *TransportAddress = NULL;
548: return;
549: }
550: --DeviceContext->PacketAllocated; // AllocatePacket added one
551:
552: //
553: // Need to modify the address packets to belong to
554: // the address, not the device context.
555: //
556:
557: SendTag = (PSEND_PACKET_TAG)(Address->Packet->NdisPacket->ProtocolReserved);
558: SendTag->Type = TYPE_G_FRAME;
559: SendTag->Packet = Address->Packet;
560: SendTag->Owner = (PVOID)Address;
561:
562:
563: Address->Type = ST_ADDRESS_SIGNATURE;
564: Address->Size = sizeof (TP_ADDRESS);
565:
566: Address->Provider = DeviceContext;
567: KeInitializeSpinLock (&Address->SpinLock);
568:
569: InitializeListHead (&Address->ConnectionDatabase);
570: InitializeListHead (&Address->AddressFileDatabase);
571: InitializeListHead (&Address->SendDatagramQueue);
572:
573: //
574: // For each address, allocate a receive packet, a receive buffer,
575: // and a UI frame.
576: //
577:
578: StAddReceivePacket (DeviceContext);
579: StAddReceiveBuffer (DeviceContext);
580:
581: *TransportAddress = Address;
582:
583: } /* StAllocateAddress */
584:
585:
586: VOID
587: StDeallocateAddress(
588: IN PDEVICE_CONTEXT DeviceContext,
589: IN PTP_ADDRESS TransportAddress
590: )
591:
592: /*++
593:
594: Routine Description:
595:
596: This routine frees storage for a transport address.
597:
598: NOTE: This routine is called with the device context spinlock
599: held, or at such a time as synchronization is unnecessary.
600:
601: Arguments:
602:
603: DeviceContext - Pointer to the device context (which is really just
604: the device object with its extension) to be associated with the
605: address.
606:
607: Address - Pointer to a transport address structure.
608:
609: Return Value:
610:
611: None.
612:
613: --*/
614:
615: {
616:
617: if (TransportAddress->NetworkName != NULL) {
618: ExFreePool (TransportAddress->NetworkName);
619: }
620: StDeallocateSendPacket (DeviceContext, TransportAddress->Packet);
621: ++DeviceContext->PacketAllocated;
622:
623: ExFreePool (TransportAddress);
624: --DeviceContext->AddressAllocated;
625: DeviceContext->MemoryUsage -= sizeof(TP_ADDRESS);
626:
627: //
628: // Remove the resources which allocating this caused.
629: //
630:
631: StRemoveReceivePacket (DeviceContext);
632: StRemoveReceiveBuffer (DeviceContext);
633:
634: } /* StDeallocateAddress */
635:
636:
637: NTSTATUS
638: StCreateAddress(
639: IN PDEVICE_CONTEXT DeviceContext,
640: IN PST_NETBIOS_ADDRESS NetworkName,
641: OUT PTP_ADDRESS *Address
642: )
643:
644: /*++
645:
646: Routine Description:
647:
648: This routine creates a transport address and associates it with
649: the specified transport device context. The reference count in the
650: address is automatically set to 1, and the reference count of the
651: device context is incremented.
652:
653: NOTE: This routine must be called with the DeviceContext
654: spinlock held.
655:
656: Arguments:
657:
658: DeviceContext - Pointer to the device context (which is really just
659: the device object with its extension) to be associated with the
660: address.
661:
662: NetworkName - Pointer to an ST_NETBIOS_ADDRESS type containing the network
663: name to be associated with this address, if any.
664:
665: Address - Pointer to a place where this routine will return a pointer
666: to a transport address structure.
667:
668: Return Value:
669:
670: NTSTATUS - status of operation.
671:
672: --*/
673:
674: {
675: PTP_ADDRESS pAddress;
676: PLIST_ENTRY p;
677:
678:
679: p = RemoveHeadList (&DeviceContext->AddressPool);
680: if (p == &DeviceContext->AddressPool) {
681:
682: if ((DeviceContext->AddressMaxAllocated == 0) ||
683: (DeviceContext->AddressAllocated < DeviceContext->AddressMaxAllocated)) {
684:
685: StAllocateAddress (DeviceContext, &pAddress);
686:
687: } else {
688:
689: StWriteResourceErrorLog (DeviceContext, sizeof(TP_ADDRESS), 401);
690: pAddress = NULL;
691:
692: }
693:
694: if (pAddress == NULL) {
695: ++DeviceContext->AddressExhausted;
696: PANIC ("StCreateConnection: Could not allocate address object!\n");
697: return STATUS_INSUFFICIENT_RESOURCES;
698: }
699:
700: } else {
701:
702: pAddress = CONTAINING_RECORD (p, TP_ADDRESS, Linkage);
703:
704: }
705:
706: ++DeviceContext->AddressInUse;
707: if (DeviceContext->AddressInUse > DeviceContext->AddressMaxInUse) {
708: ++DeviceContext->AddressMaxInUse;
709: }
710:
711: DeviceContext->AddressTotal += DeviceContext->AddressInUse;
712: ++DeviceContext->AddressSamples;
713:
714:
715: //
716: // Initialize all of the static data for this address.
717: //
718:
719: pAddress->ReferenceCount = 1;
720:
721: pAddress->Flags = ADDRESS_FLAGS_NEEDS_REG;
722: InitializeListHead (&pAddress->AddressFileDatabase);
723:
724: pAddress->NetworkName = NetworkName;
725: if ((NetworkName != (PST_NETBIOS_ADDRESS)NULL) &&
726: (NetworkName->NetbiosNameType ==
727: TDI_ADDRESS_NETBIOS_TYPE_GROUP)) {
728:
729: pAddress->Flags |= ADDRESS_FLAGS_GROUP;
730:
731: }
732:
733: //
734: // Now link this address into the specified device context's
735: // address database. To do this, we need to acquire the spin lock
736: // on the device context.
737: //
738:
739: InsertTailList (&DeviceContext->AddressDatabase, &pAddress->Linkage);
740: pAddress->Provider = DeviceContext;
741: StReferenceDeviceContext ("Create Address", DeviceContext); // count refs to the device context.
742:
743: *Address = pAddress; // return the address.
744: return STATUS_SUCCESS; // not finished yet.
745: } /* StCreateAddress */
746:
747:
748: VOID
749: StRegisterAddress(
750: PTP_ADDRESS Address
751: )
752:
753: /*++
754:
755: Routine Description:
756:
757: This routine starts the registration process of the transport address
758: specified, if it has not already been started.
759:
760: Arguments:
761:
762: Address - Pointer to a transport address object to begin registering
763: on the network.
764:
765: Return Value:
766:
767: NTSTATUS - status of operation.
768:
769: --*/
770:
771: {
772: KIRQL oldirql;
773: PLIST_ENTRY p;
774: PIRP irp;
775: PTP_ADDRESS_FILE addressFile;
776:
777: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
778: if (!(Address->Flags & ADDRESS_FLAGS_NEEDS_REG)) {
779: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
780:
781: return;
782: }
783:
784: Address->Flags &= ~ADDRESS_FLAGS_NEEDS_REG;
785: Address->Flags |= ADDRESS_FLAGS_REGISTERING;
786:
787: //
788: // Keep a reference on this address until the registration process
789: // completes or is aborted. It will be aborted in UFRAMES.C, in
790: // either the NAME_IN_CONFLICT or ADD_NAME_RESPONSE frame handlers.
791: //
792:
793: StReferenceAddress ("start registration", Address);
794: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
795:
796: //
797: // Normally we would add the name on the network, then
798: // do the following in our timeout logic, but for ST
799: // we assume that all names are OK.
800: //
801:
802: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
803: Address->Flags &= ~ADDRESS_FLAGS_REGISTERING;
804:
805: p = Address->AddressFileDatabase.Flink;
806:
807: while (p != &Address->AddressFileDatabase) {
808: addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage);
809: p = p->Flink;
810:
811: if (addressFile->Irp != NULL) {
812: irp = addressFile->Irp;
813: addressFile->Irp = NULL;
814: addressFile->State = ADDRESSFILE_STATE_OPEN;
815: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
816: irp->IoStatus.Information = 0;
817: irp->IoStatus.Status = STATUS_SUCCESS;
818:
819: IoCompleteRequest (irp, IO_NETWORK_INCREMENT);
820:
821: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
822: }
823:
824: }
825:
826: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
827:
828: //
829: // Dereference the address if we're all done.
830: //
831:
832: StDereferenceAddress ("Timer, registered", Address);
833:
834: } /* StRegisterAddress */
835:
836:
837: NTSTATUS
838: StVerifyAddressObject (
839: IN PTP_ADDRESS_FILE AddressFile
840: )
841:
842: /*++
843:
844: Routine Description:
845:
846: This routine is called to verify that the pointer given us in a file
847: object is in fact a valid address file object. We also verify that the
848: address object pointed to by it is a valid address object, and reference
849: it to keep it from disappearing while we use it.
850:
851: Arguments:
852:
853: AddressFile - potential pointer to a TP_ADDRESS_FILE object
854:
855: Return Value:
856:
857: STATUS_SUCCESS if all is well; STATUS_INVALID_ADDRESS otherwise
858:
859: --*/
860:
861: {
862: KIRQL oldirql;
863: NTSTATUS status = STATUS_SUCCESS;
864: PTP_ADDRESS address;
865:
866: //
867: // try to verify the address file signature. If the signature is valid,
868: // verify the address pointed to by it and get the address spinlock.
869: // check the address's state, and increment the reference count if it's
870: // ok to use it. Note that the only time we return an error for state is
871: // if the address is closing.
872: //
873:
874: try {
875:
876: if ((AddressFile->Size == sizeof (TP_ADDRESS_FILE)) &&
877: (AddressFile->Type == ST_ADDRESSFILE_SIGNATURE) ) {
878: // (AddressFile->State != ADDRESSFILE_STATE_CLOSING) ) {
879:
880: address = AddressFile->Address;
881:
882: if ((address->Size == sizeof (TP_ADDRESS)) &&
883: (address->Type == ST_ADDRESS_SIGNATURE) ) {
884:
885: ACQUIRE_SPIN_LOCK (&address->SpinLock, &oldirql);
886:
887: if ((address->Flags & ADDRESS_FLAGS_STOPPING) == 0) {
888:
889: StReferenceAddress ("verify", address);
890:
891: } else {
892:
893: StPrint1("StVerifyAddress: A %lx closing\n", address);
894: status = STATUS_INVALID_ADDRESS;
895: }
896:
897: RELEASE_SPIN_LOCK (&address->SpinLock, oldirql);
898:
899: } else {
900:
901: StPrint1("StVerifyAddress: A %lx bad signature\n", address);
902: status = STATUS_INVALID_ADDRESS;
903: }
904:
905: } else {
906:
907: StPrint1("StVerifyAddress: AF %lx bad signature\n", AddressFile);
908: status = STATUS_INVALID_ADDRESS;
909: }
910:
911: } except(EXCEPTION_EXECUTE_HANDLER) {
912:
913: StPrint1("StVerifyAddress: AF %lx exception\n", address);
914: return GetExceptionCode();
915: }
916:
917: return status;
918:
919: }
920:
921: NTSTATUS
922: StDestroyAddress(
923: IN PTP_ADDRESS Address
924: )
925:
926: /*++
927:
928: Routine Description:
929:
930: This routine destroys a transport address and removes all references
931: made by it to other objects in the transport. The address structure
932: is returned to nonpaged system pool or our lookaside list. It is assumed
933: that the caller has already removed all addressfile structures associated
934: with this address.
935:
936: This routine is only called by StDerefAddress. The reason for
937: this is that there may be multiple streams of execution which are
938: simultaneously referencing the same address object, and it should
939: not be deleted out from under an interested stream of execution.
940:
941: Arguments:
942:
943: Address - Pointer to a transport address structure to be destroyed.
944:
945: Return Value:
946:
947: NTSTATUS - status of operation.
948:
949: --*/
950:
951: {
952: KIRQL oldirql;
953: PDEVICE_CONTEXT DeviceContext;
954:
955: DeviceContext = Address->Provider;
956:
957: SeDeassignSecurity (&Address->SecurityDescriptor);
958:
959: //
960: // Delink this address from its associated device context's address
961: // database. To do this we must spin lock on the device context object,
962: // not on the address.
963: //
964:
965: ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
966:
967: RemoveEntryList (&Address->Linkage);
968:
969: //
970: // Now we can deallocate the transport address object.
971: //
972:
973: DeviceContext->AddressTotal += DeviceContext->AddressInUse;
974: ++DeviceContext->AddressSamples;
975: --DeviceContext->AddressInUse;
976:
977: if ((DeviceContext->AddressAllocated - DeviceContext->AddressInUse) >
978: DeviceContext->AddressInitAllocated) {
979: StDeallocateAddress (DeviceContext, Address);
980: } else {
981: InsertTailList (&DeviceContext->AddressPool, &Address->Linkage);
982: }
983:
984: RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
985: StDereferenceDeviceContext ("Destroy Address", DeviceContext); // just housekeeping.
986:
987: return STATUS_SUCCESS;
988: } /* StDestroyAddress */
989:
990:
991: VOID
992: StRefAddress(
993: IN PTP_ADDRESS Address
994: )
995:
996: /*++
997:
998: Routine Description:
999:
1000: This routine increments the reference count on a transport address.
1001:
1002: Arguments:
1003:
1004: Address - Pointer to a transport address object.
1005:
1006: Return Value:
1007:
1008: none.
1009:
1010: --*/
1011:
1012: {
1013:
1014: ASSERT (Address->ReferenceCount > 0); // not perfect, but...
1015:
1016: (VOID)ExInterlockedIncrementLong (
1017: &Address->ReferenceCount,
1018: &Address->Provider->Interlock);
1019:
1020: } /* StRefAddress */
1021:
1022:
1023: VOID
1024: StDerefAddress(
1025: IN PTP_ADDRESS Address
1026: )
1027:
1028: /*++
1029:
1030: Routine Description:
1031:
1032: This routine dereferences a transport address by decrementing the
1033: reference count contained in the structure. If, after being
1034: decremented, the reference count is zero, then this routine calls
1035: StDestroyAddress to remove it from the system.
1036:
1037: Arguments:
1038:
1039: Address - Pointer to a transport address object.
1040:
1041: Return Value:
1042:
1043: none.
1044:
1045: --*/
1046:
1047: {
1048: INTERLOCKED_RESULT result;
1049:
1050: result = ExInterlockedDecrementLong (
1051: &Address->ReferenceCount,
1052: &Address->Provider->Interlock);
1053:
1054: //
1055: // If we have deleted all references to this address, then we can
1056: // destroy the object. It is okay to have already released the spin
1057: // lock at this point because there is no possible way that another
1058: // stream of execution has access to the address any longer.
1059: //
1060:
1061: ASSERT (result != ResultNegative);
1062:
1063: if (result == ResultZero) {
1064: StDestroyAddress (Address);
1065: }
1066: } /* StDerefAddress */
1067:
1068:
1069:
1070: VOID
1071: StAllocateAddressFile(
1072: IN PDEVICE_CONTEXT DeviceContext,
1073: OUT PTP_ADDRESS_FILE *TransportAddressFile
1074: )
1075:
1076: /*++
1077:
1078: Routine Description:
1079:
1080: This routine allocates storage for an address file. Some
1081: minimal initialization is done on the object.
1082:
1083: NOTE: This routine is called with the device context spinlock
1084: held, or at such a time as synchronization is unnecessary.
1085:
1086: Arguments:
1087:
1088: DeviceContext - Pointer to the device context (which is really just
1089: the device object with its extension) to be associated with the
1090: address.
1091:
1092: TransportAddressFile - Pointer to a place where this routine will return
1093: a pointer to a transport address file structure. It returns NULL if no
1094: storage can be allocated.
1095:
1096: Return Value:
1097:
1098: None.
1099:
1100: --*/
1101:
1102: {
1103:
1104: PTP_ADDRESS_FILE AddressFile;
1105:
1106: if ((DeviceContext->MemoryLimit != 0) &&
1107: ((DeviceContext->MemoryUsage + sizeof(TP_ADDRESS_FILE)) >
1108: DeviceContext->MemoryLimit)) {
1109: PANIC("ST: Could not allocate address file: limit\n");
1110: StWriteResourceErrorLog (DeviceContext, sizeof(TP_ADDRESS_FILE), 102);
1111: *TransportAddressFile = NULL;
1112: return;
1113: }
1114:
1115: AddressFile = (PTP_ADDRESS_FILE)ExAllocatePool (NonPagedPool, sizeof (TP_ADDRESS_FILE));
1116: if (AddressFile == NULL) {
1117: PANIC("ST: Could not allocate address file: no pool\n");
1118: StWriteResourceErrorLog (DeviceContext, sizeof(TP_ADDRESS_FILE), 202);
1119: *TransportAddressFile = NULL;
1120: return;
1121: }
1122: RtlZeroMemory (AddressFile, sizeof(TP_ADDRESS_FILE));
1123:
1124: DeviceContext->MemoryUsage += sizeof(TP_ADDRESS_FILE);
1125: ++DeviceContext->AddressFileAllocated;
1126:
1127: AddressFile->Type = ST_ADDRESSFILE_SIGNATURE;
1128: AddressFile->Size = sizeof (TP_ADDRESS_FILE);
1129:
1130: InitializeListHead (&AddressFile->ReceiveDatagramQueue);
1131: InitializeListHead (&AddressFile->ConnectionDatabase);
1132:
1133: *TransportAddressFile = AddressFile;
1134:
1135: } /* StAllocateAddressFile */
1136:
1137:
1138: VOID
1139: StDeallocateAddressFile(
1140: IN PDEVICE_CONTEXT DeviceContext,
1141: IN PTP_ADDRESS_FILE TransportAddressFile
1142: )
1143:
1144: /*++
1145:
1146: Routine Description:
1147:
1148: This routine frees storage for an address file.
1149:
1150: NOTE: This routine is called with the device context spinlock
1151: held, or at such a time as synchronization is unnecessary.
1152:
1153: Arguments:
1154:
1155: DeviceContext - Pointer to the device context (which is really just
1156: the device object with its extension) to be associated with the
1157: address.
1158:
1159: TransportAddressFile - Pointer to a transport address file structure.
1160:
1161: Return Value:
1162:
1163: None.
1164:
1165: --*/
1166:
1167: {
1168:
1169: ExFreePool (TransportAddressFile);
1170: --DeviceContext->AddressFileAllocated;
1171: DeviceContext->MemoryUsage -= sizeof(TP_ADDRESS_FILE);
1172:
1173: } /* StDeallocateAddressFile */
1174:
1175:
1176: NTSTATUS
1177: StCreateAddressFile(
1178: IN PDEVICE_CONTEXT DeviceContext,
1179: OUT PTP_ADDRESS_FILE * AddressFile
1180: )
1181:
1182: /*++
1183:
1184: Routine Description:
1185:
1186: This routine creates an address file from the pool of ther
1187: specified device context. The reference count in the
1188: address is automatically set to 1.
1189:
1190: Arguments:
1191:
1192: DeviceContext - Pointer to the device context (which is really just
1193: the device object with its extension) to be associated with the
1194: address.
1195:
1196: AddressFile - Pointer to a place where this routine will return a pointer
1197: to a transport address file structure.
1198:
1199: Return Value:
1200:
1201: NTSTATUS - status of operation.
1202:
1203: --*/
1204:
1205: {
1206: KIRQL oldirql;
1207: PLIST_ENTRY p;
1208: PTP_ADDRESS_FILE addressFile;
1209:
1210: ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
1211:
1212: p = RemoveHeadList (&DeviceContext->AddressFilePool);
1213: if (p == &DeviceContext->AddressFilePool) {
1214:
1215: if ((DeviceContext->AddressFileMaxAllocated == 0) ||
1216: (DeviceContext->AddressFileAllocated < DeviceContext->AddressFileMaxAllocated)) {
1217:
1218: StAllocateAddressFile (DeviceContext, &addressFile);
1219: } else {
1220:
1221: StWriteResourceErrorLog (DeviceContext, sizeof(TP_ADDRESS_FILE), 402);
1222: addressFile = NULL;
1223:
1224: }
1225:
1226: if (addressFile == NULL) {
1227: ++DeviceContext->AddressFileExhausted;
1228: RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
1229: PANIC ("StCreateConnection: Could not allocate address file object!\n");
1230: return STATUS_INSUFFICIENT_RESOURCES;
1231: }
1232:
1233: } else {
1234:
1235: addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage);
1236:
1237: }
1238:
1239: ++DeviceContext->AddressFileInUse;
1240: if (DeviceContext->AddressFileInUse > DeviceContext->AddressFileMaxInUse) {
1241: ++DeviceContext->AddressFileMaxInUse;
1242: }
1243:
1244: DeviceContext->AddressFileTotal += DeviceContext->AddressFileInUse;
1245: ++DeviceContext->AddressFileSamples;
1246:
1247: RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
1248:
1249:
1250: InitializeListHead (&addressFile->ConnectionDatabase);
1251: addressFile->Address = NULL;
1252: addressFile->FileObject = NULL;
1253: addressFile->Provider = DeviceContext;
1254: addressFile->State = ADDRESSFILE_STATE_OPENING;
1255: addressFile->ConnectIndicationInProgress = FALSE;
1256: addressFile->ReferenceCount = 1;
1257: addressFile->CloseIrp = (PIRP)NULL;
1258:
1259: //
1260: // Initialize the request handlers.
1261: //
1262:
1263: addressFile->RegisteredConnectionHandler = FALSE;
1264: addressFile->ConnectionHandler = TdiDefaultConnectHandler;
1265: addressFile->ConnectionHandlerContext = NULL;
1266: addressFile->RegisteredDisconnectHandler = FALSE;
1267: addressFile->DisconnectHandler = TdiDefaultDisconnectHandler;
1268: addressFile->DisconnectHandlerContext = NULL;
1269: addressFile->RegisteredReceiveHandler = FALSE;
1270: addressFile->ReceiveHandler = TdiDefaultReceiveHandler;
1271: addressFile->ReceiveHandlerContext = NULL;
1272: addressFile->RegisteredReceiveDatagramHandler = FALSE;
1273: addressFile->ReceiveDatagramHandler = TdiDefaultRcvDatagramHandler;
1274: addressFile->ReceiveDatagramHandlerContext = NULL;
1275: addressFile->RegisteredExpeditedDataHandler = FALSE;
1276: addressFile->ExpeditedDataHandler = TdiDefaultRcvExpeditedHandler;
1277: addressFile->ExpeditedDataHandlerContext = NULL;
1278: addressFile->RegisteredErrorHandler = FALSE;
1279: addressFile->ErrorHandler = TdiDefaultErrorHandler;
1280: addressFile->ErrorHandlerContext = NULL;
1281:
1282:
1283: *AddressFile = addressFile;
1284: return STATUS_SUCCESS;
1285:
1286: } /* StCreateAddress */
1287:
1288:
1289: NTSTATUS
1290: StDestroyAddressFile(
1291: IN PTP_ADDRESS_FILE AddressFile
1292: )
1293:
1294: /*++
1295:
1296: Routine Description:
1297:
1298: This routine destroys an address file and removes all references
1299: made by it to other objects in the transport.
1300:
1301: This routine is only called by StDereferenceAddressFile. The reason
1302: for this is that there may be multiple streams of execution which are
1303: simultaneously referencing the same address file object, and it should
1304: not be deleted out from under an interested stream of execution.
1305:
1306: Arguments:
1307:
1308: AddressFile Pointer to a transport address file structure to be destroyed.
1309:
1310: Return Value:
1311:
1312: NTSTATUS - status of operation.
1313:
1314: --*/
1315:
1316: {
1317: KIRQL oldirql, oldirql1;
1318: PTP_ADDRESS address;
1319: PDEVICE_CONTEXT DeviceContext;
1320: PIRP CloseIrp;
1321:
1322:
1323: address = AddressFile->Address;
1324: DeviceContext = AddressFile->Provider;
1325:
1326: if (address) {
1327:
1328: //
1329: // This addressfile was associated with an address.
1330: //
1331:
1332: ACQUIRE_SPIN_LOCK (&address->SpinLock, &oldirql);
1333:
1334: //
1335: // remove this addressfile from the address list and disassociate it from
1336: // the file handle.
1337: //
1338:
1339: RemoveEntryList (&AddressFile->Linkage);
1340: InitializeListHead (&AddressFile->Linkage);
1341:
1342: if (address->AddressFileDatabase.Flink == &address->AddressFileDatabase) {
1343:
1344: //
1345: // This is the last open of this address, it will close
1346: // due to normal dereferencing but we have to set the
1347: // CLOSING flag too to stop further references.
1348: //
1349:
1350: ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql1);
1351: address->Flags |= ADDRESS_FLAGS_STOPPING;
1352: RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql1);
1353:
1354: }
1355:
1356: AddressFile->Address = NULL;
1357:
1358: AddressFile->FileObject->FsContext = NULL;
1359: AddressFile->FileObject->FsContext2 = NULL;
1360:
1361: RELEASE_SPIN_LOCK (&address->SpinLock, oldirql);
1362:
1363: //
1364: // We will already have been removed from the ShareAccess
1365: // of the owning address.
1366: //
1367:
1368: //
1369: // Now dereference the owning address.
1370: //
1371:
1372: StDereferenceAddress ("Close", address); // remove the creation hold
1373:
1374: }
1375:
1376: //
1377: // Save this for later completion.
1378: //
1379:
1380: CloseIrp = AddressFile->CloseIrp;
1381:
1382: //
1383: // return the addressFile to the pool of address files
1384: //
1385:
1386: ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
1387:
1388: DeviceContext->AddressFileTotal += DeviceContext->AddressFileInUse;
1389: ++DeviceContext->AddressFileSamples;
1390: --DeviceContext->AddressFileInUse;
1391:
1392: if ((DeviceContext->AddressFileAllocated - DeviceContext->AddressFileInUse) >
1393: DeviceContext->AddressFileInitAllocated) {
1394: StDeallocateAddressFile (DeviceContext, AddressFile);
1395: } else {
1396: InsertTailList (&DeviceContext->AddressFilePool, &AddressFile->Linkage);
1397: }
1398:
1399: RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
1400:
1401:
1402: if (CloseIrp != (PIRP)NULL) {
1403: CloseIrp->IoStatus.Information = 0;
1404: CloseIrp->IoStatus.Status = STATUS_SUCCESS;
1405: IoCompleteRequest (CloseIrp, IO_NETWORK_INCREMENT);
1406: }
1407:
1408: return STATUS_SUCCESS;
1409:
1410: } /* StDestroyAddress */
1411:
1412:
1413: VOID
1414: StReferenceAddressFile(
1415: IN PTP_ADDRESS_FILE AddressFile
1416: )
1417:
1418: /*++
1419:
1420: Routine Description:
1421:
1422: This routine increments the reference count on an address file.
1423:
1424: Arguments:
1425:
1426: AddressFile - Pointer to a transport address file object.
1427:
1428: Return Value:
1429:
1430: none.
1431:
1432: --*/
1433:
1434: {
1435:
1436: ASSERT (AddressFile->ReferenceCount > 0); // not perfect, but...
1437:
1438: (VOID)ExInterlockedIncrementLong (
1439: &AddressFile->ReferenceCount,
1440: &AddressFile->Provider->Interlock);
1441:
1442: } /* StReferenceAddressFile */
1443:
1444:
1445: VOID
1446: StDereferenceAddressFile(
1447: IN PTP_ADDRESS_FILE AddressFile
1448: )
1449:
1450: /*++
1451:
1452: Routine Description:
1453:
1454: This routine dereferences an address file by decrementing the
1455: reference count contained in the structure. If, after being
1456: decremented, the reference count is zero, then this routine calls
1457: StDestroyAddressFile to remove it from the system.
1458:
1459: Arguments:
1460:
1461: AddressFile - Pointer to a transport address file object.
1462:
1463: Return Value:
1464:
1465: none.
1466:
1467: --*/
1468:
1469: {
1470: INTERLOCKED_RESULT result;
1471:
1472: result = ExInterlockedDecrementLong (
1473: &AddressFile->ReferenceCount,
1474: &AddressFile->Provider->Interlock);
1475:
1476: //
1477: // If we have deleted all references to this address file, then we can
1478: // destroy the object. It is okay to have already released the spin
1479: // lock at this point because there is no possible way that another
1480: // stream of execution has access to the address any longer.
1481: //
1482:
1483: ASSERT (result != ResultNegative);
1484:
1485: if (result == ResultZero) {
1486: StDestroyAddressFile (AddressFile);
1487: }
1488: } /* StDerefAddressFile */
1489:
1490:
1491: PTP_ADDRESS
1492: StLookupAddress(
1493: IN PDEVICE_CONTEXT DeviceContext,
1494: IN PST_NETBIOS_ADDRESS NetworkName
1495: )
1496:
1497: /*++
1498:
1499: Routine Description:
1500:
1501: This routine scans the transport addresses defined for the given
1502: device context and compares them with the specified NETWORK
1503: NAME values. If an exact match is found, then a pointer to the
1504: TP_ADDRESS object is returned, and as a side effect, the reference
1505: count to the address object is incremented. If the address is not
1506: found, then NULL is returned.
1507:
1508: NOTE: This routine must be called with the DeviceContext
1509: spinlock held.
1510:
1511: Arguments:
1512:
1513: DeviceContext - Pointer to the device object and its extension.
1514: NetworkName - Pointer to an ST_NETBIOS_ADDRESS structure containing the
1515: network name.
1516:
1517: Return Value:
1518:
1519: Pointer to the TP_ADDRESS object found, or NULL if not found.
1520:
1521: --*/
1522:
1523: {
1524: PTP_ADDRESS address;
1525: PLIST_ENTRY p;
1526: ULONG i;
1527:
1528:
1529: p = DeviceContext->AddressDatabase.Flink;
1530:
1531: for (p = DeviceContext->AddressDatabase.Flink;
1532: p != &DeviceContext->AddressDatabase;
1533: p = p->Flink) {
1534:
1535: address = CONTAINING_RECORD (p, TP_ADDRESS, Linkage);
1536:
1537: if ((address->Flags & ADDRESS_FLAGS_STOPPING) != 0) {
1538: continue;
1539: }
1540:
1541: //
1542: // If the network name is specified and the network names don't match,
1543: // then the addresses don't match.
1544: //
1545:
1546: i = NETBIOS_NAME_LENGTH; // length of a Netbios name
1547:
1548: if (address->NetworkName != NULL) {
1549: if (NetworkName != NULL) {
1550: if (RtlCompareMemory (
1551: address->NetworkName->NetbiosName,
1552: NetworkName->NetbiosName,
1553: i) < i) {
1554: continue;
1555: }
1556: } else {
1557: continue;
1558: }
1559:
1560: } else {
1561: if (NetworkName != NULL) {
1562: continue;
1563: }
1564: }
1565:
1566: //
1567: // We found the match. Bump the reference count on the address, and
1568: // return a pointer to the address object for the caller to use.
1569: //
1570:
1571: StReferenceAddress ("lookup", address);
1572: return address;
1573:
1574: } /* for */
1575:
1576: //
1577: // The specified address was not found.
1578: //
1579:
1580: return NULL;
1581:
1582: } /* StLookupAddress */
1583:
1584:
1585: PTP_CONNECTION
1586: StLookupRemoteName(
1587: IN PTP_ADDRESS Address,
1588: IN PUCHAR RemoteName
1589: )
1590:
1591: /*++
1592:
1593: Routine Description:
1594:
1595: This routine scans the connections associated with an
1596: address, and determines if there is an connection
1597: associated with the specific remote address.
1598:
1599: Arguments:
1600:
1601: Address - Pointer to the address.
1602:
1603: RemoteName - The 16-character Netbios name of the remote.
1604:
1605: Return Value:
1606:
1607: The connection if one is found, NULL otherwise.
1608:
1609: --*/
1610:
1611: {
1612: KIRQL oldirql, oldirql1;
1613: PLIST_ENTRY p;
1614: PTP_CONNECTION connection;
1615:
1616:
1617: //
1618: // Hold the spinlock so the connection database doesn't
1619: // change.
1620: //
1621:
1622: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
1623:
1624: for (p=Address->ConnectionDatabase.Flink;
1625: p != &Address->ConnectionDatabase;
1626: p=p->Flink) {
1627:
1628: connection = CONTAINING_RECORD (p, TP_CONNECTION, AddressList);
1629:
1630: ACQUIRE_SPIN_LOCK (&connection->SpinLock, &oldirql1);
1631:
1632: if (((connection->Flags2 & CONNECTION_FLAGS2_REMOTE_VALID) != 0) &&
1633: ((connection->Flags & CONNECTION_FLAGS_READY) != 0)) {
1634:
1635: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql1);
1636:
1637: //
1638: // If the remote names match, then return the
1639: // connection.
1640: //
1641:
1642: if (RtlCompareMemory(RemoteName, connection->RemoteName, NETBIOS_NAME_LENGTH) ==
1643: NETBIOS_NAME_LENGTH) {
1644:
1645: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
1646: StReferenceConnection ("Lookup found", connection);
1647: return connection;
1648:
1649: }
1650:
1651: } else {
1652:
1653: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql1);
1654:
1655: }
1656:
1657: }
1658:
1659: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
1660:
1661: return (PTP_CONNECTION)NULL;
1662:
1663: }
1664:
1665:
1666: BOOLEAN
1667: StMatchNetbiosAddress(
1668: IN PTP_ADDRESS Address,
1669: IN PUCHAR NetBIOSName
1670: )
1671:
1672: /*++
1673:
1674: Routine Description:
1675:
1676: This routine is called to compare the addressing information in a
1677: TP_ADDRESS object with the 16-byte NetBIOS name in a frame header.
1678: If they match, then this routine returns TRUE, else it returns FALSE.
1679:
1680: Arguments:
1681:
1682: Address - Pointer to a TP_ADDRESS object.
1683:
1684: NetBIOSName - Pointer to a 16-byte character string (non-terminated),
1685: or NULL if this is a received broadcast address.
1686:
1687: Return Value:
1688:
1689: BOOLEAN, TRUE if match, FALSE if not.
1690:
1691: --*/
1692:
1693: {
1694:
1695: PULONG AddressNamePointer;
1696: ULONG UNALIGNED * NetbiosNamePointer;
1697:
1698: //
1699: // If this is address is the Netbios broadcast address, the comparison
1700: // succeeds only if the passed in address is also NULL.
1701: //
1702:
1703: if (Address->NetworkName == NULL) {
1704:
1705: if (NetBIOSName == NULL) {
1706: return TRUE;
1707: } else {
1708: return FALSE;
1709: }
1710:
1711: } else if (NetBIOSName == NULL) {
1712:
1713: return FALSE;
1714:
1715: }
1716:
1717: //
1718: // Do a quick check of the first character in the names.
1719: //
1720:
1721: if (Address->NetworkName->NetbiosName[0] != NetBIOSName[0]) {
1722: return FALSE;
1723: }
1724:
1725: //
1726: // Now compare the 16-character Netbios names as ULONGs
1727: // for speed. We know the one stored in the address
1728: // structure is aligned.
1729: //
1730:
1731: AddressNamePointer = (PULONG)(Address->NetworkName->NetbiosName);
1732: NetbiosNamePointer = (ULONG UNALIGNED *)NetBIOSName;
1733:
1734: if ((AddressNamePointer[0] == NetbiosNamePointer[0]) &&
1735: (AddressNamePointer[1] == NetbiosNamePointer[1]) &&
1736: (AddressNamePointer[2] == NetbiosNamePointer[2]) &&
1737: (AddressNamePointer[3] == NetbiosNamePointer[3])) {
1738: return TRUE;
1739: } else {
1740: return FALSE;
1741: }
1742:
1743: } /* StMatchNetbiosAddress */
1744:
1745:
1746: VOID
1747: StStopAddress(
1748: IN PTP_ADDRESS Address
1749: )
1750:
1751: /*++
1752:
1753: Routine Description:
1754:
1755: This routine is called to terminate all activity on an address and
1756: destroy the object. This is done in a graceful manner; i.e., all
1757: outstanding addressfiles are removed from the addressfile database, and
1758: all their activities are shut down.
1759:
1760: Arguments:
1761:
1762: Address - Pointer to a TP_ADDRESS object.
1763:
1764: Return Value:
1765:
1766: none.
1767:
1768: --*/
1769:
1770: {
1771: KIRQL oldirql, oldirql1;
1772: PTP_ADDRESS_FILE addressFile;
1773: PLIST_ENTRY p;
1774: PDEVICE_CONTEXT DeviceContext;
1775:
1776: DeviceContext = Address->Provider;
1777:
1778: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
1779:
1780: //
1781: // If we're already stopping this address, then don't try to do it again.
1782: //
1783:
1784: if (!(Address->Flags & ADDRESS_FLAGS_STOPPING)) {
1785:
1786: ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql1);
1787: Address->Flags |= ADDRESS_FLAGS_STOPPING;
1788: RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql1);
1789:
1790: //
1791: // Run down all addressfiles on this address. This
1792: // will leave the address with no references
1793: // potentially, but we don't need a temp one
1794: // because every place that calls StStopAddress
1795: // already has a temp reference.
1796: //
1797:
1798: while (!IsListEmpty (&Address->AddressFileDatabase)) {
1799: p = RemoveHeadList (&Address->AddressFileDatabase);
1800: addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage);
1801:
1802: addressFile->Address = NULL;
1803: addressFile->FileObject->FsContext = NULL;
1804: addressFile->FileObject->FsContext2 = NULL;
1805:
1806: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
1807:
1808: //
1809: // Run-down this addressFile without the lock on.
1810: // We don't care about removing ourselves from
1811: // the address' ShareAccess because we are
1812: // tearing it down.
1813: //
1814:
1815: StStopAddressFile (addressFile, Address);
1816:
1817: //
1818: // return the addressFile to the pool of address files
1819: //
1820:
1821: StDereferenceAddressFile (addressFile);
1822:
1823: StDereferenceAddress ("stop address", Address);
1824:
1825: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
1826: }
1827:
1828: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
1829: return;
1830:
1831: }
1832:
1833: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
1834: } /* StStopAddress */
1835:
1836:
1837: NTSTATUS
1838: StStopAddressFile(
1839: IN PTP_ADDRESS_FILE AddressFile,
1840: IN PTP_ADDRESS Address
1841: )
1842:
1843: /*++
1844:
1845: Routine Description:
1846:
1847: This routine is called to terminate all activity on an AddressFile and
1848: destroy the object. We remove every connection and datagram associated
1849: with this addressfile from the address database and terminate their
1850: activity. Then, if there are no other outstanding addressfiles open on
1851: this address, the address will go away.
1852:
1853: Arguments:
1854:
1855: AddressFile - pointer to the addressFile to be stopped
1856:
1857: Address - the owning address for this addressFile (we do not depend upon
1858: the pointer in the addressFile because we want this routine to be safe)
1859:
1860: Return Value:
1861:
1862: STATUS_SUCCESS if all is well, STATUS_INVALID_HANDLE if the Irp does not
1863: point to a real address.
1864:
1865: --*/
1866:
1867: {
1868: KIRQL oldirql, oldirql1;
1869: LIST_ENTRY localList;
1870: PLIST_ENTRY p, pFlink;
1871: PTP_REQUEST request;
1872: PTP_CONNECTION connection;
1873:
1874:
1875: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
1876:
1877: if (AddressFile->State == ADDRESSFILE_STATE_CLOSING) {
1878: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
1879: return STATUS_SUCCESS;
1880: }
1881:
1882:
1883: AddressFile->State = ADDRESSFILE_STATE_CLOSING;
1884: InitializeListHead (&localList);
1885:
1886: //
1887: // Run down all connections on this addressfile, and
1888: // preform the equivalent of StDestroyAssociation
1889: // on them.
1890: //
1891:
1892: while (!IsListEmpty (&AddressFile->ConnectionDatabase)) {
1893: p = RemoveHeadList (&AddressFile->ConnectionDatabase);
1894: connection = CONTAINING_RECORD (p, TP_CONNECTION, AddressFileList);
1895:
1896: ACQUIRE_SPIN_LOCK (&connection->SpinLock, &oldirql1);
1897:
1898: if ((connection->Flags2 & CONNECTION_FLAGS2_ASSOCIATED) == 0) {
1899:
1900: //
1901: // It is in the process of being disassociated already.
1902: //
1903:
1904: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql1);
1905: continue;
1906: }
1907:
1908: connection->Flags2 &= ~CONNECTION_FLAGS2_ASSOCIATED;
1909: connection->Flags |= CONNECTION_FLAGS_DESTROY; // BUGBUG: Is this needed?
1910: RemoveEntryList (&connection->AddressList);
1911: InitializeListHead (&connection->AddressList);
1912: InitializeListHead (&connection->AddressFileList);
1913: connection->AddressFile = NULL;
1914:
1915: StReferenceConnection ("Close AddressFile", connection);
1916: RELEASE_SPIN_LOCK (&connection->SpinLock, oldirql1);
1917:
1918: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
1919:
1920: StStopConnection (connection, STATUS_LOCAL_DISCONNECT);
1921: StDereferenceConnection ("Close AddressFile", connection);
1922:
1923: StDereferenceAddress ("Destroy association", Address);
1924:
1925: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
1926: }
1927:
1928: //
1929: // now remove all of the datagrams owned by this addressfile
1930: //
1931:
1932: for (p = Address->SendDatagramQueue.Flink;
1933: p != &Address->SendDatagramQueue;
1934: p = pFlink ) {
1935:
1936: pFlink = p->Flink;
1937: request = CONTAINING_RECORD (p, TP_REQUEST, Linkage);
1938: if ((PTP_ADDRESS_FILE)(request->Owner) == AddressFile) {
1939: RemoveEntryList (p);
1940: InitializeListHead (p);
1941: InsertTailList (&localList, p);
1942: }
1943:
1944: }
1945:
1946: for (p = AddressFile->ReceiveDatagramQueue.Flink;
1947: p != &AddressFile->ReceiveDatagramQueue;
1948: p = pFlink ) {
1949:
1950: pFlink = p->Flink;
1951: RemoveEntryList (p);
1952: InitializeListHead (p);
1953: InsertTailList (&localList, p);
1954: }
1955:
1956: //
1957: // and finally, signal failure if the address file was waiting for a
1958: // registration to complete (Irp is set to NULL when this succeeds).
1959: //
1960:
1961: if (AddressFile->Irp != NULL) {
1962: PIRP irp=AddressFile->Irp;
1963: AddressFile->Irp = NULL;
1964: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
1965: irp->IoStatus.Information = 0;
1966: irp->IoStatus.Status = STATUS_DUPLICATE_NAME;
1967:
1968: IoCompleteRequest (irp, IO_NETWORK_INCREMENT);
1969:
1970: } else {
1971:
1972: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
1973: }
1974:
1975: //
1976: // cancel all the datagrams on this address file
1977: //
1978:
1979: while (!IsListEmpty (&localList)) {
1980:
1981: p = RemoveHeadList (&localList);
1982: request = CONTAINING_RECORD (p, TP_REQUEST, Linkage);
1983:
1984: StCompleteRequest (request, STATUS_NETWORK_NAME_DELETED, 0);
1985:
1986: }
1987:
1988:
1989: } /* StStopAddressFile */
1990:
1991:
1992: NTSTATUS
1993: StCloseAddress(
1994: IN PDEVICE_OBJECT DeviceObject,
1995: IN PIRP Irp,
1996: IN PIO_STACK_LOCATION IrpSp
1997: )
1998:
1999: /*++
2000:
2001: Routine Description:
2002:
2003: This routine is called to close the addressfile pointed to by a file
2004: object. If there is any activity to be run down, we will run it down
2005: before we terminate the addressfile. We remove every connection and
2006: datagram associated with this addressfile from the address database
2007: and terminate their activity. Then, if there are no other outstanding
2008: addressfiles open on this address, the address will go away.
2009:
2010: Arguments:
2011:
2012: Irp - the Irp Address - Pointer to a TP_ADDRESS object.
2013:
2014: Return Value:
2015:
2016: STATUS_SUCCESS if all is well, STATUS_INVALID_HANDLE if the Irp does not
2017: point to a real address.
2018:
2019: --*/
2020:
2021: {
2022: PTP_ADDRESS address;
2023: PTP_ADDRESS_FILE addressFile;
2024:
2025: addressFile = IrpSp->FileObject->FsContext;
2026: addressFile->CloseIrp = Irp;
2027:
2028: //
2029: // We assume that addressFile has already been verified
2030: // at this point.
2031: //
2032:
2033: address = addressFile->Address;
2034: ASSERT (address);
2035:
2036: //
2037: // Remove us from the access info for this address.
2038: //
2039:
2040: ExAcquireResourceExclusive (&addressFile->Provider->AddressResource, TRUE);
2041: IoRemoveShareAccess (addressFile->FileObject, &address->ShareAccess);
2042: ExReleaseResource (&addressFile->Provider->AddressResource);
2043:
2044:
2045: StStopAddressFile (addressFile, address);
2046: StDereferenceAddressFile (addressFile);
2047:
2048: //
2049: // This removes a reference added by our caller.
2050: //
2051:
2052: StDereferenceAddress ("IRP_MJ_CLOSE", address);
2053:
2054: return STATUS_PENDING;
2055:
2056: } /* StCloseAddress */
2057:
2058:
2059: NTSTATUS
2060: StSendDatagramsOnAddress(
2061: PTP_ADDRESS Address
2062: )
2063:
2064: /*++
2065:
2066: Routine Description:
2067:
2068: This routine attempts to acquire a hold on the SendDatagramQueue of
2069: the specified address, prepare the next datagram for shipment, and
2070: call StSendUIMdlFrame to actually do the work. When StSendUIMdlFrame
2071: is finished, it will cause an I/O completion routine in UFRAMES.C to
2072: be called, at which time this routine is called again to handle the
2073: next datagram in the pipeline.
2074:
2075: Arguments:
2076:
2077: Address - a pointer to the address object to send the datagram on.
2078:
2079: Return Value:
2080:
2081: NTSTATUS - status of operation.
2082:
2083: --*/
2084:
2085: {
2086: KIRQL oldirql;
2087: PLIST_ENTRY p;
2088: PTP_REQUEST request;
2089: PTA_NETBIOS_ADDRESS remoteTA;
2090: PIO_STACK_LOCATION irpSp;
2091: PDEVICE_CONTEXT DeviceContext;
2092: PUCHAR SourceRouting;
2093: UINT SourceRoutingLength;
2094: UINT HeaderLength;
2095: PST_HEADER StHeader;
2096: PSEND_PACKET_TAG SendTag;
2097:
2098: DeviceContext = Address->Provider;
2099:
2100: ACQUIRE_SPIN_LOCK (&Address->SpinLock, &oldirql);
2101: StReferenceAddress ("Send datagram", Address); // keep it around
2102:
2103: if (!(Address->Flags & ADDRESS_FLAGS_SEND_IN_PROGRESS)) {
2104:
2105: //
2106: // If the queue is empty, don't do anything.
2107: //
2108:
2109: if (IsListEmpty (&Address->SendDatagramQueue)) {
2110: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
2111: StDereferenceAddress ("Queue empty", Address);
2112: return STATUS_SUCCESS;
2113: }
2114:
2115: //
2116: // Mark the address's send datagram queue as held so that the
2117: // MDL and ST header will not be used for two requests at the
2118: // same time.
2119: //
2120:
2121: Address->Flags |= ADDRESS_FLAGS_SEND_IN_PROGRESS;
2122:
2123: //
2124: // We own the hold, and we've released the spinlock. So pick off the
2125: // next datagram to be sent, and ship it.
2126: //
2127:
2128: p = Address->SendDatagramQueue.Flink;
2129: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
2130:
2131: request = CONTAINING_RECORD (p, TP_REQUEST, Linkage);
2132:
2133: //
2134: // If there is no remote Address specified (the Address specified has
2135: // length 0), this is a broadcast datagram. If anything is specified, it
2136: // will be used as a netbios address.
2137: //
2138:
2139: irpSp = IoGetCurrentIrpStackLocation (request->IoRequestPacket);
2140:
2141: remoteTA = ((PTDI_REQUEST_KERNEL_SENDDG)(&irpSp->Parameters))->
2142: SendDatagramInformation->RemoteAddress;
2143:
2144: //
2145: // Build the MAC header. DATAGRAM frames go out as
2146: // single-route source routing.
2147: //
2148:
2149: MacReturnSingleRouteSR(
2150: &DeviceContext->MacInfo,
2151: &SourceRouting,
2152: &SourceRoutingLength);
2153:
2154: MacConstructHeader (
2155: &DeviceContext->MacInfo,
2156: Address->Packet->Header,
2157: DeviceContext->MulticastAddress.Address,
2158: DeviceContext->LocalAddress.Address,
2159: sizeof(ST_HEADER) + request->Buffer2Length,
2160: SourceRouting,
2161: SourceRoutingLength,
2162: &HeaderLength);
2163:
2164: //
2165: // Build the header: 'G', dest, source
2166: //
2167:
2168: StHeader = (PST_HEADER)(&Address->Packet->Header[HeaderLength]);
2169:
2170: StHeader->Signature = ST_SIGNATURE;
2171: StHeader->Command = ST_CMD_DATAGRAM;
2172: StHeader->Flags = 0;
2173:
2174: RtlCopyMemory (StHeader->Source, Address->NetworkName->NetbiosName, 16);
2175:
2176: if (remoteTA->Address[0].AddressLength == 0) {
2177:
2178: //
2179: // A broadcast datagram
2180: //
2181:
2182: RtlZeroMemory (StHeader->Destination, 16);
2183: StHeader->Flags |= ST_FLAGS_BROADCAST;
2184:
2185: } else {
2186:
2187: RtlCopyMemory (StHeader->Destination, remoteTA->Address[0].Address[0].NetbiosName, 16);
2188:
2189: }
2190:
2191: HeaderLength += sizeof(ST_HEADER);
2192:
2193: SendTag = (PSEND_PACKET_TAG)(Address->Packet->NdisPacket->ProtocolReserved);
2194: SendTag->Type = TYPE_G_FRAME;
2195: SendTag->Packet = Address->Packet;
2196: SendTag->Owner = (PVOID)Address;
2197:
2198: //
2199: // Update our statistics for this datagram.
2200: //
2201:
2202: ++DeviceContext->DatagramsSent;
2203: ADD_TO_LARGE_INTEGER(
2204: &DeviceContext->DatagramBytesSent,
2205: request->Buffer2Length,
2206: &DeviceContext->StatisticsSpinLock);
2207:
2208:
2209: //
2210: // Munge the packet length, append the data, and send it.
2211: //
2212:
2213: StSetNdisPacketLength(Address->Packet->NdisPacket, HeaderLength);
2214:
2215: if (request->Buffer2) {
2216: NdisChainBufferAtBack (Address->Packet->NdisPacket, (PNDIS_BUFFER)request->Buffer2);
2217: }
2218:
2219: (VOID)StSendAddressFrame (
2220: Address);
2221:
2222:
2223: //
2224: // The hold will be released in the I/O completion handler.
2225: // At that time, if there is another outstanding datagram
2226: // to send, it will reset the hold and call this routine again.
2227: //
2228:
2229:
2230: } else {
2231:
2232: RELEASE_SPIN_LOCK (&Address->SpinLock, oldirql);
2233: }
2234:
2235: StDereferenceAddress ("Sent datagram", Address); // all done
2236:
2237: return STATUS_SUCCESS;
2238:
2239: } /* StSendDatagramsOnAddress */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.