Changing Serial Port Number?

Hi,

i’m feeling quite stupid to ask the list again, but i’m really stuck and
under pressure…
i wrote a driver which does nothing else than creating a virtual serial
port and
forwarding all IRPs (except from some special ioctls) to another serial
port driver.

now i want to change the serial port number of my virtual serial port to
any unused serial
port the user desires (from user mode).

currently i’m trying to achieve this through the following steps:
-telling the driver that its port changed (special ioctl)
-updating the HKLM\Hardware\Devicemap\SerialComm registry key
-retrieving a HDEVINFO handle to the PORTS class
-using a previously obtained SP_DEVINFO_DATA struct +
CM_Open_DevNode_Key function (cfgMr32.lib) to open the devices registry key
-setting the devices “PortName” registry property to the desired new
port name
-updating the devices “FriendlyName” through
SetupDiSetDeviceRegistryProperty
-updating the devices symbolic link through QueryDosDevice / DefineDosDevice
-and finally freeing the old and claiming the new port through
ComDBReleasePort/ComDBClaimPort

now i’m able to access the port through its new name (with
hyperterminal) , but first SetupDiEnumDeviceInfo
doesn’t enumerate my device anymore and second the device manager still
displays the old name
and can’t even remove my driver anymore but instead tells my, that my
device is “perhaps” required
to start the computer.

what should i do to change my drivers port name? am i completly wrong
and there’s
a single API?
the code is attached below.
regards,
daniel.

int CSerialMap::relinkPort(CString portName, const int newPortNo,
PPORT_INFO portInfo)
{
int status;
DWORD oldPortNumber;
TCHAR targetPath[MAX_NAME_PORTS],
newPortName[MAX_NAME_PORTS],
newFriendlyName[MAX_NAME_PORTS];
_GUID* guidTmp;
HDEVINFO deviceInfoSet;
BOOL guidTest = FALSE;
DWORD requiredSize = 0;
SP_DEVINFO_DATA devInfoData;
HKEY keyDevice;
static CM_Open_DevNode_Key openDevNodeKey = NULL;
static HINSTANCE cfgMan;

if (NULL == openDevNodeKey)
{
cfgMan = LoadLibrary(“cfgmgr32”);
if (!cfgMan)
{
lastError = ERR_DYNAMIC_LIB;
return lastError;
}
openDevNodeKey = (CM_Open_DevNode_Key)GetProcAddress(cfgMan,
“CM_Open_DevNode_Key”);
if (!openDevNodeKey)
{
lastError = ERR_DYNAMIC_LIB;
FreeLibrary(cfgMan);
goto rlpErr1;
}
}

devInfoData = portInfo->DeviceInfoData;

_stprintf(newPortName, “COM%d”, newPortNo + 1);

//update the devices portname and friendly name registry keys:
guidTest = SetupDiClassGuidsFromNameA(“Ports”, 0, 0, &requiredSize);
if (requiredSize < 1)
{
lastError = ERR_DEVICE_MANAGER;
goto rlpErr1;
}

guidTmp = (_GUID*) malloc(requiredSize * sizeof(GUID));

//get GUID of the ports class:
guidTest = SetupDiClassGuidsFromNameA(“Ports”, guidTmp, requiredSize *
sizeof(GUID), &requiredSize);
if (!guidTest)
{
lastError = ERR_DEVICE_MANAGER;
free(guidTmp);
goto rlpErr1;
}

//get devices within ports class:
deviceInfoSet = SetupDiGetClassDevs(guidTmp, NULL, NULL, DIGCF_PRESENT);
free(guidTmp);
if (INVALID_HANDLE_VALUE == deviceInfoSet)
{
lastError = ERR_DEVICE_MANAGER;
goto rlpErr1;
}

//open device registry key:
status = openDevNodeKey(devInfoData.DevInst, KEY_QUERY_VALUE |
KEY_SET_VALUE, 0,
RegDisposition_OpenExisting, &keyDevice, CM_REGISTRY_HARDWARE);
if (ERROR_SUCCESS != status)
{
lastError = ERR_REGISTRY;
goto rlpErr2;
}

//set the new portname registry key:
status = RegSetValueEx(keyDevice, “PortName”, 0, REG_SZ,
(PBYTE)newPortName, (_tclen(newPortName) + 1) * sizeof(TCHAR));
RegCloseKey(keyDevice);
if (ERROR_SUCCESS != status)
{
lastError = ERR_REGISTRY;
goto rlpErr2;
}

//create the new FriendlyName property:
status = SetupDiGetDeviceRegistryProperty(deviceInfoSet, &devInfoData,
SPDRP_FRIENDLYNAME,
NULL, (PBYTE)newFriendlyName, MAX_NAME_PORTS, NULL);
if (ERROR_SUCCESS == status)
{
createNewFriendlyName(newFriendlyName, newPortName);

SetupDiSetDeviceRegistryProperty(deviceInfoSet, &devInfoData,
SPDRP_FRIENDLYNAME,
(PBYTE)newFriendlyName, (_tclen(newFriendlyName) + 1) * sizeof(TCHAR));
}

SetupDiDestroyDeviceInfoList(deviceInfoSet);
FreeLibrary(cfgMan);

//query and store the target device of the specified port (i.e.
“\Device\Serial0”):
status = QueryDosDevice(portName, (PTCHAR)&targetPath, MAX_NAME_PORTS);
if (status < 1)
{
lastError = ::GetLastError();
return lastError;
}

//delete the current symbolic link:
if (TRUE != DefineDosDevice(DDD_REMOVE_DEFINITION, portName, NULL))
{
lastError = ::GetLastError();
return lastError;
}

//create the new link:
if (TRUE != DefineDosDevice(DDD_RAW_TARGET_PATH, newPortName, targetPath))
{
lastError = ::GetLastError();
//try to restore the old link:
DefineDosDevice(DDD_RAW_TARGET_PATH, portName, targetPath);
return lastError;
}

//update COM port database:
HCOMDB comDB;
status = ComDBOpen(&comDB);
if (ERROR_SUCCESS != status)
{
lastError = status;
return status;
}

oldPortNumber = atoi(portName.Mid(3));
status = ComDBReleasePort(comDB, oldPortNumber);
if (ERROR_SUCCESS != status)
lastError = status;

status = ComDBClaimPort(comDB, (DWORD)newPortNo + 1, TRUE, NULL);
if (ERROR_SUCCESS != status)
{
lastError = status;
ComDBClose(comDB);
return status;
}
ComDBClose(comDB);

return SUCCESS;

rlpErr2:
SetupDiDestroyDeviceInfoList(deviceInfoSet);
rlpErr1:
FreeLibrary(cfgMan);
return lastError;
}

Hi,

I hope the following helps.

Sincerely,
William Michael Jones “Mike”

/***

Hi,

i’m feeling quite stupid to ask the list again, but i’m really stuck and
under pressure… i wrote a driver which does nothing else than creating a
virtual serial
port and forwarding all IRPs (except from some special ioctls) to another
serial
port driver.

now i want to change the serial port number of my virtual serial port to
any unused serial port the user desires (from user mode).

currently i’m trying to achieve this through the following steps:
-telling the driver that its port changed (special ioctl)
-updating the HKLM\Hardware\Devicemap\SerialComm registry key
-retrieving a HDEVINFO handle to the PORTS class
-using a previously obtained SP_DEVINFO_DATA struct +
CM_Open_DevNode_Key function (cfgMr32.lib) to open the devices registry key
-setting the devices “PortName” registry property to the desired new
port name
-updating the devices “FriendlyName” through
SetupDiSetDeviceRegistryProperty
-updating the devices symbolic link through QueryDosDevice / DefineDosDevice
-and finally freeing the old and claiming the new port through
ComDBReleasePort/ComDBClaimPort

now i’m able to access the port through its new name (with
hyperterminal) , but first SetupDiEnumDeviceInfo
doesn’t enumerate my device anymore and second the device manager still
displays the old name
and can’t even remove my driver anymore but instead tells my, that my
device is “perhaps” required
to start the computer.

what should i do to change my drivers port name? am i completly wrong
and there’s
a single API?
the code is attached below.
regards,
daniel.

***/

int CSerialMap::relinkPort(CString portName, const int newPortNo, PPORT_INFO
portInfo)
{
int status;
DWORD oldPortNumber;
TCHAR targetPath[MAX_NAME_PORTS],
newPortName[MAX_NAME_PORTS], newFriendlyName[MAX_NAME_PORTS];
_GUID* guidTmp;
HDEVINFO deviceInfoSet;
BOOL guidTest = FALSE;
DWORD requiredSize = 0;
SP_DEVINFO_DATA devInfoData;
HKEY keyDevice;

static CM_Open_DevNode_Key openDevNodeKey = NULL;

static HINSTANCE cfgMan;

if (NULL == openDevNodeKey)
{
cfgMan = LoadLibrary(“cfgmgr32”);
if (!cfgMan)
{
lastError = ERR_DYNAMIC_LIB;
return lastError;
}
openDevNodeKey = (CM_Open_DevNode_Key)GetProcAddress(cfgMan,
“CM_Open_DevNode_Key”);
if (!openDevNodeKey)
{
lastError = ERR_DYNAMIC_LIB;
FreeLibrary(cfgMan);
goto rlpErr1;
}
}

devInfoData = portInfo->DeviceInfoData;

_stprintf(newPortName, “COM%d”, newPortNo + 1);

// update the devices portname and friendly name registry keys:
guidTest = SetupDiClassGuidsFromNameA(“Ports”, 0, 0, &requiredSize);
if (requiredSize < 1)
{
lastError = ERR_DEVICE_MANAGER;
goto rlpErr1;
}

guidTmp = (_GUID*) malloc(requiredSize * sizeof(GUID));

// get GUID of the ports class:
guidTest = SetupDiClassGuidsFromNameA(“Ports”, guidTmp, requiredSize *
sizeof(GUID), &requiredSize);
if (!guidTest)
{
lastError = ERR_DEVICE_MANAGER;
free(guidTmp);
goto rlpErr1;
}

// get devices within ports class:
deviceInfoSet = SetupDiGetClassDevs(guidTmp, NULL, NULL, DIGCF_PRESENT);
free(guidTmp);
if (INVALID_HANDLE_VALUE == deviceInfoSet)
{
lastError = ERR_DEVICE_MANAGER;
goto rlpErr1;
}

/////////
{

TCHAR szFriendlyName[MAX_PATH];
SP_DEVINFO_DATA deidThis;
HKEY hkeyDev;
TCHAR szPortNameVal[MAX_PATH];
DWORD dwLen = MAX_PATH;
LONG lRet;

// I used the SetupXXX calls
// Walk the list of port devices to make sure it is yours

deidThis.cbSize = sizeof( SP_DEVINFO_DATA );

while( SetupDiEnumDeviceInfo( hdiPortsForCard, nDevIdx++, &deidThis ) )
{
// Open the Device Parameters Key of the device
hkeyDev = SetupDiOpenDevRegKey( hdiPortsForCard, &deidThis,
DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_ALL_ACCESS );

// Now you can query and set all you want here and check with regedit

RegQueryValueEx( hkeyDev, _T(“PortName”), NULL, NULL,
(LPBYTE)szPortNameVal, &dwLen ) != ERROR_SUCCESS )

// Query and set other things too

lRet = RegSetValueEx( hkeyDev, _T(“PortName”), 0,REG_SZ,
(LPBYTE)szPortNameVal, (DWORD) (_tcslen( szPortNameVal ) + 1 ) * sizeof(
TCHAR) );
if( lRet != ERROR_SUCCESS )
{
continue;
}

RegCloseKey( hkeyDev );

// Write the new Friendly Name which includes the COM port
memset( szFriendlyName, 0x00, MAX_PATH );
wsprintf( szFriendlyName, _T(“Avocent ESP Port (COM%u)”),
dwNewComNum );

if( !SetupDiSetDeviceRegistryProperty( hdiPortsForCard,
&deidThis,SPDRP_FRIENDLYNAME,(PBYTE)szFriendlyName,
(DWORD) (_tcslen( szFriendlyName ) +
1 ) * sizeof( TCHAR) ) )
{
continue;
}

} // while( SetupDiEnumDeviceInfo( hdiPortsForCard, nDevIdx++,
&deidThis ) )

// I would not use the openDevNodeKey() stuff. Check that the registry
is changed here tool.

// Now do your QueryDosNames DDD_REMOVE_DEFINITION etc. Note I had to do
DDD_REMOVE_DEFINITION in a loop to get it
// too completely delete. You can check this with WinObj.exe from
sysinternals.com

// query and store the target device of the specified port (i.e.
“\Device\Serial0”):
status = QueryDosDevice(portName, (PTCHAR)&targetPath, MAX_NAME_PORTS);
if (status < 1)
{
lastError = ::GetLastError();
return lastError;
}

// Do a loop here till all are gone…!!! for DDD_REMOVE_DEFINITION
check with WinObj

// delete the current symbolic link:
if (TRUE != DefineDosDevice(DDD_REMOVE_DEFINITION, portName, NULL))
{
lastError = ::GetLastError();
return lastError;
}

// create the new link:
if (TRUE != DefineDosDevice(DDD_RAW_TARGET_PATH, newPortName,
targetPath))
{
lastError = ::GetLastError();
// try to restore the old link:
DefineDosDevice(DDD_RAW_TARGET_PATH, portName, targetPath);
return lastError;
}

// update COM port database:
HCOMDB comDB;
status = ComDBOpen(&comDB);
if (ERROR_SUCCESS != status)
{
lastError = status;
return status;
}

oldPortNumber = atoi(portName.Mid(3));
status = ComDBReleasePort(comDB, oldPortNumber);
if (ERROR_SUCCESS != status)
lastError = status;

status = ComDBClaimPort(comDB, (DWORD)newPortNo + 1, TRUE, NULL);
if (ERROR_SUCCESS != status)
{
lastError = status;
ComDBClose(comDB);
return status;
}
ComDBClose(comDB);

}

////////// The following you change Device Manager to renumerate the
FriendlyName

SetupDiDestroyDeviceInfoList( hdiPortsForCard );

deip.cbSize = sizeof(SP_DEVINSTALL_PARAMS);

SetupDiGetDeviceInstallParams( hdi, pdeid, &deip );

ESPPRINT((DBG_OnApply, _T(“OnApply: Old Flags for Port=0x%08x\n”),
deip.FlagsEx ));

deip.cbSize = sizeof(SP_DEVINSTALL_PARAMS);

deip.FlagsEx |= DI_FLAGSEX_PROPCHANGE_PENDING;

ESPPRINT((DBG_OnApply, _T(“OnApply():New Flags for Port=0x%08x (Set
DI_FLAGSEX_PROPCHANGE_PENDING)\n”), deip.FlagsEx ));

SetupDiSetDeviceInstallParams( hdi, pdeid, &deip );

// Do this before…

SetupDiDestroyDeviceInfoList(deviceInfoSet);
FreeLibrary(cfgMan);

////////////

// open device registry key:
status = openDevNodeKey(devInfoData.DevInst, KEY_QUERY_VALUE |
KEY_SET_VALUE, 0,
RegDisposition_OpenExisting, &keyDevice,
CM_REGISTRY_HARDWARE);
if (ERROR_SUCCESS != status)
{
lastError = ERR_REGISTRY;
goto rlpErr2;
}

// set the new portname registry key:
status = RegSetValueEx(keyDevice, “PortName”, 0, REG_SZ,
(PBYTE)newPortName, (_tclen(newPortName) + 1) *
sizeof(TCHAR));
RegCloseKey(keyDevice);
if (ERROR_SUCCESS != status)
{
lastError = ERR_REGISTRY;
goto rlpErr2;
}

// create the new FriendlyName property:
status = SetupDiGetDeviceRegistryProperty(deviceInfoSet, &devInfoData,
SPDRP_FRIENDLYNAME,
NULL, (PBYTE)newFriendlyName,
MAX_NAME_PORTS, NULL);
if (ERROR_SUCCESS == status)
{
createNewFriendlyName(newFriendlyName, newPortName);

SetupDiSetDeviceRegistryProperty(deviceInfoSet, &devInfoData,
SPDRP_FRIENDLYNAME,
(PBYTE)newFriendlyName,
(_tclen(newFriendlyName) + 1) * sizeof(TCHAR));
}

///////////

SetupDiDestroyDeviceInfoList(deviceInfoSet);
FreeLibrary(cfgMan);

// query and store the target device of the specified port (i.e.
“\Device\Serial0”):
status = QueryDosDevice(portName, (PTCHAR)&targetPath, MAX_NAME_PORTS);
if (status < 1)
{
lastError = ::GetLastError();
return lastError;
}

// delete the current symbolic link:
if (TRUE != DefineDosDevice(DDD_REMOVE_DEFINITION, portName, NULL))
{
lastError = ::GetLastError();
return lastError;
}

// create the new link:
if (TRUE != DefineDosDevice(DDD_RAW_TARGET_PATH, newPortName,
targetPath))
{
lastError = ::GetLastError();
// try to restore the old link:
DefineDosDevice(DDD_RAW_TARGET_PATH, portName, targetPath);
return lastError;
}

// update COM port database:
HCOMDB comDB;
status = ComDBOpen(&comDB);
if (ERROR_SUCCESS != status)
{
lastError = status;
return status;
}

oldPortNumber = atoi(portName.Mid(3));
status = ComDBReleasePort(comDB, oldPortNumber);
if (ERROR_SUCCESS != status)
lastError = status;

status = ComDBClaimPort(comDB, (DWORD)newPortNo + 1, TRUE, NULL);
if (ERROR_SUCCESS != status)
{
lastError = status;
ComDBClose(comDB);
return status;
}
ComDBClose(comDB);

return SUCCESS;

rlpErr2:
SetupDiDestroyDeviceInfoList(deviceInfoSet);
rlpErr1:
FreeLibrary(cfgMan);
return lastError;
}

“L3sT4Rd” wrote in message news:xxxxx@ntdev…
> Hi,
>
> i’m feeling quite stupid to ask the list again, but i’m really stuck and
> under pressure…
> i wrote a driver which does nothing else than creating a virtual serial
> port and
> forwarding all IRPs (except from some special ioctls) to another serial
> port driver.
>
> now i want to change the serial port number of my virtual serial port to
> any unused serial
> port the user desires (from user mode).
>
> currently i’m trying to achieve this through the following steps:
> -telling the driver that its port changed (special ioctl)
> -updating the HKLM\Hardware\Devicemap\SerialComm registry key
> -retrieving a HDEVINFO handle to the PORTS class
> -using a previously obtained SP_DEVINFO_DATA struct +
> CM_Open_DevNode_Key function (cfgMr32.lib) to open the devices registry
> key
> -setting the devices “PortName” registry property to the desired new
> port name
> -updating the devices “FriendlyName” through
> SetupDiSetDeviceRegistryProperty
> -updating the devices symbolic link through QueryDosDevice /
> DefineDosDevice
> -and finally freeing the old and claiming the new port through
> ComDBReleasePort/ComDBClaimPort
>
> now i’m able to access the port through its new name (with
> hyperterminal) , but first SetupDiEnumDeviceInfo
> doesn’t enumerate my device anymore and second the device manager still
> displays the old name
> and can’t even remove my driver anymore but instead tells my, that my
> device is “perhaps” required
> to start the computer.
>
> what should i do to change my drivers port name? am i completly wrong
> and there’s
> a single API?
> the code is attached below.
> regards,
> daniel.
>
> int CSerialMap::relinkPort(CString portName, const int newPortNo,
> PPORT_INFO portInfo)
> {
> int status;
> DWORD oldPortNumber;
> TCHAR targetPath[MAX_NAME_PORTS],
> newPortName[MAX_NAME_PORTS],
> newFriendlyName[MAX_NAME_PORTS];
> _GUID* guidTmp;
> HDEVINFO deviceInfoSet;
> BOOL guidTest = FALSE;
> DWORD requiredSize = 0;
> SP_DEVINFO_DATA devInfoData;
> HKEY keyDevice;
> static CM_Open_DevNode_Key openDevNodeKey = NULL;
> static HINSTANCE cfgMan;
>
> if (NULL == openDevNodeKey)
> {
> cfgMan = LoadLibrary(“cfgmgr32”);
> if (!cfgMan)
> {
> lastError = ERR_DYNAMIC_LIB;
> return lastError;
> }
> openDevNodeKey = (CM_Open_DevNode_Key)GetProcAddress(cfgMan,
> “CM_Open_DevNode_Key”);
> if (!openDevNodeKey)
> {
> lastError = ERR_DYNAMIC_LIB;
> FreeLibrary(cfgMan);
> goto rlpErr1;
> }
> }
>
> devInfoData = portInfo->DeviceInfoData;
>
> _stprintf(newPortName, “COM%d”, newPortNo + 1);
>
> //update the devices portname and friendly name registry keys:
> guidTest = SetupDiClassGuidsFromNameA(“Ports”, 0, 0, &requiredSize);
> if (requiredSize < 1)
> {
> lastError = ERR_DEVICE_MANAGER;
> goto rlpErr1;
> }
>
> guidTmp = (_GUID*) malloc(requiredSize * sizeof(GUID));
>
> //get GUID of the ports class:
> guidTest = SetupDiClassGuidsFromNameA(“Ports”, guidTmp, requiredSize *
> sizeof(GUID), &requiredSize);
> if (!guidTest)
> {
> lastError = ERR_DEVICE_MANAGER;
> free(guidTmp);
> goto rlpErr1;
> }
>
> //get devices within ports class:
> deviceInfoSet = SetupDiGetClassDevs(guidTmp, NULL, NULL, DIGCF_PRESENT);
> free(guidTmp);
> if (INVALID_HANDLE_VALUE == deviceInfoSet)
> {
> lastError = ERR_DEVICE_MANAGER;
> goto rlpErr1;
> }
>
> //open device registry key:
> status = openDevNodeKey(devInfoData.DevInst, KEY_QUERY_VALUE |
> KEY_SET_VALUE, 0,
> RegDisposition_OpenExisting, &keyDevice, CM_REGISTRY_HARDWARE);
> if (ERROR_SUCCESS != status)
> {
> lastError = ERR_REGISTRY;
> goto rlpErr2;
> }
>
> //set the new portname registry key:
> status = RegSetValueEx(keyDevice, “PortName”, 0, REG_SZ,
> (PBYTE)newPortName, (_tclen(newPortName) + 1) * sizeof(TCHAR));
> RegCloseKey(keyDevice);
> if (ERROR_SUCCESS != status)
> {
> lastError = ERR_REGISTRY;
> goto rlpErr2;
> }
>
> //create the new FriendlyName property:
> status = SetupDiGetDeviceRegistryProperty(deviceInfoSet, &devInfoData,
> SPDRP_FRIENDLYNAME,
> NULL, (PBYTE)newFriendlyName, MAX_NAME_PORTS, NULL);
> if (ERROR_SUCCESS == status)
> {
> createNewFriendlyName(newFriendlyName, newPortName);
>
> SetupDiSetDeviceRegistryProperty(deviceInfoSet, &devInfoData,
> SPDRP_FRIENDLYNAME,
> (PBYTE)newFriendlyName, (_tclen(newFriendlyName) + 1) * sizeof(TCHAR));
> }
>
> SetupDiDestroyDeviceInfoList(deviceInfoSet);
> FreeLibrary(cfgMan);
>
>
>
> //query and store the target device of the specified port (i.e.
> “\Device\Serial0”):
> status = QueryDosDevice(portName, (PTCHAR)&targetPath, MAX_NAME_PORTS);
> if (status < 1)
> {
> lastError = ::GetLastError();
> return lastError;
> }
>
> //delete the current symbolic link:
> if (TRUE != DefineDosDevice(DDD_REMOVE_DEFINITION, portName, NULL))
> {
> lastError = ::GetLastError();
> return lastError;
> }
>
> //create the new link:
> if (TRUE != DefineDosDevice(DDD_RAW_TARGET_PATH, newPortName, targetPath))
> {
> lastError = ::GetLastError();
> //try to restore the old link:
> DefineDosDevice(DDD_RAW_TARGET_PATH, portName, targetPath);
> return lastError;
> }
>
>
>
> //update COM port database:
> HCOMDB comDB;
> status = ComDBOpen(&comDB);
> if (ERROR_SUCCESS != status)
> {
> lastError = status;
> return status;
> }
>
> oldPortNumber = atoi(portName.Mid(3));
> status = ComDBReleasePort(comDB, oldPortNumber);
> if (ERROR_SUCCESS != status)
> lastError = status;
>
> status = ComDBClaimPort(comDB, (DWORD)newPortNo + 1, TRUE, NULL);
> if (ERROR_SUCCESS != status)
> {
> lastError = status;
> ComDBClose(comDB);
> return status;
> }
> ComDBClose(comDB);
>
> return SUCCESS;
>
> rlpErr2:
> SetupDiDestroyDeviceInfoList(deviceInfoSet);
> rlpErr1:
> FreeLibrary(cfgMan);
> return lastError;
> }
>
>
>
>

Instead of using CM_Open_DevNode_Key, call SetupDiOpenDevRegKey in both
spots, it does the same thing.

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of William Michael
Jones
Sent: Thursday, February 09, 2006 6:51 AM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Changing Serial Port Number?

Hi,

I hope the following helps.

Sincerely,
William Michael Jones “Mike”

/***

Hi,

i’m feeling quite stupid to ask the list again, but i’m really stuck and
under pressure… i wrote a driver which does nothing else than creating
a
virtual serial
port and forwarding all IRPs (except from some special ioctls) to
another
serial
port driver.

now i want to change the serial port number of my virtual serial port to
any unused serial port the user desires (from user mode).

currently i’m trying to achieve this through the following steps:
-telling the driver that its port changed (special ioctl)
-updating the HKLM\Hardware\Devicemap\SerialComm registry key
-retrieving a HDEVINFO handle to the PORTS class
-using a previously obtained SP_DEVINFO_DATA struct +
CM_Open_DevNode_Key function (cfgMr32.lib) to open the devices registry
key
-setting the devices “PortName” registry property to the desired new
port name
-updating the devices “FriendlyName” through
SetupDiSetDeviceRegistryProperty
-updating the devices symbolic link through QueryDosDevice /
DefineDosDevice
-and finally freeing the old and claiming the new port through
ComDBReleasePort/ComDBClaimPort

now i’m able to access the port through its new name (with
hyperterminal) , but first SetupDiEnumDeviceInfo
doesn’t enumerate my device anymore and second the device manager still
displays the old name
and can’t even remove my driver anymore but instead tells my, that my
device is “perhaps” required
to start the computer.

what should i do to change my drivers port name? am i completly wrong
and there’s
a single API?
the code is attached below.
regards,
daniel.

***/

int CSerialMap::relinkPort(CString portName, const int newPortNo,
PPORT_INFO
portInfo)
{
int status;
DWORD oldPortNumber;
TCHAR targetPath[MAX_NAME_PORTS],
newPortName[MAX_NAME_PORTS], newFriendlyName[MAX_NAME_PORTS];
_GUID* guidTmp;
HDEVINFO deviceInfoSet;
BOOL guidTest = FALSE;
DWORD requiredSize = 0;
SP_DEVINFO_DATA devInfoData;
HKEY keyDevice;

static CM_Open_DevNode_Key openDevNodeKey = NULL;

static HINSTANCE cfgMan;

if (NULL == openDevNodeKey)
{
cfgMan = LoadLibrary(“cfgmgr32”);
if (!cfgMan)
{
lastError = ERR_DYNAMIC_LIB;
return lastError;
}
openDevNodeKey = (CM_Open_DevNode_Key)GetProcAddress(cfgMan,
“CM_Open_DevNode_Key”);
if (!openDevNodeKey)
{
lastError = ERR_DYNAMIC_LIB;
FreeLibrary(cfgMan);
goto rlpErr1;
}
}

devInfoData = portInfo->DeviceInfoData;

_stprintf(newPortName, “COM%d”, newPortNo + 1);

// update the devices portname and friendly name registry keys:
guidTest = SetupDiClassGuidsFromNameA(“Ports”, 0, 0, &requiredSize);
if (requiredSize < 1)
{
lastError = ERR_DEVICE_MANAGER;
goto rlpErr1;
}

guidTmp = (_GUID*) malloc(requiredSize * sizeof(GUID));

// get GUID of the ports class:
guidTest = SetupDiClassGuidsFromNameA(“Ports”, guidTmp, requiredSize
*
sizeof(GUID), &requiredSize);
if (!guidTest)
{
lastError = ERR_DEVICE_MANAGER;
free(guidTmp);
goto rlpErr1;
}

// get devices within ports class:
deviceInfoSet = SetupDiGetClassDevs(guidTmp, NULL, NULL,
DIGCF_PRESENT);
free(guidTmp);
if (INVALID_HANDLE_VALUE == deviceInfoSet)
{
lastError = ERR_DEVICE_MANAGER;
goto rlpErr1;
}

/////////
{

TCHAR szFriendlyName[MAX_PATH];
SP_DEVINFO_DATA deidThis;
HKEY hkeyDev;
TCHAR szPortNameVal[MAX_PATH];
DWORD dwLen = MAX_PATH;
LONG lRet;

// I used the SetupXXX calls
// Walk the list of port devices to make sure it is yours

deidThis.cbSize = sizeof( SP_DEVINFO_DATA );

while( SetupDiEnumDeviceInfo( hdiPortsForCard, nDevIdx++, &deidThis
) )
{
// Open the Device Parameters Key of the device
hkeyDev = SetupDiOpenDevRegKey( hdiPortsForCard, &deidThis,
DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_ALL_ACCESS );

// Now you can query and set all you want here and check with
regedit

RegQueryValueEx( hkeyDev, _T(“PortName”), NULL, NULL,
(LPBYTE)szPortNameVal, &dwLen ) != ERROR_SUCCESS )

// Query and set other things too

lRet = RegSetValueEx( hkeyDev, _T(“PortName”), 0,REG_SZ,
(LPBYTE)szPortNameVal, (DWORD) (_tcslen( szPortNameVal ) + 1 ) * sizeof(

TCHAR) );
if( lRet != ERROR_SUCCESS )
{
continue;
}

RegCloseKey( hkeyDev );

// Write the new Friendly Name which includes the COM port
memset( szFriendlyName, 0x00, MAX_PATH );
wsprintf( szFriendlyName, _T(“Avocent ESP Port (COM%u)”),
dwNewComNum );

if( !SetupDiSetDeviceRegistryProperty( hdiPortsForCard,
&deidThis,SPDRP_FRIENDLYNAME,(PBYTE)szFriendlyName,
(DWORD) (_tcslen( szFriendlyName
) +
1 ) * sizeof( TCHAR) ) )
{
continue;
}

} // while( SetupDiEnumDeviceInfo( hdiPortsForCard, nDevIdx++,
&deidThis ) )

// I would not use the openDevNodeKey() stuff. Check that the
registry
is changed here tool.

// Now do your QueryDosNames DDD_REMOVE_DEFINITION etc. Note I had
to do
DDD_REMOVE_DEFINITION in a loop to get it
// too completely delete. You can check this with WinObj.exe from
sysinternals.com

// query and store the target device of the specified port (i.e.
“\Device\Serial0”):
status = QueryDosDevice(portName, (PTCHAR)&targetPath,
MAX_NAME_PORTS);
if (status < 1)
{
lastError = ::GetLastError();
return lastError;
}

// Do a loop here till all are gone…!!! for DDD_REMOVE_DEFINITION
check with WinObj

// delete the current symbolic link:
if (TRUE != DefineDosDevice(DDD_REMOVE_DEFINITION, portName, NULL))
{
lastError = ::GetLastError();
return lastError;
}

// create the new link:
if (TRUE != DefineDosDevice(DDD_RAW_TARGET_PATH, newPortName,
targetPath))
{
lastError = ::GetLastError();
// try to restore the old link:
DefineDosDevice(DDD_RAW_TARGET_PATH, portName, targetPath);
return lastError;
}

// update COM port database:
HCOMDB comDB;
status = ComDBOpen(&comDB);
if (ERROR_SUCCESS != status)
{
lastError = status;
return status;
}

oldPortNumber = atoi(portName.Mid(3));
status = ComDBReleasePort(comDB, oldPortNumber);
if (ERROR_SUCCESS != status)
lastError = status;

status = ComDBClaimPort(comDB, (DWORD)newPortNo + 1, TRUE, NULL);
if (ERROR_SUCCESS != status)
{
lastError = status;
ComDBClose(comDB);
return status;
}
ComDBClose(comDB);

}

////////// The following you change Device Manager to renumerate the

FriendlyName

SetupDiDestroyDeviceInfoList( hdiPortsForCard );

deip.cbSize = sizeof(SP_DEVINSTALL_PARAMS);

SetupDiGetDeviceInstallParams( hdi, pdeid, &deip );

ESPPRINT((DBG_OnApply, _T(“OnApply: Old Flags for Port=0x%08x\n”),
deip.FlagsEx ));

deip.cbSize = sizeof(SP_DEVINSTALL_PARAMS);

deip.FlagsEx |= DI_FLAGSEX_PROPCHANGE_PENDING;

ESPPRINT((DBG_OnApply, _T(“OnApply():New Flags for Port=0x%08x (Set
DI_FLAGSEX_PROPCHANGE_PENDING)\n”), deip.FlagsEx ));

SetupDiSetDeviceInstallParams( hdi, pdeid, &deip );

// Do this before…

SetupDiDestroyDeviceInfoList(deviceInfoSet);
FreeLibrary(cfgMan);

////////////

// open device registry key:
status = openDevNodeKey(devInfoData.DevInst, KEY_QUERY_VALUE |
KEY_SET_VALUE, 0,
RegDisposition_OpenExisting, &keyDevice,
CM_REGISTRY_HARDWARE);
if (ERROR_SUCCESS != status)
{
lastError = ERR_REGISTRY;
goto rlpErr2;
}

// set the new portname registry key:
status = RegSetValueEx(keyDevice, “PortName”, 0, REG_SZ,
(PBYTE)newPortName, (_tclen(newPortName) + 1)
*
sizeof(TCHAR));
RegCloseKey(keyDevice);
if (ERROR_SUCCESS != status)
{
lastError = ERR_REGISTRY;
goto rlpErr2;
}

// create the new FriendlyName property:
status = SetupDiGetDeviceRegistryProperty(deviceInfoSet,
&devInfoData,
SPDRP_FRIENDLYNAME,
NULL,
(PBYTE)newFriendlyName,
MAX_NAME_PORTS, NULL);
if (ERROR_SUCCESS == status)
{
createNewFriendlyName(newFriendlyName, newPortName);

SetupDiSetDeviceRegistryProperty(deviceInfoSet, &devInfoData,
SPDRP_FRIENDLYNAME,
(PBYTE)newFriendlyName,
(_tclen(newFriendlyName) + 1) * sizeof(TCHAR));
}

///////////

SetupDiDestroyDeviceInfoList(deviceInfoSet);
FreeLibrary(cfgMan);

// query and store the target device of the specified port (i.e.
“\Device\Serial0”):
status = QueryDosDevice(portName, (PTCHAR)&targetPath,
MAX_NAME_PORTS);
if (status < 1)
{
lastError = ::GetLastError();
return lastError;
}

// delete the current symbolic link:
if (TRUE != DefineDosDevice(DDD_REMOVE_DEFINITION, portName, NULL))
{
lastError = ::GetLastError();
return lastError;
}

// create the new link:
if (TRUE != DefineDosDevice(DDD_RAW_TARGET_PATH, newPortName,
targetPath))
{
lastError = ::GetLastError();
// try to restore the old link:
DefineDosDevice(DDD_RAW_TARGET_PATH, portName, targetPath);
return lastError;
}

// update COM port database:
HCOMDB comDB;
status = ComDBOpen(&comDB);
if (ERROR_SUCCESS != status)
{
lastError = status;
return status;
}

oldPortNumber = atoi(portName.Mid(3));
status = ComDBReleasePort(comDB, oldPortNumber);
if (ERROR_SUCCESS != status)
lastError = status;

status = ComDBClaimPort(comDB, (DWORD)newPortNo + 1, TRUE, NULL);
if (ERROR_SUCCESS != status)
{
lastError = status;
ComDBClose(comDB);
return status;
}
ComDBClose(comDB);

return SUCCESS;

rlpErr2:
SetupDiDestroyDeviceInfoList(deviceInfoSet);
rlpErr1:
FreeLibrary(cfgMan);
return lastError;
}

“L3sT4Rd” wrote in message news:xxxxx@ntdev…
> Hi,
>
> i’m feeling quite stupid to ask the list again, but i’m really stuck
and
> under pressure…
> i wrote a driver which does nothing else than creating a virtual
serial
> port and
> forwarding all IRPs (except from some special ioctls) to another
serial
> port driver.
>
> now i want to change the serial port number of my virtual serial port
to
> any unused serial
> port the user desires (from user mode).
>
> currently i’m trying to achieve this through the following steps:
> -telling the driver that its port changed (special ioctl)
> -updating the HKLM\Hardware\Devicemap\SerialComm registry key
> -retrieving a HDEVINFO handle to the PORTS class
> -using a previously obtained SP_DEVINFO_DATA struct +
> CM_Open_DevNode_Key function (cfgMr32.lib) to open the devices
registry
> key
> -setting the devices “PortName” registry property to the desired new
> port name
> -updating the devices “FriendlyName” through
> SetupDiSetDeviceRegistryProperty
> -updating the devices symbolic link through QueryDosDevice /
> DefineDosDevice
> -and finally freeing the old and claiming the new port through
> ComDBReleasePort/ComDBClaimPort
>
> now i’m able to access the port through its new name (with
> hyperterminal) , but first SetupDiEnumDeviceInfo
> doesn’t enumerate my device anymore and second the device manager
still
> displays the old name
> and can’t even remove my driver anymore but instead tells my, that my
> device is “perhaps” required
> to start the computer.
>
> what should i do to change my drivers port name? am i completly wrong
> and there’s
> a single API?
> the code is attached below.
> regards,
> daniel.
>
> int CSerialMap::relinkPort(CString portName, const int newPortNo,
> PPORT_INFO portInfo)
> {
> int status;
> DWORD oldPortNumber;
> TCHAR targetPath[MAX_NAME_PORTS],
> newPortName[MAX_NAME_PORTS],
> newFriendlyName[MAX_NAME_PORTS];
> _GUID* guidTmp;
> HDEVINFO deviceInfoSet;
> BOOL guidTest = FALSE;
> DWORD requiredSize = 0;
> SP_DEVINFO_DATA devInfoData;
> HKEY keyDevice;
> static CM_Open_DevNode_Key openDevNodeKey = NULL;
> static HINSTANCE cfgMan;
>
> if (NULL == openDevNodeKey)
> {
> cfgMan = LoadLibrary(“cfgmgr32”);
> if (!cfgMan)
> {
> lastError = ERR_DYNAMIC_LIB;
> return lastError;
> }
> openDevNodeKey = (CM_Open_DevNode_Key)GetProcAddress(cfgMan,
> “CM_Open_DevNode_Key”);
> if (!openDevNodeKey)
> {
> lastError = ERR_DYNAMIC_LIB;
> FreeLibrary(cfgMan);
> goto rlpErr1;
> }
> }
>
> devInfoData = portInfo->DeviceInfoData;
>
> _stprintf(newPortName, “COM%d”, newPortNo + 1);
>
> //update the devices portname and friendly name registry keys:
> guidTest = SetupDiClassGuidsFromNameA(“Ports”, 0, 0, &requiredSize);
> if (requiredSize < 1)
> {
> lastError = ERR_DEVICE_MANAGER;
> goto rlpErr1;
> }
>
> guidTmp = (_GUID*) malloc(requiredSize * sizeof(GUID));
>
> //get GUID of the ports class:
> guidTest = SetupDiClassGuidsFromNameA(“Ports”, guidTmp, requiredSize *
> sizeof(GUID), &requiredSize);
> if (!guidTest)
> {
> lastError = ERR_DEVICE_MANAGER;
> free(guidTmp);
> goto rlpErr1;
> }
>
> //get devices within ports class:
> deviceInfoSet = SetupDiGetClassDevs(guidTmp, NULL, NULL,
DIGCF_PRESENT);
> free(guidTmp);
> if (INVALID_HANDLE_VALUE == deviceInfoSet)
> {
> lastError = ERR_DEVICE_MANAGER;
> goto rlpErr1;
> }
>
> //open device registry key:
> status = openDevNodeKey(devInfoData.DevInst, KEY_QUERY_VALUE |
> KEY_SET_VALUE, 0,
> RegDisposition_OpenExisting, &keyDevice, CM_REGISTRY_HARDWARE);
> if (ERROR_SUCCESS != status)
> {
> lastError = ERR_REGISTRY;
> goto rlpErr2;
> }
>
> //set the new portname registry key:
> status = RegSetValueEx(keyDevice, “PortName”, 0, REG_SZ,
> (PBYTE)newPortName, (_tclen(newPortName) + 1) * sizeof(TCHAR));
> RegCloseKey(keyDevice);
> if (ERROR_SUCCESS != status)
> {
> lastError = ERR_REGISTRY;
> goto rlpErr2;
> }
>
> //create the new FriendlyName property:
> status = SetupDiGetDeviceRegistryProperty(deviceInfoSet, &devInfoData,
> SPDRP_FRIENDLYNAME,
> NULL, (PBYTE)newFriendlyName, MAX_NAME_PORTS, NULL);
> if (ERROR_SUCCESS == status)
> {
> createNewFriendlyName(newFriendlyName, newPortName);
>
> SetupDiSetDeviceRegistryProperty(deviceInfoSet, &devInfoData,
> SPDRP_FRIENDLYNAME,
> (PBYTE)newFriendlyName, (_tclen(newFriendlyName) + 1) *
sizeof(TCHAR));
> }
>
> SetupDiDestroyDeviceInfoList(deviceInfoSet);
> FreeLibrary(cfgMan);
>
>
>
> //query and store the target device of the specified port (i.e.
> “\Device\Serial0”):
> status = QueryDosDevice(portName, (PTCHAR)&targetPath,
MAX_NAME_PORTS);
> if (status < 1)
> {
> lastError = ::GetLastError();
> return lastError;
> }
>
> //delete the current symbolic link:
> if (TRUE != DefineDosDevice(DDD_REMOVE_DEFINITION, portName, NULL))
> {
> lastError = ::GetLastError();
> return lastError;
> }
>
> //create the new link:
> if (TRUE != DefineDosDevice(DDD_RAW_TARGET_PATH, newPortName,
targetPath))
> {
> lastError = ::GetLastError();
> //try to restore the old link:
> DefineDosDevice(DDD_RAW_TARGET_PATH, portName, targetPath);
> return lastError;
> }
>
>
>
> //update COM port database:
> HCOMDB comDB;
> status = ComDBOpen(&comDB);
> if (ERROR_SUCCESS != status)
> {
> lastError = status;
> return status;
> }
>
> oldPortNumber = atoi(portName.Mid(3));
> status = ComDBReleasePort(comDB, oldPortNumber);
> if (ERROR_SUCCESS != status)
> lastError = status;
>
> status = ComDBClaimPort(comDB, (DWORD)newPortNo + 1, TRUE, NULL);
> if (ERROR_SUCCESS != status)
> {
> lastError = status;
> ComDBClose(comDB);
> return status;
> }
> ComDBClose(comDB);
>
> return SUCCESS;
>
> rlpErr2:
> SetupDiDestroyDeviceInfoList(deviceInfoSet);
> rlpErr1:
> FreeLibrary(cfgMan);
> return lastError;
> }
>
>
>
>


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@microsoft.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

William Michael Jones wrote:

////////// The following you change Device Manager to renumerate the
FriendlyName

SetupDiDestroyDeviceInfoList( hdiPortsForCard );

deip.cbSize = sizeof(SP_DEVINSTALL_PARAMS);

SetupDiGetDeviceInstallParams( hdi, pdeid, &deip );

ESPPRINT((DBG_OnApply, _T(“OnApply: Old Flags for Port=0x%08x\n”),
deip.FlagsEx ));

deip.cbSize = sizeof(SP_DEVINSTALL_PARAMS);

deip.FlagsEx |= DI_FLAGSEX_PROPCHANGE_PENDING;

ESPPRINT((DBG_OnApply, _T(“OnApply():New Flags for Port=0x%08x (Set
DI_FLAGSEX_PROPCHANGE_PENDING)\n”), deip.FlagsEx ));

SetupDiSetDeviceInstallParams( hdi, pdeid, &deip );

thanks for your help so far, it’s working quite fine now!
think it’s been a stupid mistake, i wrote _tclen instead of _tcslen… :-[

but i still got problems with the above code;
the device manager doesn’t recognize the changes immediately, but instead
i got to close and re-open it to make it display the new FriendlyName.
is it possible, that the DI_FLAGSEX_PROPCHANGE_PENDING flag
is never checked by device manager cause i’m not setting it from within a
device property sheet ?

MSDN says about DI_FLAGSEX_PROPCHANGE_PENDING:
“When the user closes the device property sheet, Device Manager checks
the DI_FLAGSEX_PROPCHANGE_PENDING flag. If it is set, Device Manager
clears this flag, sets the DI_PROPERTIES_CHANGE flag, and sends a
DIF_PROPERTYCHANGE request to the installers to notify them that
something has changed.”

But i also tried calling SetupDiChangeState (for both, the new and old
DeviceInfoData), so does the DI_FLAGSEX_PROPCHANGE_PENDING:
perhaps instruct the device manager only to update a devices properties but
not to re-enumerate the devices and if yes, is there any function to
make the
device manger re-enumerate all devices of a given class (been searching for
about 2hours now, but can’t find anything…)

daniel.

Hi,

I hope the following helps.

Sincerely,
William Michael Jones “Mike”

/***

Hi,

i’m feeling quite stupid to ask the list again, but i’m really stuck and
under pressure… i wrote a driver which does nothing else than creating a
virtual serial
port and forwarding all IRPs (except from some special ioctls) to another
serial
port driver.

now i want to change the serial port number of my virtual serial port to
any unused serial port the user desires (from user mode).

currently i’m trying to achieve this through the following steps:
-telling the driver that its port changed (special ioctl)
-updating the HKLM\Hardware\Devicemap\SerialComm registry key
-retrieving a HDEVINFO handle to the PORTS class
-using a previously obtained SP_DEVINFO_DATA struct +
CM_Open_DevNode_Key function (cfgMr32.lib) to open the devices registry key
-setting the devices “PortName” registry property to the desired new
port name
-updating the devices “FriendlyName” through
SetupDiSetDeviceRegistryProperty
-updating the devices symbolic link through QueryDosDevice / DefineDosDevice
-and finally freeing the old and claiming the new port through
ComDBReleasePort/ComDBClaimPort

now i’m able to access the port through its new name (with
hyperterminal) , but first SetupDiEnumDeviceInfo
doesn’t enumerate my device anymore and second the device manager still
displays the old name
and can’t even remove my driver anymore but instead tells my, that my
device is “perhaps” required
to start the computer.

what should i do to change my drivers port name? am i completly wrong
and there’s
a single API?
the code is attached below.
regards,
daniel.

***/

int CSerialMap::relinkPort(CString portName, const int newPortNo, PPORT_INFO
portInfo)
{
int status;
DWORD oldPortNumber;
TCHAR targetPath[MAX_NAME_PORTS],
newPortName[MAX_NAME_PORTS], newFriendlyName[MAX_NAME_PORTS];
_GUID* guidTmp;
HDEVINFO deviceInfoSet;
BOOL guidTest = FALSE;
DWORD requiredSize = 0;
SP_DEVINFO_DATA devInfoData;
HKEY keyDevice;

static CM_Open_DevNode_Key openDevNodeKey = NULL;

static HINSTANCE cfgMan;

if (NULL == openDevNodeKey)
{
cfgMan = LoadLibrary(“cfgmgr32”);
if (!cfgMan)
{
lastError = ERR_DYNAMIC_LIB;
return lastError;
}
openDevNodeKey = (CM_Open_DevNode_Key)GetProcAddress(cfgMan,
“CM_Open_DevNode_Key”);
if (!openDevNodeKey)
{
lastError = ERR_DYNAMIC_LIB;
FreeLibrary(cfgMan);
goto rlpErr1;
}
}

devInfoData = portInfo->DeviceInfoData;

_stprintf(newPortName, “COM%d”, newPortNo + 1);

// update the devices portname and friendly name registry keys:
guidTest = SetupDiClassGuidsFromNameA(“Ports”, 0, 0, &requiredSize);
if (requiredSize < 1)
{
lastError = ERR_DEVICE_MANAGER;
goto rlpErr1;
}

guidTmp = (_GUID*) malloc(requiredSize * sizeof(GUID));

// get GUID of the ports class:
guidTest = SetupDiClassGuidsFromNameA(“Ports”, guidTmp, requiredSize *
sizeof(GUID), &requiredSize);
if (!guidTest)
{
lastError = ERR_DEVICE_MANAGER;
free(guidTmp);
goto rlpErr1;
}

// get devices within ports class:
deviceInfoSet = SetupDiGetClassDevs(guidTmp, NULL, NULL, DIGCF_PRESENT);
free(guidTmp);
if (INVALID_HANDLE_VALUE == deviceInfoSet)
{
lastError = ERR_DEVICE_MANAGER;
goto rlpErr1;
}

/////////
{

TCHAR szFriendlyName[MAX_PATH];
SP_DEVINFO_DATA deidThis;
HKEY hkeyDev;
TCHAR szPortNameVal[MAX_PATH];
DWORD dwLen = MAX_PATH;
LONG lRet;

// I used the SetupXXX calls
// Walk the list of port devices to make sure it is yours

deidThis.cbSize = sizeof( SP_DEVINFO_DATA );

while( SetupDiEnumDeviceInfo( hdiPortsForCard, nDevIdx++, &deidThis ) )
{
// Open the Device Parameters Key of the device
hkeyDev = SetupDiOpenDevRegKey( hdiPortsForCard, &deidThis,
DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_ALL_ACCESS );

// Now you can query and set all you want here and check with regedit

RegQueryValueEx( hkeyDev, _T(“PortName”), NULL, NULL,
(LPBYTE)szPortNameVal, &dwLen ) != ERROR_SUCCESS )

// Query and set other things too

lRet = RegSetValueEx( hkeyDev, _T(“PortName”), 0,REG_SZ,
(LPBYTE)szPortNameVal, (DWORD) (_tcslen( szPortNameVal ) + 1 ) * sizeof(
TCHAR) );
if( lRet != ERROR_SUCCESS )
{
continue;
}

RegCloseKey( hkeyDev );

// Write the new Friendly Name which includes the COM port
memset( szFriendlyName, 0x00, MAX_PATH );
wsprintf( szFriendlyName, _T(“Avocent ESP Port (COM%u)”),
dwNewComNum );

if( !SetupDiSetDeviceRegistryProperty( hdiPortsForCard,
&deidThis,SPDRP_FRIENDLYNAME,(PBYTE)szFriendlyName,
(DWORD) (_tcslen( szFriendlyName ) +
1 ) * sizeof( TCHAR) ) )
{
continue;
}

} // while( SetupDiEnumDeviceInfo( hdiPortsForCard, nDevIdx++,
&deidThis ) )

// I would not use the openDevNodeKey() stuff. Check that the registry
is changed here tool.

// Now do your QueryDosNames DDD_REMOVE_DEFINITION etc. Note I had to do
DDD_REMOVE_DEFINITION in a loop to get it
// too completely delete. You can check this with WinObj.exe from
sysinternals.com

// query and store the target device of the specified port (i.e.
“\Device\Serial0”):
status = QueryDosDevice(portName, (PTCHAR)&targetPath, MAX_NAME_PORTS);
if (status < 1)
{
lastError = ::GetLastError();
return lastError;
}

// Do a loop here till all are gone…!!! for DDD_REMOVE_DEFINITION
check with WinObj

// delete the current symbolic link:
if (TRUE != DefineDosDevice(DDD_REMOVE_DEFINITION, portName, NULL))
{
lastError = ::GetLastError();
return lastError;
}

// create the new link:
if (TRUE != DefineDosDevice(DDD_RAW_TARGET_PATH, newPortName,
targetPath))
{
lastError = ::GetLastError();
// try to restore the old link:
DefineDosDevice(DDD_RAW_TARGET_PATH, portName, targetPath);
return lastError;
}

// update COM port database:
HCOMDB comDB;
status = ComDBOpen(&comDB);
if (ERROR_SUCCESS != status)
{
lastError = status;
return status;
}

oldPortNumber = atoi(portName.Mid(3));
status = ComDBReleasePort(comDB, oldPortNumber);
if (ERROR_SUCCESS != status)
lastError = status;

status = ComDBClaimPort(comDB, (DWORD)newPortNo + 1, TRUE, NULL);
if (ERROR_SUCCESS != status)
{
lastError = status;
ComDBClose(comDB);
return status;
}
ComDBClose(comDB);

}

////////// The following you change Device Manager to renumerate the
FriendlyName

SetupDiDestroyDeviceInfoList( hdiPortsForCard );

deip.cbSize = sizeof(SP_DEVINSTALL_PARAMS);

SetupDiGetDeviceInstallParams( hdi, pdeid, &deip );

ESPPRINT((DBG_OnApply, _T(“OnApply: Old Flags for Port=0x%08x\n”),
deip.FlagsEx ));

deip.cbSize = sizeof(SP_DEVINSTALL_PARAMS);

deip.FlagsEx |= DI_FLAGSEX_PROPCHANGE_PENDING;

ESPPRINT((DBG_OnApply, _T(“OnApply():New Flags for Port=0x%08x (Set
DI_FLAGSEX_PROPCHANGE_PENDING)\n”), deip.FlagsEx ));

SetupDiSetDeviceInstallParams( hdi, pdeid, &deip );

// Do this before…

SetupDiDestroyDeviceInfoList(deviceInfoSet);
FreeLibrary(cfgMan);

////////////

// open device registry key:
status = openDevNodeKey(devInfoData.DevInst, KEY_QUERY_VALUE |
KEY_SET_VALUE, 0,
RegDisposition_OpenExisting, &keyDevice,
CM_REGISTRY_HARDWARE);
if (ERROR_SUCCESS != status)
{
lastError = ERR_REGISTRY;
goto rlpErr2;
}

// set the new portname registry key:
status = RegSetValueEx(keyDevice, “PortName”, 0, REG_SZ,
(PBYTE)newPortName, (_tclen(newPortName) + 1) *
sizeof(TCHAR));
RegCloseKey(keyDevice);
if (ERROR_SUCCESS != status)
{
lastError = ERR_REGISTRY;
goto rlpErr2;
}

// create the new FriendlyName property:
status = SetupDiGetDeviceRegistryProperty(deviceInfoSet, &devInfoData,
SPDRP_FRIENDLYNAME,
NULL, (PBYTE)newFriendlyName,
MAX_NAME_PORTS, NULL);
if (ERROR_SUCCESS == status)
{
createNewFriendlyName(newFriendlyName, newPortName);

SetupDiSetDeviceRegistryProperty(deviceInfoSet, &devInfoData,
SPDRP_FRIENDLYNAME,
(PBYTE)newFriendlyName,
(_tclen(newFriendlyName) + 1) * sizeof(TCHAR));
}

///////////

SetupDiDestroyDeviceInfoList(deviceInfoSet);
FreeLibrary(cfgMan);

// query and store the target device of the specified port (i.e.
“\Device\Serial0”):
status = QueryDosDevice(portName, (PTCHAR)&targetPath, MAX_NAME_PORTS);
if (status < 1)
{
lastError = ::GetLastError();
return lastError;
}

// delete the current symbolic link:
if (TRUE != DefineDosDevice(DDD_REMOVE_DEFINITION, portName, NULL))
{
lastError = ::GetLastError();
return lastError;
}

// create the new link:
if (TRUE != DefineDosDevice(DDD_RAW_TARGET_PATH, newPortName,
targetPath))
{
lastError = ::GetLastError();
// try to restore the old link:
DefineDosDevice(DDD_RAW_TARGET_PATH, portName, targetPath);
return lastError;
}

// update COM port database:
HCOMDB comDB;
status = ComDBOpen(&comDB);
if (ERROR_SUCCESS != status)
{
lastError = status;
return status;
}

oldPortNumber = atoi(portName.Mid(3));
status = ComDBReleasePort(comDB, oldPortNumber);
if (ERROR_SUCCESS != status)
lastError = status;

status = ComDBClaimPort(comDB, (DWORD)newPortNo + 1, TRUE, NULL);
if (ERROR_SUCCESS != status)
{
lastError = status;
ComDBClose(comDB);
return status;
}
ComDBClose(comDB);

return SUCCESS;

rlpErr2:
SetupDiDestroyDeviceInfoList(deviceInfoSet);
rlpErr1:
FreeLibrary(cfgMan);
return lastError;
}

“L3sT4Rd” wrote in message news:xxxxx@ntdev…
>
>
>>Hi,
>>
>>i’m feeling quite stupid to ask the list again, but i’m really stuck and
>>under pressure…
>>i wrote a driver which does nothing else than creating a virtual serial
>>port and
>>forwarding all IRPs (except from some special ioctls) to another serial
>>port driver.
>>
>>now i want to change the serial port number of my virtual serial port to
>>any unused serial
>>port the user desires (from user mode).
>>
>>currently i’m trying to achieve this through the following steps:
>>-telling the driver that its port changed (special ioctl)
>>-updating the HKLM\Hardware\Devicemap\SerialComm registry key
>>-retrieving a HDEVINFO handle to the PORTS class
>>-using a previously obtained SP_DEVINFO_DATA struct +
>>CM_Open_DevNode_Key function (cfgMr32.lib) to open the devices registry
>>key
>>-setting the devices “PortName” registry property to the desired new
>>port name
>>-updating the devices “FriendlyName” through
>>SetupDiSetDeviceRegistryProperty
>>-updating the devices symbolic link through QueryDosDevice /
>>DefineDosDevice
>>-and finally freeing the old and claiming the new port through
>>ComDBReleasePort/ComDBClaimPort
>>
>>now i’m able to access the port through its new name (with
>>hyperterminal) , but first SetupDiEnumDeviceInfo
>>doesn’t enumerate my device anymore and second the device manager still
>>displays the old name
>>and can’t even remove my driver anymore but instead tells my, that my
>>device is “perhaps” required
>>to start the computer.
>>
>>what should i do to change my drivers port name? am i completly wrong
>>and there’s
>>a single API?
>>the code is attached below.
>>regards,
>>daniel.
>>
>>int CSerialMap::relinkPort(CString portName, const int newPortNo,
>>PPORT_INFO portInfo)
>>{
>>int status;
>>DWORD oldPortNumber;
>>TCHAR targetPath[MAX_NAME_PORTS],
>>newPortName[MAX_NAME_PORTS],
>>newFriendlyName[MAX_NAME_PORTS];
>>_GUID* guidTmp;
>>HDEVINFO deviceInfoSet;
>>BOOL guidTest = FALSE;
>>DWORD requiredSize = 0;
>>SP_DEVINFO_DATA devInfoData;
>>HKEY keyDevice;
>>static CM_Open_DevNode_Key openDevNodeKey = NULL;
>>static HINSTANCE cfgMan;
>>
>>if (NULL == openDevNodeKey)
>>{
>>cfgMan = LoadLibrary(“cfgmgr32”);
>>if (!cfgMan)
>>{
>>lastError = ERR_DYNAMIC_LIB;
>>return lastError;
>>}
>>openDevNodeKey = (CM_Open_DevNode_Key)GetProcAddress(cfgMan,
>>“CM_Open_DevNode_Key”);
>>if (!openDevNodeKey)
>>{
>>lastError = ERR_DYNAMIC_LIB;
>>FreeLibrary(cfgMan);
>>goto rlpErr1;
>>}
>>}
>>
>>devInfoData = portInfo->DeviceInfoData;
>>
>>_stprintf(newPortName, “COM%d”, newPortNo + 1);
>>
>>//update the devices portname and friendly name registry keys:
>>guidTest = SetupDiClassGuidsFromNameA(“Ports”, 0, 0, &requiredSize);
>>if (requiredSize < 1)
>>{
>>lastError = ERR_DEVICE_MANAGER;
>>goto rlpErr1;
>>}
>>
>>guidTmp = (_GUID*) malloc(requiredSize * sizeof(GUID));
>>
>>//get GUID of the ports class:
>>guidTest = SetupDiClassGuidsFromNameA(“Ports”, guidTmp, requiredSize *
>>sizeof(GUID), &requiredSize);
>>if (!guidTest)
>>{
>>lastError = ERR_DEVICE_MANAGER;
>>free(guidTmp);
>>goto rlpErr1;
>>}
>>
>>//get devices within ports class:
>>deviceInfoSet = SetupDiGetClassDevs(guidTmp, NULL, NULL, DIGCF_PRESENT);
>>free(guidTmp);
>>if (INVALID_HANDLE_VALUE == deviceInfoSet)
>>{
>>lastError = ERR_DEVICE_MANAGER;
>>goto rlpErr1;
>>}
>>
>>//open device registry key:
>>status = openDevNodeKey(devInfoData.DevInst, KEY_QUERY_VALUE |
>>KEY_SET_VALUE, 0,
>>RegDisposition_OpenExisting, &keyDevice, CM_REGISTRY_HARDWARE);
>>if (ERROR_SUCCESS != status)
>>{
>>lastError = ERR_REGISTRY;
>>goto rlpErr2;
>>}
>>
>>//set the new portname registry key:
>>status = RegSetValueEx(keyDevice, “PortName”, 0, REG_SZ,
>>(PBYTE)newPortName, (_tclen(newPortName) + 1) * sizeof(TCHAR));
>>RegCloseKey(keyDevice);
>>if (ERROR_SUCCESS != status)
>>{
>>lastError = ERR_REGISTRY;
>>goto rlpErr2;
>>}
>>
>>//create the new FriendlyName property:
>>status = SetupDiGetDeviceRegistryProperty(deviceInfoSet, &devInfoData,
>>SPDRP_FRIENDLYNAME,
>>NULL, (PBYTE)newFriendlyName, MAX_NAME_PORTS, NULL);
>>if (ERROR_SUCCESS == status)
>>{
>>createNewFriendlyName(newFriendlyName, newPortName);
>>
>>SetupDiSetDeviceRegistryProperty(deviceInfoSet, &devInfoData,
>>SPDRP_FRIENDLYNAME,
>>(PBYTE)newFriendlyName, (_tclen(newFriendlyName) + 1) * sizeof(TCHAR));
>>}
>>
>>SetupDiDestroyDeviceInfoList(deviceInfoSet);
>>FreeLibrary(cfgMan);
>>
>>
>>
>>//query and store the target device of the specified port (i.e.
>>“\Device\Serial0”):
>>status = QueryDosDevice(portName, (PTCHAR)&targetPath, MAX_NAME_PORTS);
>>if (status < 1)
>>{
>>lastError = ::GetLastError();
>>return lastError;
>>}
>>
>>//delete the current symbolic link:
>>if (TRUE != DefineDosDevice(DDD_REMOVE_DEFINITION, portName, NULL))
>>{
>>lastError = ::GetLastError();
>>return lastError;
>>}
>>
>>//create the new link:
>>if (TRUE != DefineDosDevice(DDD_RAW_TARGET_PATH, newPortName, targetPath))
>>{
>>lastError = ::GetLastError();
>>//try to restore the old link:
>>DefineDosDevice(DDD_RAW_TARGET_PATH, portName, targetPath);
>>return lastError;
>>}
>>
>>
>>
>>//update COM port database:
>>HCOMDB comDB;
>>status = ComDBOpen(&comDB);
>>if (ERROR_SUCCESS != status)
>>{
>>lastError = status;
>>return status;
>>}
>>
>>oldPortNumber = atoi(portName.Mid(3));
>>status = ComDBReleasePort(comDB, oldPortNumber);
>>if (ERROR_SUCCESS != status)
>>lastError = status;
>>
>>status = ComDBClaimPort(comDB, (DWORD)newPortNo + 1, TRUE, NULL);
>>if (ERROR_SUCCESS != status)
>>{
>>lastError = status;
>>ComDBClose(comDB);
>>return status;
>>}
>>ComDBClose(comDB);
>>
>>return SUCCESS;
>>
>>rlpErr2:
>>SetupDiDestroyDeviceInfoList(deviceInfoSet);
>>rlpErr1:
>>FreeLibrary(cfgMan);
>>return lastError;
>>}
>>
>>
>>
>>
>>
>>
>
>
>
>—
>Questions? First check the Kernel Driver FAQ at http://www.osronline.com/article.cfm?id=256
>
>You are currently subscribed to ntdev as: xxxxx@gmx.net
>To unsubscribe send a blank email to xxxxx@lists.osr.com
>
>
>

well… the WM_DEVICECHANGE method really sounds interresting, but raises
the new question, how to identify the device manager window. spy++ displays
that the class name of device manager window is spy++ MMCMainFrame and no
other window seems to have this class. so perhaps a FindWindow call for
MMCMainFrame and checking the binary name of the module which created the
window for mmc.exe is already sufficient… (i don’t wanna involve the
window title in the progress of detecting the device manager window) i’ll
check this out later today and let you know how it goes

regards,

daniel.

Jones, Michael wrote:

To answer your question I have always been in the Property Sheet Dialog
when I use this method. One way would be for you application to call into
your driver with a say a private IOCTL if you have have the source for the
driver and then do an IoInvalidateDeviceRelations(). This will cause an
open version of Device Manger to re-enumeration its window. Another way
would be to send the messages to the device manger window that corresponds
to Scan for New Hardware within its Action Menu item. >I would not recomment
this way unless nothing else works. Another way that I did not try but I am
interested in all the documentation in the SDK is eht WM_DEVICECHANGE using
I would try DBT_DEVNODES_CHANGED. Note these are only suggestions as I have
NOT exactly what you are decribing. Good Luck let me know how it goes.

Regards

William Michael Jones “Mike”

“L3sT4Rd” wrote in message news:xxxxx@ntdev…
> Hi,
>
> i’m feeling quite stupid to ask the list again, but i’m really stuck and
> under pressure…
> i wrote a driver which does nothing else than creating a virtual serial
> port and
> forwarding all IRPs (except from some special ioctls) to another serial
> port driver.
>
> now i want to change the serial port number of my virtual serial port to
> any unused serial
> port the user desires (from user mode).
>
> currently i’m trying to achieve this through the following steps:
> -telling the driver that its port changed (special ioctl)
> -updating the HKLM\Hardware\Devicemap\SerialComm registry key
> -retrieving a HDEVINFO handle to the PORTS class
> -using a previously obtained SP_DEVINFO_DATA struct +
> CM_Open_DevNode_Key function (cfgMr32.lib) to open the devices registry
> key
> -setting the devices “PortName” registry property to the desired new
> port name
> -updating the devices “FriendlyName” through
> SetupDiSetDeviceRegistryProperty
> -updating the devices symbolic link through QueryDosDevice /
> DefineDosDevice
> -and finally freeing the old and claiming the new port through
> ComDBReleasePort/ComDBClaimPort
>
> now i’m able to access the port through its new name (with
> hyperterminal) , but first SetupDiEnumDeviceInfo
> doesn’t enumerate my device anymore and second the device manager still
> displays the old name
> and can’t even remove my driver anymore but instead tells my, that my
> device is “perhaps” required
> to start the computer.
>
> what should i do to change my drivers port name? am i completly wrong
> and there’s
> a single API?
> the code is attached below.
> regards,
> daniel.
>
> int CSerialMap::relinkPort(CString portName, const int newPortNo,
> PPORT_INFO portInfo)
> {
> int status;
> DWORD oldPortNumber;
> TCHAR targetPath[MAX_NAME_PORTS],
> newPortName[MAX_NAME_PORTS],
> newFriendlyName[MAX_NAME_PORTS];
> _GUID* guidTmp;
> HDEVINFO deviceInfoSet;
> BOOL guidTest = FALSE;
> DWORD requiredSize = 0;
> SP_DEVINFO_DATA devInfoData;
> HKEY keyDevice;
> static CM_Open_DevNode_Key openDevNodeKey = NULL;
> static HINSTANCE cfgMan;
>
> if (NULL == openDevNodeKey)
> {
> cfgMan = LoadLibrary(“cfgmgr32”);
> if (!cfgMan)
> {
> lastError = ERR_DYNAMIC_LIB;
> return lastError;
> }
> openDevNodeKey = (CM_Open_DevNode_Key)GetProcAddress(cfgMan,
> “CM_Open_DevNode_Key”);
> if (!openDevNodeKey)
> {
> lastError = ERR_DYNAMIC_LIB;
> FreeLibrary(cfgMan);
> goto rlpErr1;
> }
> }
>
> devInfoData = portInfo->DeviceInfoData;
>
> _stprintf(newPortName, “COM%d”, newPortNo + 1);
>
> //update the devices portname and friendly name registry keys:
> guidTest = SetupDiClassGuidsFromNameA(“Ports”, 0, 0, &requiredSize);
> if (requiredSize < 1)
> {
> lastError = ERR_DEVICE_MANAGER;
> goto rlpErr1;
> }
>
> guidTmp = (_GUID*) malloc(requiredSize * sizeof(GUID));
>
> //get GUID of the ports class:
> guidTest = SetupDiClassGuidsFromNameA(“Ports”, guidTmp, requiredSize *
> sizeof(GUID), &requiredSize);
> if (!guidTest)
> {
> lastError = ERR_DEVICE_MANAGER;
> free(guidTmp);
> goto rlpErr1;
> }
>
> //get devices within ports class:
> deviceInfoSet = SetupDiGetClassDevs(guidTmp, NULL, NULL, DIGCF_PRESENT);
> free(guidTmp);
> if (INVALID_HANDLE_VALUE == deviceInfoSet)
> {
> lastError = ERR_DEVICE_MANAGER;
> goto rlpErr1;
> }
>
> //open device registry key:
> status = openDevNodeKey(devInfoData.DevInst, KEY_QUERY_VALUE |
> KEY_SET_VALUE, 0,
> RegDisposition_OpenExisting, &keyDevice, CM_REGISTRY_HARDWARE);
> if (ERROR_SUCCESS != status)
> {
> lastError = ERR_REGISTRY;
> goto rlpErr2;
> }
>
> //set the new portname registry key:
> status = RegSetValueEx(keyDevice, “PortName”, 0, REG_SZ,
> (PBYTE)newPortName, (_tclen(newPortName) + 1) * sizeof(TCHAR));
> RegCloseKey(keyDevice);
> if (ERROR_SUCCESS != status)
> {
> lastError = ERR_REGISTRY;
> goto rlpErr2;
> }
>
> //create the new FriendlyName property:
> status = SetupDiGetDeviceRegistryProperty(deviceInfoSet, &devInfoData,
> SPDRP_FRIENDLYNAME,
> NULL, (PBYTE)newFriendlyName, MAX_NAME_PORTS, NULL);
> if (ERROR_SUCCESS == status)
> {
> createNewFriendlyName(newFriendlyName, newPortName);
>
> SetupDiSetDeviceRegistryProperty(deviceInfoSet, &devInfoData,
> SPDRP_FRIENDLYNAME,
> (PBYTE)newFriendlyName, (_tclen(newFriendlyName) + 1) * sizeof(TCHAR));
> }
>
> SetupDiDestroyDeviceInfoList(deviceInfoSet);
> FreeLibrary(cfgMan);
>
>
>
> //query and store the target device of the specified port (i.e.
> “\Device\Serial0”):
> status = QueryDosDevice(portName, (PTCHAR)&targetPath, MAX_NAME_PORTS);
> if (status < 1)
> {
> lastError = ::GetLastError();
> return lastError;
> }
>
> //delete the current symbolic link:
> if (TRUE != DefineDosDevice(DDD_REMOVE_DEFINITION, portName, NULL))
> {
> lastError = ::GetLastError();
> return lastError;
> }
>
> //create the new link:
> if (TRUE != DefineDosDevice(DDD_RAW_TARGET_PATH, newPortName, targetPath))
> {
> lastError = ::GetLastError();
> //try to restore the old link:
> DefineDosDevice(DDD_RAW_TARGET_PATH, portName, targetPath);
> return lastError;
> }
>
>
>
> //update COM port database:
> HCOMDB comDB;
> status = ComDBOpen(&comDB);
> if (ERROR_SUCCESS != status)
> {
> lastError = status;
> return status;
> }
>
> oldPortNumber = atoi(portName.Mid(3));
> status = ComDBReleasePort(comDB, oldPortNumber);
> if (ERROR_SUCCESS != status)
> lastError = status;
>
> status = ComDBClaimPort(comDB, (DWORD)newPortNo + 1, TRUE, NULL);
> if (ERROR_SUCCESS != status)
> {
> lastError = status;
> ComDBClose(comDB);
> return status;
> }
> ComDBClose(comDB);
>
> return SUCCESS;
>
> rlpErr2:
> SetupDiDestroyDeviceInfoList(deviceInfoSet);
> rlpErr1:
> FreeLibrary(cfgMan);
> return lastError;
> }
>
>
>
>

Look at src\steup\pnpports\advandlg.c for how the std COM port renaming
works in the OS, specifically look at EnactComNameChanges() and
SaveAdvancedSettings(). Here is the code of interest

//
// Now broadcast this change to the device manager
//
ZeroMemory(&spDevInstall, sizeof(SP_DEVINSTALL_PARAMS));
spDevInstall.cbSize = sizeof(SP_DEVINSTALL_PARAMS);

if (SetupDiGetDeviceInstallParams(AdvancedData->DeviceInfoSet,
AdvancedData->DeviceInfoData,
&spDevInstall)) {
spDevInstall.Flags |= DI_PROPERTIES_CHANGE;
SetupDiSetDeviceInstallParams(AdvancedData->DeviceInfoSet,
AdvancedData->DeviceInfoData,
&spDevInstall);
}

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of William Michael
Jones
Sent: Monday, February 13, 2006 10:27 AM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Changing Serial Port Number?

well… the WM_DEVICECHANGE method really sounds interresting, but
raises
the new question, how to identify the device manager window. spy++
displays
that the class name of device manager window is spy++ MMCMainFrame and
no
other window seems to have this class. so perhaps a FindWindow call for
MMCMainFrame and checking the binary name of the module which created
the
window for mmc.exe is already sufficient… (i don’t wanna involve the
window title in the progress of detecting the device manager window)
i’ll
check this out later today and let you know how it goes

regards,

daniel.

Jones, Michael wrote:

To answer your question I have always been in the Property Sheet Dialog
when I use this method. One way would be for you application to call
into
your driver with a say a private IOCTL if you have have the source for
the
driver and then do an IoInvalidateDeviceRelations(). This will cause an

open version of Device Manger to re-enumeration its window. Another way
would be to send the messages to the device manger window that
corresponds
to Scan for New Hardware within its Action Menu item. >I would not
recomment
this way unless nothing else works. Another way that I did not try but
I am
interested in all the documentation in the SDK is eht WM_DEVICECHANGE
using
I would try DBT_DEVNODES_CHANGED. Note these are only suggestions as I
have
NOT exactly what you are decribing. Good Luck let me know how it goes.

Regards

William Michael Jones “Mike”

“L3sT4Rd” wrote in message news:xxxxx@ntdev…
> Hi,
>
> i’m feeling quite stupid to ask the list again, but i’m really stuck
and
> under pressure…
> i wrote a driver which does nothing else than creating a virtual
serial
> port and
> forwarding all IRPs (except from some special ioctls) to another
serial
> port driver.
>
> now i want to change the serial port number of my virtual serial port
to
> any unused serial
> port the user desires (from user mode).
>
> currently i’m trying to achieve this through the following steps:
> -telling the driver that its port changed (special ioctl)
> -updating the HKLM\Hardware\Devicemap\SerialComm registry key
> -retrieving a HDEVINFO handle to the PORTS class
> -using a previously obtained SP_DEVINFO_DATA struct +
> CM_Open_DevNode_Key function (cfgMr32.lib) to open the devices
registry
> key
> -setting the devices “PortName” registry property to the desired new
> port name
> -updating the devices “FriendlyName” through
> SetupDiSetDeviceRegistryProperty
> -updating the devices symbolic link through QueryDosDevice /
> DefineDosDevice
> -and finally freeing the old and claiming the new port through
> ComDBReleasePort/ComDBClaimPort
>
> now i’m able to access the port through its new name (with
> hyperterminal) , but first SetupDiEnumDeviceInfo
> doesn’t enumerate my device anymore and second the device manager
still
> displays the old name
> and can’t even remove my driver anymore but instead tells my, that my
> device is “perhaps” required
> to start the computer.
>
> what should i do to change my drivers port name? am i completly wrong
> and there’s
> a single API?
> the code is attached below.
> regards,
> daniel.
>
> int CSerialMap::relinkPort(CString portName, const int newPortNo,
> PPORT_INFO portInfo)
> {
> int status;
> DWORD oldPortNumber;
> TCHAR targetPath[MAX_NAME_PORTS],
> newPortName[MAX_NAME_PORTS],
> newFriendlyName[MAX_NAME_PORTS];
> _GUID* guidTmp;
> HDEVINFO deviceInfoSet;
> BOOL guidTest = FALSE;
> DWORD requiredSize = 0;
> SP_DEVINFO_DATA devInfoData;
> HKEY keyDevice;
> static CM_Open_DevNode_Key openDevNodeKey = NULL;
> static HINSTANCE cfgMan;
>
> if (NULL == openDevNodeKey)
> {
> cfgMan = LoadLibrary(“cfgmgr32”);
> if (!cfgMan)
> {
> lastError = ERR_DYNAMIC_LIB;
> return lastError;
> }
> openDevNodeKey = (CM_Open_DevNode_Key)GetProcAddress(cfgMan,
> “CM_Open_DevNode_Key”);
> if (!openDevNodeKey)
> {
> lastError = ERR_DYNAMIC_LIB;
> FreeLibrary(cfgMan);
> goto rlpErr1;
> }
> }
>
> devInfoData = portInfo->DeviceInfoData;
>
> _stprintf(newPortName, “COM%d”, newPortNo + 1);
>
> //update the devices portname and friendly name registry keys:
> guidTest = SetupDiClassGuidsFromNameA(“Ports”, 0, 0, &requiredSize);
> if (requiredSize < 1)
> {
> lastError = ERR_DEVICE_MANAGER;
> goto rlpErr1;
> }
>
> guidTmp = (_GUID*) malloc(requiredSize * sizeof(GUID));
>
> //get GUID of the ports class:
> guidTest = SetupDiClassGuidsFromNameA(“Ports”, guidTmp, requiredSize *
> sizeof(GUID), &requiredSize);
> if (!guidTest)
> {
> lastError = ERR_DEVICE_MANAGER;
> free(guidTmp);
> goto rlpErr1;
> }
>
> //get devices within ports class:
> deviceInfoSet = SetupDiGetClassDevs(guidTmp, NULL, NULL,
DIGCF_PRESENT);
> free(guidTmp);
> if (INVALID_HANDLE_VALUE == deviceInfoSet)
> {
> lastError = ERR_DEVICE_MANAGER;
> goto rlpErr1;
> }
>
> //open device registry key:
> status = openDevNodeKey(devInfoData.DevInst, KEY_QUERY_VALUE |
> KEY_SET_VALUE, 0,
> RegDisposition_OpenExisting, &keyDevice, CM_REGISTRY_HARDWARE);
> if (ERROR_SUCCESS != status)
> {
> lastError = ERR_REGISTRY;
> goto rlpErr2;
> }
>
> //set the new portname registry key:
> status = RegSetValueEx(keyDevice, “PortName”, 0, REG_SZ,
> (PBYTE)newPortName, (_tclen(newPortName) + 1) * sizeof(TCHAR));
> RegCloseKey(keyDevice);
> if (ERROR_SUCCESS != status)
> {
> lastError = ERR_REGISTRY;
> goto rlpErr2;
> }
>
> //create the new FriendlyName property:
> status = SetupDiGetDeviceRegistryProperty(deviceInfoSet, &devInfoData,
> SPDRP_FRIENDLYNAME,
> NULL, (PBYTE)newFriendlyName, MAX_NAME_PORTS, NULL);
> if (ERROR_SUCCESS == status)
> {
> createNewFriendlyName(newFriendlyName, newPortName);
>
> SetupDiSetDeviceRegistryProperty(deviceInfoSet, &devInfoData,
> SPDRP_FRIENDLYNAME,
> (PBYTE)newFriendlyName, (_tclen(newFriendlyName) + 1) *
sizeof(TCHAR));
> }
>
> SetupDiDestroyDeviceInfoList(deviceInfoSet);
> FreeLibrary(cfgMan);
>
>
>
> //query and store the target device of the specified port (i.e.
> “\Device\Serial0”):
> status = QueryDosDevice(portName, (PTCHAR)&targetPath,
MAX_NAME_PORTS);
> if (status < 1)
> {
> lastError = ::GetLastError();
> return lastError;
> }
>
> //delete the current symbolic link:
> if (TRUE != DefineDosDevice(DDD_REMOVE_DEFINITION, portName, NULL))
> {
> lastError = ::GetLastError();
> return lastError;
> }
>
> //create the new link:
> if (TRUE != DefineDosDevice(DDD_RAW_TARGET_PATH, newPortName,
targetPath))
> {
> lastError = ::GetLastError();
> //try to restore the old link:
> DefineDosDevice(DDD_RAW_TARGET_PATH, portName, targetPath);
> return lastError;
> }
>
>
>
> //update COM port database:
> HCOMDB comDB;
> status = ComDBOpen(&comDB);
> if (ERROR_SUCCESS != status)
> {
> lastError = status;
> return status;
> }
>
> oldPortNumber = atoi(portName.Mid(3));
> status = ComDBReleasePort(comDB, oldPortNumber);
> if (ERROR_SUCCESS != status)
> lastError = status;
>
> status = ComDBClaimPort(comDB, (DWORD)newPortNo + 1, TRUE, NULL);
> if (ERROR_SUCCESS != status)
> {
> lastError = status;
> ComDBClose(comDB);
> return status;
> }
> ComDBClose(comDB);
>
> return SUCCESS;
>
> rlpErr2:
> SetupDiDestroyDeviceInfoList(deviceInfoSet);
> rlpErr1:
> FreeLibrary(cfgMan);
> return lastError;
> }
>
>
>
>


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@microsoft.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

One time in the same situation I setup my “virtual” serial port without
Device Manager, via .inf file. You must name your driver instead of
serial.sys only.

The single problem was Windows assigns COMx for virtual ports only from
x=5 (COM5,…) and some applications are not able to work with COM5.

The problem was solved stupidly simply. Find your port in
HKLM\HARDWARE\DEVICEMAP\SERAILCOMM and assign port which you want by
hand.
The change is valuable after reboot…

Regards,
Michael.