1 /* 2 * PROJECT: ReactOS PCI Bus driver 3 * FILE: pci.c 4 * PURPOSE: Driver entry 5 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 6 * UPDATE HISTORY: 7 * 10-09-2001 CSH Created 8 */ 9 10 #include "pci.h" 11 12 #include <stdio.h> 13 14 #define NDEBUG 15 #include <debug.h> 16 17 static DRIVER_DISPATCH PciDispatchDeviceControl; 18 static NTSTATUS NTAPI PciDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 19 20 static DRIVER_ADD_DEVICE PciAddDevice; 21 static NTSTATUS NTAPI PciAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject); 22 23 static DRIVER_DISPATCH PciPowerControl; 24 static NTSTATUS NTAPI PciPowerControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 25 26 static DRIVER_DISPATCH PciPnpControl; 27 static NTSTATUS NTAPI PciPnpControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); 28 29 /*** PUBLIC ******************************************************************/ 30 31 PPCI_DRIVER_EXTENSION DriverExtension = NULL; 32 BOOLEAN HasDebuggingDevice = FALSE; 33 PCI_TYPE1_CFG_CYCLE_BITS PciDebuggingDevice[2] = {0}; 34 35 /*** PRIVATE *****************************************************************/ 36 37 static NTSTATUS 38 NTAPI 39 PciDispatchDeviceControl( 40 IN PDEVICE_OBJECT DeviceObject, 41 IN PIRP Irp) 42 { 43 PIO_STACK_LOCATION IrpSp; 44 NTSTATUS Status; 45 46 UNREFERENCED_PARAMETER(DeviceObject); 47 DPRINT("Called. IRP is at (0x%p)\n", Irp); 48 49 Irp->IoStatus.Information = 0; 50 51 IrpSp = IoGetCurrentIrpStackLocation(Irp); 52 switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) 53 { 54 default: 55 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->Parameters.DeviceIoControl.IoControlCode); 56 Status = STATUS_NOT_IMPLEMENTED; 57 break; 58 } 59 60 if (Status != STATUS_PENDING) 61 { 62 Irp->IoStatus.Status = Status; 63 64 DPRINT("Completing IRP at 0x%p\n", Irp); 65 66 IoCompleteRequest(Irp, IO_NO_INCREMENT); 67 } 68 69 DPRINT("Leaving. Status 0x%X\n", Status); 70 71 return Status; 72 } 73 74 75 static NTSTATUS 76 NTAPI 77 PciPnpControl( 78 IN PDEVICE_OBJECT DeviceObject, 79 IN PIRP Irp) 80 /* 81 * FUNCTION: Handle Plug and Play IRPs 82 * ARGUMENTS: 83 * DeviceObject = Pointer to PDO or FDO 84 * Irp = Pointer to IRP that should be handled 85 * RETURNS: 86 * Status 87 */ 88 { 89 PCOMMON_DEVICE_EXTENSION DeviceExtension; 90 NTSTATUS Status; 91 92 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 93 94 DPRINT("IsFDO %u\n", DeviceExtension->IsFDO); 95 96 if (DeviceExtension->IsFDO) 97 { 98 Status = FdoPnpControl(DeviceObject, Irp); 99 } 100 else 101 { 102 Status = PdoPnpControl(DeviceObject, Irp); 103 } 104 105 return Status; 106 } 107 108 109 static NTSTATUS 110 NTAPI 111 PciPowerControl( 112 IN PDEVICE_OBJECT DeviceObject, 113 IN PIRP Irp) 114 /* 115 * FUNCTION: Handle power management IRPs 116 * ARGUMENTS: 117 * DeviceObject = Pointer to PDO or FDO 118 * Irp = Pointer to IRP that should be handled 119 * RETURNS: 120 * Status 121 */ 122 { 123 PCOMMON_DEVICE_EXTENSION DeviceExtension; 124 NTSTATUS Status; 125 126 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 127 128 if (DeviceExtension->IsFDO) 129 { 130 Status = FdoPowerControl(DeviceObject, Irp); 131 } 132 else 133 { 134 Status = PdoPowerControl(DeviceObject, Irp); 135 } 136 137 return Status; 138 } 139 140 141 static NTSTATUS 142 NTAPI 143 PciAddDevice( 144 IN PDRIVER_OBJECT DriverObject, 145 IN PDEVICE_OBJECT PhysicalDeviceObject) 146 { 147 PFDO_DEVICE_EXTENSION DeviceExtension; 148 PDEVICE_OBJECT Fdo; 149 NTSTATUS Status; 150 151 DPRINT("Called\n"); 152 if (PhysicalDeviceObject == NULL) 153 return STATUS_SUCCESS; 154 155 Status = IoCreateDevice(DriverObject, 156 sizeof(FDO_DEVICE_EXTENSION), 157 NULL, 158 FILE_DEVICE_BUS_EXTENDER, 159 FILE_DEVICE_SECURE_OPEN, 160 TRUE, 161 &Fdo); 162 if (!NT_SUCCESS(Status)) 163 { 164 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status); 165 return Status; 166 } 167 168 DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension; 169 170 RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION)); 171 172 DeviceExtension->Common.IsFDO = TRUE; 173 174 DeviceExtension->Ldo = IoAttachDeviceToDeviceStack(Fdo, 175 PhysicalDeviceObject); 176 177 DeviceExtension->State = dsStopped; 178 179 Fdo->Flags &= ~DO_DEVICE_INITIALIZING; 180 181 //Fdo->Flags |= DO_POWER_PAGABLE; 182 183 DPRINT("Done AddDevice\n"); 184 185 return STATUS_SUCCESS; 186 } 187 188 DRIVER_UNLOAD PciUnload; 189 190 VOID 191 NTAPI 192 PciUnload( 193 IN PDRIVER_OBJECT DriverObject) 194 { 195 /* The driver object extension is destroyed by the I/O manager */ 196 UNREFERENCED_PARAMETER(DriverObject); 197 } 198 199 static 200 CODE_SEG("INIT") 201 VOID 202 PciLocateKdDevices(VOID) 203 { 204 ULONG i; 205 NTSTATUS Status; 206 WCHAR KeyNameBuffer[16]; 207 ULONG BusNumber, SlotNumber; 208 RTL_QUERY_REGISTRY_TABLE QueryTable[3]; 209 210 RtlZeroMemory(QueryTable, sizeof(QueryTable)); 211 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; 212 QueryTable[0].Name = L"Bus"; 213 QueryTable[0].EntryContext = &BusNumber; 214 QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; 215 QueryTable[1].Name = L"Slot"; 216 QueryTable[1].EntryContext = &SlotNumber; 217 218 for (i = 0; i < RTL_NUMBER_OF(PciDebuggingDevice); ++i) 219 { 220 PCI_SLOT_NUMBER PciSlot; 221 222 RtlStringCbPrintfW(KeyNameBuffer, sizeof(KeyNameBuffer), L"PCI\\Debug\\%d", i); 223 224 Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, 225 KeyNameBuffer, 226 QueryTable, 227 NULL, 228 NULL); 229 if (!NT_SUCCESS(Status)) 230 return; 231 232 HasDebuggingDevice = TRUE; 233 234 PciSlot.u.AsULONG = SlotNumber; 235 PciDebuggingDevice[i].DeviceNumber = PciSlot.u.bits.DeviceNumber; 236 PciDebuggingDevice[i].FunctionNumber = PciSlot.u.bits.FunctionNumber; 237 PciDebuggingDevice[i].BusNumber = BusNumber; 238 PciDebuggingDevice[i].InUse = TRUE; 239 240 DPRINT1("PCI debugging device %02x:%02x.%x\n", 241 BusNumber, 242 PciSlot.u.bits.DeviceNumber, 243 PciSlot.u.bits.FunctionNumber); 244 } 245 } 246 247 CODE_SEG("INIT") 248 NTSTATUS 249 NTAPI 250 DriverEntry( 251 IN PDRIVER_OBJECT DriverObject, 252 IN PUNICODE_STRING RegistryPath) 253 { 254 NTSTATUS Status; 255 256 UNREFERENCED_PARAMETER(RegistryPath); 257 DPRINT("Peripheral Component Interconnect Bus Driver\n"); 258 259 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PciDispatchDeviceControl; 260 DriverObject->MajorFunction[IRP_MJ_PNP] = PciPnpControl; 261 DriverObject->MajorFunction[IRP_MJ_POWER] = PciPowerControl; 262 DriverObject->DriverExtension->AddDevice = PciAddDevice; 263 DriverObject->DriverUnload = PciUnload; 264 265 Status = IoAllocateDriverObjectExtension(DriverObject, 266 DriverObject, 267 sizeof(PCI_DRIVER_EXTENSION), 268 (PVOID*)&DriverExtension); 269 if (!NT_SUCCESS(Status)) 270 return Status; 271 272 RtlZeroMemory(DriverExtension, sizeof(PCI_DRIVER_EXTENSION)); 273 274 InitializeListHead(&DriverExtension->BusListHead); 275 KeInitializeSpinLock(&DriverExtension->BusListLock); 276 277 PciLocateKdDevices(); 278 279 return STATUS_SUCCESS; 280 } 281 282 283 NTSTATUS 284 PciCreateDeviceIDString(PUNICODE_STRING DeviceID, 285 PPCI_DEVICE Device) 286 { 287 WCHAR Buffer[256]; 288 289 swprintf(Buffer, 290 L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X", 291 Device->PciConfig.VendorID, 292 Device->PciConfig.DeviceID, 293 (Device->PciConfig.u.type0.SubSystemID << 16) + 294 Device->PciConfig.u.type0.SubVendorID, 295 Device->PciConfig.RevisionID); 296 297 return RtlCreateUnicodeString(DeviceID, Buffer) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; 298 } 299 300 301 NTSTATUS 302 PciCreateInstanceIDString(PUNICODE_STRING InstanceID, 303 PPCI_DEVICE Device) 304 { 305 WCHAR Buffer[3]; 306 307 swprintf(Buffer, L"%02X", Device->SlotNumber.u.AsULONG & 0xff); 308 309 return RtlCreateUnicodeString(InstanceID, Buffer) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; 310 } 311 312 313 NTSTATUS 314 PciCreateHardwareIDsString(PUNICODE_STRING HardwareIDs, 315 PPCI_DEVICE Device) 316 { 317 WCHAR Buffer[256]; 318 UNICODE_STRING BufferU; 319 ULONG Index; 320 321 Index = 0; 322 Index += swprintf(&Buffer[Index], 323 L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X", 324 Device->PciConfig.VendorID, 325 Device->PciConfig.DeviceID, 326 (Device->PciConfig.u.type0.SubSystemID << 16) + 327 Device->PciConfig.u.type0.SubVendorID, 328 Device->PciConfig.RevisionID); 329 Index++; 330 331 Index += swprintf(&Buffer[Index], 332 L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X", 333 Device->PciConfig.VendorID, 334 Device->PciConfig.DeviceID, 335 (Device->PciConfig.u.type0.SubSystemID << 16) + 336 Device->PciConfig.u.type0.SubVendorID); 337 Index++; 338 339 Index += swprintf(&Buffer[Index], 340 L"PCI\\VEN_%04X&DEV_%04X&CC_%02X%02X%02X", 341 Device->PciConfig.VendorID, 342 Device->PciConfig.DeviceID, 343 Device->PciConfig.BaseClass, 344 Device->PciConfig.SubClass, 345 Device->PciConfig.ProgIf); 346 Index++; 347 348 Index += swprintf(&Buffer[Index], 349 L"PCI\\VEN_%04X&DEV_%04X&CC_%02X%02X", 350 Device->PciConfig.VendorID, 351 Device->PciConfig.DeviceID, 352 Device->PciConfig.BaseClass, 353 Device->PciConfig.SubClass); 354 Index++; 355 356 Buffer[Index] = UNICODE_NULL; 357 358 BufferU.Length = BufferU.MaximumLength = (USHORT) Index * sizeof(WCHAR); 359 BufferU.Buffer = Buffer; 360 361 return PciDuplicateUnicodeString(0, &BufferU, HardwareIDs); 362 } 363 364 365 NTSTATUS 366 PciCreateCompatibleIDsString(PUNICODE_STRING CompatibleIDs, 367 PPCI_DEVICE Device) 368 { 369 WCHAR Buffer[256]; 370 UNICODE_STRING BufferU; 371 ULONG Index; 372 373 Index = 0; 374 Index += swprintf(&Buffer[Index], 375 L"PCI\\VEN_%04X&DEV_%04X&REV_%02X", 376 Device->PciConfig.VendorID, 377 Device->PciConfig.DeviceID, 378 Device->PciConfig.RevisionID); 379 Index++; 380 381 Index += swprintf(&Buffer[Index], 382 L"PCI\\VEN_%04X&DEV_%04X", 383 Device->PciConfig.VendorID, 384 Device->PciConfig.DeviceID); 385 Index++; 386 387 Index += swprintf(&Buffer[Index], 388 L"PCI\\VEN_%04X&CC_%02X%02X%02X", 389 Device->PciConfig.VendorID, 390 Device->PciConfig.BaseClass, 391 Device->PciConfig.SubClass, 392 Device->PciConfig.ProgIf); 393 Index++; 394 395 Index += swprintf(&Buffer[Index], 396 L"PCI\\VEN_%04X&CC_%02X%02X", 397 Device->PciConfig.VendorID, 398 Device->PciConfig.BaseClass, 399 Device->PciConfig.SubClass); 400 Index++; 401 402 Index += swprintf(&Buffer[Index], 403 L"PCI\\VEN_%04X", 404 Device->PciConfig.VendorID); 405 Index++; 406 407 Index += swprintf(&Buffer[Index], 408 L"PCI\\CC_%02X%02X%02X", 409 Device->PciConfig.BaseClass, 410 Device->PciConfig.SubClass, 411 Device->PciConfig.ProgIf); 412 Index++; 413 414 Index += swprintf(&Buffer[Index], 415 L"PCI\\CC_%02X%02X", 416 Device->PciConfig.BaseClass, 417 Device->PciConfig.SubClass); 418 Index++; 419 420 Buffer[Index] = UNICODE_NULL; 421 422 BufferU.Length = BufferU.MaximumLength = (USHORT)Index * sizeof(WCHAR); 423 BufferU.Buffer = Buffer; 424 425 return PciDuplicateUnicodeString(0, &BufferU, CompatibleIDs); 426 } 427 428 429 NTSTATUS 430 PciCreateDeviceDescriptionString(PUNICODE_STRING DeviceDescription, 431 PPCI_DEVICE Device) 432 { 433 PCWSTR Description; 434 435 switch (Device->PciConfig.BaseClass) 436 { 437 case PCI_CLASS_PRE_20: 438 switch (Device->PciConfig.SubClass) 439 { 440 case PCI_SUBCLASS_PRE_20_VGA: 441 Description = L"VGA device"; 442 break; 443 444 default: 445 case PCI_SUBCLASS_PRE_20_NON_VGA: 446 Description = L"PCI device"; 447 break; 448 } 449 break; 450 451 case PCI_CLASS_MASS_STORAGE_CTLR: 452 switch (Device->PciConfig.SubClass) 453 { 454 case PCI_SUBCLASS_MSC_SCSI_BUS_CTLR: 455 Description = L"SCSI controller"; 456 break; 457 458 case PCI_SUBCLASS_MSC_IDE_CTLR: 459 Description = L"IDE controller"; 460 break; 461 462 case PCI_SUBCLASS_MSC_FLOPPY_CTLR: 463 Description = L"Floppy disk controller"; 464 break; 465 466 case PCI_SUBCLASS_MSC_IPI_CTLR: 467 Description = L"IPI controller"; 468 break; 469 470 case PCI_SUBCLASS_MSC_RAID_CTLR: 471 Description = L"RAID controller"; 472 break; 473 474 default: 475 Description = L"Mass storage controller"; 476 break; 477 } 478 break; 479 480 case PCI_CLASS_NETWORK_CTLR: 481 switch (Device->PciConfig.SubClass) 482 { 483 case PCI_SUBCLASS_NET_ETHERNET_CTLR: 484 Description = L"Ethernet controller"; 485 break; 486 487 case PCI_SUBCLASS_NET_TOKEN_RING_CTLR: 488 Description = L"Token-Ring controller"; 489 break; 490 491 case PCI_SUBCLASS_NET_FDDI_CTLR: 492 Description = L"FDDI controller"; 493 break; 494 495 case PCI_SUBCLASS_NET_ATM_CTLR: 496 Description = L"ATM controller"; 497 break; 498 499 default: 500 Description = L"Network controller"; 501 break; 502 } 503 break; 504 505 case PCI_CLASS_DISPLAY_CTLR: 506 switch (Device->PciConfig.SubClass) 507 { 508 case PCI_SUBCLASS_VID_VGA_CTLR: 509 Description = L"VGA display controller"; 510 break; 511 512 case PCI_SUBCLASS_VID_XGA_CTLR: 513 Description = L"XGA display controller"; 514 break; 515 516 case PCI_SUBCLASS_VID_3D_CTLR: 517 Description = L"Multimedia display controller"; 518 break; 519 520 default: 521 Description = L"Other display controller"; 522 break; 523 } 524 break; 525 526 case PCI_CLASS_MULTIMEDIA_DEV: 527 switch (Device->PciConfig.SubClass) 528 { 529 case PCI_SUBCLASS_MM_VIDEO_DEV: 530 Description = L"Multimedia video device"; 531 break; 532 533 case PCI_SUBCLASS_MM_AUDIO_DEV: 534 Description = L"Multimedia audio device"; 535 break; 536 537 case PCI_SUBCLASS_MM_TELEPHONY_DEV: 538 Description = L"Multimedia telephony device"; 539 break; 540 541 default: 542 Description = L"Other multimedia device"; 543 break; 544 } 545 break; 546 547 case PCI_CLASS_MEMORY_CTLR: 548 switch (Device->PciConfig.SubClass) 549 { 550 case PCI_SUBCLASS_MEM_RAM: 551 Description = L"PCI Memory"; 552 break; 553 554 case PCI_SUBCLASS_MEM_FLASH: 555 Description = L"PCI Flash Memory"; 556 break; 557 558 default: 559 Description = L"Other memory controller"; 560 break; 561 } 562 break; 563 564 case PCI_CLASS_BRIDGE_DEV: 565 switch (Device->PciConfig.SubClass) 566 { 567 case PCI_SUBCLASS_BR_HOST: 568 Description = L"PCI-Host bridge"; 569 break; 570 571 case PCI_SUBCLASS_BR_ISA: 572 Description = L"PCI-ISA bridge"; 573 break; 574 575 case PCI_SUBCLASS_BR_EISA: 576 Description = L"PCI-EISA bridge"; 577 break; 578 579 case PCI_SUBCLASS_BR_MCA: 580 Description = L"PCI-Micro Channel bridge"; 581 break; 582 583 case PCI_SUBCLASS_BR_PCI_TO_PCI: 584 Description = L"PCI-PCI bridge"; 585 break; 586 587 case PCI_SUBCLASS_BR_PCMCIA: 588 Description = L"PCI-PCMCIA bridge"; 589 break; 590 591 case PCI_SUBCLASS_BR_NUBUS: 592 Description = L"PCI-NUBUS bridge"; 593 break; 594 595 case PCI_SUBCLASS_BR_CARDBUS: 596 Description = L"PCI-CARDBUS bridge"; 597 break; 598 599 default: 600 Description = L"Other bridge device"; 601 break; 602 } 603 break; 604 605 case PCI_CLASS_SIMPLE_COMMS_CTLR: 606 switch (Device->PciConfig.SubClass) 607 { 608 609 default: 610 Description = L"Communication device"; 611 break; 612 } 613 break; 614 615 case PCI_CLASS_BASE_SYSTEM_DEV: 616 switch (Device->PciConfig.SubClass) 617 { 618 619 default: 620 Description = L"System device"; 621 break; 622 } 623 break; 624 625 case PCI_CLASS_INPUT_DEV: 626 switch (Device->PciConfig.SubClass) 627 { 628 629 default: 630 Description = L"Input device"; 631 break; 632 } 633 break; 634 635 case PCI_CLASS_DOCKING_STATION: 636 switch (Device->PciConfig.SubClass) 637 { 638 639 default: 640 Description = L"Docking station"; 641 break; 642 } 643 break; 644 645 case PCI_CLASS_PROCESSOR: 646 switch (Device->PciConfig.SubClass) 647 { 648 649 default: 650 Description = L"Processor"; 651 break; 652 } 653 break; 654 655 case PCI_CLASS_SERIAL_BUS_CTLR: 656 switch (Device->PciConfig.SubClass) 657 { 658 case PCI_SUBCLASS_SB_IEEE1394: 659 Description = L"FireWire controller"; 660 break; 661 662 case PCI_SUBCLASS_SB_ACCESS: 663 Description = L"ACCESS bus controller"; 664 break; 665 666 case PCI_SUBCLASS_SB_SSA: 667 Description = L"SSA controller"; 668 break; 669 670 case PCI_SUBCLASS_SB_USB: 671 Description = L"USB controller"; 672 break; 673 674 case PCI_SUBCLASS_SB_FIBRE_CHANNEL: 675 Description = L"Fibre Channel controller"; 676 break; 677 678 case PCI_SUBCLASS_SB_SMBUS: 679 Description = L"SMBus controller"; 680 break; 681 682 default: 683 Description = L"Other serial bus controller"; 684 break; 685 } 686 break; 687 688 default: 689 Description = L"Other PCI Device"; 690 break; 691 } 692 693 return RtlCreateUnicodeString(DeviceDescription, Description) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; 694 } 695 696 697 NTSTATUS 698 PciCreateDeviceLocationString(PUNICODE_STRING DeviceLocation, 699 PPCI_DEVICE Device) 700 { 701 WCHAR Buffer[256]; 702 703 swprintf(Buffer, 704 L"PCI-Bus %lu, Device %u, Function %u", 705 Device->BusNumber, 706 Device->SlotNumber.u.bits.DeviceNumber, 707 Device->SlotNumber.u.bits.FunctionNumber); 708 709 return RtlCreateUnicodeString(DeviceLocation, Buffer) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; 710 } 711 712 NTSTATUS 713 PciDuplicateUnicodeString( 714 IN ULONG Flags, 715 IN PCUNICODE_STRING SourceString, 716 OUT PUNICODE_STRING DestinationString) 717 { 718 if (SourceString == NULL || 719 DestinationString == NULL || 720 SourceString->Length > SourceString->MaximumLength || 721 (SourceString->Length == 0 && SourceString->MaximumLength > 0 && SourceString->Buffer == NULL) || 722 Flags == RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING || 723 Flags >= 4) 724 { 725 return STATUS_INVALID_PARAMETER; 726 } 727 728 if ((SourceString->Length == 0) && 729 (Flags != (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE | 730 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING))) 731 { 732 DestinationString->Length = 0; 733 DestinationString->MaximumLength = 0; 734 DestinationString->Buffer = NULL; 735 } 736 else 737 { 738 USHORT DestMaxLength = SourceString->Length; 739 740 if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE) 741 DestMaxLength += sizeof(UNICODE_NULL); 742 743 DestinationString->Buffer = ExAllocatePoolWithTag(PagedPool, DestMaxLength, TAG_PCI); 744 if (DestinationString->Buffer == NULL) 745 return STATUS_NO_MEMORY; 746 747 RtlCopyMemory(DestinationString->Buffer, SourceString->Buffer, SourceString->Length); 748 DestinationString->Length = SourceString->Length; 749 DestinationString->MaximumLength = DestMaxLength; 750 751 if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE) 752 DestinationString->Buffer[DestinationString->Length / sizeof(WCHAR)] = 0; 753 } 754 755 return STATUS_SUCCESS; 756 } 757 758 /* EOF */ 759