Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

356 lines
9.6 KiB

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
locintrf.c
Abstract:
This module implements the device location interface
supported by the PCI driver.
This interface reports the bus-relative location identifier
string(s) of a given device.
Author:
Davis Walker (dwalker) 5 December 2001
Revision History:
--*/
#include "pcip.h"
#define LOCINTRF_VERSION 1
//
// The length - in characters - of the Multi-Sz strings returned from the interface.
// count one extra character for the MultiSz second terminator
//
#define PCI_LOCATION_STRING_COUNT (sizeof "PCI(XXXX)" + 1)
#define PCIROOT_LOCATION_STRING_COUNT (sizeof "PCIROOT(XX)" + 1)
//
// Prototypes for routines exposed only through the "interface"
// mechanism.
//
NTSTATUS
locintrf_Constructor(
IN PVOID DeviceExtension,
IN PVOID PciInterface,
IN PVOID InterfaceSpecificData,
IN USHORT Version,
IN USHORT Size,
IN PINTERFACE InterfaceReturn
);
VOID
locintrf_Reference(
IN PVOID Context
);
VOID
locintrf_Dereference(
IN PVOID Context
);
NTSTATUS
locintrf_Initializer(
IN PVOID Instance
);
NTSTATUS
PciGetLocationStrings(
IN PVOID Context,
OUT PWCHAR *LocationStrings
);
//
// Define this interface's PCI_INTERFACE structure.
//
PCI_INTERFACE PciLocationInterface = {
&GUID_PNP_LOCATION_INTERFACE, // InterfaceType
sizeof(PNP_LOCATION_INTERFACE), // MinSize
LOCINTRF_VERSION, // MinVersion
LOCINTRF_VERSION, // MaxVersion
PCIIF_PDO | PCIIF_FDO | PCIIF_ROOT, // Flags - supported on PDOs and root FDOs
0, // ReferenceCount
PciInterface_Location, // Signature
locintrf_Constructor, // Constructor
locintrf_Initializer // Instance Initializer
};
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, locintrf_Constructor)
#pragma alloc_text(PAGE, locintrf_Dereference)
#pragma alloc_text(PAGE, locintrf_Initializer)
#pragma alloc_text(PAGE, locintrf_Reference)
#pragma alloc_text(PAGE, PciGetLocationStrings)
#endif
NTSTATUS
locintrf_Constructor(
IN PVOID DeviceExtension,
IN PVOID PciInterface,
IN PVOID InterfaceSpecificData,
IN USHORT Version,
IN USHORT Size,
IN PINTERFACE InterfaceReturn
)
/*++
Routine Description:
This routine constructs a PNP_LOCATION_INTERFACE.
Arguments:
DeviceExtension - An extension pointer.
PCIInterface - PciInterface_Location.
InterfaceSpecificData - Unused.
Version - Interface version.
Size - Size of the PNP_LOCATION_INTERFACE interface object.
InterfaceReturn - The interface object pointer to be filled in.
Return Value:
Returns NTSTATUS.
--*/
{
PPNP_LOCATION_INTERFACE interface;
interface = (PPNP_LOCATION_INTERFACE)InterfaceReturn;
interface->Size = sizeof(PNP_LOCATION_INTERFACE);
interface->Version = LOCINTRF_VERSION;
interface->Context = DeviceExtension;
interface->InterfaceReference = locintrf_Reference;
interface->InterfaceDereference = locintrf_Dereference;
interface->GetLocationString = PciGetLocationStrings;
return STATUS_SUCCESS;
}
NTSTATUS
locintrf_Initializer(
IN PVOID Instance
)
/*++
Routine Description:
For the location interface, this does nothing, shouldn't actually be called.
Arguments:
Instance - FDO extension pointer.
Return Value:
Returns NTSTATUS.
--*/
{
ASSERTMSG("PCI locintrf_Initializer, unexpected call.", FALSE);
return STATUS_UNSUCCESSFUL;
}
VOID
locintrf_Reference(
IN PVOID Context
)
/*++
Routine Description:
This routine adds a reference to a location interface.
Arguments:
Context - device extension pointer.
Return Value:
None.
--*/
{
}
VOID
locintrf_Dereference(
IN PVOID Context
)
/*++
Routine Description:
This routine releases a reference to a location interface.
Arguments:
Context - extension pointer.
Return Value:
None.
--*/
{
}
NTSTATUS
PciGetLocationStrings(
IN PVOID Context,
OUT PWCHAR *LocationStrings
)
/*++
Routine Description:
This routine allocates, fills in, and returns a Multi-Sz string
containing the bus-relative location identifier string for the
given device.
For a PCI device, this is "PCI(XXYY)", where XX is the device
number of the device, and YY is the function number of the device.
For a PCI root bus, this is PCIROOT(XX), where XX is the bus number
of the root bus. This relies on the fact that bus numbers of root
buses will not change, which is believed to be a safe assumption
for some time to come.
This interface is permitted to return a Multi-Sz containing
multiple strings describing the same device, but in this
first implementation, only the single strings listed above
will be returned from the interface. The string must still
be in the format of a Multi-Sz, however, meaning a double-NULL
terminator is required.
Arguments:
Context - extension pointer.
Return Value:
NTSTATUS code.
--*/
{
PPCI_COMMON_EXTENSION extension = (PPCI_COMMON_EXTENSION)Context;
PPCI_PDO_EXTENSION pdoExtension;
PPCI_FDO_EXTENSION rootExtension;
PWCHAR stringBuffer;
PCI_SLOT_NUMBER slotNumber;
SIZE_T remainingChars;
BOOLEAN ok;
if (extension->ExtensionType == PciPdoExtensionType) {
pdoExtension = (PPCI_PDO_EXTENSION)extension;
slotNumber = pdoExtension->Slot;
stringBuffer = ExAllocatePoolWithTag(PagedPool,PCI_LOCATION_STRING_COUNT*sizeof(WCHAR),'coLP');
if (!stringBuffer) {
*LocationStrings = NULL;
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// The location string for a PCI device is "PCI(XXYY)"
// where XX is the device number and YY is the function number
// We use the STRSAFE_FILL_BEHIND_NULL flag to ensure the unused portion
// of the buffer is filled with 0s which null terminates the multsz
//
ok = SUCCEEDED(StringCchPrintfExW(stringBuffer,
PCI_LOCATION_STRING_COUNT,
NULL,
&remainingChars,
STRSAFE_FILL_BEHIND_NULL,
L"PCI(%.2X%.2X)",
slotNumber.u.bits.DeviceNumber,
slotNumber.u.bits.FunctionNumber
));
ASSERT(ok);
//
// Make sure there was room for the multisz termination NUL
// N.B. remainingChars counts the NUL terminatiun of the regular string
// as being available so we need to ensure 2 chars are left for the 2 NULS
//
ASSERT(remainingChars >= 2);
*LocationStrings = stringBuffer;
return STATUS_SUCCESS;
} else {
rootExtension = (PPCI_FDO_EXTENSION)extension;
ASSERT(PCI_IS_ROOT_FDO(rootExtension));
if (PCI_IS_ROOT_FDO(rootExtension)) {
stringBuffer = ExAllocatePoolWithTag(PagedPool,PCIROOT_LOCATION_STRING_COUNT*sizeof(WCHAR),'coLP');
if (!stringBuffer) {
*LocationStrings = NULL;
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// The location string for a PCI root is "PCIROOT(X)"
// where X is the bus number of root bus.
// We use the STRSAFE_FILL_BEHIND_NULL flag to ensure the unused portion
// of the buffer is filled with 0s which null terminates the multsz
//
ok = SUCCEEDED(StringCchPrintfExW(stringBuffer,
PCIROOT_LOCATION_STRING_COUNT,
NULL,
&remainingChars,
STRSAFE_FILL_BEHIND_NULL,
L"PCIROOT(%X)",
rootExtension->BaseBus
));
ASSERT(ok);
//
// Make sure there was room for the multisz termination NUL
// N.B. remainingChars counts the NUL terminatiun of the regular string
// as being available so we need to ensure 2 chars are left for the 2 NULS
//
ASSERT(remainingChars >= 2);
*LocationStrings = stringBuffer;
//
// returning STATUS_TRANSLATION_COMPLETE indicates that PnP shouldn't
// query for this interface any further up the tree. Stop here.
//
return STATUS_TRANSLATION_COMPLETE;
} else {
//
// In the interface constructor, we specified that this interface
// is only valid for root FDOs. If we get here, we've been asked
// to fill in this interface for a P-P bridge FDO, which is illegal.
//
*LocationStrings = NULL;
return STATUS_INVALID_PARAMETER;
}
}
}