?? pnp.c
字號:
/*
* NTKERN expects a new pointer each time it calls QUERY_DEVICE_RELATIONS;
* it then FREES THE POINTER.
* So we have to return a new pointer each time, whether or not we actually
* created our copy of the device relations for this call.
*/
irp->IoStatus.Information = (ULONG)CopyDeviceRelations(parentFdoExt->deviceRelations);
if (irp->IoStatus.Information){
ULONG i;
/*
* The kernel dereferences each device object
* in the device relations list after each call.
* So for each call, add an extra reference.
*/
for (i = 0; i < parentFdoExt->deviceRelations->Count; i++){
ObReferenceObject(parentFdoExt->deviceRelations->Objects[i]);
parentFdoExt->deviceRelations->Objects[i]->Flags &= ~DO_DEVICE_INITIALIZING;
}
DBGVERBOSE(("Returned %d child PDOs", parentFdoExt->deviceRelations->Count));
status = STATUS_SUCCESS;
}
else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
ASSERT(NT_SUCCESS(status));
}
else {
ASSERT(irpSp->Parameters.QueryDeviceRelations.Type == BusRelations);
status = irp->IoStatus.Status;
}
return status;
}
NTSTATUS PDO_PnP(POSPDOEXT *pdoExt, PIRP irp)
{
NTSTATUS status;
PIO_STACK_LOCATION irpSp;
irpSp = IoGetCurrentIrpStackLocation(irp);
DBG_LOG_PNP_IRP(irp, irpSp->MinorFunction, TRUE, FALSE, -1);
switch (irpSp->MinorFunction){
case IRP_MN_START_DEVICE:
status = CreateSymbolicLink(pdoExt);
if (NT_SUCCESS(status)){
pdoExt->state = STATE_STARTED;
/*
* Initializing URB to read the status endpoint for Serial Emulation.
*/
if(pdoExt->parentFdoExt->posFlag & SERIAL_EMULATION) {
StatusPipe(pdoExt, pdoExt->statusEndpointInfo.pipeHandle);
DBGVERBOSE(("PDO_PnP: URB to read Status Endpoint initialized"));
}
}
else {
pdoExt->state = STATE_START_FAILED;
}
break;
case IRP_MN_QUERY_STOP_DEVICE:
status = STATUS_SUCCESS;
break;
case IRP_MN_STOP_DEVICE:
pdoExt->state = STATE_STOPPED;
status = STATUS_SUCCESS;
break;
case IRP_MN_SURPRISE_REMOVAL:
status = FlushBuffers(pdoExt);
break;
case IRP_MN_REMOVE_DEVICE:
{
ULONG oldState = pdoExt->state;
KIRQL oldIrql;
BOOLEAN foundPdo = FALSE;
ULONG i;
pdoExt->state = STATE_REMOVED;
if ((oldState == STATE_STARTED) || (oldState == STATE_STOPPED)){
DestroySymbolicLink(pdoExt);
}
else {
DBGWARN(("previous state is %xh during pdo REMOVE_DEVICE", oldState));
}
/*
* See if this child PDO is still in the parent's device relations array.
*/
KeAcquireSpinLock(&pdoExt->parentFdoExt->devExtSpinLock, &oldIrql);
for (i = 0; i < pdoExt->parentFdoExt->deviceRelations->Count; i++){
if (pdoExt->parentFdoExt->deviceRelations->Objects[i] == pdoExt->pdo){
foundPdo = TRUE;
}
}
KeReleaseSpinLock(&pdoExt->parentFdoExt->devExtSpinLock, oldIrql);
FlushBuffers(pdoExt);
if (foundPdo){
/*
* If we are still in the parent's deviceRelations, then don't
* free the pdo or pdoName.Buffer . We may get another START
* on this same PDO.
*/
}
else {
/*
* This shouldn't happen.
*/
ASSERT(foundPdo);
/*
* We've recorded this COM port statically in our software key,
* so don't free it in the COM name arbiter.
*/
// ReleaseCOMPort(pdoExt->comPortNumber);
DeleteChildPdo(pdoExt);
}
status = STATUS_SUCCESS;
}
break;
case IRP_MN_QUERY_ID:
status = QueryPdoID(pdoExt, irp);
break;
case IRP_MN_QUERY_CAPABILITIES:
ASSERT(irpSp->Parameters.DeviceCapabilities.Capabilities);
RtlCopyMemory( irpSp->Parameters.DeviceCapabilities.Capabilities,
&pdoExt->parentFdoExt->deviceCapabilities,
sizeof(DEVICE_CAPABILITIES));
/*
* Set the 'Raw' capability so that the child PDO gets started immediately,
* without anyone having to do an open on it first.
*/
irpSp->Parameters.DeviceCapabilities.Capabilities->RawDeviceOK = TRUE;
irpSp->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = TRUE;
status = STATUS_SUCCESS;
break;
case IRP_MN_QUERY_PNP_DEVICE_STATE:
status = CallNextDriverSync(pdoExt->parentFdoExt, irp);
break;
case IRP_MN_QUERY_DEVICE_RELATIONS:
if (irpSp->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation){
/*
* Return a reference to this PDO
*/
PDEVICE_RELATIONS devRel = ALLOCPOOL(PagedPool, sizeof(DEVICE_RELATIONS));
if (devRel){
/*
* Add a reference to the PDO, since CONFIGMG will free it.
*/
ObReferenceObject(pdoExt->pdo);
devRel->Objects[0] = pdoExt->pdo;
devRel->Count = 1;
irp->IoStatus.Information = (ULONG_PTR)devRel;
status = STATUS_SUCCESS;
}
else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
}
else {
/*
* Fail this Irp by returning the default
* status (typically STATUS_NOT_SUPPORTED).
*/
DBGVERBOSE(("PDO_PnP: not handling QueryDeviceRelations type %xh.", (ULONG)irpSp->Parameters.QueryDeviceRelations.Type));
status = irp->IoStatus.Status;
}
break;
default:
/*
* Fail the IRP with the default status
*/
status = irp->IoStatus.Status;
break;
}
DBG_LOG_PNP_IRP(irp, irpSp->MinorFunction, TRUE, TRUE, status);
return status;
}
NTSTATUS SubstituteOneBusName(PWCHAR hwId)
{
NTSTATUS status;
ULONG len = WStrLen(hwId);
if ((len > 4) && !WStrNCmpI(hwId, L"USB\\", 4)){
hwId[0] = L'P';
hwId[1] = L'O';
hwId[2] = L'S';
status = STATUS_SUCCESS;
}
else {
DBGERR(("SubstituteOneBusName: badly formed name at %ph.", hwId));
status = STATUS_UNSUCCESSFUL;
}
return status;
}
/*
* SubstituteBusNames
*
* busNames is a multi-string of PnP ids.
* Subsitute 'POS\' for 'USB\' in each one.
*/
NTSTATUS SubstituteBusNames(PWCHAR busNames)
{
NTSTATUS status = STATUS_SUCCESS;
while (*busNames && (status == STATUS_SUCCESS)){
ULONG len = WStrLen(busNames);
status = SubstituteOneBusName(busNames);
busNames += (len+1);
}
ASSERT(NT_SUCCESS(status));
return status;
}
NTSTATUS QueryPdoID(POSPDOEXT *pdoExt, PIRP irp)
{
PIO_STACK_LOCATION irpSp;
NTSTATUS status;
PAGED_CODE();
irpSp = IoGetCurrentIrpStackLocation(irp);
DBGVERBOSE((" QueryPdoId: idType = %xh ", irpSp->Parameters.QueryId.IdType));
switch (irpSp->Parameters.QueryId.IdType){
case BusQueryHardwareIDs:
/*
* Return a multi-string containing the PnP ID for the POS serial interface.
* Must terminate multi-string with a double unicode null.
*/
(PWCHAR)irp->IoStatus.Information =
MemDup(L"POS\\POS_SERIAL_INTERFACE\0", sizeof(L"POS\\POS_SERIAL_INTERFACE\0"));
if (irp->IoStatus.Information){
status = STATUS_SUCCESS;
}
else {
ASSERT(irp->IoStatus.Information);
status = STATUS_INSUFFICIENT_RESOURCES;
}
break;
case BusQueryDeviceID:
/*
* Return the PnP ID for the POS serial interface.
*/
(PWCHAR)irp->IoStatus.Information =
MemDup(L"POS\\POS_SERIAL_INTERFACE", sizeof(L"POS\\POS_SERIAL_INTERFACE"));
if (irp->IoStatus.Information){
status = STATUS_SUCCESS;
}
else {
ASSERT(irp->IoStatus.Information);
status = STATUS_INSUFFICIENT_RESOURCES;
}
break;
case BusQueryInstanceID:
/*
* Produce an instance-id for this function-PDO.
*
* Note: NTKERN frees the returned pointer, so we must provide a fresh pointer.
*/
{
PWSTR instanceId = MemDup(L"0000", sizeof(L"0000"));
if (instanceId){
KIRQL oldIrql;
ULONG i;
/*
* Find this collection-PDO in the device-relations array
* and make the id be the PDO's index within that array.
*/
KeAcquireSpinLock(&pdoExt->parentFdoExt->devExtSpinLock, &oldIrql);
for (i = 0; i < pdoExt->parentFdoExt->deviceRelations->Count; i++){
if (pdoExt->parentFdoExt->deviceRelations->Objects[i] == pdoExt->pdo){
break;
}
}
if (i < pdoExt->parentFdoExt->deviceRelations->Count){
NumToDecString(instanceId, (USHORT)i, 4);
irp->IoStatus.Information = (ULONG)instanceId;
status = STATUS_SUCCESS;
}
else {
ASSERT(i < pdoExt->parentFdoExt->deviceRelations->Count);
status = STATUS_DEVICE_DATA_ERROR;
}
KeReleaseSpinLock(&pdoExt->parentFdoExt->devExtSpinLock, oldIrql);
if (!NT_SUCCESS(status)){
FREEPOOL(instanceId);
}
}
else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
}
ASSERT(NT_SUCCESS(status));
break;
case BusQueryCompatibleIDs:
/*
* Return multi-string of compatible IDs.
*/
(PWCHAR)irp->IoStatus.Information = MemDup(L"\0\0", sizeof(L"\0\0"));
if (irp->IoStatus.Information) {
status = STATUS_SUCCESS;
}
else {
ASSERT(irp->IoStatus.Information);
status = STATUS_INSUFFICIENT_RESOURCES;
}
break;
default:
/*
* Do not return STATUS_NOT_SUPPORTED;
* keep the default status
* (this allows filter drivers to work).
*/
status = irp->IoStatus.Status;
break;
}
return status;
}
VOID DeleteChildPdo(POSPDOEXT *pdoExt)
{
ASSERT(pdoExt->pdoName.Buffer);
FREEPOOL(pdoExt->pdoName.Buffer);
IoDeleteDevice(pdoExt->pdo);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -