Leaked source code of windows server 2003
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.
 
 
 
 
 
 

413 lines
11 KiB

/*
File mdm.cpp
Library for dealing with and installing modems.
Paul Mayfield, 5/20/98
*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <winerror.h>
#include <netcfgx.h>
#include <netcon.h>
#include <setupapi.h>
#include <devguid.h>
#include <unimodem.h>
#include "mdm.h"
//
// String definitions
//
const WCHAR pszNullModemId[] = L"PNPC031";
const WCHAR pszNullModemInfFile[] = L"mdmhayes.inf";
const WCHAR pszComPortRegKey[] = L"HARDWARE\\DEVICEMAP\\SERIALCOMM";
//
// Common allocation
//
PVOID MdmAlloc (DWORD dwSize, BOOL bZero) {
return LocalAlloc ((bZero) ? LPTR : LMEM_FIXED, dwSize);
}
//
// Common free
//
VOID MdmFree (PVOID pvData) {
LocalFree(pvData);
}
//
// Enumerates the serial ports on the system
//
DWORD MdmEnumComPorts(
IN MdmPortEnumFuncPtr pEnumFunc,
IN HANDLE hData)
{
DWORD dwErr = NO_ERROR, dwValSize, dwNameSize, dwBufSize, i,
dwValBufSize, dwNameBufSize, dwType, dwCount;
PWCHAR pszValBuf = NULL, pszNameBuf = NULL;
HKEY hkPorts;
// Open the hardware key
dwErr = RegOpenKeyEx (
HKEY_LOCAL_MACHINE,
pszComPortRegKey,
0,
KEY_READ,
&hkPorts);
if (dwErr != ERROR_SUCCESS)
return dwErr;
__try {
// Get the number of values
dwErr = RegQueryInfoKeyW (
hkPorts,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
&dwCount,
&dwNameBufSize,
&dwValBufSize,
NULL,
NULL);
if (dwErr != NO_ERROR)
{
__leave; //For whistler 524726
}
// If the count is zero, we're done
if (dwCount == 0)
{
dwErr = NO_ERROR;
__leave;
}
// Initialize the buffer to hold the names
dwNameBufSize++;
dwNameBufSize *= sizeof(WCHAR);
pszNameBuf = (PWCHAR) MdmAlloc(dwNameBufSize, FALSE);
if (pszNameBuf == NULL)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
__leave;
}
// Initialize the buffer to hold the values
dwValBufSize++;
pszValBuf = (PWCHAR) MdmAlloc(dwValBufSize, FALSE);
if (pszValBuf == NULL)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
__leave;
}
// Enumerate the values
for (i = 0; i < dwCount; i++)
{
dwValSize = dwValBufSize;
dwNameSize = dwNameBufSize;
dwErr = RegEnumValueW (
hkPorts,
i,
pszNameBuf,
&dwNameSize,
NULL,
NULL,
(LPBYTE)pszValBuf,
&dwValSize);
if (dwErr != ERROR_SUCCESS)
{
__leave;
}
if ((*(pEnumFunc))(pszValBuf, hData) == TRUE)
break;
}
}
__finally {
RegCloseKey (hkPorts);
if (pszValBuf)
MdmFree(pszValBuf);
if (pszNameBuf)
MdmFree(pszNameBuf);
}
return dwErr;
}
//
// Installs a null modem on the given port
//
DWORD MdmInstallNullModem(
IN PWCHAR pszPort)
{
GUID Guid = GUID_DEVCLASS_MODEM;
SP_DEVINFO_DATA deid;
SP_DEVINSTALL_PARAMS deip;
SP_DRVINFO_DATA drid;
UM_INSTALL_WIZARD miw = {sizeof(UM_INSTALL_WIZARD), 0};
SP_INSTALLWIZARD_DATA iwd;
PWCHAR pszTempId = NULL;
DWORD dwSize, dwErr = NO_ERROR;
HDEVINFO hdi;
BOOL bOk;
// Create the device info list
hdi = SetupDiCreateDeviceInfoList (&Guid, NULL);
if (hdi == INVALID_HANDLE_VALUE)
return ERROR_CAN_NOT_COMPLETE;
__try {
// Create a new devinfo.
deid.cbSize = sizeof(SP_DEVINFO_DATA);
bOk = SetupDiCreateDeviceInfo (
hdi,
pszNullModemId,
&Guid,
NULL,
NULL,
DICD_GENERATE_ID,
&deid);
if (bOk == FALSE)
{
dwErr = ERROR_CAN_NOT_COMPLETE;
__leave;
}
// In order to find the Inf file, Device Installer Api needs the
// component id which it calls the Hardware id.
// We need to include an extra null since this registry value is a
// multi-sz
//
dwSize = sizeof(pszNullModemId) + (2*sizeof(WCHAR));
pszTempId = (PWCHAR) MdmAlloc(dwSize * sizeof(WCHAR), FALSE);
if(NULL == pszTempId)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
__leave;
}
lstrcpyn(pszTempId, pszNullModemId, dwSize);
pszTempId[lstrlen(pszNullModemId) + 1] = L'\0';
bOk = SetupDiSetDeviceRegistryProperty(
hdi,
&deid,
SPDRP_HARDWAREID,
(LPBYTE)pszTempId,
dwSize);
if (bOk == FALSE)
{
dwErr = GetLastError();
__leave;
}
// We can let Device Installer Api know that we want
// to use a single inf. if we can't get the params and
// set it it isn't an error since it only slows things
// down a bit.
//
deip.cbSize = sizeof(deip);
bOk = SetupDiGetDeviceInstallParams(
hdi,
&deid,
&deip);
if (bOk == FALSE)
{
dwErr = GetLastError();
__leave;
}
lstrcpyn(deip.DriverPath, pszNullModemInfFile, MAX_PATH);
deip.Flags |= DI_ENUMSINGLEINF;
bOk = SetupDiSetDeviceInstallParams(hdi, &deid, &deip);
if (bOk == FALSE)
{
dwErr = GetLastError();
__leave;
}
// Now we let Device Installer Api build a driver list
// based on the information we have given so far. This
// will result in the Inf file being found if it exists
// in the usual Inf directory
//
bOk = SetupDiBuildDriverInfoList(
hdi,
&deid,
SPDIT_COMPATDRIVER);
if (bOk == FALSE)
{
dwErr = GetLastError();
__leave;
}
// Now that Device Installer Api has found the right inf
// file, we need to get the information and make it the
// selected driver
//
ZeroMemory(&drid, sizeof(drid));
drid.cbSize = sizeof(drid);
bOk = SetupDiEnumDriverInfo(
hdi,
&deid,
SPDIT_COMPATDRIVER,
0,
&drid);
if (bOk == FALSE)
{
dwErr = GetLastError();
__leave;
}
bOk = SetupDiSetSelectedDriver(
hdi,
&deid,
&drid);
if (bOk == FALSE)
{
dwErr = ERROR_CAN_NOT_COMPLETE;
__leave;
}
miw.InstallParams.Flags = MIPF_DRIVER_SELECTED;
lstrcpyn (miw.InstallParams.szPort, pszPort, UM_MAX_BUF_SHORT);
ZeroMemory(&iwd, sizeof(iwd));
iwd.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
iwd.ClassInstallHeader.InstallFunction = DIF_INSTALLWIZARD;
iwd.hwndWizardDlg = NULL;
iwd.PrivateData = (LPARAM)&miw;
bOk = SetupDiSetClassInstallParams (
hdi,
&deid,
(PSP_CLASSINSTALL_HEADER)&iwd,
sizeof(iwd));
if (bOk == FALSE)
{
dwErr = GetLastError();
__leave;
}
// Call the class installer to invoke the installation
// wizard.
bOk = SetupDiCallClassInstaller (
DIF_INSTALLWIZARD,
hdi,
&deid);
if (bOk == FALSE)
{
dwErr = GetLastError();
__leave;
}
SetupDiCallClassInstaller (
DIF_DESTROYWIZARDDATA,
hdi,
&deid);
}
__finally {
SetupDiDestroyDeviceInfoList (hdi);
if (pszTempId)
MdmFree(pszTempId);
}
return dwErr;
}
/*
const WCHAR pszComPortService[] = L"Serial";
const WCHAR pszPortDelimeter[] = L"(";
//
// Enumerates the serial ports on the system
//
// The old way
//
DWORD MdmEnumComPorts(
IN MdmPortEnumFuncPtr pEnumFunc,
IN HANDLE hData)
{
GUID Guid = GUID_DEVCLASS_PORTS;
SP_DEVINFO_DATA deid;
DWORD dwErr, i;
WCHAR pszName[512], pszPort[64], *pszTemp;
HDEVINFO hdi;
BOOL bOk;
// Create the device info list
hdi = SetupDiGetClassDevs (&Guid, NULL, NULL, DIGCF_PRESENT);
if (hdi == INVALID_HANDLE_VALUE)
return ERROR_CAN_NOT_COMPLETE;
ZeroMemory(&deid, sizeof(deid));
deid.cbSize = sizeof(deid);
__try {
i = 0;
while (TRUE) {
// Enumerate the next device
bOk = SetupDiEnumDeviceInfo (hdi, i++, &deid);
if (bOk == FALSE) {
dwErr = GetLastError();
break;
}
// Find out if this is a serial port
bOk = SetupDiGetDeviceRegistryPropertyW(
hdi,
&deid,
SPDRP_SERVICE,
NULL,
(PBYTE)pszName,
sizeof (pszName),
NULL);
if (bOk == FALSE)
continue;
// Filter out non-serial devices
if (lstrcmpi(pszName, pszComPortService) != 0)
continue;
// Get the friendly name
bOk = SetupDiGetDeviceRegistryPropertyW(
hdi,
&deid,
SPDRP_FRIENDLYNAME,
NULL,
(PBYTE)pszName,
sizeof (pszName),
NULL);
if (bOk == TRUE) {
// Add the real name of the port. Use this hack for
// now.
pszTemp = wcsstr(pszName, pszPortDelimeter);
if (pszTemp) {
lstrcpynW(pszPort, pszTemp + 1, sizeof(pszPort) / sizeof(WCHAR));
pszPort[wcslen(pszPort) - 1] = (WCHAR)0;
}
bOk = (*pEnumFunc)(pszName, pszPort, hData);
if (bOk)
break;
}
}
}
__finally {
SetupDiDestroyDeviceInfoList (hdi);
}
return NO_ERROR;
}
*/