Re: fopen vs CreateFile Driver Access issue

MS’s C runtime library source is provided with the Visual Studio, you can
debug it.

I personally never ever used fopen() for driver’s control devices.

You also have another way - to associate the handle returned by CreateFile
with the UNIX-style “fd” by _open_osfhandle(), then associate “fd” with “struct
FILE” using _fdopen.


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

“Paul Ryan” wrote in message news:xxxxx@ntdev…
> Calling CreateFile directly works just fine as far as I can tell, however it
> concerns me that a call as basic as fopen is failing (and with mutiple
> implementations of fopen). I think this means there is something more
> fundamentally wrong with my driver. Also as was stated in the original email
> chain the point of using fopen is for portability of the user mode code.
> Sorry if I’m just being a pain but I really do want to understand the
> problem here.
>
> Thanks,
>
> Paul Ryan
>
> On Sun, Jun 8, 2008 at 1:07 AM, Maxim S. Shatskih
> wrote:
>
> > > behavior I’ve witnessed. When fopen is called it appears that at some
> > point
> > > another part of the process decides that my driver file is not proper and
> > > throws an error back out without ever calling the CreateFile.
> >
> > How about calling CreateFile directly?
> >
> > –
> > Maxim Shatskih, Windows DDK MVP
> > StorageCraft Corporation
> > xxxxx@storagecraft.com
> > http://www.storagecraft.com
> >
> >
> > —
> > NTDEV is sponsored by OSR
> >
> > For our schedule of WDF, WDM, debugging and other seminars visit:
> > http://www.osr.com/seminars
> >
> > To unsubscribe, visit the List Server section of OSR Online at
> > http://www.osronline.com/page.cfm?name=ListServer
> >
>

Well no that is not the right answer. Standalone control devices are fine
for things like filter drivers that need an administrative interface, but
are inappropriate for FDO IO targets and introduce needless complexity.
Instead the OP can either use a device interface (the recommended method) or
get the name of the PDO and use that to create the symbolic link.

Status= IoGetDeviceProperty(pdo,
DevicePropertyPhysicalDeviceObjectName,
(ULONG)(pdoName.MaximumLength - sizeof(UNICODE_NULL)),
pdoName.Buffer,
&stringLength);

On Sat, Jun 7, 2008 at 10:12 PM, wrote:

> > if I set null on the name how do I link this device to a dos device name
> so that it can be referenced
> > from the create file.
>
> This is why you have to create a standalone named device object that is
> not on the stack, and logically associate it with your FDO/filter that is on
> the stack. When you want to access your FDO/filter, you will send an IOCTL
> to the named standalone object, rather than device on the stack. This
> suggestion is based solely upon the security concerns - otherwise, if PDO
> and named FDO/filter have different user access permissions, by supplying
> the name of the least restrictively protected one in CreateFile() call you
> automatically gain an access to all devices on the stack…
>
> > //Store next-layered device object
> > //Attach device object to device stack
>
> > p_DVCEXT->NextDeviceObject = IoAttachDeviceToDeviceStack(ptr_PDO,
> PhysicalDeviceObject); >ptr_PDO->Flags &= ~DO_DEVICE_INITIALIZING;
>
> This is already a better option. In general, clearing
> DO_DEVICE_INITIALIZING flag should be done when you have done all
> initialization, so normally it gets done right before returning from
> AddDEvice(). Check any WDK sample, so that you will see it yourself…
>
> Anton Bassov
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>


Mark Roddy

> Calling CreateFile directly works just fine as far as I can tell, however it

concerns me that a call as basic as fopen is failing (and with mutiple
implementations of fopen). I think this means there is something more
fundamentally wrong with my driver.

Wrong and totally illogical conclusion!!! According to the above logic, if user-mode caller supplies wrong arguments to CreateFile() and system fails the call, then it must must be a driver’s, rather than caller’s, fault. The problem lies not with a driver but with fopen(), which, apparently, just supplies the wrong arguments to CreateFile().

BTW, I am not sure that you are supposed to use fopen() for opening device files , in the first place.
IIRC, GNU’s implementation of fopen() does not seem to work for opening device files on Linux - I tried it, but somehow failed, so that, from now on, I use only open() system call for this purpose. Therefore, if portability of your code between Windows and Linux is your primary objective, then you have met it - the code produces exactly the same results on both systems, i.e. does not work properly on either of them…

Anton Bassov

> Standalone control devices are fine for things like filter drivers that need an

administrative interface, but are inappropriate for FDO IO targets and introduce needless
complexity.

This is because, unlike filters, FDOs rarely require admin operations that are totally unrelated to the actual IO. However, the way I understood it, this is exactly what the OP wants to do - otherwise, there would be just no need to be bothered about FDO’s name, in the first place, because the OP would just use PDO’s name in his CreateFile() call …

Anton Bassov

With this particular argument I think we just hit on the extent of my
ignorance here. I don’t want to necessarily run extra admin operations on
the driver. I just need full IO access to the device through the file
descriptor (as we created this device, we understand the interrupt scheme
necessary for this once I get this naming issue worked out). I may have
inadvertently added a naming scheme here, to the FDO, that was
un-intentional. Could you please explain what I should have done if I just
wanted to name the PDO (something human readable). I think I might have made
this mistake in attempting to make the driver feel more unix like to the
user. I apologize for any confusion the code I posted might have caused in
this regard, again I am new to windows driver development.

My guess is that I would leave the IoCreateDevice name argument null then I
would discover the name prior to attach and set a dosdevice symlink to that
discovered name. Is this correct?

Paul Ryan

On Sun, Jun 8, 2008 at 12:13 PM, wrote:

> > Standalone control devices are fine for things like filter drivers that
> need an
> > administrative interface, but are inappropriate for FDO IO targets and
> introduce needless
> > complexity.
>
> This is because, unlike filters, FDOs rarely require admin operations that
> are totally unrelated to the actual IO. However, the way I understood it,
> this is exactly what the OP wants to do - otherwise, there would be just no
> need to be bothered about FDO’s name, in the first place, because the OP
> would just use PDO’s name in his CreateFile() call …
>
>
> Anton Bassov
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>


Paul Ryan
xxxxx@gmail.com

Right - I understood that - and you should use the PDO name to create your
symbolic link, or implement a device interface, which does essentially the
same thing but provides an obscure device name that you find through the
cumbersome setupdi apis. I’d go with the symlink for now. Yes leave the name
null and use the PDO.

On Sun, Jun 8, 2008 at 2:25 PM, Paul Ryan wrote:

> With this particular argument I think we just hit on the extent of my
> ignorance here. I don’t want to necessarily run extra admin operations on
> the driver. I just need full IO access to the device through the file
> descriptor (as we created this device, we understand the interrupt scheme
> necessary for this once I get this naming issue worked out). I may have
> inadvertently added a naming scheme here, to the FDO, that was
> un-intentional. Could you please explain what I should have done if I just
> wanted to name the PDO (something human readable). I think I might have made
> this mistake in attempting to make the driver feel more unix like to the
> user. I apologize for any confusion the code I posted might have caused in
> this regard, again I am new to windows driver development.
>
> My guess is that I would leave the IoCreateDevice name argument null then I
> would discover the name prior to attach and set a dosdevice symlink to that
> discovered name. Is this correct?
>
> Paul Ryan
>
>
> On Sun, Jun 8, 2008 at 12:13 PM, wrote:
>
>> > Standalone control devices are fine for things like filter drivers that
>> need an
>> > administrative interface, but are inappropriate for FDO IO targets and
>> introduce needless
>> > complexity.
>>
>> This is because, unlike filters, FDOs rarely require admin operations
>> that are totally unrelated to the actual IO. However, the way I understood
>> it, this is exactly what the OP wants to do - otherwise, there would be just
>> no need to be bothered about FDO’s name, in the first place, because the OP
>> would just use PDO’s name in his CreateFile() call …
>>
>>
>> Anton Bassov
>>
>> —
>> NTDEV is sponsored by OSR
>>
>> For our schedule of WDF, WDM, debugging and other seminars visit:
>> http://www.osr.com/seminars
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http://www.osronline.com/page.cfm?name=ListServer
>>
>
>
>
> –
> Paul Ryan
> xxxxx@gmail.com — NTDEV is sponsored by OSR For our schedule of WDF,
> WDM, debugging and other seminars visit: http://www.osr.com/seminars To
> unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer


Mark Roddy

> Could you please explain what I should have done if I just wanted to name

the PDO (something human readable).

You can choose either of the things below

1.Create a symlink to PDO’s name so that the user will be able to open it with CreateFile()

  1. Don’t be bothered about the name in a driver, and, instead of CreateFile() library function, use
    ZwCreateFile() system call in your app. If you do it this way you will be able to open PDO by its name

I would say that, for the sake of simplicity, it is better to take the former option, so that you will be able to hardcode your device name right in app’s code…

Anton Bassov

Ok I’ve done the symlink version using the example code from doron’s blog
but am still getting the same results. What’s odd is my create interupt
handler is getting called:

NTSTATUS
PsdoDispatchCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PIO_STACK_LOCATION p_IO_STK;
PDEVICE_EXTENSION p_DVCEXT;
NTSTATUS status;
DbgPrint(“In print device\n”);

p_IO_STK = IoGetCurrentIrpStackLocation(Irp);
p_DVCEXT = DeviceObject->DeviceExtension;
status = IoAcquireRemoveLock(&p_DVCEXT->RemoveLock,
p_IO_STK->FileObject);
if (NT_SUCCESS(status)) {
DbgPrint(“Lock remove success\n”);
CompleteRequest(Irp, STATUS_SUCCESS, 0);
return STATUS_SUCCESS;
} else {
DbgPrint(“Lock remove failure\n”);
IoReleaseRemoveLock(&p_DVCEXT->RemoveLock, p_IO_STK->FileObject);
CompleteRequest(Irp, status, 0);
return status;
}
}

as the Lock remove success is being printed in the debugger, however the
client right away exits with the error because the file descriptor pointer
is null. My new modified code is:
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
DbgPrint(“In driver entry: begin\n”);
RtlInitUnicodeString(
&Global_sz_Drv_RegInfo,
RegistryPath->Buffer);

// Initialize function pointers

DriverObject->DriverUnload = DriverUnload;
//DriverObject->DriverStartIo = (PVOID)StartIo;
DriverObject->DriverExtension->AddDevice = AddDevice;

DriverObject->MajorFunction[IRP_MJ_CREATE] = PsdoDispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = PsdoDispatchClose;
DriverObject->MajorFunction[IRP_MJ_READ] = PsdoDispatchRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = PsdoDispatchWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
PsdoDispatchDeviceControl;
DriverObject->MajorFunction[IRP_MJ_POWER] = PsdoDispatchPower;
DriverObject->MajorFunction[IRP_MJ_PNP] = PsdoDispatchPnP;
DbgPrint(“In driver entry: end\n”);

return STATUS_SUCCESS;
}

NTSTATUS
AddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
{
ULONG DeviceExtensionSize;
PDEVICE_EXTENSION p_DVCEXT;
PDEVICE_OBJECT ptr_PDO;
NTSTATUS status;
//UNICODE_STRING devname;
UNICODE_STRING dosdevname;
ULONG IdxPwrState;
static long lastIndex = -1;
long devIndex = InterlockedIncrement(&lastIndex);
//WCHAR name[32];
WCHAR symname[32];

DbgPrint(“*******************************Update 5\n”);

//_snwprintf(name, 32, L"\Device\OSEC%d", devIndex);
_snwprintf(symname, 32, L"\DosDevices\OSEC%d", devIndex);

//RtlInitUnicodeString(&devname, name);
RtlInitUnicodeString(&dosdevname, symname);
// TODO (pryan) point at actual device location.
DbgPrint(“Loading device in to %s file\n”, dosdevname);
//Get DEVICE_EXTENSION required memory space
DeviceExtensionSize = sizeof(DEVICE_EXTENSION);
status = IoCreateDevice(
DriverObject,
DeviceExtensionSize,
NULL,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
TRUE,
&ptr_PDO
);

if (NT_SUCCESS(status)) {
ptr_PDO->Flags |= DO_DIRECT_IO;
p_DVCEXT = ptr_PDO->DeviceExtension;
p_DVCEXT->DeviceObject = ptr_PDO;
RtlInitUnicodeString(
&p_DVCEXT->Device_Description,
L"This is a Direct I/O Driver for Pseudo Device\r\n"
L"Created by mjtsai 2003/8/4\r\n");
IoInitializeRemoveLock(
&p_DVCEXT->RemoveLock,
‘KCOL’,
0,
0
);
p_DVCEXT->DataBuffer = ExAllocatePoolWithTag(NonPagedPool, 1024,
‘datB’);
RtlZeroMemory(
p_DVCEXT->DataBuffer,
1024);
//Initialize driver power state
p_DVCEXT->SysPwrState = PowerSystemWorking;
p_DVCEXT->DevPwrState = PowerDeviceD0;

//Initialize device power information
Global_PowerInfo_Ptr = ExAllocatePoolWithTag(NonPagedPool,
sizeof(DEVICE_POWER_INFORMATION), ‘powP’);

RtlZeroMemory(
Global_PowerInfo_Ptr,
sizeof(DEVICE_POWER_INFORMATION));
Global_PowerInfo_Ptr->SupportQueryCapability = FALSE;
Global_PowerInfo_Ptr->DeviceD1 = 0;
Global_PowerInfo_Ptr->DeviceD2 = 0;
Global_PowerInfo_Ptr->WakeFromD0 = 0;
Global_PowerInfo_Ptr->WakeFromD1 = 0;
Global_PowerInfo_Ptr->WakeFromD2 = 0;
Global_PowerInfo_Ptr->WakeFromD3 = 0;
Global_PowerInfo_Ptr->DeviceWake = 0;
Global_PowerInfo_Ptr->SystemWake = 0;
for (IdxPwrState = 0;
IdxPwrState < PowerSystemMaximum;
IdxPwrState++)
{
Global_PowerInfo_Ptr->DeviceState[IdxPwrState] = 0;
}
status = setDeviceSymlink(PhysicalDeviceObject, dosdevname,
p_DVCEXT);

if (!NT_SUCCESS(status)) {
DbgPrint(“Error creating symlink for device to
\DosDevices\OSEC%d\n”, devIndex, devIndex);
return status;
}

//Store next-layered device object
//Attach device object to device stack
p_DVCEXT->NextDeviceObject =
IoAttachDeviceToDeviceStack(ptr_PDO, PhysicalDeviceObject);
ptr_PDO->Flags &= ~DO_DEVICE_INITIALIZING;
}

return status;
}

NTSTATUS setDeviceSymlink(PDEVICE_OBJECT pPdo, UNICODE_STRING symlinkName,
PDEVICE_EXTENSION deviceExtension)
{
ULONG length;
NTSTATUS status;
PWSTR pName;
UNICODE_STRING pdoName;

length = 0;

status = IoGetDeviceProperty(pPdo,
DevicePropertyPhysicalDeviceObjectName,
0,
NULL,
&length);

if (status != STATUS_BUFFER_TOO_SMALL && !NT_SUCCESS(status)) {
DbgPrint(“Failed to get device name length: %s\n”,
OsrNTStatusToString(status));
return status;
}
else if (length > USHORT_MAX) {
DbgPrint(“Name buffer overflow\n”);
return STATUS_INTEGER_OVERFLOW;
}
else if (length == 0) {
DbgPrint(“Error: invalid device state for making symlink”);
//
// We can get zero back if the PDO is being deleted. This can only
happen if we are
// creating the symbolic link outside of AddDevice() or a PnP start.
//
return STATUS_INVALID_DEVICE_STATE;
}

pName = (PWSTR) ExAllocatePoolWithTag(PagedPool, length, ‘nBUF’);
if (pName == NULL) {
DbgPrint(“Error: insufficient resources to make symlink”);
return STATUS_INSUFFICIENT_RESOURCES;
}

status = IoGetDeviceProperty(pPdo,
DevicePropertyPhysicalDeviceObjectName,
length,
pName,
&length);

if (!NT_SUCCESS(status)) {
DbgPrint(“Failed to get device name: %s\n”,
OsrNTStatusToString(status));
ExFreePool(pName);
pName = NULL;
return status;
}

pdoName.Buffer = pName;
pdoName.Length = (USHORT) length - sizeof(UNICODE_NULL);
pdoName.MaximumLength = (USHORT) length;

status = IoCreateSymbolicLink(&symlinkName, &pdoName);

if (NT_SUCCESS(status)) {
DbgPrint(“Generated symlink %s to %s\n”, symlinkName, pdoName);
// the type of DeviceExtension->PdoName is UNICODE_STRING
RtlCopyMemory(&deviceExtension->PdoName, &pdoName, sizeof(pdoName));

// now that we stored the buffer in our extension, remove all
references to the buffer
// so that we don’t accidentally free it while still pointing to it
in the extension
pName = NULL;
RtlZeroMemory(&pdoName, sizeof(pdoName));
}
else {
DbgPrint(“Could not generate symlink %s to %s: %s\n”, symlinkName,
pdoName, OsrNTStatusToString(status));
ExFreePool(pName);
pName = NULL;
}

return status;
}

Thanks,

Paul Ryan

On Sun, Jun 8, 2008 at 3:50 PM, wrote:

> > Could you please explain what I should have done if I just wanted to name
> > the PDO (something human readable).
>
> You can choose either of the things below
>
> 1.Create a symlink to PDO’s name so that the user will be able to open it
> with CreateFile()
>
> 2. Don’t be bothered about the name in a driver, and, instead of
> CreateFile() library function, use
> ZwCreateFile() system call in your app. If you do it this way you will be
> able to open PDO by its name
>
> I would say that, for the sake of simplicity, it is better to take the
> former option, so that you will be able to hardcode your device name right
> in app’s code…
>
> Anton Bassov
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

I’ve also done a test with the _open_osfhandle method using createfile to
see if that might work:

HANDLE hdevice = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, 0, NULL);
if (hdevice == INVALID_HANDLE_VALUE)
{
printf(“Unable to open OSEC device %s for access %s - error %s\n”,
filename, access, strerror(GetLastError()));
return 1;
}
else
{
// Get the file descriptor from the handle
int fd = _open_osfhandle((long)hdevice, _O_RDONLY);
printf(“File descriptor = %d\n”,fd);

if(fd == -1)
{
printf(“Unable to open OSEC device %s for access %s - error
%s\n”, filename, access, strerror(GetLastError()));
return 2;
}
}

and I always get the -1 file descriptor so I’m not even sure createfile is
truly working at this point.

Paul Ryan

On Sun, Jun 8, 2008 at 6:39 PM, Paul Ryan wrote:

> Ok I’ve done the symlink version using the example code from doron’s blog
> but am still getting the same results. What’s odd is my create interupt
> handler is getting called:
>
> NTSTATUS
> PsdoDispatchCreate(
> IN PDEVICE_OBJECT DeviceObject,
> IN PIRP Irp
> )
> {
> PIO_STACK_LOCATION p_IO_STK;
> PDEVICE_EXTENSION p_DVCEXT;
> NTSTATUS status;
> DbgPrint(“In print device\n”);
>
> p_IO_STK = IoGetCurrentIrpStackLocation(Irp);
> p_DVCEXT = DeviceObject->DeviceExtension;
> status = IoAcquireRemoveLock(&p_DVCEXT->RemoveLock,
> p_IO_STK->FileObject);
> if (NT_SUCCESS(status)) {
> DbgPrint(“Lock remove success\n”);
> CompleteRequest(Irp, STATUS_SUCCESS, 0);
> return STATUS_SUCCESS;
> } else {
> DbgPrint(“Lock remove failure\n”);
> IoReleaseRemoveLock(&p_DVCEXT->RemoveLock, p_IO_STK->FileObject);
> CompleteRequest(Irp, status, 0);
> return status;
> }
> }
>
> as the Lock remove success is being printed in the debugger, however the
> client right away exits with the error because the file descriptor pointer
> is null. My new modified code is:
>
> NTSTATUS
> DriverEntry(
> IN PDRIVER_OBJECT DriverObject,
> IN PUNICODE_STRING RegistryPath
> )
> {
> DbgPrint(“In driver entry: begin\n”);
> RtlInitUnicodeString(
> &Global_sz_Drv_RegInfo,
> RegistryPath->Buffer);
>
> // Initialize function pointers
>
> DriverObject->DriverUnload = DriverUnload;
> //DriverObject->DriverStartIo = (PVOID)StartIo;
> DriverObject->DriverExtension->AddDevice = AddDevice;
>
> DriverObject->MajorFunction[IRP_MJ_CREATE] = PsdoDispatchCreate;
> DriverObject->MajorFunction[IRP_MJ_CLOSE] = PsdoDispatchClose;
> DriverObject->MajorFunction[IRP_MJ_READ] = PsdoDispatchRead;
> DriverObject->MajorFunction[IRP_MJ_WRITE] = PsdoDispatchWrite;
> DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
> PsdoDispatchDeviceControl;
> DriverObject->MajorFunction[IRP_MJ_POWER] = PsdoDispatchPower;
> DriverObject->MajorFunction[IRP_MJ_PNP] = PsdoDispatchPnP;
> DbgPrint(“In driver entry: end\n”);
>
> return STATUS_SUCCESS;
> }
>
> NTSTATUS
> AddDevice(
> IN PDRIVER_OBJECT DriverObject,
> IN PDEVICE_OBJECT PhysicalDeviceObject
> )
> {
> ULONG DeviceExtensionSize;
> PDEVICE_EXTENSION p_DVCEXT;
> PDEVICE_OBJECT ptr_PDO;
> NTSTATUS status;
> //UNICODE_STRING devname;
> UNICODE_STRING dosdevname;
> ULONG IdxPwrState;
> static long lastIndex = -1;
> long devIndex = InterlockedIncrement(&lastIndex);
> //WCHAR name[32];
> WCHAR symname[32];
>
> DbgPrint(" ******************************* Update 5\n");
>
> //_snwprintf(name, 32, L"\Device\OSEC%d", devIndex);
> _snwprintf(symname, 32, L"\DosDevices\OSEC%d", devIndex);
>
> //RtlInitUnicodeString(&devname, name);
> RtlInitUnicodeString(&dosdevname, symname);
> // TODO (pryan) point at actual device location.
> DbgPrint(“Loading device in to %s file\n”, dosdevname);
> //Get DEVICE_EXTENSION required memory space
> DeviceExtensionSize = sizeof(DEVICE_EXTENSION);
> status = IoCreateDevice(
> DriverObject,
> DeviceExtensionSize,
> NULL,
> FILE_DEVICE_UNKNOWN,
> FILE_DEVICE_SECURE_OPEN,
> TRUE,
> &ptr_PDO
> );
>
> if (NT_SUCCESS(status)) {
> ptr_PDO->Flags |= DO_DIRECT_IO;
> p_DVCEXT = ptr_PDO->DeviceExtension;
> p_DVCEXT->DeviceObject = ptr_PDO;
> RtlInitUnicodeString(
> &p_DVCEXT->Device_Description,
> L"This is a Direct I/O Driver for Pseudo Device\r\n"
> L"Created by mjtsai 2003/8/4\r\n");
> IoInitializeRemoveLock(
> &p_DVCEXT->RemoveLock,
> ‘KCOL’,
> 0,
> 0
> );
> p_DVCEXT->DataBuffer = ExAllocatePoolWithTag(NonPagedPool, 1024,
> ‘datB’);
> RtlZeroMemory(
> p_DVCEXT->DataBuffer,
> 1024);
> //Initialize driver power state
> p_DVCEXT->SysPwrState = PowerSystemWorking;
> p_DVCEXT->DevPwrState = PowerDeviceD0;
>
> //Initialize device power information
> Global_PowerInfo_Ptr = ExAllocatePoolWithTag(NonPagedPool,
> sizeof(DEVICE_POWER_INFORMATION), ‘powP’);
>
> RtlZeroMemory(
> Global_PowerInfo_Ptr,
> sizeof(DEVICE_POWER_INFORMATION));
> Global_PowerInfo_Ptr->SupportQueryCapability = FALSE;
> Global_PowerInfo_Ptr->DeviceD1 = 0;
> Global_PowerInfo_Ptr->DeviceD2 = 0;
> Global_PowerInfo_Ptr->WakeFromD0 = 0;
> Global_PowerInfo_Ptr->WakeFromD1 = 0;
> Global_PowerInfo_Ptr->WakeFromD2 = 0;
> Global_PowerInfo_Ptr->WakeFromD3 = 0;
> Global_PowerInfo_Ptr->DeviceWake = 0;
> Global_PowerInfo_Ptr->SystemWake = 0;
> for (IdxPwrState = 0;
> IdxPwrState < PowerSystemMaximum;
> IdxPwrState++)
> {
> Global_PowerInfo_Ptr->DeviceState[IdxPwrState] = 0;
> }
> status = setDeviceSymlink(PhysicalDeviceObject, dosdevname,
> p_DVCEXT);
>
> if (!NT_SUCCESS(status)) {
> DbgPrint(“Error creating symlink for device to
> \DosDevices\OSEC%d\n”, devIndex, devIndex);
> return status;
> }
>
> //Store next-layered device object
> //Attach device object to device stack
> p_DVCEXT->NextDeviceObject =
> IoAttachDeviceToDeviceStack(ptr_PDO, PhysicalDeviceObject);
> ptr_PDO->Flags &= ~DO_DEVICE_INITIALIZING;
> }
>
> return status;
> }
>
> NTSTATUS setDeviceSymlink(PDEVICE_OBJECT pPdo, UNICODE_STRING symlinkName,
> PDEVICE_EXTENSION deviceExtension)
> {
> ULONG length;
> NTSTATUS status;
> PWSTR pName;
> UNICODE_STRING pdoName;
>
> length = 0;
>
> status = IoGetDeviceProperty(pPdo,
> DevicePropertyPhysicalDeviceObjectName,
> 0,
> NULL,
> &length);
>
> if (status != STATUS_BUFFER_TOO_SMALL && !NT_SUCCESS(status)) {
> DbgPrint(“Failed to get device name length: %s\n”,
> OsrNTStatusToString(status));
> return status;
> }
> else if (length > USHORT_MAX) {
> DbgPrint(“Name buffer overflow\n”);
> return STATUS_INTEGER_OVERFLOW;
> }
> else if (length == 0) {
> DbgPrint(“Error: invalid device state for making symlink”);
> //
> // We can get zero back if the PDO is being deleted. This can only
> happen if we are
> // creating the symbolic link outside of AddDevice() or a PnP
> start.
> //
> return STATUS_INVALID_DEVICE_STATE;
> }
>
> pName = (PWSTR) ExAllocatePoolWithTag(PagedPool, length, ‘nBUF’);
> if (pName == NULL) {
> DbgPrint(“Error: insufficient resources to make symlink”);
> return STATUS_INSUFFICIENT_RESOURCES;
> }
>
> status = IoGetDeviceProperty(pPdo,
> DevicePropertyPhysicalDeviceObjectName,
> length,
> pName,
> &length);
>
> if (!NT_SUCCESS(status)) {
> DbgPrint(“Failed to get device name: %s\n”,
> OsrNTStatusToString(status));
> ExFreePool(pName);
> pName = NULL;
> return status;
> }
>
> pdoName.Buffer = pName;
> pdoName.Length = (USHORT) length - sizeof(UNICODE_NULL);
> pdoName.MaximumLength = (USHORT) length;
>
> status = IoCreateSymbolicLink(&symlinkName, &pdoName);
>
> if (NT_SUCCESS(status)) {
> DbgPrint(“Generated symlink %s to %s\n”, symlinkName, pdoName);
> // the type of DeviceExtension->PdoName is UNICODE_STRING
> RtlCopyMemory(&deviceExtension->PdoName, &pdoName,
> sizeof(pdoName));
>
> // now that we stored the buffer in our extension, remove all
> references to the buffer
> // so that we don’t accidentally free it while still pointing to it
> in the extension
> pName = NULL;
> RtlZeroMemory(&pdoName, sizeof(pdoName));
> }
> else {
> DbgPrint(“Could not generate symlink %s to %s: %s\n”, symlinkName,
> pdoName, OsrNTStatusToString(status));
> ExFreePool(pName);
> pName = NULL;
> }
>
> return status;
> }
>
> Thanks,
>
> Paul Ryan
>
>
> On Sun, Jun 8, 2008 at 3:50 PM, wrote:
>
>> > Could you please explain what I should have done if I just wanted to
>> name
>> > the PDO (something human readable).
>>
>> You can choose either of the things below
>>
>> 1.Create a symlink to PDO’s name so that the user will be able to open it
>> with CreateFile()
>>
>> 2. Don’t be bothered about the name in a driver, and, instead of
>> CreateFile() library function, use
>> ZwCreateFile() system call in your app. If you do it this way you will be
>> able to open PDO by its name
>>
>> I would say that, for the sake of simplicity, it is better to take the
>> former option, so that you will be able to hardcode your device name right
>> in app’s code…
>>
>> Anton Bassov
>>
>> —
>> NTDEV is sponsored by OSR
>>
>> For our schedule of WDF, WDM, debugging and other seminars visit:
>> http://www.osr.com/seminars
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http://www.osronline.com/page.cfm?name=ListServer
>>
>


Paul Ryan
xxxxx@gmail.com

Paul Ryan wrote:

Ok the user mode code is as follows:

#include <stdio.h>
> #include <errno.h>
> #include <string.h>
>
> int main(int argc, char* argv)
> {
> //char* filename = argv[1];
> char filename[256] = argv[1];

This can’t really be your code, because that line is illegal. You can’t
initialize a character array from a character pointer. It gets a
compile-time error in both C and C++.

> char* access = argv[2];
> FILE* file = fopen(filename, access);

Well, this doesn’t help at ALL. Look, what we’re trying to find out is
EXACTLY what strings you are passing to fopen. This just passes the
parameters. Show us EXACTLY what you passed for the file name, and
EXACTLY what you passed for the access string.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.</string.h></errno.h></stdio.h>

If the acquisition of the remlock fails, you do not release it (the else case). Again, I strongly recommend that you consider KMDF, this type of cruft is taken care of for you.

If the create dispatch routine is being called and you are completing the request successfully, then either there is a driver layered on top of you which is failing the request (what device class are you installing under?) or your app is misinterpreting the results.

d

From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Paul Ryan
Sent: Sunday, June 08, 2008 5:39 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Re: fopen vs CreateFile Driver Access issue

Ok I’ve done the symlink version using the example code from doron’s blog but am still getting the same results. What’s odd is my create interupt handler is getting called:

NTSTATUS
PsdoDispatchCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PIO_STACK_LOCATION p_IO_STK;
PDEVICE_EXTENSION p_DVCEXT;
NTSTATUS status;
DbgPrint(“In print device\n”);

p_IO_STK = IoGetCurrentIrpStackLocation(Irp);
p_DVCEXT = DeviceObject->DeviceExtension;
status = IoAcquireRemoveLock(&p_DVCEXT->RemoveLock, p_IO_STK->FileObject);
if (NT_SUCCESS(status)) {
DbgPrint(“Lock remove success\n”);
CompleteRequest(Irp, STATUS_SUCCESS, 0);
return STATUS_SUCCESS;
} else {
DbgPrint(“Lock remove failure\n”);
IoReleaseRemoveLock(&p_DVCEXT->RemoveLock, p_IO_STK->FileObject);
CompleteRequest(Irp, status, 0);
return status;
}
}

as the Lock remove success is being printed in the debugger, however the client right away exits with the error because the file descriptor pointer is null. My new modified code is:
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
DbgPrint(“In driver entry: begin\n”);
RtlInitUnicodeString(
&Global_sz_Drv_RegInfo,
RegistryPath->Buffer);

// Initialize function pointers

DriverObject->DriverUnload = DriverUnload;
//DriverObject->DriverStartIo = (PVOID)StartIo;
DriverObject->DriverExtension->AddDevice = AddDevice;

DriverObject->MajorFunction[IRP_MJ_CREATE] = PsdoDispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = PsdoDispatchClose;
DriverObject->MajorFunction[IRP_MJ_READ] = PsdoDispatchRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = PsdoDispatchWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PsdoDispatchDeviceControl;
DriverObject->MajorFunction[IRP_MJ_POWER] = PsdoDispatchPower;
DriverObject->MajorFunction[IRP_MJ_PNP] = PsdoDispatchPnP;
DbgPrint(“In driver entry: end\n”);

return STATUS_SUCCESS;
}

NTSTATUS
AddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
{
ULONG DeviceExtensionSize;
PDEVICE_EXTENSION p_DVCEXT;
PDEVICE_OBJECT ptr_PDO;
NTSTATUS status;
//UNICODE_STRING devname;
UNICODE_STRING dosdevname;
ULONG IdxPwrState;
static long lastIndex = -1;
long devIndex = InterlockedIncrement(&lastIndex);
//WCHAR name[32];
WCHAR symname[32];

DbgPrint(“*******************************Update 5\n”);

//_snwprintf(name, 32, L"\Device\OSEC%d", devIndex);
_snwprintf(symname, 32, L"\DosDevices\OSEC%d", devIndex);

//RtlInitUnicodeString(&devname, name);
RtlInitUnicodeString(&dosdevname, symname);
// TODO (pryan) point at actual device location.
DbgPrint(“Loading device in to %s file\n”, dosdevname);
//Get DEVICE_EXTENSION required memory space
DeviceExtensionSize = sizeof(DEVICE_EXTENSION);
status = IoCreateDevice(
DriverObject,
DeviceExtensionSize,
NULL,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
TRUE,
&ptr_PDO
);

if (NT_SUCCESS(status)) {
ptr_PDO->Flags |= DO_DIRECT_IO;
p_DVCEXT = ptr_PDO->DeviceExtension;
p_DVCEXT->DeviceObject = ptr_PDO;
RtlInitUnicodeString(
&p_DVCEXT->Device_Description,
L"This is a Direct I/O Driver for Pseudo Device\r\n"
L"Created by mjtsai 2003/8/4\r\n");
IoInitializeRemoveLock(
&p_DVCEXT->RemoveLock,
‘KCOL’,
0,
0
);
p_DVCEXT->DataBuffer = ExAllocatePoolWithTag(NonPagedPool, 1024, ‘datB’);
RtlZeroMemory(
p_DVCEXT->DataBuffer,
1024);
//Initialize driver power state
p_DVCEXT->SysPwrState = PowerSystemWorking;
p_DVCEXT->DevPwrState = PowerDeviceD0;

//Initialize device power information
Global_PowerInfo_Ptr = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_POWER_INFORMATION), ‘powP’);

RtlZeroMemory(
Global_PowerInfo_Ptr,
sizeof(DEVICE_POWER_INFORMATION));
Global_PowerInfo_Ptr->SupportQueryCapability = FALSE;
Global_PowerInfo_Ptr->DeviceD1 = 0;
Global_PowerInfo_Ptr->DeviceD2 = 0;
Global_PowerInfo_Ptr->WakeFromD0 = 0;
Global_PowerInfo_Ptr->WakeFromD1 = 0;
Global_PowerInfo_Ptr->WakeFromD2 = 0;
Global_PowerInfo_Ptr->WakeFromD3 = 0;
Global_PowerInfo_Ptr->DeviceWake = 0;
Global_PowerInfo_Ptr->SystemWake = 0;
for (IdxPwrState = 0;
IdxPwrState < PowerSystemMaximum;
IdxPwrState++)
{
Global_PowerInfo_Ptr->DeviceState[IdxPwrState] = 0;
}
status = setDeviceSymlink(PhysicalDeviceObject, dosdevname, p_DVCEXT);

if (!NT_SUCCESS(status)) {
DbgPrint(“Error creating symlink for device to \DosDevices\OSEC%d\n”, devIndex, devIndex);
return status;
}

//Store next-layered device object
//Attach device object to device stack
p_DVCEXT->NextDeviceObject =
IoAttachDeviceToDeviceStack(ptr_PDO, PhysicalDeviceObject);
ptr_PDO->Flags &= ~DO_DEVICE_INITIALIZING;
}

return status;
}

NTSTATUS setDeviceSymlink(PDEVICE_OBJECT pPdo, UNICODE_STRING symlinkName, PDEVICE_EXTENSION deviceExtension)
{
ULONG length;
NTSTATUS status;
PWSTR pName;
UNICODE_STRING pdoName;

length = 0;

status = IoGetDeviceProperty(pPdo,
DevicePropertyPhysicalDeviceObjectName,
0,
NULL,
&length);

if (status != STATUS_BUFFER_TOO_SMALL && !NT_SUCCESS(status)) {
DbgPrint(“Failed to get device name length: %s\n”, OsrNTStatusToString(status));
return status;
}
else if (length > USHORT_MAX) {
DbgPrint(“Name buffer overflow\n”);
return STATUS_INTEGER_OVERFLOW;
}
else if (length == 0) {
DbgPrint(“Error: invalid device state for making symlink”);
//
// We can get zero back if the PDO is being deleted. This can only happen if we are
// creating the symbolic link outside of AddDevice() or a PnP start.
//
return STATUS_INVALID_DEVICE_STATE;
}

pName = (PWSTR) ExAllocatePoolWithTag(PagedPool, length, ‘nBUF’);
if (pName == NULL) {
DbgPrint(“Error: insufficient resources to make symlink”);
return STATUS_INSUFFICIENT_RESOURCES;
}

status = IoGetDeviceProperty(pPdo,
DevicePropertyPhysicalDeviceObjectName,
length,
pName,
&length);

if (!NT_SUCCESS(status)) {
DbgPrint(“Failed to get device name: %s\n”, OsrNTStatusToString(status));
ExFreePool(pName);
pName = NULL;
return status;
}

pdoName.Buffer = pName;
pdoName.Length = (USHORT) length - sizeof(UNICODE_NULL);
pdoName.MaximumLength = (USHORT) length;

status = IoCreateSymbolicLink(&symlinkName, &pdoName);

if (NT_SUCCESS(status)) {
DbgPrint(“Generated symlink %s to %s\n”, symlinkName, pdoName);
// the type of DeviceExtension->PdoName is UNICODE_STRING
RtlCopyMemory(&deviceExtension->PdoName, &pdoName, sizeof(pdoName));

// now that we stored the buffer in our extension, remove all references to the buffer
// so that we don’t accidentally free it while still pointing to it in the extension
pName = NULL;
RtlZeroMemory(&pdoName, sizeof(pdoName));
}
else {
DbgPrint(“Could not generate symlink %s to %s: %s\n”, symlinkName, pdoName, OsrNTStatusToString(status));
ExFreePool(pName);
pName = NULL;
}

return status;
}

Thanks,

Paul Ryan
On Sun, Jun 8, 2008 at 3:50 PM, > wrote:
> Could you please explain what I should have done if I just wanted to name
> the PDO (something human readable).
You can choose either of the things below

1.Create a symlink to PDO’s name so that the user will be able to open it with CreateFile()

2. Don’t be bothered about the name in a driver, and, instead of CreateFile() library function, use
ZwCreateFile() system call in your app. If you do it this way you will be able to open PDO by its name

I would say that, for the sake of simplicity, it is better to take the former option, so that you will be able to hardcode your device name right in app’s code…

Anton Bassov


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer
— NTDEV is sponsored by OSR For our schedule of WDF, WDM, debugging and other seminars visit: http://www.osr.com/seminars To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

your right the line is the one that is commented out sorry I was just trying
to get a concise dump and made mistake on my changes: char* filename =
argv[1];

I was passing \.\OSEC0 or whatever number the device was the access string
was r

Sorry and thank you,

Paul Ryan

On Mon, Jun 9, 2008 at 11:49 AM, Tim Roberts wrote:

> Paul Ryan wrote:
>
>> Ok the user mode code is as follows:
>>
>> #include <stdio.h>
>> #include <errno.h>
>> #include <string.h>
>>
>> int main(int argc, char* argv)
>> {
>> //char* filename = argv[1];
>> char filename[256] = argv[1];
>>
>
> This can’t really be your code, because that line is illegal. You can’t
> initialize a character array from a character pointer. It gets a
> compile-time error in both C and C++.
>
>
> char* access = argv[2];
>> FILE* file = fopen(filename, access);
>>
>
> Well, this doesn’t help at ALL. Look, what we’re trying to find out is
> EXACTLY what strings you are passing to fopen. This just passes the
> parameters. Show us EXACTLY what you passed for the file name, and EXACTLY
> what you passed for the access string.
>
> –
> Tim Roberts, xxxxx@probo.com
> Providenza & Boekelheide, Inc.
>
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>


Paul Ryan
xxxxx@gmail.com</string.h></errno.h></stdio.h>

I think your asking if it is under system, usb etc. and it is currently
under system. If I’m assuming wrong could you please point me at what I need
to look at to tell you the device class. Should this be a usb controller
instead?

[Version]
Signature = “$Windows NT$”
Class=System

On Mon, Jun 9, 2008 at 3:45 PM, Doron Holan
wrote:

> If the acquisition of the remlock fails, you do not release it (the else
> case). Again, I strongly recommend that you consider KMDF, this type of
> cruft is taken care of for you.
>
>
>
> If the create dispatch routine is being called and you are completing the
> request successfully, then either there is a driver layered on top of you
> which is failing the request (what device class are you installing under?)
> or your app is misinterpreting the results.
>
>
>
> d
>
>
>
> From: xxxxx@lists.osr.com [mailto:
> xxxxx@lists.osr.com] *On Behalf Of *Paul Ryan
> Sent: Sunday, June 08, 2008 5:39 PM
> To: Windows System Software Devs Interest List
> Subject: Re: [ntdev] Re: fopen vs CreateFile Driver Access issue
>
>
>
> Ok I’ve done the symlink version using the example code from doron’s blog
> but am still getting the same results. What’s odd is my create interupt
> handler is getting called:
>
> NTSTATUS
> PsdoDispatchCreate(
> IN PDEVICE_OBJECT DeviceObject,
> IN PIRP Irp
> )
> {
> PIO_STACK_LOCATION p_IO_STK;
> PDEVICE_EXTENSION p_DVCEXT;
> NTSTATUS status;
> DbgPrint(“In print device\n”);
>
> p_IO_STK = IoGetCurrentIrpStackLocation(Irp);
> p_DVCEXT = DeviceObject->DeviceExtension;
> status = IoAcquireRemoveLock(&p_DVCEXT->RemoveLock,
> p_IO_STK->FileObject);
> if (NT_SUCCESS(status)) {
> DbgPrint(“Lock remove success\n”);
> CompleteRequest(Irp, STATUS_SUCCESS, 0);
> return STATUS_SUCCESS;
> } else {
> DbgPrint(“Lock remove failure\n”);
> IoReleaseRemoveLock(&p_DVCEXT->RemoveLock, p_IO_STK->FileObject);
> CompleteRequest(Irp, status, 0);
> return status;
> }
> }
>
> as the Lock remove success is being printed in the debugger, however the
> client right away exits with the error because the file descriptor pointer
> is null. My new modified code is:
> NTSTATUS
> DriverEntry(
> IN PDRIVER_OBJECT DriverObject,
> IN PUNICODE_STRING RegistryPath
> )
> {
> DbgPrint(“In driver entry: begin\n”);
> RtlInitUnicodeString(
> &Global_sz_Drv_RegInfo,
> RegistryPath->Buffer);
>
> // Initialize function pointers
>
> DriverObject->DriverUnload = DriverUnload;
> //DriverObject->DriverStartIo = (PVOID)StartIo;
> DriverObject->DriverExtension->AddDevice = AddDevice;
>
> DriverObject->MajorFunction[IRP_MJ_CREATE] = PsdoDispatchCreate;
> DriverObject->MajorFunction[IRP_MJ_CLOSE] = PsdoDispatchClose;
> DriverObject->MajorFunction[IRP_MJ_READ] = PsdoDispatchRead;
> DriverObject->MajorFunction[IRP_MJ_WRITE] = PsdoDispatchWrite;
> DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
> PsdoDispatchDeviceControl;
> DriverObject->MajorFunction[IRP_MJ_POWER] = PsdoDispatchPower;
> DriverObject->MajorFunction[IRP_MJ_PNP] = PsdoDispatchPnP;
> DbgPrint(“In driver entry: end\n”);
>
> return STATUS_SUCCESS;
> }
>
> NTSTATUS
> AddDevice(
> IN PDRIVER_OBJECT DriverObject,
> IN PDEVICE_OBJECT PhysicalDeviceObject
> )
> {
> ULONG DeviceExtensionSize;
> PDEVICE_EXTENSION p_DVCEXT;
> PDEVICE_OBJECT ptr_PDO;
> NTSTATUS status;
> //UNICODE_STRING devname;
> UNICODE_STRING dosdevname;
> ULONG IdxPwrState;
> static long lastIndex = -1;
> long devIndex = InterlockedIncrement(&lastIndex);
> //WCHAR name[32];
> WCHAR symname[32];
>
> DbgPrint(" ******************************* Update 5\n");
>
> //_snwprintf(name, 32, L"\Device\OSEC%d", devIndex);
> _snwprintf(symname, 32, L"\DosDevices\OSEC%d", devIndex);
>
> //RtlInitUnicodeString(&devname, name);
> RtlInitUnicodeString(&dosdevname, symname);
> // TODO (pryan) point at actual device location.
> DbgPrint(“Loading device in to %s file\n”, dosdevname);
> //Get DEVICE_EXTENSION required memory space
> DeviceExtensionSize = sizeof(DEVICE_EXTENSION);
> status = IoCreateDevice(
> DriverObject,
> DeviceExtensionSize,
> NULL,
> FILE_DEVICE_UNKNOWN,
> FILE_DEVICE_SECURE_OPEN,
> TRUE,
> &ptr_PDO
> );
>
> if (NT_SUCCESS(status)) {
> ptr_PDO->Flags |= DO_DIRECT_IO;
> p_DVCEXT = ptr_PDO->DeviceExtension;
> p_DVCEXT->DeviceObject = ptr_PDO;
> RtlInitUnicodeString(
> &p_DVCEXT->Device_Description,
> L"This is a Direct I/O Driver for Pseudo Device\r\n"
> L"Created by mjtsai 2003/8/4\r\n");
> IoInitializeRemoveLock(
> &p_DVCEXT->RemoveLock,
> ‘KCOL’,
> 0,
> 0
> );
> p_DVCEXT->DataBuffer = ExAllocatePoolWithTag(NonPagedPool, 1024,
> ‘datB’);
> RtlZeroMemory(
> p_DVCEXT->DataBuffer,
> 1024);
> //Initialize driver power state
> p_DVCEXT->SysPwrState = PowerSystemWorking;
> p_DVCEXT->DevPwrState = PowerDeviceD0;
>
> //Initialize device power information
> Global_PowerInfo_Ptr = ExAllocatePoolWithTag(NonPagedPool,
> sizeof(DEVICE_POWER_INFORMATION), ‘powP’);
>
> RtlZeroMemory(
> Global_PowerInfo_Ptr,
> sizeof(DEVICE_POWER_INFORMATION));
> Global_PowerInfo_Ptr->SupportQueryCapability = FALSE;
> Global_PowerInfo_Ptr->DeviceD1 = 0;
> Global_PowerInfo_Ptr->DeviceD2 = 0;
> Global_PowerInfo_Ptr->WakeFromD0 = 0;
> Global_PowerInfo_Ptr->WakeFromD1 = 0;
> Global_PowerInfo_Ptr->WakeFromD2 = 0;
> Global_PowerInfo_Ptr->WakeFromD3 = 0;
> Global_PowerInfo_Ptr->DeviceWake = 0;
> Global_PowerInfo_Ptr->SystemWake = 0;
> for (IdxPwrState = 0;
> IdxPwrState < PowerSystemMaximum;
> IdxPwrState++)
> {
> Global_PowerInfo_Ptr->DeviceState[IdxPwrState] = 0;
> }
> status = setDeviceSymlink(PhysicalDeviceObject, dosdevname,
> p_DVCEXT);
>
> if (!NT_SUCCESS(status)) {
> DbgPrint(“Error creating symlink for device to
> \DosDevices\OSEC%d\n”, devIndex, devIndex);
> return status;
> }
>
> //Store next-layered device object
> //Attach device object to device stack
> p_DVCEXT->NextDeviceObject =
> IoAttachDeviceToDeviceStack(ptr_PDO, PhysicalDeviceObject);
> ptr_PDO->Flags &= ~DO_DEVICE_INITIALIZING;
> }
>
> return status;
> }
>
> NTSTATUS setDeviceSymlink(PDEVICE_OBJECT pPdo, UNICODE_STRING symlinkName,
> PDEVICE_EXTENSION deviceExtension)
> {
> ULONG length;
> NTSTATUS status;
> PWSTR pName;
> UNICODE_STRING pdoName;
>
> length = 0;
>
> status = IoGetDeviceProperty(pPdo,
> DevicePropertyPhysicalDeviceObjectName,
> 0,
> NULL,
> &length);
>
> if (status != STATUS_BUFFER_TOO_SMALL && !NT_SUCCESS(status)) {
> DbgPrint(“Failed to get device name length: %s\n”,
> OsrNTStatusToString(status));
> return status;
> }
> else if (length > USHORT_MAX) {
> DbgPrint(“Name buffer overflow\n”);
> return STATUS_INTEGER_OVERFLOW;
> }
> else if (length == 0) {
> DbgPrint(“Error: invalid device state for making symlink”);
> //
> // We can get zero back if the PDO is being deleted. This can only
> happen if we are
> // creating the symbolic link outside of AddDevice() or a PnP
> start.
> //
> return STATUS_INVALID_DEVICE_STATE;
> }
>
> pName = (PWSTR) ExAllocatePoolWithTag(PagedPool, length, ‘nBUF’);
> if (pName == NULL) {
> DbgPrint(“Error: insufficient resources to make symlink”);
> return STATUS_INSUFFICIENT_RESOURCES;
> }
>
> status = IoGetDeviceProperty(pPdo,
> DevicePropertyPhysicalDeviceObjectName,
> length,
> pName,
> &length);
>
> if (!NT_SUCCESS(status)) {
> DbgPrint(“Failed to get device name: %s\n”,
> OsrNTStatusToString(status));
> ExFreePool(pName);
> pName = NULL;
> return status;
> }
>
> pdoName.Buffer = pName;
> pdoName.Length = (USHORT) length - sizeof(UNICODE_NULL);
> pdoName.MaximumLength = (USHORT) length;
>
> status = IoCreateSymbolicLink(&symlinkName, &pdoName);
>
> if (NT_SUCCESS(status)) {
> DbgPrint(“Generated symlink %s to %s\n”, symlinkName, pdoName);
> // the type of DeviceExtension->PdoName is UNICODE_STRING
> RtlCopyMemory(&deviceExtension->PdoName, &pdoName,
> sizeof(pdoName));
>
> // now that we stored the buffer in our extension, remove all
> references to the buffer
> // so that we don’t accidentally free it while still pointing to it
> in the extension
> pName = NULL;
> RtlZeroMemory(&pdoName, sizeof(pdoName));
> }
> else {
> DbgPrint(“Could not generate symlink %s to %s: %s\n”, symlinkName,
> pdoName, OsrNTStatusToString(status));
> ExFreePool(pName);
> pName = NULL;
> }
>
> return status;
> }
>
> Thanks,
>
> Paul Ryan
>
> On Sun, Jun 8, 2008 at 3:50 PM, wrote:
>
> > Could you please explain what I should have done if I just wanted to name
> > the PDO (something human readable).
>
> You can choose either of the things below
>
> 1.Create a symlink to PDO’s name so that the user will be able to open it
> with CreateFile()
>
> 2. Don’t be bothered about the name in a driver, and, instead of
> CreateFile() library function, use
> ZwCreateFile() system call in your app. If you do it this way you will be
> able to open PDO by its name
>
> I would say that, for the sake of simplicity, it is better to take the
> former option, so that you will be able to hardcode your device name right
> in app’s code…
>
>
> Anton Bassov
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>
> — NTDEV is sponsored by OSR For our schedule of WDF, WDM, debugging and
> other seminars visit: http://www.osr.com/seminars To unsubscribe, visit
> the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>


Paul Ryan
xxxxx@gmail.com

Paul Ryan wrote:

your right the line is the one that is commented out sorry I was just
trying to get a concise dump and made mistake on my changes: char*
filename = argv[1];

I was passing \.\OSEC0 or whatever number the device was the access
string was r

But your CreateFile example used GENERIC_READ|GENERIC_WRITE. You almost
certainly want “r+b” here.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Not, it should most definitely not be in the usb device class (should be reserved for usb host controllers and hubs). System if fine. I asked about the class b/c some classes (like keyboards and mice) have automatic filters that layer on top of your driver, altering the perceived behavior of the drivers underneath.

If this is a usb device, going the device interface routine will certainly help you if you need to dynamically find out when the device has been inserted and opportunistically open a handle to the device (as compared to a pci device which you can probably assume is not going to show up after the system has been started, although a disable/enable in device manager will make that happen as well)

d

From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Paul Ryan
Sent: Monday, June 09, 2008 4:06 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Re: fopen vs CreateFile Driver Access issue

I think your asking if it is under system, usb etc. and it is currently under system. If I’m assuming wrong could you please point me at what I need to look at to tell you the device class. Should this be a usb controller instead?

[Version]
Signature = “$Windows NT$”
Class=System
On Mon, Jun 9, 2008 at 3:45 PM, Doron Holan > wrote:

If the acquisition of the remlock fails, you do not release it (the else case). Again, I strongly recommend that you consider KMDF, this type of cruft is taken care of for you.

If the create dispatch routine is being called and you are completing the request successfully, then either there is a driver layered on top of you which is failing the request (what device class are you installing under?) or your app is misinterpreting the results.

d

From: xxxxx@lists.osr.commailto:xxxxx [mailto:xxxxx@lists.osr.commailto:xxxxx] On Behalf Of Paul Ryan
Sent: Sunday, June 08, 2008 5:39 PM

To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Re: fopen vs CreateFile Driver Access issue

Ok I’ve done the symlink version using the example code from doron’s blog but am still getting the same results. What’s odd is my create interupt handler is getting called:

NTSTATUS
PsdoDispatchCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PIO_STACK_LOCATION p_IO_STK;
PDEVICE_EXTENSION p_DVCEXT;
NTSTATUS status;
DbgPrint(“In print device\n”);

p_IO_STK = IoGetCurrentIrpStackLocation(Irp);
p_DVCEXT = DeviceObject->DeviceExtension;
status = IoAcquireRemoveLock(&p_DVCEXT->RemoveLock, p_IO_STK->FileObject);
if (NT_SUCCESS(status)) {
DbgPrint(“Lock remove success\n”);
CompleteRequest(Irp, STATUS_SUCCESS, 0);
return STATUS_SUCCESS;
} else {
DbgPrint(“Lock remove failure\n”);
IoReleaseRemoveLock(&p_DVCEXT->RemoveLock, p_IO_STK->FileObject);
CompleteRequest(Irp, status, 0);
return status;
}
}

as the Lock remove success is being printed in the debugger, however the client right away exits with the error because the file descriptor pointer is null. My new modified code is:
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
DbgPrint(“In driver entry: begin\n”);
RtlInitUnicodeString(
&Global_sz_Drv_RegInfo,
RegistryPath->Buffer);

// Initialize function pointers

DriverObject->DriverUnload = DriverUnload;
//DriverObject->DriverStartIo = (PVOID)StartIo;
DriverObject->DriverExtension->AddDevice = AddDevice;

DriverObject->MajorFunction[IRP_MJ_CREATE] = PsdoDispatchCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = PsdoDispatchClose;
DriverObject->MajorFunction[IRP_MJ_READ] = PsdoDispatchRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = PsdoDispatchWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PsdoDispatchDeviceControl;
DriverObject->MajorFunction[IRP_MJ_POWER] = PsdoDispatchPower;
DriverObject->MajorFunction[IRP_MJ_PNP] = PsdoDispatchPnP;
DbgPrint(“In driver entry: end\n”);

return STATUS_SUCCESS;
}

NTSTATUS
AddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
{
ULONG DeviceExtensionSize;
PDEVICE_EXTENSION p_DVCEXT;
PDEVICE_OBJECT ptr_PDO;
NTSTATUS status;
//UNICODE_STRING devname;
UNICODE_STRING dosdevname;
ULONG IdxPwrState;
static long lastIndex = -1;
long devIndex = InterlockedIncrement(&lastIndex);
//WCHAR name[32];
WCHAR symname[32];

DbgPrint(" ******************************* Update 5\n");

//_snwprintf(name, 32, L"\Device\OSEC%d", devIndex);
_snwprintf(symname, 32, L"\DosDevices\OSEC%d", devIndex);

//RtlInitUnicodeString(&devname, name);
RtlInitUnicodeString(&dosdevname, symname);
// TODO (pryan) point at actual device location.
DbgPrint(“Loading device in to %s file\n”, dosdevname);
//Get DEVICE_EXTENSION required memory space
DeviceExtensionSize = sizeof(DEVICE_EXTENSION);
status = IoCreateDevice(
DriverObject,
DeviceExtensionSize,
NULL,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
TRUE,
&ptr_PDO
);

if (NT_SUCCESS(status)) {
ptr_PDO->Flags |= DO_DIRECT_IO;
p_DVCEXT = ptr_PDO->DeviceExtension;
p_DVCEXT->DeviceObject = ptr_PDO;
RtlInitUnicodeString(
&p_DVCEXT->Device_Description,
L"This is a Direct I/O Driver for Pseudo Device\r\n"
L"Created by mjtsai 2003/8/4\r\n");
IoInitializeRemoveLock(
&p_DVCEXT->RemoveLock,
‘KCOL’,
0,
0
);
p_DVCEXT->DataBuffer = ExAllocatePoolWithTag(NonPagedPool, 1024, ‘datB’);
RtlZeroMemory(
p_DVCEXT->DataBuffer,
1024);
//Initialize driver power state
p_DVCEXT->SysPwrState = PowerSystemWorking;
p_DVCEXT->DevPwrState = PowerDeviceD0;

//Initialize device power information
Global_PowerInfo_Ptr = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_POWER_INFORMATION), ‘powP’);

RtlZeroMemory(
Global_PowerInfo_Ptr,
sizeof(DEVICE_POWER_INFORMATION));
Global_PowerInfo_Ptr->SupportQueryCapability = FALSE;
Global_PowerInfo_Ptr->DeviceD1 = 0;
Global_PowerInfo_Ptr->DeviceD2 = 0;
Global_PowerInfo_Ptr->WakeFromD0 = 0;
Global_PowerInfo_Ptr->WakeFromD1 = 0;
Global_PowerInfo_Ptr->WakeFromD2 = 0;
Global_PowerInfo_Ptr->WakeFromD3 = 0;
Global_PowerInfo_Ptr->DeviceWake = 0;
Global_PowerInfo_Ptr->SystemWake = 0;
for (IdxPwrState = 0;
IdxPwrState < PowerSystemMaximum;
IdxPwrState++)
{
Global_PowerInfo_Ptr->DeviceState[IdxPwrState] = 0;
}
status = setDeviceSymlink(PhysicalDeviceObject, dosdevname, p_DVCEXT);

if (!NT_SUCCESS(status)) {
DbgPrint(“Error creating symlink for device to \DosDevices\OSEC%d\n”, devIndex, devIndex);
return status;
}

//Store next-layered device object
//Attach device object to device stack
p_DVCEXT->NextDeviceObject =
IoAttachDeviceToDeviceStack(ptr_PDO, PhysicalDeviceObject);
ptr_PDO->Flags &= ~DO_DEVICE_INITIALIZING;
}

return status;
}

NTSTATUS setDeviceSymlink(PDEVICE_OBJECT pPdo, UNICODE_STRING symlinkName, PDEVICE_EXTENSION deviceExtension)
{
ULONG length;
NTSTATUS status;
PWSTR pName;
UNICODE_STRING pdoName;

length = 0;

status = IoGetDeviceProperty(pPdo,
DevicePropertyPhysicalDeviceObjectName,
0,
NULL,
&length);

if (status != STATUS_BUFFER_TOO_SMALL && !NT_SUCCESS(status)) {
DbgPrint(“Failed to get device name length: %s\n”, OsrNTStatusToString(status));
return status;
}
else if (length > USHORT_MAX) {
DbgPrint(“Name buffer overflow\n”);
return STATUS_INTEGER_OVERFLOW;
}
else if (length == 0) {
DbgPrint(“Error: invalid device state for making symlink”);
//
// We can get zero back if the PDO is being deleted. This can only happen if we are
// creating the symbolic link outside of AddDevice() or a PnP start.
//
return STATUS_INVALID_DEVICE_STATE;
}

pName = (PWSTR) ExAllocatePoolWithTag(PagedPool, length, ‘nBUF’);
if (pName == NULL) {
DbgPrint(“Error: insufficient resources to make symlink”);
return STATUS_INSUFFICIENT_RESOURCES;
}

status = IoGetDeviceProperty(pPdo,
DevicePropertyPhysicalDeviceObjectName,
length,
pName,
&length);

if (!NT_SUCCESS(status)) {
DbgPrint(“Failed to get device name: %s\n”, OsrNTStatusToString(status));
ExFreePool(pName);
pName = NULL;
return status;
}

pdoName.Buffer = pName;
pdoName.Length = (USHORT) length - sizeof(UNICODE_NULL);
pdoName.MaximumLength = (USHORT) length;

status = IoCreateSymbolicLink(&symlinkName, &pdoName);

if (NT_SUCCESS(status)) {
DbgPrint(“Generated symlink %s to %s\n”, symlinkName, pdoName);
// the type of DeviceExtension->PdoName is UNICODE_STRING
RtlCopyMemory(&deviceExtension->PdoName, &pdoName, sizeof(pdoName));

// now that we stored the buffer in our extension, remove all references to the buffer
// so that we don’t accidentally free it while still pointing to it in the extension
pName = NULL;
RtlZeroMemory(&pdoName, sizeof(pdoName));
}
else {
DbgPrint(“Could not generate symlink %s to %s: %s\n”, symlinkName, pdoName, OsrNTStatusToString(status));
ExFreePool(pName);
pName = NULL;
}

return status;
}

Thanks,

Paul Ryan

On Sun, Jun 8, 2008 at 3:50 PM, > wrote:

> Could you please explain what I should have done if I just wanted to name
> the PDO (something human readable).

You can choose either of the things below

1.Create a symlink to PDO’s name so that the user will be able to open it with CreateFile()

2. Don’t be bothered about the name in a driver, and, instead of CreateFile() library function, use
ZwCreateFile() system call in your app. If you do it this way you will be able to open PDO by its name

I would say that, for the sake of simplicity, it is better to take the former option, so that you will be able to hardcode your device name right in app’s code…

Anton Bassov


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

— NTDEV is sponsored by OSR For our schedule of WDF, WDM, debugging and other seminars visit: http://www.osr.com/seminars To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer


Paul Ryan
xxxxx@gmail.commailto:xxxxx — NTDEV is sponsored by OSR For our schedule of WDF, WDM, debugging and other seminars visit: http://www.osr.com/seminars To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer</mailto:xxxxx></mailto:xxxxx></mailto:xxxxx>

I’ve also tried r+b with the same results as well as w, w+b, w+, etc.

Thanks,

Paul Ryan

On Mon, Jun 9, 2008 at 5:07 PM, Tim Roberts wrote:

> Paul Ryan wrote:
>
>> your right the line is the one that is commented out sorry I was just
>> trying to get a concise dump and made mistake on my changes: char* filename
>> = argv[1];
>>
>> I was passing \.\OSEC0 or whatever number the device was the access
>> string was r
>>
>
> But your CreateFile example used GENERIC_READ|GENERIC_WRITE. You almost
> certainly want “r+b” here.
>
>
> –
> Tim Roberts, xxxxx@probo.com
> Providenza & Boekelheide, Inc.
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>


Paul Ryan
xxxxx@gmail.com