334 lines
10 KiB
C
334 lines
10 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1994 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
findscsi.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Find what controller (if any) the ScsiAdapter hangs off of, so a
|
|||
|
symbolic link can be made between the ARC and NT names during
|
|||
|
SCSI cdrom initialization.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
John Cornelison (v-jcorn)
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
kernel mode only
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
Created to resolve NT Bug # 26354
|
|||
|
|
|||
|
Each call processes both a controller and the controller number.
|
|||
|
This routine can be called recursively since there may be an
|
|||
|
arbitary number of nesting controllers, although typically 0 or 1
|
|||
|
are most likely.
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "ntddk.h"
|
|||
|
#include "scsi.h"
|
|||
|
#include "class.h"
|
|||
|
#include "string.h"
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
FindScsiAdapter (
|
|||
|
IN HANDLE KeyHandle,
|
|||
|
IN UNICODE_STRING ScsiUnicodeString[],
|
|||
|
OUT PUCHAR IntermediateController
|
|||
|
);
|
|||
|
|
|||
|
#define INIT_OPEN_KEY(name, rootHandle, pNewHandle) \
|
|||
|
InitializeObjectAttributes( \
|
|||
|
&objectAttributes, \
|
|||
|
(name), \
|
|||
|
OBJ_CASE_INSENSITIVE, \
|
|||
|
(rootHandle), \
|
|||
|
NULL \
|
|||
|
); \
|
|||
|
\
|
|||
|
status = ZwOpenKey( \
|
|||
|
(pNewHandle), \
|
|||
|
KEY_READ | KEY_ENUMERATE_SUB_KEYS, \
|
|||
|
&objectAttributes \
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
FindScsiAdapter (
|
|||
|
IN HANDLE KeyHandle,
|
|||
|
IN UNICODE_STRING ScsiUnicodeString[],
|
|||
|
OUT UCHAR *IntermediateController
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Recursive routine to walk registry tree under KeyHandle looking for
|
|||
|
location of ScsiAdapter and other valid controllers that the ScsiAdapter
|
|||
|
might hang off of. When ScsiAdapter is found, FindScsiAdapter
|
|||
|
returns an ARC name for the intervening controller(s) between the
|
|||
|
original key and ScsiAdapter.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
KeyHandle -- Handle of open registry key (somewhere under
|
|||
|
\Registry\Machine\Hardware\Description\System)
|
|||
|
|
|||
|
ScsiUnicodeString -- NT name of SCSI device being sought in the registry
|
|||
|
|
|||
|
IntermediateController -- Null terminated buffer which this routine fills with
|
|||
|
ARC name for intervening controller(s). Null is returned
|
|||
|
if ScsiAdapter sits at the root or if it is not found.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS -- IntermediateController set to something like multi(1)
|
|||
|
|
|||
|
STATUS_OBJECT_PATH_NOT_FOUND -- all ok, but no ScsiAdapter
|
|||
|
(with correct scsi id & lun info) found; In this case
|
|||
|
IntermediateController is explicitly set to null.
|
|||
|
|
|||
|
Other status codes as returned by open\enumerate registry routines
|
|||
|
may also be returned.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS status;
|
|||
|
ULONG index;
|
|||
|
ULONG resultLength;
|
|||
|
UCHAR lowerController[64];
|
|||
|
BOOLEAN validControllerNumber;
|
|||
|
UNICODE_STRING unicodeString[64];
|
|||
|
OBJECT_ATTRIBUTES objectAttributes;
|
|||
|
|
|||
|
HANDLE controllerHandle;
|
|||
|
HANDLE controllerNumberHandle;
|
|||
|
ULONG controllerIndex;
|
|||
|
ULONG controllerNumberIndex;
|
|||
|
UCHAR keyBuffer[256]; // Allow for variable length name at end
|
|||
|
UCHAR numberKeyBuffer[64];
|
|||
|
PKEY_BASIC_INFORMATION pControllerKeyInformation;
|
|||
|
PKEY_BASIC_INFORMATION pControllerNumberKeyInformation;
|
|||
|
|
|||
|
// TODO: Any PAGED_CODE stuff...
|
|||
|
|
|||
|
//
|
|||
|
// Walk enumerated subkeys, looking for valid controllers
|
|||
|
//
|
|||
|
|
|||
|
for (controllerIndex = 0; TRUE; controllerIndex++) {
|
|||
|
|
|||
|
//
|
|||
|
// Ensure pControllerKeyInformation->Name is null terminated
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory(keyBuffer, sizeof(keyBuffer));
|
|||
|
|
|||
|
pControllerKeyInformation = (PKEY_BASIC_INFORMATION) keyBuffer;
|
|||
|
|
|||
|
status = ZwEnumerateKey(
|
|||
|
KeyHandle,
|
|||
|
controllerIndex,
|
|||
|
KeyBasicInformation,
|
|||
|
pControllerKeyInformation,
|
|||
|
sizeof(keyBuffer),
|
|||
|
&resultLength
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
|
|||
|
if (status != STATUS_NO_MORE_ENTRIES) {
|
|||
|
DebugPrint ((2, "FindScsiAdapter: Error 0x%x enumerating key\n", status));
|
|||
|
return(status);
|
|||
|
}
|
|||
|
|
|||
|
break; // return NOT_FOUND
|
|||
|
}
|
|||
|
|
|||
|
DebugPrint ((3, "FindScsiAdapter: Found Adapter=%S\n", pControllerKeyInformation->Name));
|
|||
|
|
|||
|
if (!_wcsicmp(pControllerKeyInformation->Name, L"ScsiAdapter")) {
|
|||
|
|
|||
|
//
|
|||
|
// Found scsi, now verify that it's the same one we're trying to initialize.
|
|||
|
//
|
|||
|
|
|||
|
INIT_OPEN_KEY (ScsiUnicodeString, KeyHandle, &controllerHandle);
|
|||
|
|
|||
|
ZwClose(controllerHandle);
|
|||
|
|
|||
|
if (NT_SUCCESS(status)) {
|
|||
|
|
|||
|
//
|
|||
|
// Found correct scsi, now build ARC name of IntermediateController
|
|||
|
// (i.e. the intervening controllers, or everything above ScsiAdapter)
|
|||
|
// start with null, and build string one controller at a time as we
|
|||
|
// return up the recursively called routine.
|
|||
|
//
|
|||
|
|
|||
|
IntermediateController = "\0";
|
|||
|
|
|||
|
return (STATUS_SUCCESS);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Found ScsiAdapter, but wrong scsi id or Lun info doesn't match,
|
|||
|
// (ignore other ZwOpenKey errors &) keep looking...
|
|||
|
//
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
else if (!_wcsicmp(pControllerKeyInformation->Name, L"MultifunctionAdapter") ||
|
|||
|
!_wcsicmp(pControllerKeyInformation->Name, L"EisaAdapter")) {
|
|||
|
|
|||
|
//
|
|||
|
// This is a valid controller that may have ScsiAdapter beneath it.
|
|||
|
// Open controller & walk controller's subkeys: 0, 1, 2, etc....
|
|||
|
//
|
|||
|
|
|||
|
RtlInitUnicodeString (unicodeString, pControllerKeyInformation->Name);
|
|||
|
|
|||
|
INIT_OPEN_KEY (unicodeString, KeyHandle, &controllerHandle);
|
|||
|
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
DebugPrint ((2, "FindScsiAdapter: ZwOpenKey got status = %x \n", status));
|
|||
|
ZwClose (controllerHandle);
|
|||
|
return (status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
for (controllerNumberIndex = 0; TRUE; controllerNumberIndex++) {
|
|||
|
|
|||
|
RtlZeroMemory(numberKeyBuffer, sizeof(numberKeyBuffer));
|
|||
|
|
|||
|
pControllerNumberKeyInformation = (PKEY_BASIC_INFORMATION) numberKeyBuffer;
|
|||
|
|
|||
|
status = ZwEnumerateKey(
|
|||
|
controllerHandle,
|
|||
|
controllerNumberIndex,
|
|||
|
KeyBasicInformation,
|
|||
|
pControllerNumberKeyInformation,
|
|||
|
sizeof(numberKeyBuffer),
|
|||
|
&resultLength
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
|
|||
|
if (status != STATUS_NO_MORE_ENTRIES) {
|
|||
|
DebugPrint ((2, "FindScsiAdapter: Status %x enumerating key\n", status));
|
|||
|
ZwClose(controllerHandle);
|
|||
|
return (status);
|
|||
|
}
|
|||
|
|
|||
|
ZwClose(controllerHandle);
|
|||
|
|
|||
|
break; // next controller
|
|||
|
}
|
|||
|
|
|||
|
DebugPrint ((3, "FindScsiAdapter: Found Adapter #=%S\n", pControllerNumberKeyInformation->Name));
|
|||
|
|
|||
|
validControllerNumber = TRUE;
|
|||
|
|
|||
|
for (index = 0; index < pControllerNumberKeyInformation->NameLength / 2; index++) {
|
|||
|
|
|||
|
if (!isxdigit(pControllerNumberKeyInformation->Name[index])) {
|
|||
|
validControllerNumber = FALSE;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (validControllerNumber) {
|
|||
|
|
|||
|
//
|
|||
|
// Found valid controller and controller number: check children for scsi.
|
|||
|
//
|
|||
|
|
|||
|
RtlInitUnicodeString (unicodeString, pControllerNumberKeyInformation->Name);
|
|||
|
|
|||
|
INIT_OPEN_KEY (unicodeString, controllerHandle, &controllerNumberHandle);
|
|||
|
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
DebugPrint ((2, "FindScsiAdapter: Status %x opening controller number key\n", status));
|
|||
|
ZwClose(controllerNumberHandle);
|
|||
|
ZwClose(controllerHandle);
|
|||
|
return (status);
|
|||
|
}
|
|||
|
|
|||
|
RtlZeroMemory(lowerController, sizeof(lowerController));
|
|||
|
|
|||
|
status = FindScsiAdapter(
|
|||
|
controllerNumberHandle,
|
|||
|
ScsiUnicodeString,
|
|||
|
&lowerController[0]
|
|||
|
);
|
|||
|
|
|||
|
ZwClose(controllerNumberHandle);
|
|||
|
|
|||
|
if (NT_SUCCESS(status)) {
|
|||
|
|
|||
|
//
|
|||
|
// SUCCESS!
|
|||
|
//
|
|||
|
// Scsi adapter DOES exist under this node,
|
|||
|
// prepend Arc Name for the current adapter to whatever was returned
|
|||
|
// by other calls to this routine.
|
|||
|
//
|
|||
|
|
|||
|
if (!_wcsicmp(pControllerKeyInformation->Name, L"MultifunctionAdapter")) {
|
|||
|
sprintf(IntermediateController, "multi(0)%s", lowerController);
|
|||
|
} else {
|
|||
|
sprintf(IntermediateController, "eisa(0)%s", lowerController);
|
|||
|
}
|
|||
|
|
|||
|
ZwClose(controllerHandle);
|
|||
|
|
|||
|
return(STATUS_SUCCESS);
|
|||
|
}
|
|||
|
|
|||
|
else if (status != STATUS_OBJECT_PATH_NOT_FOUND) {
|
|||
|
ZwClose(controllerHandle);
|
|||
|
return(status);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Scsi not found under this controller number, check next one
|
|||
|
//
|
|||
|
|
|||
|
} // if validControllerNumber
|
|||
|
|
|||
|
} // for controllerNumberIndex
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// ScsiAdapter not found under this controller
|
|||
|
//
|
|||
|
|
|||
|
ZwClose(controllerHandle);
|
|||
|
|
|||
|
} // else if valid subkey (i.e., scsi, multi, eisa)
|
|||
|
|
|||
|
} // for controllerIndex
|
|||
|
|
|||
|
//
|
|||
|
// ScsiAdapter not found under key we were called with
|
|||
|
//
|
|||
|
|
|||
|
IntermediateController = "\0";
|
|||
|
|
|||
|
return (STATUS_OBJECT_PATH_NOT_FOUND);
|
|||
|
}
|
|||
|
|