Bug in the cdrom.sys driver for Win2K.

Here is the snipit of code in error from the DDK for the cdrom.sys driver.
The module name is cdrom.c.
The cdrom.sys driver does not assign the suffix number correctly to the
device name/symbolic link name when there is another cdrom driver installed
in the system. The ‘CdRomCounter’ variable below is used to generate the
device name and symbolic link suffix name below.

Example

//device/cdrom%d where %d is equal to CdRomCounter.

//Snipit of Code Begin
NTSTATUS
CdRomAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)

/*++

Routine Description:

This routine creates and initializes a new FDO for the corresponding
PDO. It may perform property queries on the FDO but cannot do any
media access operations.

Arguments:

DriverObject - CDROM class driver object.

Pdo - the physical device object we are being added to

Return Value:

status

–*/

{
NTSTATUS status;

PAGED_CODE();

//
// Get the address of the count of the number of cdroms already
initialized.
//

status = CreateCdRomDeviceObject(
DriverObject,
PhysicalDeviceObject,
CdRomCounter);

//
// Note: this always increments CdRomCounter
// it will eventually wrap, and fail additions
// if an existing cdrom has the given number.
// so unlikely that we won’t even bother considering
// this case, since the cure is quite likely worse
// than the symptoms.
//

if(NT_SUCCESS(status)) {
DebugPrint((2, “CDROM.SYS Add #%x succeeded\n”,CdRomCounter));
IoGetConfigurationInformation()->CdRomCount++;
CdRomCounter++;
} else {
DebugPrint((1, “CDROM.SYS Add #%x failed! %x\n”,CdRomCounter,
status));
}

return status;
}
//Snipit of Code End

The CdRomCounter variable is a global counter which is assigned to zero to
begin with. If the CdRom.sys driver was the only driver in the system that
controlled CdRoms for that system, then there is no
problem. But, if there are multiple drivers on a system that control CdRoms
then there is a problem. The code above is using it’s own internal counter
to generate the device names. It does not
call IoGetConfigurationInformation to get the number of CdRomCounts already
seen by the system. An even better solution would be to do what the disk
driver did. This code is taken from a snipit of code from the DDK for the
disk.sys driver. Module Name disk.c, Function Name DiskCreateFdo().

//Snipit of Code Begin
*DeviceCount = 0;

//
// Set up an object directory to contain the objects for this
// device and all its partitions.
//

do {

WCHAR buffer[64];
UNICODE_STRING unicodeDirectoryName;

swprintf(buffer, L"\Device\Harddisk%d", *DeviceCount);

RtlInitUnicodeString(&unicodeDirectoryName, buffer);

InitializeObjectAttributes(&objectAttributes,
&unicodeDirectoryName,
OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
NULL,
NULL);

status = ZwCreateDirectoryObject(&handle,
DIRECTORY_ALL_ACCESS,
&objectAttributes);

(*DeviceCount)++;

} while((status == STATUS_OBJECT_NAME_COLLISION) ||
(status == STATUS_OBJECT_NAME_EXISTS));

if (!NT_SUCCESS(status)) {

DebugPrint((1, “DiskCreateFdo: Could not create directory - %lx\n”,
status));

return(status);
}

//
// When this loop exits the count is inflated by one - fix that.
//

(*DeviceCount)–;

//
// Claim the device.
//

lowerDevice = IoGetAttachedDeviceReference(PhysicalDeviceObject);

status = ClassClaimDevice(lowerDevice, FALSE);

if (!NT_SUCCESS(status)) {
ZwMakeTemporaryObject(handle);
ZwClose(handle);
ObDereferenceObject(lowerDevice);
return status;
}

//
// Create a device object for this device. Each physical disk will
// have at least one device object. The required device object
// describes the entire device. Its directory path is
// \Device\HarddiskN\Partition0, where N = device number.
//

status = DiskGenerateDeviceName(TRUE,
*DeviceCount,
0,
NULL,
NULL,
&deviceName);

if(!NT_SUCCESS(status)) {
DebugPrint((1, “DiskCreateFdo - couldn’t create name %lx\n”,
status));

goto DiskCreateFdoExit;

}
// End Snipit of Code

The disk driver above first searches the device name space looking for an
open suffix number to use. In this case:

swprintf(buffer, L"\Device\Harddisk%d", *DeviceCount);

It will not come out of this while loop until it has found an open device
name. This will ensure that
if there is another disk driver in the system assigning device names that
the two will not interfere with each other in assigning those names.

In conclusion, if you are writing your own cdrom device driver and you need
to use Microsoft’s cdrom driver as well. Then you will have a problem with
the two assigning identical device names because Microsoft’s driver only
assumes that it is the only driver assigning device names for cdroms. In my
case, my cdrom driver loaded first and grabbed \Device\CdRom0, then
Microsoft’s cdrom driver loaded and tried to assign \Device\CdRom0 for the
USB cdrom attached to our system. It failed it’s AddDevice entry because it
was already assigned to the other cdrom in the system controlled by my
driver. The user is unable to access the cdrom on the USB bus. Major
problem. If I could get around PnP driver order loading, then I could fix
this by loading my driver second. But my driver is loaded first even when
the tag ordering value I supply in the SCSI CDROM Group is after the
cdrom.sys drivers tag value.

I have tried Service Pack 1 and still get the same problem. I sure hope
this can get fixed for Service Pack 2.

Thanks,
Joe


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

class driver is the only driver which manage its own devices. Just do not
use \device\cdrom%d name in your driver. for example in my cdrom driver I
use \device\xxxCdrom_%d, where xxx is the name of my company.

You can develop a scsi miniport for your own cdrom, in this case cdrom.sys
enumerate your device automatically.

Regards,
Max Lyadvinsky


??: Joe Moriarty[SMTP:xxxxx@east.sun.com]
???: NT Developers Interest List
???: 9 ??? 2001 ?. 0:06
???: NT Developers Interest List
???: SunPCI Team; NT Development List
???: [ntdev] Bug in the cdrom.sys driver for Win2K.

Here is the snipit of code in error from the DDK for the cdrom.sys driver.
The module name is cdrom.c.
The cdrom.sys driver does not assign the suffix number correctly to the
device name/symbolic link name when there is another cdrom driver installed
in the system. The ‘CdRomCounter’ variable below is used to generate the
device name and symbolic link suffix name below.

Example

//device/cdrom%d where %d is equal to CdRomCounter.

//Snipit of Code Begin
NTSTATUS
CdRomAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)

/*++

Routine Description:

This routine creates and initializes a new FDO for the corresponding
PDO. It may perform property queries on the FDO but cannot do any
media access operations.

Arguments:

DriverObject - CDROM class driver object.

Pdo - the physical device object we are being added to

Return Value:

status

–*/

{
NTSTATUS status;

PAGED_CODE();

//
// Get the address of the count of the number of cdroms already
initialized.
//

status = CreateCdRomDeviceObject(
DriverObject,
PhysicalDeviceObject,
CdRomCounter);

//
// Note: this always increments CdRomCounter
// it will eventually wrap, and fail additions
// if an existing cdrom has the given number.
// so unlikely that we won’t even bother considering
// this case, since the cure is quite likely worse
// than the symptoms.
//

if(NT_SUCCESS(status)) {
DebugPrint((2, “CDROM.SYS Add #%x succeeded\n”,CdRomCounter));
IoGetConfigurationInformation()->CdRomCount++;
CdRomCounter++;
} else {
DebugPrint((1, “CDROM.SYS Add #%x failed! %x\n”,CdRomCounter,
status));
}

return status;
}
//Snipit of Code End

The CdRomCounter variable is a global counter which is assigned to zero to
begin with. If the CdRom.sys driver was the only driver in the system that
controlled CdRoms for that system, then there is no
problem. But, if there are multiple drivers on a system that control
CdRoms
then there is a problem. The code above is using it’s own internal counter
to generate the device names. It does not
call IoGetConfigurationInformation to get the number of CdRomCounts already
seen by the system. An even better solution would be to do what the disk
driver did. This code is taken from a snipit of code from the DDK for the
disk.sys driver. Module Name disk.c, Function Name DiskCreateFdo().

//Snipit of Code Begin
*DeviceCount = 0;

//
// Set up an object directory to contain the objects for this
// device and all its partitions.
//

do {

WCHAR buffer[64];
UNICODE_STRING unicodeDirectoryName;

swprintf(buffer, L"\Device\Harddisk%d", *DeviceCount);

RtlInitUnicodeString(&unicodeDirectoryName, buffer);

InitializeObjectAttributes(&objectAttributes,
&unicodeDirectoryName,
OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
NULL,
NULL);

status = ZwCreateDirectoryObject(&handle,
DIRECTORY_ALL_ACCESS,
&objectAttributes);

(*DeviceCount)++;

} while((status == STATUS_OBJECT_NAME_COLLISION) ||
(status == STATUS_OBJECT_NAME_EXISTS));

if (!NT_SUCCESS(status)) {

DebugPrint((1, “DiskCreateFdo: Could not create directory - %lx\n”,
status));

return(status);
}

//
// When this loop exits the count is inflated by one - fix that.
//

(*DeviceCount)–;

//
// Claim the device.
//

lowerDevice = IoGetAttachedDeviceReference(PhysicalDeviceObject);

status = ClassClaimDevice(lowerDevice, FALSE);

if (!NT_SUCCESS(status)) {
ZwMakeTemporaryObject(handle);
ZwClose(handle);
ObDereferenceObject(lowerDevice);
return status;
}

//
// Create a device object for this device. Each physical disk will
// have at least one device object. The required device object
// describes the entire device. Its directory path is
// \Device\HarddiskN\Partition0, where N = device number.
//

status = DiskGenerateDeviceName(TRUE,
*DeviceCount,
0,
NULL,
NULL,
&deviceName);

if(!NT_SUCCESS(status)) {
DebugPrint((1, “DiskCreateFdo - couldn’t create name %lx\n”,
status));

goto DiskCreateFdoExit;

}
// End Snipit of Code

The disk driver above first searches the device name space looking for an
open suffix number to use. In this case:

swprintf(buffer, L"\Device\Harddisk%d", *DeviceCount);

It will not come out of this while loop until it has found an open device
name. This will ensure that
if there is another disk driver in the system assigning device names that
the two will not interfere with each other in assigning those names.

In conclusion, if you are writing your own cdrom device driver and you need
to use Microsoft’s cdrom driver as well. Then you will have a problem with
the two assigning identical device names because Microsoft’s driver only
assumes that it is the only driver assigning device names for cdroms. In
my
case, my cdrom driver loaded first and grabbed \Device\CdRom0, then
Microsoft’s cdrom driver loaded and tried to assign \Device\CdRom0 for
the
USB cdrom attached to our system. It failed it’s AddDevice entry because
it
was already assigned to the other cdrom in the system controlled by my
driver. The user is unable to access the cdrom on the USB bus. Major
problem. If I could get around PnP driver order loading, then I could fix
this by loading my driver second. But my driver is loaded first even when
the tag ordering value I supply in the SCSI CDROM Group is after the
cdrom.sys drivers tag value.

I have tried Service Pack 1 and still get the same problem. I sure hope
this can get fixed for Service Pack 2.

Thanks,
Joe


You are currently subscribed to ntdev as: xxxxx@zelmail.ru
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

Hi,

I had this problem too. In fact, you cannot solve this by tweaking with the
load order because there may always arrive new cd-rom devices after yours.

For me the solution was quite easier than expected. Just let cdrom.sys name
its devices \Device\CdRom%d and give your devices another name. The “dos
name” can still be \DosDevices\CdRom%d because cdrom.sys does this
correctly. (See CdRomCreateWellKnownName() in cdrom.c)

Best regards,
Detlef Golze


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

Changing the device name causes the system too not show my cdrom in disk
administrator. It does let the other cdrom on the USB bus to come up. But
I still think you need the device name to be \Device\CdRom%d for the system
to recognize your cdrom under disk administrator. If your cdrom does not
show up under disk administrator then there is no way for the user to assign
a different drive letter for your cdrom. Do you have this same problem.

Joe

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of xxxxx@gmx.de
Sent: Wednesday, May 09, 2001 12:00 AM
To: NT Developers Interest List
Subject: [ntdev] Re: Bug in the cdrom.sys driver for Win2K.

Hi,

I had this problem too. In fact, you cannot solve this by tweaking with the
load order because there may always arrive new cd-rom devices after yours.

For me the solution was quite easier than expected. Just let cdrom.sys name
its devices \Device\CdRom%d and give your devices another name. The “dos
name” can still be \DosDevices\CdRom%d because cdrom.sys does this
correctly. (See CdRomCreateWellKnownName() in cdrom.c)

Best regards,
Detlef Golze


You are currently subscribed to ntdev as: xxxxx@east.sun.com
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com