|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1989-1993 Microsoft Corporation
4:
5: Module Name:
6:
7: stdrvr.c
8:
9: Abstract:
10:
11: This module contains code which defines the NT Sample
12: transport provider's device object.
13:
14: Environment:
15:
16: Kernel mode
17:
18: Revision History:
19:
20:
21: --*/
22:
23: #include "st.h"
24:
25:
26: //
27: // This is a list of all the device contexts that ST owns,
28: // used while unloading.
29: //
30:
31: LIST_ENTRY StDeviceList = {0,0}; // initialized for real at runtime.
32:
33:
34:
35: //
36: // Forward declaration of various routines used in this module.
37: //
38:
39: NTSTATUS
40: DriverEntry(
41: IN PDRIVER_OBJECT DriverObject,
42: IN PUNICODE_STRING RegistryPath
43: );
44:
45: VOID
46: StUnload(
47: IN PDRIVER_OBJECT DriverObject
48: );
49:
50: NTSTATUS
51: StConfigureTransport (
52: IN PUNICODE_STRING RegistryPath,
53: IN PCONFIG_DATA * ConfigData
54: );
55:
56: VOID
57: StFreeConfigurationInfo (
58: IN PCONFIG_DATA ConfigurationInfo
59: );
60:
61: NTSTATUS
62: StDeviceControl(
63: IN PDEVICE_OBJECT DeviceObject,
64: IN PIRP Irp,
65: IN PIO_STACK_LOCATION IrpSp
66: );
67:
68: NTSTATUS
69: StOpenAddress(
70: IN PDEVICE_OBJECT DeviceObject,
71: IN PIRP Irp,
72: IN PIO_STACK_LOCATION IrpSp
73: );
74:
75: NTSTATUS
76: StCloseAddress(
77: IN PDEVICE_OBJECT DeviceObject,
78: IN PIRP Irp,
79: IN PIO_STACK_LOCATION IrpSp
80: );
81:
82: NTSTATUS
83: StOpenConnection(
84: IN PDEVICE_OBJECT DeviceObject,
85: IN PIRP Irp,
86: IN PIO_STACK_LOCATION IrpSp
87: );
88:
89: NTSTATUS
90: StCloseConnection(
91: IN PDEVICE_OBJECT DeviceObject,
92: IN PIRP Irp,
93: IN PIO_STACK_LOCATION IrpSp
94: );
95:
96: NTSTATUS
97: StTdiAccept(
98: IN PIRP Irp
99: );
100:
101: NTSTATUS
102: StTdiConnect(
103: IN PIRP Irp
104: );
105:
106: NTSTATUS
107: StTdiDisconnect(
108: IN PIRP Irp
109: );
110:
111: NTSTATUS
112: StTdiDisassociateAddress (
113: IN PIRP Irp
114: );
115:
116: NTSTATUS
117: StTdiAssociateAddress(
118: IN PIRP Irp
119: );
120:
121: NTSTATUS
122: StTdiListen(
123: IN PIRP Irp
124: );
125:
126: NTSTATUS
127: StTdiQueryInformation(
128: IN PDEVICE_CONTEXT DeviceContext,
129: IN PIRP Irp
130: );
131:
132: NTSTATUS
133: StTdiReceive(
134: IN PIRP Irp
135: );
136:
137: NTSTATUS
138: StTdiReceiveDatagram(
139: IN PIRP Irp
140: );
141:
142: NTSTATUS
143: StTdiSend(
144: IN PIRP Irp
145: );
146:
147: NTSTATUS
148: StTdiSendDatagram(
149: IN PIRP Irp
150: );
151:
152: NTSTATUS
153: StTdiSetEventHandler(
154: IN PIRP Irp
155: );
156:
157: NTSTATUS
158: StTdiSetInformation(
159: IN PIRP Irp
160: );
161:
162: VOID
163: StDeallocateResources(
164: IN PDEVICE_CONTEXT DeviceContext
165: );
166:
167: #ifdef ALLOC_PRAGMA
168: #pragma alloc_text(init,DriverEntry)
169: #endif
170:
171:
172:
173: NTSTATUS
174: DriverEntry(
175: IN PDRIVER_OBJECT DriverObject,
176: IN PUNICODE_STRING RegistryPath
177: )
178:
179: /*++
180:
181: Routine Description:
182:
183: This routine performs initialization of the sample
184: transport driver. It creates the device objects for the transport
185: provider and performs other driver initialization.
186:
187: Arguments:
188:
189: DriverObject - Pointer to driver object created by the system.
190:
191: RegistryPath - The name of ST's node in the registry.
192:
193: Return Value:
194:
195: The function value is the final status from the initialization operation.
196:
197: --*/
198:
199: {
200: ULONG i, j;
201: STRING nameString;
202: PDEVICE_CONTEXT DeviceContext;
203: PTP_REQUEST Request;
204: PTP_CONNECTION Connection;
205: PTP_ADDRESS_FILE AddressFile;
206: PTP_ADDRESS Address;
207: PTP_PACKET Packet;
208: PNDIS_PACKET NdisPacket;
209: PRECEIVE_PACKET_TAG ReceiveTag;
210: PBUFFER_TAG BufferTag;
211: NTSTATUS status;
212: UINT SuccessfulOpens;
213: UINT MaxUserData;
214:
215: PCONFIG_DATA StConfig = NULL;
216:
217:
218: ASSERT (sizeof (SHORT) == 2);
219:
220: //
221: // This allocates the CONFIG_DATA structure and returns
222: // it in StConfig.
223: //
224:
225: status = StConfigureTransport(RegistryPath, &StConfig);
226:
227: if (!NT_SUCCESS (status)) {
228: PANIC (" Failed to initialize transport, St initialization failed.\n");
229: return STATUS_INSUFFICIENT_RESOURCES;
230: }
231:
232: //
233: // make ourselves known to the NDIS wrapper.
234: //
235:
236: RtlInitString( &nameString, ST_DEVICE_NAME );
237:
238: status = StRegisterProtocol (&nameString);
239:
240: if (!NT_SUCCESS (status)) {
241:
242: StFreeConfigurationInfo(StConfig);
243: PANIC ("StInitialize: RegisterProtocol failed!\n");
244:
245: StWriteGeneralErrorLog(
246: (PVOID)DriverObject,
247: EVENT_TRANSPORT_REGISTER_FAILED,
248: 607,
249: status,
250: NULL,
251: 0,
252: NULL);
253:
254: return STATUS_INSUFFICIENT_RESOURCES;
255:
256: }
257:
258:
259: //
260: // Initialize the driver object with this driver's entry points.
261: //
262:
263: DriverObject->MajorFunction [IRP_MJ_CREATE] = StDispatchOpenClose;
264: DriverObject->MajorFunction [IRP_MJ_CLOSE] = StDispatchOpenClose;
265: DriverObject->MajorFunction [IRP_MJ_CLEANUP] = StDispatchOpenClose;
266: DriverObject->MajorFunction [IRP_MJ_INTERNAL_DEVICE_CONTROL] = StDispatchInternal;
267: DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = StDispatch;
268:
269: DriverObject->DriverUnload = StUnload;
270:
271: //
272: // Initialize the global list of devices.
273: //
274:
275: InitializeListHead (&StDeviceList);
276:
277: SuccessfulOpens = 0;
278:
279: for (j=0;j<StConfig->NumAdapters;j++ ) {
280:
281:
282: //
283: // Loop through all the adapters that are in the configuration
284: // information structure. Allocate a device object for each
285: // one that we find.
286: //
287:
288: status = StCreateDeviceContext (DriverObject, &StConfig->Names[StConfig->DevicesOffset+j], &DeviceContext);
289:
290: if (!NT_SUCCESS (status)) {
291: continue;
292: }
293:
294: //
295: // Initialize our counter that records memory usage.
296: //
297:
298: DeviceContext->MemoryUsage = 0;
299: DeviceContext->MemoryLimit = StConfig->MaxMemoryUsage;
300:
301: //
302: // Now fire up NDIS so this adapter talks
303: //
304:
305: status = StInitializeNdis (DeviceContext,
306: StConfig,
307: j);
308:
309: if (!NT_SUCCESS (status)) {
310:
311: //
312: // Log an error.
313: //
314:
315: StWriteGeneralErrorLog(
316: DeviceContext,
317: EVENT_TRANSPORT_BINDING_FAILED,
318: 601,
319: status,
320: StConfig->Names[j].Buffer,
321: 0,
322: NULL);
323:
324: StDereferenceDeviceContext ("Initialize NDIS failed", DeviceContext);
325: continue;
326:
327: }
328:
329:
330: //
331: // Initialize our provider information structure; since it
332: // doesn't change, we just keep it around and copy it to
333: // whoever requests it.
334: //
335:
336:
337: MacReturnMaxDataSize(
338: &DeviceContext->MacInfo,
339: NULL,
340: 0,
341: DeviceContext->MaxSendPacketSize,
342: &MaxUserData);
343:
344: DeviceContext->Information.Version = 0x0100;
345: DeviceContext->Information.MaxSendSize = 0x1fffe; // 128k - 2
346: DeviceContext->Information.MaxConnectionUserData = 0;
347: DeviceContext->Information.MaxDatagramSize = MaxUserData - sizeof(ST_HEADER);
348: DeviceContext->Information.ServiceFlags = ST_SERVICE_FLAGS;
349: DeviceContext->Information.MinimumLookaheadData = 128;
350: DeviceContext->Information.MaximumLookaheadData =
351: DeviceContext->MaxReceivePacketSize - sizeof(ST_HEADER);
352: DeviceContext->Information.NumberOfResources = ST_TDI_RESOURCES;
353: KeQuerySystemTime (&DeviceContext->Information.StartTime);
354:
355:
356: //
357: // Allocate various structures we will need.
358: //
359:
360:
361: //
362: // The TP_PACKET structure has a CHAR[1] field at the end
363: // which we expand upon to include all the headers needed;
364: // the size of the MAC header depends on what the adapter
365: // told us about its max header size.
366: //
367:
368: DeviceContext->PacketHeaderLength =
369: DeviceContext->MacInfo.MaxHeaderLength +
370: sizeof (ST_HEADER);
371:
372: DeviceContext->PacketLength =
373: FIELD_OFFSET(TP_PACKET, Header[0]) +
374: DeviceContext->PacketHeaderLength;
375:
376:
377: //
378: // The BUFFER_TAG structure has a CHAR[1] field at the end
379: // which we expand upong to include all the frame data.
380: //
381:
382: DeviceContext->ReceiveBufferLength =
383: DeviceContext->MaxReceivePacketSize +
384: FIELD_OFFSET(BUFFER_TAG, Buffer[0]);
385:
386:
387: for (i=0; i<StConfig->InitRequests; i++) {
388:
389: StAllocateRequest (DeviceContext, &Request);
390:
391: if (Request == NULL) {
392: PANIC ("StInitialize: insufficient memory to allocate requests.\n");
393: status = STATUS_INSUFFICIENT_RESOURCES;
394: goto cleanup;
395: }
396:
397: InsertTailList (&DeviceContext->RequestPool, &Request->Linkage);
398: }
399:
400: DeviceContext->RequestInitAllocated = StConfig->InitRequests;
401: DeviceContext->RequestMaxAllocated = StConfig->MaxRequests;
402:
403:
404: for (i=0; i<StConfig->InitConnections; i++) {
405:
406: StAllocateConnection (DeviceContext, &Connection);
407:
408: if (Connection == NULL) {
409: PANIC ("StInitialize: insufficient memory to allocate connections.\n");
410: status = STATUS_INSUFFICIENT_RESOURCES;
411: goto cleanup;
412: }
413:
414: InsertTailList (&DeviceContext->ConnectionPool, &Connection->LinkList);
415: }
416:
417: DeviceContext->ConnectionInitAllocated = StConfig->InitConnections;
418: DeviceContext->ConnectionMaxAllocated = StConfig->MaxConnections;
419:
420:
421: for (i=0; i<StConfig->InitAddressFiles; i++) {
422:
423: StAllocateAddressFile (DeviceContext, &AddressFile);
424:
425: if (AddressFile == NULL) {
426: PANIC ("StInitialize: insufficient memory to allocate Address Files.\n");
427: status = STATUS_INSUFFICIENT_RESOURCES;
428: goto cleanup;
429: }
430:
431: InsertTailList (&DeviceContext->AddressFilePool, &AddressFile->Linkage);
432: }
433:
434: DeviceContext->AddressFileInitAllocated = StConfig->InitAddressFiles;
435: DeviceContext->AddressFileMaxAllocated = StConfig->MaxAddressFiles;
436:
437:
438: for (i=0; i<StConfig->InitAddresses; i++) {
439:
440: StAllocateAddress (DeviceContext, &Address);
441: if (Address == NULL) {
442: PANIC ("StInitialize: insufficient memory to allocate addresses.\n");
443: status = STATUS_INSUFFICIENT_RESOURCES;
444: goto cleanup;
445: }
446:
447: InsertTailList (&DeviceContext->AddressPool, &Address->Linkage);
448: }
449:
450: DeviceContext->AddressInitAllocated = StConfig->InitAddresses;
451: DeviceContext->AddressMaxAllocated = StConfig->MaxAddresses;
452:
453:
454: for (i=0; i<StConfig->InitPackets; i++) {
455:
456: StAllocateSendPacket (DeviceContext, &Packet);
457: if (Packet == NULL) {
458: PANIC ("StInitialize: insufficient memory to allocate packets.\n");
459: status = STATUS_INSUFFICIENT_RESOURCES;
460: goto cleanup;
461: }
462:
463: PushEntryList (&DeviceContext->PacketPool, (PSINGLE_LIST_ENTRY)&Packet->Linkage);
464: }
465:
466: DeviceContext->PacketInitAllocated = StConfig->InitPackets;
467:
468:
469: for (i=0; i<StConfig->InitReceivePackets; i++) {
470:
471: StAllocateReceivePacket (DeviceContext, &NdisPacket);
472:
473: if (NdisPacket == NULL) {
474: PANIC ("StInitialize: insufficient memory to allocate packet MDLs.\n");
475: status = STATUS_INSUFFICIENT_RESOURCES;
476: goto cleanup;
477: }
478:
479: ReceiveTag = (PRECEIVE_PACKET_TAG)NdisPacket->ProtocolReserved;
480: PushEntryList (&DeviceContext->ReceivePacketPool, (PSINGLE_LIST_ENTRY)&ReceiveTag->Linkage);
481:
482: }
483:
484: DeviceContext->ReceivePacketInitAllocated = StConfig->InitReceivePackets;
485:
486:
487: for (i=0; i<StConfig->InitReceiveBuffers; i++) {
488:
489: StAllocateReceiveBuffer (DeviceContext, &BufferTag);
490:
491: if (BufferTag == NULL) {
492: PANIC ("StInitialize: Unable to allocate receive packet.\n");
493: status = STATUS_INSUFFICIENT_RESOURCES;
494: goto cleanup;
495: }
496:
497: PushEntryList (&DeviceContext->ReceiveBufferPool, &BufferTag->Linkage);
498:
499: }
500:
501: DeviceContext->ReceiveBufferInitAllocated = StConfig->InitReceiveBuffers;
502:
503:
504: //
505: // Now link the device into the global list.
506: //
507:
508: InsertTailList (&StDeviceList, &DeviceContext->Linkage);
509:
510: DeviceContext->State = DEVICECONTEXT_STATE_OPEN;
511:
512: ++SuccessfulOpens;
513:
514: continue;
515:
516: cleanup:
517:
518: StWriteResourceErrorLog (DeviceContext, DeviceContext->MemoryUsage, 501);
519:
520: //
521: // Cleanup whatever device context we were initializing
522: // when we failed.
523: //
524:
525: StFreeResources (DeviceContext);
526: StCloseNdis (DeviceContext);
527: StDereferenceDeviceContext ("Load failed", DeviceContext);
528:
529: }
530:
531: StFreeConfigurationInfo(StConfig);
532:
533: return ((SuccessfulOpens > 0) ? STATUS_SUCCESS : STATUS_DEVICE_DOES_NOT_EXIST);
534:
535: }
536:
537: VOID
538: StUnload(
539: IN PDRIVER_OBJECT DriverObject
540: )
541:
542: /*++
543:
544: Routine Description:
545:
546: This routine unloads the sample transport driver.
547: It unbinds from any NDIS drivers that are open and frees all resources
548: associated with the transport. The I/O system will not call us until
549: nobody above has ST open.
550:
551: Arguments:
552:
553: DriverObject - Pointer to driver object created by the system.
554:
555: Return Value:
556:
557: None. When the function returns, the driver is unloaded.
558:
559: --*/
560:
561: {
562:
563: PDEVICE_CONTEXT DeviceContext;
564: PLIST_ENTRY p;
565:
566:
567: UNREFERENCED_PARAMETER (DriverObject);
568:
569: //
570: // Walk the list of device contexts.
571: //
572:
573: while (!IsListEmpty (&StDeviceList)) {
574:
575: p = RemoveHeadList (&StDeviceList);
576: DeviceContext = CONTAINING_RECORD (p, DEVICE_CONTEXT, Linkage);
577:
578: //
579: // Remove all the storage associated with the device.
580: //
581:
582: StFreeResources (DeviceContext);
583:
584: //
585: // Free the packet pools, etc. and close the
586: // adapter.
587: //
588:
589: StCloseNdis (DeviceContext);
590:
591: //
592: // And remove the creation reference from the device
593: // context.
594: //
595:
596: StDereferenceDeviceContext ("Unload", DeviceContext);
597:
598: }
599:
600:
601: //
602: // Finally, remove ourselves as an NDIS protocol.
603: //
604:
605: StDeregisterProtocol();
606:
607: return;
608:
609: }
610:
611:
612: VOID
613: StFreeResources (
614: IN PDEVICE_CONTEXT DeviceContext
615: )
616: /*++
617:
618: Routine Description:
619:
620: This routine is called by ST to clean up the data structures associated
621: with a given DeviceContext. When this routine exits, the DeviceContext
622: should be deleted as it no longer has any assocaited resources.
623:
624: Arguments:
625:
626: DeviceContext - Pointer to the DeviceContext we wish to clean up.
627:
628: Return Value:
629:
630: None.
631:
632: --*/
633: {
634: PLIST_ENTRY p;
635: PSINGLE_LIST_ENTRY s;
636: PTP_PACKET packet;
637: PTP_ADDRESS address;
638: PTP_CONNECTION connection;
639: PTP_REQUEST request;
640: PTP_ADDRESS_FILE addressFile;
641: PNDIS_PACKET ndisPacket;
642: PBUFFER_TAG BufferTag;
643:
644:
645: //
646: // Clean up packet pool.
647: //
648:
649: while ( DeviceContext->PacketPool.Next != NULL ) {
650: s = PopEntryList( &DeviceContext->PacketPool );
651: packet = CONTAINING_RECORD( s, TP_PACKET, Linkage );
652:
653: StDeallocateSendPacket (DeviceContext, packet);
654: }
655:
656: //
657: // Clean up address pool.
658: //
659:
660: while ( !IsListEmpty (&DeviceContext->AddressPool) ) {
661: p = RemoveHeadList (&DeviceContext->AddressPool);
662: address = CONTAINING_RECORD (p, TP_ADDRESS, Linkage);
663:
664: StDeallocateAddress (DeviceContext, address);
665: }
666:
667: //
668: // Clean up address file pool.
669: //
670:
671: while ( !IsListEmpty (&DeviceContext->AddressFilePool) ) {
672: p = RemoveHeadList (&DeviceContext->AddressFilePool);
673: addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage);
674:
675: StDeallocateAddressFile (DeviceContext, addressFile);
676: }
677:
678: //
679: // Clean up connection pool.
680: //
681:
682: while ( !IsListEmpty (&DeviceContext->ConnectionPool) ) {
683: p = RemoveHeadList (&DeviceContext->ConnectionPool);
684: connection = CONTAINING_RECORD (p, TP_CONNECTION, LinkList);
685:
686: StDeallocateConnection (DeviceContext, connection);
687: }
688:
689: //
690: // Clean up request pool.
691: //
692:
693: while ( !IsListEmpty( &DeviceContext->RequestPool ) ) {
694: p = RemoveHeadList( &DeviceContext->RequestPool );
695: request = CONTAINING_RECORD (p, TP_REQUEST, Linkage );
696:
697: StDeallocateRequest (DeviceContext, request);
698: }
699:
700: //
701: // Clean up receive packet pool
702: //
703:
704: while ( DeviceContext->ReceivePacketPool.Next != NULL) {
705: s = PopEntryList (&DeviceContext->ReceivePacketPool);
706:
707: //
708: // HACK: This works because Linkage is the first field in
709: // ProtocolReserved for a receive packet.
710: //
711:
712: ndisPacket = CONTAINING_RECORD (s, NDIS_PACKET, ProtocolReserved[0]);
713:
714: StDeallocateReceivePacket (DeviceContext, ndisPacket);
715: }
716:
717:
718: //
719: // Clean up receive buffer pool.
720: //
721:
722: while ( DeviceContext->ReceiveBufferPool.Next != NULL ) {
723: s = PopEntryList( &DeviceContext->ReceiveBufferPool );
724: BufferTag = CONTAINING_RECORD (s, BUFFER_TAG, Linkage );
725:
726: StDeallocateReceiveBuffer (DeviceContext, BufferTag);
727: }
728:
729:
730: return;
731:
732: } /* StFreeResources */
733:
734:
735: NTSTATUS
736: StDispatch(
737: IN PDEVICE_OBJECT DeviceObject,
738: IN PIRP Irp
739: )
740:
741: /*++
742:
743: Routine Description:
744:
745: This routine is the main dispatch routine for the ST device driver.
746: It accepts an I/O Request Packet, performs the request, and then
747: returns with the appropriate status.
748:
749: Arguments:
750:
751: DeviceObject - Pointer to the device object for this driver.
752:
753: Irp - Pointer to the request packet representing the I/O request.
754:
755: Return Value:
756:
757: The function value is the status of the operation.
758:
759: --*/
760:
761: {
762: NTSTATUS Status;
763: PIO_STACK_LOCATION IrpSp;
764: PDEVICE_CONTEXT DeviceContext;
765:
766: //
767: // Check to see if ST has been initialized; if not, don't allow any use.
768: // Note that this only covers any user mode code use; kernel TDI clients
769: // will fail on their creation of an endpoint.
770: //
771:
772: DeviceContext = (PDEVICE_CONTEXT)DeviceObject;
773: if (DeviceContext->State != DEVICECONTEXT_STATE_OPEN) {
774: Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
775: IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
776: return STATUS_INVALID_DEVICE_STATE;
777: }
778:
779: //
780: // Make sure status information is consistent every time.
781: //
782:
783: IoMarkIrpPending (Irp);
784: Irp->IoStatus.Status = STATUS_PENDING;
785: Irp->IoStatus.Information = 0;
786:
787: //
788: // Get a pointer to the current stack location in the IRP. This is where
789: // the function codes and parameters are stored.
790: //
791:
792: IrpSp = IoGetCurrentIrpStackLocation (Irp);
793:
794: //
795: // Case on the function that is being performed by the requestor. If the
796: // operation is a valid one for this device, then make it look like it was
797: // successfully completed, where possible.
798: //
799:
800:
801: switch (IrpSp->MajorFunction) {
802:
803: case IRP_MJ_DEVICE_CONTROL:
804: Status = StDeviceControl (DeviceObject, Irp, IrpSp);
805: break;
806:
807: default:
808: Status = STATUS_INVALID_DEVICE_REQUEST;
809:
810: } /* major function switch */
811:
812: if (Status != STATUS_PENDING) {
813: IrpSp->Control &= ~SL_PENDING_RETURNED;
814: Irp->IoStatus.Status = Status;
815: IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
816: }
817:
818: //
819: // Return the immediate status code to the caller.
820: //
821:
822: return Status;
823: } /* StDispatch */
824:
825:
826: NTSTATUS
827: StDispatchOpenClose(
828: IN PDEVICE_OBJECT DeviceObject,
829: IN PIRP Irp
830: )
831:
832: /*++
833:
834: Routine Description:
835:
836: This routine is the main dispatch routine for the ST device driver.
837: It accepts an I/O Request Packet, performs the request, and then
838: returns with the appropriate status.
839:
840: Arguments:
841:
842: DeviceObject - Pointer to the device object for this driver.
843:
844: Irp - Pointer to the request packet representing the I/O request.
845:
846: Return Value:
847:
848: The function value is the status of the operation.
849:
850: --*/
851:
852: {
853: KIRQL oldirql;
854: PDEVICE_CONTEXT DeviceContext;
855: NTSTATUS Status;
856: PIO_STACK_LOCATION IrpSp;
857: PFILE_FULL_EA_INFORMATION openType;
858: USHORT i;
859: BOOLEAN found;
860: PTP_ADDRESS_FILE AddressFile;
861: PTP_CONNECTION Connection;
862:
863: //
864: // Check to see if ST has been initialized; if not, don't allow any use.
865: // Note that this only covers any user mode code use; kernel TDI clients
866: // will fail on their creation of an endpoint.
867: //
868:
869: DeviceContext = (PDEVICE_CONTEXT)DeviceObject;
870: if (DeviceContext->State != DEVICECONTEXT_STATE_OPEN) {
871: Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
872: IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
873: return STATUS_INVALID_DEVICE_STATE;
874: }
875:
876: //
877: // Make sure status information is consistent every time.
878: //
879:
880: IoMarkIrpPending (Irp);
881: Irp->IoStatus.Status = STATUS_PENDING;
882: Irp->IoStatus.Information = 0;
883:
884: //
885: // Get a pointer to the current stack location in the IRP. This is where
886: // the function codes and parameters are stored.
887: //
888:
889: IrpSp = IoGetCurrentIrpStackLocation (Irp);
890:
891: //
892: // Case on the function that is being performed by the requestor. If the
893: // operation is a valid one for this device, then make it look like it was
894: // successfully completed, where possible.
895: //
896:
897:
898: switch (IrpSp->MajorFunction) {
899:
900: //
901: // The Create function opens a transport object (either address or
902: // connection). Access checking is performed on the specified
903: // address to ensure security of transport-layer addresses.
904: //
905:
906: case IRP_MJ_CREATE:
907:
908: openType =
909: (PFILE_FULL_EA_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
910:
911: if (openType != NULL) {
912:
913: found = TRUE;
914:
915: for (i=0;i<(USHORT)openType->EaNameLength;i++) {
916: if (openType->EaName[i] == TdiTransportAddress[i]) {
917: continue;
918: } else {
919: found = FALSE;
920: break;
921: }
922: }
923:
924: if (found) {
925: Status = StOpenAddress (DeviceObject, Irp, IrpSp);
926: break;
927: }
928:
929: //
930: // Connection?
931: //
932:
933: found = TRUE;
934:
935: for (i=0;i<(USHORT)openType->EaNameLength;i++) {
936: if (openType->EaName[i] == TdiConnectionContext[i]) {
937: continue;
938: } else {
939: found = FALSE;
940: break;
941: }
942: }
943:
944: if (found) {
945: Status = StOpenConnection (DeviceObject, Irp, IrpSp);
946: break;
947: }
948:
949: } else {
950:
951: ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
952:
953: IrpSp->FileObject->FsContext = (PVOID)(DeviceContext->ControlChannelIdentifier);
954: ++DeviceContext->ControlChannelIdentifier;
955: if (DeviceContext->ControlChannelIdentifier == 0) {
956: DeviceContext->ControlChannelIdentifier = 1;
957: }
958:
959: RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
960:
961: IrpSp->FileObject->FsContext2 = (PVOID)ST_FILE_TYPE_CONTROL;
962: Status = STATUS_SUCCESS;
963: }
964:
965: break;
966:
967: case IRP_MJ_CLOSE:
968:
969: //
970: // The Close function closes a transport endpoint, terminates
971: // all outstanding transport activity on the endpoint, and unbinds
972: // the endpoint from its transport address, if any. If this
973: // is the last transport endpoint bound to the address, then
974: // the address is removed from the provider.
975: //
976:
977: switch ((ULONG)IrpSp->FileObject->FsContext2) {
978: case TDI_TRANSPORT_ADDRESS_FILE:
979: AddressFile = (PTP_ADDRESS_FILE)IrpSp->FileObject->FsContext;
980:
981: //
982: // This creates a reference to AddressFile->Address
983: // which is removed by StCloseAddress.
984: //
985:
986: Status = StVerifyAddressObject(AddressFile);
987:
988: if (!NT_SUCCESS (Status)) {
989: Status = STATUS_INVALID_HANDLE;
990: } else {
991: Status = StCloseAddress (DeviceObject, Irp, IrpSp);
992: }
993:
994: break;
995:
996: case TDI_CONNECTION_FILE:
997:
998: //
999: // This is a connection
1000: //
1001:
1002: Connection = (PTP_CONNECTION)IrpSp->FileObject->FsContext;
1003: Status = StVerifyConnectionObject (Connection);
1004: if (NT_SUCCESS (Status)) {
1005:
1006: Status = StCloseConnection (DeviceObject, Irp, IrpSp);
1007: StDereferenceConnection ("Temporary Use",Connection);
1008:
1009: }
1010:
1011: break;
1012:
1013: case ST_FILE_TYPE_CONTROL:
1014:
1015: //
1016: // this always succeeds
1017: //
1018:
1019: Status = STATUS_SUCCESS;
1020: break;
1021:
1022: default:
1023: Status = STATUS_INVALID_HANDLE;
1024: }
1025:
1026: break;
1027:
1028: case IRP_MJ_CLEANUP:
1029:
1030: //
1031: // Handle the two stage IRP for a file close operation. When the first
1032: // stage hits, run down all activity on the object of interest. This
1033: // do everything to it but remove the creation hold. Then, when the
1034: // CLOSE irp hits, actually close the object.
1035: //
1036:
1037: switch ((ULONG)IrpSp->FileObject->FsContext2) {
1038: case TDI_TRANSPORT_ADDRESS_FILE:
1039: AddressFile = (PTP_ADDRESS_FILE)IrpSp->FileObject->FsContext;
1040: Status = StVerifyAddressObject(AddressFile);
1041: if (!NT_SUCCESS (Status)) {
1042:
1043: Status = STATUS_INVALID_HANDLE;
1044:
1045: } else {
1046:
1047: StStopAddressFile (AddressFile, AddressFile->Address);
1048: StDereferenceAddress ("IRP_MJ_CLEANUP", AddressFile->Address);
1049: Status = STATUS_SUCCESS;
1050: }
1051:
1052: break;
1053:
1054: case TDI_CONNECTION_FILE:
1055:
1056: Connection = (PTP_CONNECTION)IrpSp->FileObject->FsContext;
1057: Status = StVerifyConnectionObject (Connection);
1058: if (NT_SUCCESS (Status)) {
1059: StStopConnection (Connection, STATUS_LOCAL_DISCONNECT);
1060: Status = STATUS_SUCCESS;
1061: StDereferenceConnection ("Temporary Use",Connection);
1062: }
1063:
1064: break;
1065:
1066: case ST_FILE_TYPE_CONTROL:
1067:
1068: Status = STATUS_SUCCESS;
1069: break;
1070:
1071: default:
1072: Status = STATUS_INVALID_HANDLE;
1073: }
1074:
1075: break;
1076:
1077: default:
1078: Status = STATUS_INVALID_DEVICE_REQUEST;
1079:
1080: } /* major function switch */
1081:
1082: if (Status != STATUS_PENDING) {
1083: IrpSp->Control &= ~SL_PENDING_RETURNED;
1084: Irp->IoStatus.Status = Status;
1085: IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
1086: }
1087:
1088:
1089: //
1090: // Return the immediate status code to the caller.
1091: //
1092:
1093: return Status;
1094: } /* StDispatchOpenClose */
1095:
1096:
1097: NTSTATUS
1098: StDeviceControl(
1099: IN PDEVICE_OBJECT DeviceObject,
1100: IN PIRP Irp,
1101: IN PIO_STACK_LOCATION IrpSp
1102: )
1103:
1104: /*++
1105:
1106: Routine Description:
1107:
1108: This routine dispatches TDI request types to different handlers based
1109: on the minor IOCTL function code in the IRP's current stack location.
1110: In addition to cracking the minor function code, this routine also
1111: reaches into the IRP and passes the packetized parameters stored there
1112: as parameters to the various TDI request handlers so that they are
1113: not IRP-dependent.
1114:
1115: Arguments:
1116:
1117: DeviceObject - Pointer to the device object for this driver.
1118:
1119: Irp - Pointer to the request packet representing the I/O request.
1120:
1121: IrpSp - Pointer to current IRP stack frame.
1122:
1123: Return Value:
1124:
1125: The function value is the status of the operation.
1126:
1127: --*/
1128:
1129: {
1130: NTSTATUS Status;
1131: PDEVICE_CONTEXT DeviceContext = (PDEVICE_CONTEXT)DeviceObject;
1132:
1133:
1134: //
1135: // Branch to the appropriate request handler. Preliminary checking of
1136: // the size of the request block is performed here so that it is known
1137: // in the handlers that the minimum input parameters are readable. It
1138: // is *not* determined here whether variable length input fields are
1139: // passed correctly; this is a check which must be made within each routine.
1140: //
1141:
1142: switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
1143:
1144: default:
1145:
1146: //
1147: // Convert the user call to the proper internal device call.
1148: //
1149:
1150: Status = TdiMapUserRequest (DeviceObject, Irp, IrpSp);
1151:
1152: if (Status == STATUS_SUCCESS) {
1153:
1154: //
1155: // If TdiMapUserRequest returns SUCCESS then the IRP
1156: // has been converted into an IRP_MJ_INTERNAL_DEVICE_CONTROL
1157: // IRP, so we dispatch it as usual. The IRP will
1158: // be completed by this call.
1159: //
1160: // StDispatchInternal expects to complete the IRP,
1161: // so we change Status to PENDING so we don't.
1162: //
1163:
1164: (VOID)StDispatchInternal (DeviceObject, Irp);
1165: Status = STATUS_PENDING;
1166:
1167: }
1168: }
1169:
1170: return Status;
1171: } /* StDeviceControl */
1172:
1173:
1174: NTSTATUS
1175: StDispatchInternal (
1176: IN PDEVICE_OBJECT DeviceObject,
1177: IN PIRP Irp
1178: )
1179:
1180: /*++
1181:
1182: Routine Description:
1183:
1184: This routine dispatches TDI request types to different handlers based
1185: on the minor IOCTL function code in the IRP's current stack location.
1186: In addition to cracking the minor function code, this routine also
1187: reaches into the IRP and passes the packetized parameters stored there
1188: as parameters to the various TDI request handlers so that they are
1189: not IRP-dependent.
1190:
1191: Arguments:
1192:
1193: DeviceObject - Pointer to the device object for this driver.
1194:
1195: Irp - Pointer to the request packet representing the I/O request.
1196:
1197: Return Value:
1198:
1199: The function value is the status of the operation.
1200:
1201: --*/
1202:
1203: {
1204: NTSTATUS Status;
1205: PDEVICE_CONTEXT DeviceContext;
1206: PIO_STACK_LOCATION IrpSp;
1207:
1208:
1209: //
1210: // Get a pointer to the current stack location in the IRP. This is where
1211: // the function codes and parameters are stored.
1212: //
1213:
1214: IrpSp = IoGetCurrentIrpStackLocation (Irp);
1215:
1216: DeviceContext = (PDEVICE_CONTEXT)DeviceObject;
1217:
1218:
1219: if (DeviceContext->State != DEVICECONTEXT_STATE_OPEN) {
1220: Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE;
1221: IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
1222: return STATUS_INVALID_DEVICE_STATE;
1223: }
1224:
1225:
1226: //
1227: // Make sure status information is consistent every time.
1228: //
1229:
1230: IoMarkIrpPending (Irp);
1231: Irp->IoStatus.Status = STATUS_PENDING;
1232: Irp->IoStatus.Information = 0;
1233:
1234:
1235: //
1236: // Branch to the appropriate request handler. Preliminary checking of
1237: // the size of the request block is performed here so that it is known
1238: // in the handlers that the minimum input parameters are readable. It
1239: // is *not* determined here whether variable length input fields are
1240: // passed correctly; this is a check which must be made within each routine.
1241: //
1242:
1243: switch (IrpSp->MinorFunction) {
1244:
1245: case TDI_ACCEPT:
1246: Status = StTdiAccept (Irp);
1247: break;
1248:
1249: case TDI_ACTION:
1250: Status = STATUS_SUCCESS;
1251: break;
1252:
1253: case TDI_ASSOCIATE_ADDRESS:
1254: Status = StTdiAssociateAddress (Irp);
1255: break;
1256:
1257: case TDI_DISASSOCIATE_ADDRESS:
1258: Status = StTdiDisassociateAddress (Irp);
1259: break;
1260:
1261: case TDI_CONNECT:
1262: Status = StTdiConnect (Irp);
1263: break;
1264:
1265: case TDI_DISCONNECT:
1266: Status = StTdiDisconnect (Irp);
1267: break;
1268:
1269: case TDI_LISTEN:
1270: Status = StTdiListen (Irp);
1271: break;
1272:
1273: case TDI_QUERY_INFORMATION:
1274: Status = StTdiQueryInformation (DeviceContext, Irp);
1275: break;
1276:
1277: case TDI_RECEIVE:
1278: Status = StTdiReceive (Irp);
1279: break;
1280:
1281: case TDI_RECEIVE_DATAGRAM:
1282: Status = StTdiReceiveDatagram (Irp);
1283: break;
1284:
1285: case TDI_SEND:
1286: Status = StTdiSend (Irp);
1287: break;
1288:
1289: case TDI_SEND_DATAGRAM:
1290: Status = StTdiSendDatagram (Irp);
1291: break;
1292:
1293: case TDI_SET_EVENT_HANDLER:
1294:
1295: //
1296: // Because this request will enable direct callouts from the
1297: // transport provider at DISPATCH_LEVEL to a client-specified
1298: // routine, this request is only valid in kernel mode, denying
1299: // access to this request in user mode.
1300: //
1301:
1302: Status = StTdiSetEventHandler (Irp);
1303: break;
1304:
1305: case TDI_SET_INFORMATION:
1306: Status = StTdiSetInformation (Irp);
1307: break;
1308:
1309:
1310: //
1311: // Something we don't know about was submitted.
1312: //
1313:
1314: default:
1315: Status = STATUS_INVALID_DEVICE_REQUEST;
1316: }
1317:
1318: if (Status != STATUS_PENDING) {
1319: IrpSp->Control &= ~SL_PENDING_RETURNED;
1320: Irp->IoStatus.Status = Status;
1321: IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
1322: }
1323:
1324:
1325: //
1326: // Return the immediate status code to the caller.
1327: //
1328:
1329: return Status;
1330:
1331: } /* StDispatchInternal */
1332:
1333:
1334: VOID
1335: StWriteResourceErrorLog(
1336: IN PDEVICE_CONTEXT DeviceContext,
1337: IN ULONG BytesNeeded,
1338: IN ULONG UniqueErrorValue
1339: )
1340:
1341: /*++
1342:
1343: Routine Description:
1344:
1345: This routine allocates and writes an error log entry indicating
1346: an out of resources condition.
1347:
1348: Arguments:
1349:
1350: DeviceContext - Pointer to the device context.
1351:
1352: BytesNeeded - If applicable, the number of bytes that could not
1353: be allocated.
1354:
1355: UniqueErrorValue - Used as the UniqueErrorValue in the error log
1356: packet.
1357:
1358: Return Value:
1359:
1360: None.
1361:
1362: --*/
1363:
1364: {
1365: PIO_ERROR_LOG_PACKET errorLogEntry;
1366: UCHAR EntrySize;
1367: PUCHAR StringLoc;
1368: ULONG TempUniqueError;
1369: static WCHAR UniqueErrorBuffer[4] = L"000";
1370: UINT i;
1371:
1372:
1373: EntrySize = sizeof(IO_ERROR_LOG_PACKET) +
1374: DeviceContext->DeviceNameLength +
1375: sizeof(UniqueErrorBuffer);
1376:
1377: errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
1378: (PDEVICE_OBJECT)DeviceContext,
1379: EntrySize
1380: );
1381:
1382: //
1383: // Convert the error value into a buffer.
1384: //
1385:
1386: TempUniqueError = UniqueErrorValue;
1387: for (i=1; i>=0; i--) {
1388: UniqueErrorBuffer[i] = (WCHAR)((TempUniqueError % 10) + L'0');
1389: TempUniqueError /= 10;
1390: }
1391:
1392: if (errorLogEntry != NULL) {
1393:
1394: errorLogEntry->MajorFunctionCode = (UCHAR)-1;
1395: errorLogEntry->RetryCount = (UCHAR)-1;
1396: errorLogEntry->DumpDataSize = sizeof(ULONG);
1397: errorLogEntry->NumberOfStrings = 2;
1398: errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET);
1399: errorLogEntry->EventCategory = 0;
1400: errorLogEntry->ErrorCode = EVENT_TRANSPORT_RESOURCE_POOL;
1401: errorLogEntry->UniqueErrorValue = UniqueErrorValue;
1402: errorLogEntry->FinalStatus = STATUS_INSUFFICIENT_RESOURCES;
1403: errorLogEntry->SequenceNumber = (ULONG)-1;
1404: errorLogEntry->IoControlCode = 0;
1405: errorLogEntry->DumpData[0] = BytesNeeded;
1406:
1407: StringLoc = ((PUCHAR)errorLogEntry) + errorLogEntry->StringOffset;
1408: RtlCopyMemory (StringLoc, DeviceContext->DeviceName, DeviceContext->DeviceNameLength);
1409:
1410: StringLoc += DeviceContext->DeviceNameLength;
1411: RtlCopyMemory (StringLoc, UniqueErrorBuffer, sizeof(UniqueErrorBuffer));
1412:
1413: IoWriteErrorLogEntry(errorLogEntry);
1414:
1415: }
1416:
1417: } /* StWriteResourceErrorLog */
1418:
1419:
1420: VOID
1421: StWriteGeneralErrorLog(
1422: IN PDEVICE_CONTEXT DeviceContext,
1423: IN NTSTATUS ErrorCode,
1424: IN ULONG UniqueErrorValue,
1425: IN NTSTATUS FinalStatus,
1426: IN PWSTR SecondString,
1427: IN ULONG DumpDataCount,
1428: IN ULONG DumpData[]
1429: )
1430:
1431: /*++
1432:
1433: Routine Description:
1434:
1435: This routine allocates and writes an error log entry indicating
1436: a general problem as indicated by the parameters. It handles
1437: event codes REGISTER_FAILED, BINDING_FAILED, ADAPTER_NOT_FOUND,
1438: TRANSFER_DATA, TOO_MANY_LINKS, and BAD_PROTOCOL. All these
1439: events have messages with one or two strings in them.
1440:
1441: Arguments:
1442:
1443: DeviceContext - Pointer to the device context, or this may be
1444: a driver object instead.
1445:
1446: ErrorCode - The transport event code.
1447:
1448: UniqueErrorValue - Used as the UniqueErrorValue in the error log
1449: packet.
1450:
1451: FinalStatus - Used as the FinalStatus in the error log packet.
1452:
1453: SecondString - If not NULL, the string to use as the %3
1454: value in the error log packet.
1455:
1456: DumpDataCount - The number of ULONGs of dump data.
1457:
1458: DumpData - Dump data for the packet.
1459:
1460: Return Value:
1461:
1462: None.
1463:
1464: --*/
1465:
1466: {
1467: PIO_ERROR_LOG_PACKET errorLogEntry;
1468: UCHAR EntrySize;
1469: ULONG SecondStringSize;
1470: PUCHAR StringLoc;
1471: static WCHAR DriverName[3] = L"St";
1472:
1473: EntrySize = sizeof(IO_ERROR_LOG_PACKET) +
1474: (DumpDataCount * sizeof(ULONG));
1475:
1476: if (DeviceContext->Type == IO_TYPE_DEVICE) {
1477: EntrySize += (UCHAR)DeviceContext->DeviceNameLength;
1478: } else {
1479: EntrySize += sizeof(DriverName);
1480: }
1481:
1482: if (SecondString) {
1483: SecondStringSize = (wcslen(SecondString)*sizeof(WCHAR)) + sizeof(UNICODE_NULL);
1484: EntrySize += (UCHAR)SecondStringSize;
1485: }
1486:
1487: errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
1488: (PDEVICE_OBJECT)DeviceContext,
1489: EntrySize
1490: );
1491:
1492: if (errorLogEntry != NULL) {
1493:
1494: errorLogEntry->MajorFunctionCode = (UCHAR)-1;
1495: errorLogEntry->RetryCount = (UCHAR)-1;
1496: errorLogEntry->DumpDataSize = (USHORT)(DumpDataCount * sizeof(ULONG));
1497: errorLogEntry->NumberOfStrings = (SecondString == NULL) ? 1 : 2;
1498: errorLogEntry->StringOffset =
1499: sizeof(IO_ERROR_LOG_PACKET) + ((DumpDataCount-1) * sizeof(ULONG));
1500: errorLogEntry->EventCategory = 0;
1501: errorLogEntry->ErrorCode = ErrorCode;
1502: errorLogEntry->UniqueErrorValue = UniqueErrorValue;
1503: errorLogEntry->FinalStatus = FinalStatus;
1504: errorLogEntry->SequenceNumber = (ULONG)-1;
1505: errorLogEntry->IoControlCode = 0;
1506:
1507: if (DumpDataCount) {
1508: RtlCopyMemory(errorLogEntry->DumpData, DumpData, DumpDataCount * sizeof(ULONG));
1509: }
1510:
1511: StringLoc = ((PUCHAR)errorLogEntry) + errorLogEntry->StringOffset;
1512: if (DeviceContext->Type == IO_TYPE_DEVICE) {
1513: RtlCopyMemory (StringLoc, DeviceContext->DeviceName, DeviceContext->DeviceNameLength);
1514: StringLoc += DeviceContext->DeviceNameLength;
1515: } else {
1516: RtlCopyMemory (StringLoc, DriverName, sizeof(DriverName));
1517: StringLoc += sizeof(DriverName);
1518: }
1519: if (SecondString) {
1520: RtlCopyMemory (StringLoc, SecondString, SecondStringSize);
1521: }
1522:
1523: IoWriteErrorLogEntry(errorLogEntry);
1524:
1525: }
1526:
1527: } /* StWriteGeneralErrorLog */
1528:
1529:
1530: VOID
1531: StWriteOidErrorLog(
1532: IN PDEVICE_CONTEXT DeviceContext,
1533: IN NTSTATUS ErrorCode,
1534: IN NTSTATUS FinalStatus,
1535: IN PWSTR AdapterString,
1536: IN ULONG OidValue
1537: )
1538:
1539: /*++
1540:
1541: Routine Description:
1542:
1543: This routine allocates and writes an error log entry indicating
1544: a problem querying or setting an OID on an adapter. It handles
1545: event codes SET_OID_FAILED and QUERY_OID_FAILED.
1546:
1547: Arguments:
1548:
1549: DeviceContext - Pointer to the device context.
1550:
1551: ErrorCode - Used as the ErrorCode in the error log packet.
1552:
1553: FinalStatus - Used as the FinalStatus in the error log packet.
1554:
1555: AdapterString - The name of the adapter we were bound to.
1556:
1557: OidValue - The OID which could not be set or queried.
1558:
1559: Return Value:
1560:
1561: None.
1562:
1563: --*/
1564:
1565: {
1566: PIO_ERROR_LOG_PACKET errorLogEntry;
1567: UCHAR EntrySize;
1568: ULONG AdapterStringSize;
1569: PUCHAR StringLoc;
1570: static WCHAR OidBuffer[9] = L"00000000";
1571: UINT i;
1572: UINT CurrentDigit;
1573:
1574: AdapterStringSize = (wcslen(AdapterString)*sizeof(WCHAR)) + sizeof(UNICODE_NULL);
1575: EntrySize = sizeof(IO_ERROR_LOG_PACKET) -
1576: sizeof(ULONG) +
1577: DeviceContext->DeviceNameLength +
1578: AdapterStringSize +
1579: sizeof(OidBuffer);
1580:
1581: errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
1582: (PDEVICE_OBJECT)DeviceContext,
1583: EntrySize
1584: );
1585:
1586: //
1587: // Convert the OID into a buffer.
1588: //
1589:
1590: for (i=7; i>=0; i--) {
1591: CurrentDigit = OidValue & 0xf;
1592: OidValue >>= 4;
1593: if (CurrentDigit >= 0xa) {
1594: OidBuffer[i] = (WCHAR)(CurrentDigit - 0xa + L'A');
1595: } else {
1596: OidBuffer[i] = (WCHAR)(CurrentDigit + L'0');
1597: }
1598: }
1599:
1600: if (errorLogEntry != NULL) {
1601:
1602: errorLogEntry->MajorFunctionCode = (UCHAR)-1;
1603: errorLogEntry->RetryCount = (UCHAR)-1;
1604: errorLogEntry->DumpDataSize = 0;
1605: errorLogEntry->NumberOfStrings = 3;
1606: errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET) - sizeof(ULONG);
1607: errorLogEntry->EventCategory = 0;
1608: errorLogEntry->ErrorCode = ErrorCode;
1609: errorLogEntry->UniqueErrorValue = 0;
1610: errorLogEntry->FinalStatus = FinalStatus;
1611: errorLogEntry->SequenceNumber = (ULONG)-1;
1612: errorLogEntry->IoControlCode = 0;
1613:
1614: StringLoc = ((PUCHAR)errorLogEntry) + errorLogEntry->StringOffset;
1615: RtlCopyMemory (StringLoc, DeviceContext->DeviceName, DeviceContext->DeviceNameLength);
1616: StringLoc += DeviceContext->DeviceNameLength;
1617:
1618: RtlCopyMemory (StringLoc, OidBuffer, sizeof(OidBuffer));
1619: StringLoc += sizeof(OidBuffer);
1620:
1621: RtlCopyMemory (StringLoc, AdapterString, AdapterStringSize);
1622:
1623: IoWriteErrorLogEntry(errorLogEntry);
1624:
1625: }
1626:
1627: } /* StWriteOidErrorLog */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.