306 lines
9.1 KiB
C
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;
|
|
}
|