[MMIXER] Fix additional data size initialization for different audio formats (#6753)
[reactos.git] / drivers / bus / pci / pci.c
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 */