2025-04-27 07:49:33 -04:00

306 lines
9.1 KiB
C

/* comdev.c -- Communication device manipulation routines. These routines
* can be called by installation routines, etc. without
* including the rest of the com package. Use comdev.h for
* declarations.
*
* Copyright 1992 by Hilgraeve Inc. -- Monroe, MI
* All rights reserved
*
* $Revision: 3 $
* $Date: 3/22/01 11:27a $
*/
#include <windows.h>
#include <stdlib.h>
#include <tdll\stdtyp.h>
#include "com.h"
#include "comdev.h"
#include "com.hh"
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: ComFindDevices
*
* DESCRIPTION:
* May be called repeatedly to enumerate all com drivers available on the
* system. pstFind->uAction should be set to COM_FIND_FIRST before the
* first call. If the function returns COM_OK, then the fields of pstFind
* will have been filled in with information about the driver found. The
* uAction member will have automatically been changed to COM_FIND_NEXT.
* As long as subsequent calls return COM_OK, the structure will contain
* info on the next driver.
* Note: between consecutive calls to this function, no changes should be
* made to the COM_FIND_DEVICE structure.
*
* ARGUMENTS:
* pstFind -- Pointer to a structure of type COM_FIND_DEVICE. The usAction
* member of this structure must be set to COM_FIND_FIRST prior
* to the first call.
*
* RETURNS:
* COM_OK if another valid driver was found. The pstFind structure
* will be updated with information about the driver. To
* retrieve all drivers, this function should be called again
* if this value is returned.
* COM_NOT_FOUND if no more drivers are found. One more call to the function
* should be made with pstFind->usAction set to COM_FIND_DONE
* COM_FAILED if arguments are invalid: NULL passed as argument; uAction
* member invalid; or calls made out of sequence (COM_FIND_NEXT
* called before COM_FIND_FIRST, COM_FIND_DONE called without
* COM_FIND_FIRST)
*/
int ComFindDevices(COM_FIND_DEVICE * const pstFind)
{
int iRetVal = COM_OK;
unsigned uDriverVersion;
TCHAR szPath[MAX_PATH];
TCHAR *pszNamePart;
int fFound = FALSE;
int fResult;
HINSTANCE hModule;
int (*pfDeviceGetInfo)(unsigned *, TCHAR *, int);
if (!pstFind)
return COM_FAILED;
szPath[0] = (TCHAR)0;
if (pstFind->iAction == COM_FIND_DONE)
{
// Can't do a find done until we've at least done a find first
if (pstFind->iReserved != 1)
iRetVal = COM_FAILED;
else
{
pstFind->iReserved = 0;
if (pstFind->hFind != INVALID_HANDLE_VALUE)
FindClose(pstFind->hFind);
}
}
else
{
if (pstFind->iAction == COM_FIND_FIRST)
{
GetModuleFileName((HINSTANCE)0, pstFind->szFileName,
sizeof(pstFind->szFileName));
GetFullPathName(pstFind->szFileName, sizeof(szPath), szPath,
&pszNamePart);
// GetFullPathName gave us the address of the file name
// component of the path. Lop off the name and replace it
// with the pattern we want to search for.
*pszNamePart = (TCHAR)0;
lstrcat(szPath, TEXT("HACW*.DLL"));
// set flag to indicate that the find first has been done so
// we know that find nexts are ok
pstFind->iReserved = 1;
}
else if (pstFind->iAction == COM_FIND_NEXT)
{
if (pstFind->iReserved != 1)
iRetVal = COM_FAILED;
}
else
iRetVal = COM_FAILED;
fFound = FALSE;
while (iRetVal == COM_OK && !fFound)
{
if (pstFind->iAction == COM_FIND_FIRST)
{
pstFind->hFind = FindFirstFile(szPath, &pstFind->stFindData);
fResult = (pstFind->hFind != INVALID_HANDLE_VALUE);
pstFind->iAction = COM_FIND_NEXT;
}
else
{
fResult = FindNextFile(pstFind->hFind, &pstFind->stFindData);
}
if (!fResult)
{
if (pstFind->hFind != INVALID_HANDLE_VALUE)
FindClose(pstFind->hFind);
iRetVal = COM_NOT_FOUND;
pstFind->iReserved = 0;
pstFind->iAction = COM_FIND_DONE;
}
else
{
// Found a file, check to see if it is a valid driver and
// retrieve the device name
lstrcpy(pstFind->szFileName, pstFind->stFindData.cFileName);
hModule = LoadLibrary(pstFind->szFileName);
if (hModule)
{
// Note that GetProcAddress does not accept unicode strings
pfDeviceGetInfo = (int (*)(unsigned *, TCHAR *, int))
GetProcAddress(hModule, "DeviceGetInfo");
if (pfDeviceGetInfo &&
(*pfDeviceGetInfo)(&uDriverVersion,
pstFind->szDeviceName,
sizeof(pstFind->szDeviceName)) == COM_OK &&
uDriverVersion == COM_VERSION)
fFound = TRUE;
FreeLibrary(hModule);
lstrcpy(pstFind->szFileName, pstFind->stFindData.cFileName);
}
}
}
}
return iRetVal;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: ComFindPorts
*
* DESCRIPTION:
* Allows enumeration of all standard port names acceptable to a given
* com device driver. Note that it is not always possible to enumerate
* all possible port names. This function will provide a list of names
* to suggest to the user, but non-enumerated names may also be valid.
*
* ARGUMENTS:
* pstFind -- A structure of type COM_FIND_PORT that must be supplied
* by the caller.
* pszFileName -- The file name of the module to be queried. If the desired
* module has already been loaded, then this field can be
* passed as NULL and the hModule argument can be
* included. If only a device type name is known, the
* function ComGetFileNameFromDeviceName() can be used.
* hModule -- The module handle of the driver from which port names
* should be obtained. If this argument is non-zero, this
* module will be used and pszFileName will be ignored.
*
* RETURNS:
* COM_OK If another port name was found. The pstFind structure
* will be updated with information about the Name. To
* retrieve all drivers, this function should be called again
* if this value is returned.
* COM_NOT_FOUND if no more names are found.
* COM_FAILED if arguments are invalid
*/
int ComFindPorts(COM_FIND_PORT * const pstFind, const TCHAR * const pszFileName,
const HINSTANCE hModule)
{
int iRetVal = COM_OK;
int (*pfFindPorts)(COM_FIND_PORT *);
if (!pstFind || (!pszFileName && hModule == (HINSTANCE)0))
return COM_FAILED;
switch (pstFind->iAction)
{
case COM_FIND_FIRST:
if (hModule)
pstFind->hModule = hModule;
else
pstFind->hModule = LoadLibrary(pszFileName);
if (!pstFind->hModule)
iRetVal = COM_DEVICE_INVALID;
break;
case COM_FIND_NEXT:
case COM_FIND_DONE:
if (!pstFind->hModule)
iRetVal = COM_FAILED;
break;
default:
iRetVal = COM_FAILED;
break;
}
if (iRetVal == COM_OK)
{
pfFindPorts = (int (*)(COM_FIND_PORT *))
GetProcAddress(pstFind->hModule, "DeviceFindPorts");
if (!pfFindPorts)
iRetVal = COM_DEVICE_ERROR;
else
iRetVal = (*pfFindPorts)(pstFind);
switch (pstFind->iAction)
{
case COM_FIND_FIRST:
case COM_FIND_NEXT:
if (iRetVal == COM_OK)
{
pstFind->iAction = COM_FIND_NEXT;
break;
}
/* fall through */
case COM_FIND_DONE:
if (pstFind->hModule)
FreeLibrary(pstFind->hModule);
pstFind->hModule = (HINSTANCE)0;
pstFind->iAction = COM_FIND_DONE;
break;
default:
iRetVal = COM_FAILED;
break;
}
}
return iRetVal;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* FUNCTION: ComGetFileNameFromDeviceName
*
* DESCRIPTION:
* Given the name of a com device, this routine will attempt to find the
* .DLL file that implements that device and return its name.
*
* ARGUMENTS:
* pszDeviceName -- The name of the device whose file should be found
* pszFileName -- A buffer to receive the file name if it is located
* usSize -- The size of the pszFileName buffer
*
* RETURNS:
* COM_OK if device driver was found (file name is copied to pszFileName)
* COM_NOT_FOUND if no such driver can be found
* COM_FAILED if arguments are invalid or if usSize is too small.
*/
int ComGetFileNameFromDeviceName(const TCHAR * const pszDeviceName,
TCHAR * const pszFileName, const int nSize)
{
int iRetVal = COM_NOT_FOUND;
COM_FIND_DEVICE stComFind;
// Note: since this routine can be called from non-HA/Win programs (such
// as install routines, it must not call any functions that
// assume HA/Win is running.
if (!pszDeviceName || !*pszDeviceName || !pszFileName)
return COM_FAILED;
*pszFileName = (TCHAR)0;
stComFind.iAction = COM_FIND_FIRST;
while (ComFindDevices(&stComFind) == COM_OK)
{
if (lstrcmpi(pszDeviceName, stComFind.szDeviceName) == 0)
{
if ((lstrlen(stComFind.szFileName) + 1) > nSize)
iRetVal = COM_FAILED;
else
{
lstrcpy(pszFileName, stComFind.szFileName);
iRetVal = COM_OK;
}
// Since we stop scanning names early, we must shut down search
stComFind.iAction = COM_FIND_DONE;
ComFindDevices(&stComFind);
break;
}
}
return iRetVal;
}