You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
811 lines
21 KiB
811 lines
21 KiB
// Copyright (c) 1998-1999 Microsoft Corporation
|
|
/******************************************************************************
|
|
*
|
|
* CHGPORT.C
|
|
*
|
|
* Change serial port mapping.
|
|
*
|
|
*
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <winstaw.h>
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <utilsub.h>
|
|
#include <string.h>
|
|
#include <printfoa.h>
|
|
#include <locale.h>
|
|
#include <winnlsp.h>
|
|
|
|
#include "chgport.h"
|
|
|
|
|
|
// max length of the locale string
|
|
#define MAX_LOCALE_STRING 64
|
|
|
|
|
|
/*
|
|
* Global Data
|
|
*/
|
|
WCHAR user_string[MAX_IDS_LEN+1]; // parsed user input
|
|
USHORT help_flag = FALSE; // User wants help
|
|
USHORT fDelete = FALSE; // delete mapped port
|
|
USHORT fquery = FALSE; // query the mapped ports
|
|
PCOMNAME pValidNames = NULL; // list of valid com names in registry
|
|
|
|
TOKMAP ptm[] = {
|
|
{L" ", TMFLAG_OPTIONAL, TMFORM_STRING, MAX_IDS_LEN, user_string},
|
|
{L"/d", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &fDelete},
|
|
{L"/?", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &help_flag},
|
|
{L"/QUERY", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &fquery},
|
|
{L"/Q", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &fquery},
|
|
{0, 0, 0, 0, 0}
|
|
};
|
|
|
|
|
|
/*
|
|
* Constants
|
|
*/
|
|
#define DOSDEVICE_STRING L"\\DosDevices"
|
|
|
|
/*
|
|
* Local function prototypes.
|
|
*/
|
|
void Usage(BOOLEAN bError);
|
|
BOOL DeleteMappedPort(PWCHAR user_string);
|
|
BOOL GetPorts(PWCHAR user_string,
|
|
PWCHAR pwcSrcPort,
|
|
PWCHAR pwcDestPort,
|
|
ULONG ulbufsize);
|
|
BOOL MapPorts(PWCHAR pwcSrcPort,
|
|
PWCHAR pwcDestPort);
|
|
void ListSerialPorts();
|
|
BOOL IsSerialDevice(PWCHAR pwcName);
|
|
ULONG GetNTObjectName(PWCHAR pwcDOSdev,
|
|
PWCHAR pwcNTObjName,
|
|
ULONG ulbufsize);
|
|
ULONG AddComName(PCOMNAME *pComList,
|
|
PWCHAR pwcNTName,
|
|
PWCHAR pwcDOSName);
|
|
void DelComName(PCOMNAME pEntry);
|
|
PCOMNAME FindComName(PCOMNAME pComList,
|
|
PWCHAR pwcName);
|
|
|
|
BOOL IsVDMdeviceName(PWCHAR pwcName);
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* main
|
|
*
|
|
******************************************************************************/
|
|
|
|
int __cdecl
|
|
main(INT argc, CHAR **argv)
|
|
{
|
|
WCHAR **argvW;
|
|
WCHAR wcSrcPort[MAX_PATH], wcDestPort[MAX_PATH];
|
|
ULONG ulSrcPort, ulDestPort, rc;
|
|
INT i;
|
|
WCHAR wszString[MAX_LOCALE_STRING + 1];
|
|
|
|
setlocale(LC_ALL, ".OCP");
|
|
|
|
// We don't want LC_CTYPE set the same as the others or else we will see
|
|
// garbage output in the localized version, so we need to explicitly
|
|
// set it to correct console output code page
|
|
_snwprintf(wszString, sizeof(wszString)/sizeof(WCHAR), L".%d", GetConsoleOutputCP());
|
|
wszString[sizeof(wszString)/sizeof(WCHAR) - 1] = L'\0';
|
|
_wsetlocale(LC_CTYPE, wszString);
|
|
|
|
SetThreadUILanguage(0);
|
|
|
|
|
|
/*
|
|
* Massage the command line.
|
|
*/
|
|
|
|
argvW = MassageCommandLine((DWORD)argc);
|
|
if (argvW == NULL) {
|
|
ErrorPrintf(IDS_ERROR_MALLOC);
|
|
return(FAILURE);
|
|
}
|
|
|
|
/*
|
|
* parse the cmd line without parsing the program name (argc-1, argv+1)
|
|
*/
|
|
rc = ParseCommandLine(argc-1, argvW+1, ptm, 0);
|
|
|
|
/*
|
|
* Check for error from ParseCommandLine
|
|
*/
|
|
if ( help_flag || (rc && !(rc & PARSE_FLAG_NO_PARMS)) ) {
|
|
|
|
if ( !help_flag ) {
|
|
|
|
Usage(TRUE);
|
|
return(FAILURE);
|
|
|
|
} else {
|
|
|
|
Usage(FALSE);
|
|
return(SUCCESS);
|
|
}
|
|
}
|
|
|
|
//If we are not Running under Terminal Server, Return Error
|
|
|
|
if(!AreWeRunningTerminalServices())
|
|
{
|
|
ErrorPrintf(IDS_ERROR_NOT_TS);
|
|
return (FAILURE);
|
|
}
|
|
|
|
if (fDelete) {
|
|
DeleteMappedPort(user_string);
|
|
} else if (*user_string) {
|
|
GetPorts(user_string, wcSrcPort, wcDestPort, MAX_PATH);
|
|
MapPorts(wcSrcPort, wcDestPort);
|
|
} else { // query the mapped ports
|
|
ListSerialPorts();
|
|
}
|
|
|
|
// Free up the list of valid port names
|
|
if (pValidNames) {
|
|
PCOMNAME pEntry, pPrev;
|
|
|
|
pEntry = pValidNames;
|
|
while (pEntry) {
|
|
pPrev = pEntry;
|
|
pEntry = pEntry->com_pnext;
|
|
DelComName(pPrev);
|
|
}
|
|
}
|
|
|
|
return(SUCCESS);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Usage
|
|
*
|
|
* Output the usage message for this utility.
|
|
*
|
|
* ENTRY:
|
|
* bError (input)
|
|
* TRUE if the 'invalid parameter(s)' message should preceed the usage
|
|
* message and the output go to stderr; FALSE for no such error
|
|
* string and output goes to stdout.
|
|
*
|
|
* EXIT:
|
|
*
|
|
*
|
|
******************************************************************************/
|
|
|
|
void
|
|
Usage( BOOLEAN bError )
|
|
{
|
|
if ( bError ) {
|
|
ErrorPrintf(IDS_ERROR_INVALID_PARAMETERS);
|
|
}
|
|
ErrorPrintf(IDS_HELP_USAGE1);
|
|
ErrorPrintf(IDS_HELP_USAGE2);
|
|
ErrorPrintf(IDS_HELP_USAGE3);
|
|
ErrorPrintf(IDS_HELP_USAGE4);
|
|
ErrorPrintf(IDS_HELP_USAGE5);
|
|
|
|
} /* Usage() */
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* DeleteMappedPort
|
|
*
|
|
* This routine deletes the specified mapped port
|
|
*
|
|
*
|
|
* ENTRY:
|
|
* PWCHAR pwcport (In): Pointer to port mapping to delete
|
|
*
|
|
* EXIT:
|
|
* TRUE: port was deleted
|
|
* FALSE: error deleting port
|
|
*
|
|
******************************************************************************/
|
|
|
|
BOOL DeleteMappedPort(PWCHAR pwcport)
|
|
{
|
|
ULONG rc;
|
|
PWCHAR pwch;
|
|
WCHAR wcbuff[MAX_PATH];
|
|
|
|
// Check if this a serial device and if it is, remove it
|
|
if (!GetNTObjectName(pwcport, wcbuff, sizeof(wcbuff)/sizeof(WCHAR)) &&
|
|
IsSerialDevice(wcbuff)) {
|
|
|
|
if (DefineDosDevice(DDD_REMOVE_DEFINITION,
|
|
pwcport,
|
|
NULL)) {
|
|
return(TRUE);
|
|
} else {
|
|
rc = GetLastError();
|
|
}
|
|
} else {
|
|
rc = ERROR_FILE_NOT_FOUND;
|
|
}
|
|
|
|
StringDwordErrorPrintf(IDS_ERROR_DEL_PORT_MAPPING, pwcport, rc);
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* GetPorts
|
|
*
|
|
* This routine converts the string to the source and destination ports
|
|
*
|
|
*
|
|
* ENTRY:
|
|
* PWCHAR pwcstring (In): Pointer to user string
|
|
* PWCHAR pwcSrcPort (Out): Pointer to return source port
|
|
* PWCHAR pwcSrcPort (Out): Pointer to return destination port
|
|
* ULONG ulbufsize (In): Size of return buffers
|
|
*
|
|
* EXIT:
|
|
* TRUE: string converted to source and destination ports
|
|
* FALSE: error
|
|
*
|
|
******************************************************************************/
|
|
|
|
BOOL GetPorts(PWCHAR pwcstring, PWCHAR pwcSrcPort, PWCHAR pwcDestPort,
|
|
ULONG ulbufsize)
|
|
{
|
|
PWCHAR pwch;
|
|
ULONG ulcnt;
|
|
BOOL fSawEqual = FALSE;
|
|
|
|
pwch = pwcstring;
|
|
|
|
// find next non alphanumeric character
|
|
for (ulcnt = 0; pwch[ulcnt] && iswalnum(pwch[ulcnt]); ulcnt++) {
|
|
}
|
|
|
|
// Get the source port
|
|
if (pwch[ulcnt] && (ulcnt < ulbufsize)) {
|
|
wcsncpy(pwcSrcPort, pwch, ulcnt);
|
|
} else {
|
|
return(FALSE);
|
|
}
|
|
pwcSrcPort[ulcnt] = L'\0';
|
|
|
|
pwch += ulcnt;
|
|
|
|
// get to destination port
|
|
while (*pwch && !iswalnum(*pwch)) {
|
|
if (*pwch == L'=') {
|
|
fSawEqual = TRUE;
|
|
}
|
|
pwch++;
|
|
}
|
|
|
|
// If the syntax is OK and there's room in the buffer, copy the dest. port
|
|
if (*pwch && fSawEqual && (wcslen(pwch) < ulbufsize)) {
|
|
wcscpy(pwcDestPort, pwch);
|
|
} else {
|
|
return(FALSE);
|
|
}
|
|
|
|
// remove the : if they entered comn:
|
|
if (pwch = wcsrchr(pwcSrcPort, L':')) {
|
|
*pwch = L'\0';
|
|
}
|
|
if (pwch = wcsrchr(pwcDestPort, L':')) {
|
|
*pwch = L'\0';
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* MapPorts
|
|
*
|
|
* This routine maps the source port number to the destination port.
|
|
*
|
|
*
|
|
* ENTRY:
|
|
* PWCHAR pwcSrcPort (In): Source port
|
|
* PWCHAR pwcDestPort (In): Destination port
|
|
*
|
|
* EXIT:
|
|
* TRUE: port was mapped
|
|
* FALSE: error mapping port
|
|
*
|
|
******************************************************************************/
|
|
|
|
BOOL MapPorts(PWCHAR pwcSrcPort, PWCHAR pwcDestPort)
|
|
{
|
|
ULONG rc = ERROR_FILE_NOT_FOUND;
|
|
WCHAR wcdest[MAX_PATH], wcsrc[MAX_PATH];
|
|
|
|
// Get the NT name of the destination and make sure it's a serial device
|
|
rc = GetNTObjectName(pwcDestPort, wcdest, sizeof(wcdest)/sizeof(WCHAR));
|
|
if ((rc == 0) && IsSerialDevice(wcdest))
|
|
{
|
|
// see if this mapping already exists
|
|
if (!GetNTObjectName(pwcSrcPort, wcsrc, sizeof(wcsrc)/sizeof(WCHAR)) &&
|
|
!_wcsicmp(wcdest, wcsrc)) {
|
|
ErrorPrintf(IDS_ERROR_PORT_MAPPING_EXISTS,
|
|
pwcSrcPort,
|
|
pwcDestPort);
|
|
return(FALSE);
|
|
}
|
|
|
|
if (DefineDosDevice(DDD_RAW_TARGET_PATH,
|
|
pwcSrcPort,
|
|
wcdest)) {
|
|
return(TRUE);
|
|
} else {
|
|
rc = GetLastError();
|
|
}
|
|
}
|
|
|
|
StringDwordErrorPrintf(IDS_ERROR_CREATE_PORT_MAPPING, pwcSrcPort, rc);
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* GetNTObjectName
|
|
*
|
|
* This routine returns the NT object name for a DOS device.
|
|
*
|
|
* ENTRY:
|
|
* PWCHAR pwcDOSdev (In): pointer to DOS device name
|
|
* PWCHAR pwcNTObjName (Out): pointer for NT object name
|
|
* ULONG ulbufsize (In): size (in wide chars) of object name buffer
|
|
*
|
|
* EXIT:
|
|
* Success:
|
|
* returns 0
|
|
* Failure:
|
|
* returns error code
|
|
*
|
|
******************************************************************************/
|
|
|
|
ULONG GetNTObjectName(PWCHAR pwcDOSdev, PWCHAR pwcNTObjName, ULONG ulbufsize)
|
|
{
|
|
WCHAR wcbuff[MAX_PATH];
|
|
PWCHAR pwch;
|
|
|
|
// Make a copy of the name passed in
|
|
wcscpy(wcbuff, pwcDOSdev);
|
|
|
|
// Strip off any trailing colon (comn:)
|
|
if (pwch = wcsrchr(wcbuff, L':')) {
|
|
*pwch = L'\0';
|
|
}
|
|
|
|
if (QueryDosDevice(pwcDOSdev, pwcNTObjName, ulbufsize)) {
|
|
return(0);
|
|
} else {
|
|
return(GetLastError());
|
|
}
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* ListSerialPorts
|
|
*
|
|
* This routine lists all of the mapped ports.
|
|
*
|
|
* ENTRY:
|
|
*
|
|
* EXIT:
|
|
*
|
|
******************************************************************************/
|
|
|
|
void ListSerialPorts(void)
|
|
{
|
|
ULONG ulcnt, rc;
|
|
WCHAR TargetPath[4096];
|
|
PWCH pwch;
|
|
PCOMNAME pComList = NULL;
|
|
PCOMNAME pEntry, pPrev;
|
|
|
|
DWORD dwBufferSize = 2048;
|
|
WCHAR *DeviceNames = malloc(dwBufferSize);
|
|
|
|
if (!DeviceNames)
|
|
{
|
|
ErrorPrintf(IDS_ERROR_MALLOC);
|
|
free(DeviceNames);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Get all of the defined DOS devices
|
|
//
|
|
|
|
//
|
|
// QueryDosDevice function returns success even if buffer is too small!
|
|
// Lets get around it
|
|
//
|
|
|
|
SetLastError(0);
|
|
while ( (!QueryDosDevice(NULL, DeviceNames, dwBufferSize / sizeof(WCHAR))) ||
|
|
(GetLastError() == ERROR_INSUFFICIENT_BUFFER) )
|
|
{
|
|
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
SetLastError(0);
|
|
free(DeviceNames);
|
|
dwBufferSize *= 2;
|
|
|
|
DeviceNames = malloc(dwBufferSize);
|
|
|
|
if (!DeviceNames)
|
|
{
|
|
ErrorPrintf(IDS_ERROR_MALLOC);
|
|
return;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
ErrorPrintf(IDS_ERROR_GETTING_COMPORTS, GetLastError());
|
|
free(DeviceNames);
|
|
return;
|
|
}
|
|
}
|
|
|
|
pwch = DeviceNames;
|
|
|
|
// Go through each DOS device and get it's NT object name, then check if
|
|
// it's a serial device, and if so display it
|
|
while (*pwch)
|
|
{
|
|
rc = GetNTObjectName(pwch,
|
|
TargetPath,
|
|
sizeof(TargetPath)/sizeof(WCHAR));
|
|
if (rc)
|
|
{
|
|
ErrorPrintf(IDS_ERROR_GETTING_COMPORTS, rc);
|
|
}
|
|
else if (IsSerialDevice(TargetPath))
|
|
{
|
|
AddComName(&pComList, TargetPath, pwch);
|
|
}
|
|
|
|
pwch += wcslen(pwch) + 1;
|
|
}
|
|
|
|
if (pComList)
|
|
{
|
|
// print out the entries
|
|
pEntry = pComList;
|
|
while (pEntry)
|
|
{
|
|
wprintf(L"%s = %s\n", pEntry->com_pwcDOSName, pEntry->com_pwcNTName);
|
|
pPrev = pEntry;
|
|
pEntry = pEntry->com_pnext;
|
|
DelComName(pPrev);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ErrorPrintf(IDS_ERROR_NO_SERIAL_PORTS);
|
|
}
|
|
|
|
free(DeviceNames);
|
|
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* IsSerialDevice
|
|
*
|
|
* This routine checks if the NT file name is a serial device
|
|
*
|
|
*
|
|
* ENTRY:
|
|
* PWCHAR pwcName (In): Pointer to name to check
|
|
*
|
|
* EXIT:
|
|
* TRUE: Is a serial device
|
|
* FALSE: Not a serial device
|
|
*
|
|
******************************************************************************/
|
|
|
|
BOOL IsSerialDevice(PWCHAR pwcName)
|
|
{
|
|
NTSTATUS Status;
|
|
HANDLE Handle;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
FILE_FS_DEVICE_INFORMATION FileFSDevInfo;
|
|
OBJECT_ATTRIBUTES ObjFile;
|
|
UNICODE_STRING UniFile;
|
|
WCHAR wcbuff[MAX_PATH];
|
|
WCHAR wcvalue[MAX_PATH];
|
|
PWCHAR pwch;
|
|
HKEY hKey;
|
|
ULONG ulType, ulSize, ulcnt, ulValSize;
|
|
BOOL fIsSerial = FALSE;
|
|
|
|
|
|
if (IsVDMdeviceName(pwcName)) {
|
|
return FALSE;
|
|
}
|
|
|
|
RtlInitUnicodeString(&UniFile, pwcName);
|
|
|
|
InitializeObjectAttributes(&ObjFile,
|
|
&UniFile,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
//
|
|
// Open the device
|
|
//
|
|
Status = NtOpenFile(&Handle,
|
|
(ACCESS_MASK)FILE_READ_ATTRIBUTES | SYNCHRONIZE,
|
|
&ObjFile,
|
|
&IoStatusBlock,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
Status = NtQueryVolumeInformationFile(Handle,
|
|
&IoStatusBlock,
|
|
&FileFSDevInfo,
|
|
sizeof(FileFSDevInfo),
|
|
FileFsDeviceInformation);
|
|
|
|
// Check if this is actually a serial device or not
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if ( (FileFSDevInfo.DeviceType == FILE_DEVICE_NETWORK_REDIRECTOR) ||
|
|
(FileFSDevInfo.DeviceType == FILE_DEVICE_SERIAL_PORT) )
|
|
{
|
|
fIsSerial = TRUE;
|
|
}
|
|
}
|
|
|
|
// Close the file handle
|
|
NtClose(Handle);
|
|
|
|
} else {
|
|
// If we couldn't open the device, look for the name in the registry
|
|
|
|
#ifdef DEBUG
|
|
wprintf(L"Error opening: %s, error = %x\n", pwcName, Status);
|
|
#endif
|
|
|
|
// strip off the leading \device
|
|
pwch = wcschr(pwcName+2, L'\\');
|
|
if (pwch != NULL)
|
|
{
|
|
pwch++;
|
|
|
|
|
|
// If we haven't built the list of valid names from the registry,
|
|
// build it.
|
|
if (pValidNames == NULL) {
|
|
// Open the serialcomm entry in the registry
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
L"Hardware\\DeviceMap\\SerialComm",
|
|
0,
|
|
KEY_READ,
|
|
&hKey) == ERROR_SUCCESS) {
|
|
|
|
ulValSize = ulSize = MAX_PATH;
|
|
ulcnt = 0;
|
|
|
|
// Put all of the valid entries into the valid names list
|
|
while (!RegEnumValue (hKey, ulcnt++, wcvalue, &ulValSize,
|
|
NULL, &ulType, (LPBYTE) wcbuff, &ulSize))
|
|
{
|
|
if (ulType != REG_SZ)
|
|
continue;
|
|
|
|
AddComName(&pValidNames, wcvalue, wcbuff);
|
|
|
|
ulValSize = ulSize = MAX_PATH;
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
// look for the name in the list of valid com names
|
|
if (FindComName(pValidNames, pwch)) {
|
|
fIsSerial = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return(fIsSerial);
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* AddComName
|
|
*
|
|
* This routines adds a new node onto the specified com port names.
|
|
*
|
|
* ENTRY:
|
|
* PCOMNAME *pComList (In) - Pointer to list to add entry to
|
|
* PWCHAR pwcNTName (In) - NT name of device
|
|
* PWCHAR pwcDOSName (In) - DOW name of device
|
|
*
|
|
* EXIT:
|
|
* SUCCESS:
|
|
* return ERROR_SUCCESS
|
|
* FAILURE:
|
|
* returns error code
|
|
*
|
|
****************************************************************************/
|
|
|
|
ULONG AddComName(PCOMNAME *pComList,
|
|
PWCHAR pwcNTName,
|
|
PWCHAR pwcDOSName)
|
|
{
|
|
PCOMNAME pnext, pprev, pnew;
|
|
LONG rc = ERROR_SUCCESS;
|
|
|
|
if (pnew = malloc(sizeof(COMNAME))) {
|
|
|
|
// clear out the new entry
|
|
memset(pnew, 0, sizeof(COMNAME));
|
|
|
|
// Allocate and initialize the NT name
|
|
if (pnew->com_pwcNTName =
|
|
malloc((wcslen(pwcNTName) + 1)*sizeof(WCHAR))) {
|
|
wcscpy(pnew->com_pwcNTName, pwcNTName);
|
|
} else {
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
// Allocate and initialize the DOS name
|
|
if ((rc == ERROR_SUCCESS) && (pnew->com_pwcDOSName =
|
|
malloc((wcslen(pwcDOSName) + 1)*sizeof(WCHAR)))) {
|
|
wcscpy(pnew->com_pwcDOSName, pwcDOSName);
|
|
} else {
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
} else {
|
|
rc = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
// If we allocate everything OK, add the node into the list
|
|
if (rc == ERROR_SUCCESS) {
|
|
pprev = NULL;
|
|
pnext = *pComList;
|
|
|
|
// Insert the entry into the list in ascending order
|
|
while (pnext &&
|
|
((rc = _wcsicmp(pwcDOSName, pnext->com_pwcDOSName)) > 0)) {
|
|
pprev = pnext;
|
|
pnext = pnext->com_pnext;
|
|
}
|
|
|
|
// just return if this name is already in the list
|
|
if (pnext && (rc == 0)) {
|
|
return(ERROR_SUCCESS);
|
|
}
|
|
|
|
// Insert this entry into the list
|
|
pnew->com_pnext = pnext;
|
|
|
|
// If this is going to the front of the list, update list pointer
|
|
if (pprev == NULL) {
|
|
*pComList = pnew;
|
|
} else {
|
|
pprev->com_pnext = pnew;
|
|
}
|
|
|
|
} else if (pnew) {
|
|
|
|
// Didn't allocate everything, release the memory we got
|
|
DelComName(pnew);
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* DelComName
|
|
*
|
|
* This routines frees up the memory allocated to a com name node.
|
|
*
|
|
* ENTRY:
|
|
* PCOMNAME pEntry (In) - Node to delete
|
|
*
|
|
* EXIT:
|
|
* NONE
|
|
*
|
|
****************************************************************************/
|
|
|
|
void DelComName(PCOMNAME pEntry)
|
|
{
|
|
if (pEntry) {
|
|
if (pEntry->com_pwcNTName) {
|
|
free(pEntry->com_pwcNTName);
|
|
}
|
|
if (pEntry->com_pwcDOSName) {
|
|
free(pEntry->com_pwcDOSName);
|
|
}
|
|
free(pEntry);
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* FindComName
|
|
*
|
|
* This routines searches for the specified name in the com port list.
|
|
*
|
|
* ENTRY:
|
|
* PCOMNAME pComList (In) - List to search
|
|
* PWCHAR pwcName (In) - Name to search for
|
|
*
|
|
* EXIT:
|
|
* SUCCESS:
|
|
* returns pointer to node containing the specified name
|
|
* FAILURE:
|
|
* returns NULL (name not found)
|
|
*
|
|
****************************************************************************/
|
|
|
|
PCOMNAME FindComName(PCOMNAME pComList,
|
|
PWCHAR pwcName)
|
|
{
|
|
PCOMNAME pcom;
|
|
|
|
pcom = pComList;
|
|
while (pcom) {
|
|
//Check if the name matches either the NT or DOS device name
|
|
if (!_wcsicmp(pwcName, pcom->com_pwcDOSName) ||
|
|
!_wcsicmp(pwcName, pcom->com_pwcNTName)) {
|
|
return(pcom);
|
|
}
|
|
pcom = pcom->com_pnext;
|
|
}
|
|
return(NULL);
|
|
}
|
|
|
|
BOOL IsVDMdeviceName(PWCHAR pwcName)
|
|
{
|
|
UINT index;
|
|
UINT vdmlength = wcslen(L"VDM");
|
|
|
|
for (index = 0; (index+vdmlength-1) < wcslen(pwcName); index++) {
|
|
if (_wcsnicmp(&pwcName[index], L"VDM", vdmlength) == 0) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|