Assign user desired com port numbers at the time of driver installation

Hi everyone.

we are writing a virtual com port driver, which is almost completed and
working fine. the com port numbers to this virtual port drivers are
allocated by ports class installer.

now we want to assign this comport number to user desired one. we have user
application which will write the user desired comports number into registry
before driver got installed. when we are installing the driver we need to
assign same com port numbers to driver.

To Implement this i am reading the com port numbers from the registry and
saving into my driver sources in DriverEntry Routine.

In AddDevice Routine, after creating device object i am opening registry
key and doing the following things.

status = IoOpenDeviceRegistryKey(pdx->PhysicalDeviceObject,
PLUGPLAY_REGKEY_DEVICE, KEY_ALL_ACCESS, &hkey);

RtlInitUnicodeString(&tempPort, L"COM66");//user desired com port number
temporally hardcoded.

//setting the new “PortName”
status = ZwSetValueKey(hKey, &keyname, 0, REG_SZ, pData, DataLength);
//keyname=“PortName” pData=“COM66” only providing required data

//getting the New “PortName”

status = ZwQueryValueKey(hKey_, &valname, KeyValuePartialInformation, vpip,
size, &size);

//valname=“PortName”

here i got vpip->date=“COM66” so i am thinking that what ever i assinged is
getting reflected.Created the symbolic link(\Dosdevices\COM66) and wrote
vpip->data to SerialMap registry key using
status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP,
SERIAL_DEVICE_MAP,
pdx->uniNameString.Buffer,
REG_SZ,
portname.Buffer,
portname.Length + sizeof(WCHAR));

After installing the driver i am able to communicate with COM66, but where
as in device manager the com port number is showing as different number
means other number. is there any way to change the name in device manager
from with in the driver sources itself.

here my Questions are, can we implement this logic to assign user desired
comports. if Yes why it is not reflecting in device manager. please suggest
me proper way to achieve this.

as i know we can implement co-installer also to achieve this. which one is
preferred way to solve this problem.

please forgive me if did any wrong thinking in implementing this type of
logic, as i am very less experienced in windows drivers and for this
lengthy Question also.

This sounds very familiar. Have you read the thread beginning at

http://www.osronline.com/showThread.cfm?link=280340

?

From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of johnny basha
Sent: 10 March 2017 12:31
To: Windows System Software Devs Interest List
Subject: [ntdev] Assign user desired com port numbers at the time of driver installation

Hi everyone.

we are writing a virtual com port driver, which is almost completed and working fine. the com port numbers to this virtual port drivers are allocated by ports class installer.

now we want to assign this comport number to user desired one. we have user application which will write the user desired comports number into registry before driver got installed. when we are installing the driver we need to assign same com port numbers to driver.

To Implement this i am reading the com port numbers from the registry and saving into my driver sources in DriverEntry Routine.

In AddDevice Routine, after creating device object i am opening registry key and doing the following things.

status = IoOpenDeviceRegistryKey(pdx->PhysicalDeviceObject, PLUGPLAY_REGKEY_DEVICE, KEY_ALL_ACCESS, &hkey);

RtlInitUnicodeString(&tempPort, L"COM66");//user desired com port number temporally hardcoded.

//setting the new “PortName”
status = ZwSetValueKey(hKey, &keyname, 0, REG_SZ, pData, DataLength); //keyname=“PortName” pData=“COM66” only providing required data

//getting the New “PortName”

status = ZwQueryValueKey(hKey_, &valname, KeyValuePartialInformation, vpip, size, &size);

//valname=“PortName”

here i got vpip->date=“COM66” so i am thinking that what ever i assinged is getting reflected.Created the symbolic link(\Dosdevices\COM66<file:>) and wrote vpip->data to SerialMap registry key using
status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP,
SERIAL_DEVICE_MAP,
pdx->uniNameString.Buffer,
REG_SZ,
portname.Buffer,
portname.Length + sizeof(WCHAR));

After installing the driver i am able to communicate with COM66, but where as in device manager the com port number is showing as different number means other number. is there any way to change the name in device manager from with in the driver sources itself.

here my Questions are, can we implement this logic to assign user desired comports. if Yes why it is not reflecting in device manager. please suggest me proper way to achieve this.

as i know we can implement co-installer also to achieve this. which one is preferred way to solve this problem.

please forgive me if did any wrong thinking in implementing this type of logic, as i am very less experienced in windows drivers and for this lengthy Question also.
— NTDEV is sponsored by OSR Visit the list online at: MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers! Details at To unsubscribe, visit the List Server section of OSR Online at</file:>

johnny basha wrote:

we are writing a virtual com port driver, which is almost completed
and working fine. the com port numbers to this virtual port drivers
are allocated by ports class installer.

Right. That’s how it is intended to work.

now we want to assign this comport number to user desired one. we have
user application which will write the user desired comports number
into registry before driver got installed.

Nope. That’s not how it works. How can the user know that COM66 isn’t
already assigned to some other purpose? The whole reason for having the
port class installer arbitrate the numbering is to ensure that there are
no conflicts. You just need to provide a safe place (registry?) to
record what number you were assigned. The app can then look in that
safe place to get the name. THAT’S the sustainable solution.


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

Isn’t the user thinking he has a USB printer ?

I had always thought that in this kind of setup, the virtual COM port was invisible for the user. Indeed it should be, just imagine the user opens the virtual COM port and sends data just like it was a MODEM.

So, does the port number really matter for the user ?

@David Boyce: i have gone through this thread, it seems to be this thread explaining about knowing ports assigned to a driver after it got installed like using setup Api’s to find all the serial device details from user/application level as well as can use in co-installer to know the each serial device details including the com port numbers.

@Tim Roberts: The user application is already searching into ComDB, listing the free Com ports from the ComDB and storing the user desired com port number into registry. then we need to enumerate(install driver) virtual serial port with that same serial port number. here the user application is doing lot more thing rather then this based on this port number.

so i am trying above mentioned logic to implement the user desired com port and i have temporally hardcoded the COM66 as user desired com port number for POC.
i am able to communicate with the device using COM66 with any standard serial application.

But here my problem is, in Device Manager the port number is showing as different one not COM66. Ex: communication port(COM10) not Communication port(COM66).but i am able communicate with com66 and i am not able communicate with com 10.

please do provide some inputs to change name in device manager from the driver itself and also see what ever i have written is correct or not?

You need to update the friendly name

Bent from my phone


From: xxxxx@lists.osr.com on behalf of xxxxx@gmail.com
Sent: Tuesday, March 14, 2017 4:25:38 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Assign user desired com port numbers at the time of driver installation

@David Boyce: i have gone through this thread, it seems to be this thread explaining about knowing ports assigned to a driver after it got installed like using setup Api’s to find all the serial device details from user/application level as well as can use in co-installer to know the each serial device details including the com port numbers.

@Tim Roberts: The user application is already searching into ComDB, listing the free Com ports from the ComDB and storing the user desired com port number into registry. then we need to enumerate(install driver) virtual serial port with that same serial port number. here the user application is doing lot more thing rather then this based on this port number.

so i am trying above mentioned logic to implement the user desired com port and i have temporally hardcoded the COM66 as user desired com port number for POC.
i am able to communicate with the device using COM66 with any standard serial application.

But here my problem is, in Device Manager the port number is showing as different one not COM66. Ex: communication port(COM10) not Communication port(COM66).but i am able communicate with com66 and i am not able communicate with com 10.

please do provide some inputs to change name in device manager from the driver itself and also see what ever i have written is correct or not?


NTDEV is sponsored by OSR

Visit the list online at: http:

MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
Details at http:

To unsubscribe, visit the List Server section of OSR Online at http:</http:></http:></http:>

@Doron: but i am not getting how to update the friendly name from the driver itself. i googled and tried it by using IoSetDevicePropertyData(). this Api returning the status as status_succees but no change in device manager display name, here is the code what i have used for updating friendly name. continuous to above written code.

RtlInitUnicodeString(&FrndlyName, L"XXX Communication Port1 (COM66)");//temporarly hardcoded

status = IoSetDevicePropertyData(
pdx->PhysicalDeviceObject,
&DEVPKEY_Device_FriendlyName,
LOCALE_NEUTRAL,
PLUGPLAY_PROPERTY_PERSISTENT,
DEVPROP_TYPE_STRING,
sizeof(WCHAR) * FrndlyName.Length,
FrndlyName.Buffer);

if (status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL) {
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERROR, (“IoSetDeviceProperty failed with error : 0x%x\n”, status));
return(status);
}

This api returning the status_succees and now i tried getting the same property using below code

pDevicePropertyData = ExAllocatePool(NonPagedPool, bufferLength);
if (pDevicePropertyData == NULL) {
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERROR, (“first ExAllocatePool failed with error : 0x%x\n”, status));
return(status);
}

status = IoGetDevicePropertyData(
pdx->PhysicalDeviceObject, // PhysicalDeviceObject
&DEVPKEY_Device_FriendlyName,
LOCALE_NEUTRAL,
0,
bufferLength,
pDevicePropertyData,
&returnedLength,
&devicePropertyType);
if (status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL) {
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERROR, (“first IoGetDeviceProperty failed with error : 0x%x\n”, status));
return(status);
}
if (status == STATUS_BUFFER_TOO_SMALL) {
ExFreePool(pDevicePropertyData);
bufferLength = returnedLength;
pDevicePropertyData = ExAllocatePool(NonPagedPool, bufferLength);
if (pDevicePropertyData == NULL) {
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERROR, (“second ExAllocatePool failed with error : 0x%x\n”, status));
return(status);
}
status = IoGetDevicePropertyData(
pdx->PhysicalDeviceObject, // PhysicalDeviceObject
&DEVPKEY_Device_FriendlyName,
LOCALE_NEUTRAL,
0,
bufferLength,
pDevicePropertyData,
&returnedLength,
&devicePropertyType
);
if (status != STATUS_SUCCESS) {
DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_ERROR, (“second IoGetDeviceProperty failed with error : 0x%x\n”, status));
return(status);
}
}

This Api is also returning status_succees and i have seen the pDevicePropertyData, it contains the name what ever i have set like “XXX Communication Port1 (COM66)” . but finally in device manager their in no change in the display name.

i am testing this in windows 7 64 bit. am i missing any thing in above code.
is it possible to change the display/friendly name in the device manager from the driver itself while installation.

please suggest the me the proper solution to resolve the issue. i am stuck up at this point.

Because the device manager displays the ‘Device Description’ property.

You still do not understand what the Length and MaximumLength members of the UNICODE_STRING structure mean.

You are lucky that IoSetDevicePropertyData performs a read only access and that the terminating NULL is preventing the API from smashing the stack.

So just let the compiler compute the buffer size for you:

#define DEV_STRING L"My Device Description and Friendly name";

status = IoSetDevicePropertyData(
pdx->PhysicalDeviceObject,
&DEVPKEY_Device_FriendlyName,
LOCALE_NEUTRAL,
PLUGPLAY_PROPERTY_PERSISTENT,
DEVPROP_TYPE_STRING,
sizeof(DEV_STRING),
(PVOID)DEV_STRING);

if(!NT_SUCCESS(status)){
return status;
}

status = IoSetDevicePropertyData(
pdx->PhysicalDeviceObject,
&DEVPKEY_Device_DeviceDesc,
LOCALE_NEUTRAL,
PLUGPLAY_PROPERTY_PERSISTENT,
DEVPROP_TYPE_STRING,
sizeof(DEV_STRING),
(PVOID)DEV_STRING);

if(!NT_SUCCESS(status)){
return status;
}

Hi D.T thank u for reply but still no luck :),

Even after updating the device descriptor(used the same code snippet what ever ur provided for sample purpose) also there is no change in the device manager. even i have seen the registry key also no changes in registry key and the registry key is “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\Root\PORTS\0000”
i am not getting what i am missing here.

i did all this changes/updates in addDevice routine just after creating the fdo and before creating the symbolic link. is there any other place where i need to write this code to update portnumbers and display names in driver sources.
please provide some inputs to solve this problem

Sorry about my last comment, it was wrong. Constant strings are not stored on the stack but on a read-only section of the driver’s binary (like .data).

I can’t see what is wrong in the code except that sizeof(DEV_STRING) may be cast to a ULONG. On x86, this could be ok, but not on x64.

You should try to perform the task from user mode. This could be done with SetupDiSetDeviceProperty/SetupDiGetDeviceProperty.

>Constant strings are not stored on the stack but on a read-only section of the driver’s binary (like .data).

Also note that constant strings defined in a PAGED function are put in PAGED memory. There was a discussion about this a year or so ago on this list. This is important if for example you put error handing or initialization code in a paged function, and then expect stored string values to be accessible at a higher IRQL.

Jan

>Also note that constant strings defined in a PAGED function are put in PAGED memory. There was a discussion about this a year or so ago on this list. This is important if for example you put error handing or initialization code in a paged function, and then expect stored string values to be accessible at a higher IRQL.

Ok, thank you.

Hi D.T,

In my case i have copied the constant string into unicode string and then used in IoSetDevicePropertyData() for both the DEVPKEY_Device_FriendlyName and DEVPKEY_Device_DeviceDesc for updating both friendly name and device decription but still no change in the device manager.

is there any way to resolve my problem form the driver itself.please do provide some inputs.

or else finally i need to go with user level application/co-installer to change the portname and friendly name dynamically.
I am stuck up here at this juncture. Please provide some inputs to resolve this problem.