?? setup.cpp
字號:
/*
* $Id: setup.cpp,v 1.11 2006/11/21 11:36:06 vfrolov Exp $
*
* Copyright (c) 2006 Vyacheslav Frolov
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* $Log: setup.cpp,v $
* Revision 1.11 2006/11/21 11:36:06 vfrolov
* Added --output option
*
* Revision 1.10 2006/11/10 14:07:40 vfrolov
* Implemented remove command
*
* Revision 1.9 2006/11/03 16:13:29 vfrolov
* Added port name length checkings
*
* Revision 1.8 2006/11/03 13:22:07 vfrolov
* Added checking of BusyMask::AddNum() return value
*
* Revision 1.7 2006/11/02 16:20:44 vfrolov
* Added usage the fixed port numbers
*
* Revision 1.6 2006/10/27 13:23:49 vfrolov
* Added check if port name is already used for other device
* Fixed incorrect port restart
* Fixed prompts
*
* Revision 1.5 2006/10/23 12:08:31 vfrolov
* Added interactive mode
* Added more help
* Added SetTitle() calls
*
* Revision 1.4 2006/10/19 13:28:50 vfrolov
* Added InfFile::UninstallAllInfFiles()
*
* Revision 1.3 2006/10/13 10:26:35 vfrolov
* Some defines moved to ../include/com0com.h
* Changed name of device object (for WMI)
*
* Revision 1.2 2006/08/25 10:36:48 vfrolov
* Added C0C_PREF_PORT_NAME_A and C0C_PREF_PORT_NAME_B defines
* Added deleting Class subkeys
*
* Revision 1.1 2006/07/28 12:16:42 vfrolov
* Initial revision
*
*/
#include "precomp.h"
#include "inffile.h"
#include "params.h"
#include "devutils.h"
#include "msg.h"
#include "utils.h"
#include "portnum.h"
#define TEXT_PREF
#include "../include/com0com.h"
#define C0C_INF_NAME "com0com.inf"
#define C0C_CLASS_GUID "{df799e12-3c56-421b-b298-b6d3642bc878}"
#define C0C_CLASS "CNCPorts"
#define C0C_PROVIDER "Vyacheslav Frolov"
#define C0C_REGKEY_EVENTLOG REGSTR_PATH_SERVICES "\\Eventlog\\System\\" C0C_SERVICE
#define C0C_COPY_DRIVERS_SECTION "com0com_CopyDrivers"
#define C0C_SETUP_TITLE "Setup for com0com"
///////////////////////////////////////////////////////////////
static BOOL IsValidPortNum(int num)
{
if (num < 0)
return FALSE;
char buf[C0C_PORT_NAME_LEN + 1];
if (SNPRINTF(buf, sizeof(buf)/sizeof(buf[0]), C0C_PREF_BUS_NAME "%d", num) < 0 ||
SNPRINTF(buf, sizeof(buf)/sizeof(buf[0]), C0C_PREF_PORT_NAME_A "%d", num) < 0 ||
SNPRINTF(buf, sizeof(buf)/sizeof(buf[0]), C0C_PREF_PORT_NAME_B "%d", num) < 0)
{
int res = ShowMsg(MB_OKCANCEL|MB_ICONWARNING, "The port number %d is too big.\n", num);
if (res == IDCANCEL)
return FALSE;
}
return TRUE;
}
///////////////////////////////////////////////////////////////
static BOOL IsValidPortName(
const char *pPortName,
const char *pPhDevName)
{
int res;
if (lstrlen(pPortName) > C0C_PORT_NAME_LEN) {
res = ShowMsg(MB_OKCANCEL|MB_ICONWARNING,
"The length of port name %s\n"
"is too big (greater then %d).\n",
pPortName, C0C_PORT_NAME_LEN);
if (res == IDCANCEL)
return FALSE;
}
do {
res = IDCONTINUE;
char phDevName[80];
if (!QueryDosDevice(pPortName, phDevName, sizeof(phDevName)/sizeof(phDevName[0]))) {
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
break;
phDevName[0] = 0;
}
if (pPhDevName && !lstrcmpi(pPhDevName, phDevName))
break;
res = ShowMsg(MB_CANCELTRYCONTINUE,
"The port name %s is already used for other device %s.",
pPortName, phDevName);
} while (res == IDTRYAGAIN);
if (res != IDCONTINUE)
return FALSE;
return TRUE;
}
///////////////////////////////////////////////////////////////
struct ChangeDeviceParams {
ChangeDeviceParams(InfFile &_infFile, const char *_pPhPortName, const char *_pParameters)
: pInfFile(&_infFile), pPhPortName(_pPhPortName), pParameters(_pParameters) {}
InfFile *pInfFile;
const char *pPhPortName;
const char *pParameters;
};
static BOOL ChangeDevice(
HDEVINFO hDevInfo,
PSP_DEVINFO_DATA pDevInfoData,
PCDevProperties /*pDevProperties*/,
BOOL *pRebootRequired,
void *pParam)
{
int i = GetPortNum(hDevInfo, pDevInfoData);
if (i >= 0) {
InfFile &infFile = *((ChangeDeviceParams *)pParam)->pInfFile;
const char *pPhPortName = ((ChangeDeviceParams *)pParam)->pPhPortName;
const char *pParameters = ((ChangeDeviceParams *)pParam)->pParameters;
for (int j = 0 ; j < 2 ; j++) {
char phPortName[20];
SNPRINTF(phPortName, sizeof(phPortName)/sizeof(phPortName[0]), "%s%d",
j ? C0C_PREF_PORT_NAME_B : C0C_PREF_PORT_NAME_A, i);
PortParameters portParameters(C0C_SERVICE, phPortName);
LONG err = portParameters.Load();
char buf[100];
portParameters.FillParametersStr(buf, sizeof(buf)/sizeof(buf[0]));
Trace(" %s %s\n", phPortName, buf);
if (err == ERROR_SUCCESS) {
if (pPhPortName && !lstrcmpi(pPhPortName, phPortName)) {
portParameters.ParseParametersStr(pParameters);
char phDevName[40];
SNPRINTF(phDevName, sizeof(phDevName)/sizeof(phDevName[0]), "%s%d",
j ? C0C_PREF_DEVICE_NAME_B : C0C_PREF_DEVICE_NAME_A, i);
char portName[20];
portParameters.FillPortName(portName, sizeof(portName)/sizeof(portName[0]));
if (IsValidPortName(portName, phDevName) && portParameters.Changed()) {
err = portParameters.Save();
if (err == ERROR_SUCCESS) {
portParameters.FillParametersStr(buf, sizeof(buf)/sizeof(buf[0]));
Trace("change %s %s\n", phPortName, buf);
DevProperties devProperties;
devProperties.pDevId = C0C_PORT_DEVICE_ID;
devProperties.pPhObjName = phDevName;
RestartDevices(infFile, &devProperties, pRebootRequired);
} else {
ShowError(MB_OK|MB_ICONWARNING, err, "portParameters.Save(%s)", phPortName);
}
}
}
} else {
ShowError(MB_OK|MB_ICONWARNING, err, "portParameters.Load(%s)", phPortName);
}
}
}
return TRUE;
}
int Change(InfFile &infFile, const char *pPhPortName, const char *pParameters)
{
BOOL rebootRequired = FALSE;
ChangeDeviceParams params(infFile, pPhPortName, pParameters);
DevProperties devProperties;
devProperties.pDevId = C0C_BUS_DEVICE_ID;
EnumDevices(infFile, &devProperties, &rebootRequired, ChangeDevice, ¶ms);
if (rebootRequired)
SetupPromptReboot(NULL, NULL, FALSE);
return 0;
}
///////////////////////////////////////////////////////////////
struct RemoveDeviceParams {
RemoveDeviceParams(int _num) : num(_num), res(IDCANCEL) {}
int num;
int res;
};
static BOOL RemoveDevice(
HDEVINFO hDevInfo,
PSP_DEVINFO_DATA pDevInfoData,
PCDevProperties pDevProperties,
BOOL *pRebootRequired,
void *pParam)
{
int i = GetPortNum(hDevInfo, pDevInfoData);
if (i == ((RemoveDeviceParams *)pParam)->num) {
((RemoveDeviceParams *)pParam)->res =
DisableDevice(hDevInfo, pDevInfoData, pDevProperties, pRebootRequired);
if (((RemoveDeviceParams *)pParam)->res != IDCONTINUE)
return FALSE;
return RemoveDevice(hDevInfo, pDevInfoData, pDevProperties, pRebootRequired);
}
return TRUE;
}
int Remove(InfFile &infFile, int num)
{
int res;
BOOL rebootRequired = FALSE;
do {
RemoveDeviceParams removeDeviceParams(num);
DevProperties devProperties;
devProperties.pDevId = C0C_BUS_DEVICE_ID;
EnumDevices(infFile, &devProperties, &rebootRequired, RemoveDevice, &removeDeviceParams);
res = removeDeviceParams.res;
} while (res == IDTRYAGAIN);
if (res == IDCONTINUE) {
for (int j = 0 ; j < 2 ; j++) {
char phPortName[20];
SNPRINTF(phPortName, sizeof(phPortName)/sizeof(phPortName[0]), "%s%d",
j ? C0C_PREF_PORT_NAME_B : C0C_PREF_PORT_NAME_A, num);
DevProperties devProperties;
devProperties.pDevId = C0C_PORT_DEVICE_ID;
devProperties.pLocation = phPortName;
RemoveDevices(infFile, &devProperties, NULL);
}
}
if (rebootRequired)
SetupPromptReboot(NULL, NULL, FALSE);
if (res != IDCONTINUE)
return 1;
return 0;
}
///////////////////////////////////////////////////////////////
int Preinstall(InfFile &infFile)
{
if (!infFile.InstallOEMInf())
return 1;
int res;
do {
res = IDCONTINUE;
if (SetupDiInstallClass(NULL, infFile.Path(), 0, NULL)) {
Trace("Installed Class %s\n", infFile.ClassGUID());
} else {
res = ShowLastError(MB_CANCELTRYCONTINUE, "SetupDiInstallClass()");
}
} while (res == IDTRYAGAIN);
if (res != IDCONTINUE)
return 1;
return 0;
}
///////////////////////////////////////////////////////////////
int Update(InfFile &infFile)
{
if (!UpdateDriverForPlugAndPlayDevices(0, C0C_BUS_DEVICE_ID, infFile.Path(), INSTALLFLAG_FORCE, NULL))
return 1;
return 0;
}
///////////////////////////////////////////////////////////////
static BOOL SetPortNum(
HDEVINFO hDevInfo,
PSP_DEVINFO_DATA pDevInfoData,
PCDevProperties /*pDevProperties*/,
BOOL * /*pRebootRequired*/,
void *pParam)
{
int res;
do {
res = IDCONTINUE;
LONG err = SetPortNum(hDevInfo, pDevInfoData, *(int *)pParam);
if (err != ERROR_SUCCESS)
res = ShowError(MB_CANCELTRYCONTINUE, err, "SetPortNum(%d)", *(int *)pParam);
} while (res == IDTRYAGAIN);
if (res != IDCONTINUE)
return FALSE;
return TRUE;
}
static BOOL InstallBusDevice(InfFile &infFile, int num)
{
return InstallDevice(infFile, C0C_BUS_DEVICE_ID, SetPortNum, &num);
}
static BOOL AddDeviceToBusyMask(
HDEVINFO hDevInfo,
PSP_DEVINFO_DATA pDevInfoData,
PCDevProperties /*pDevProperties*/,
BOOL * /*pRebootRequired*/,
void *pParam)
{
int i = GetPortNum(hDevInfo, pDevInfoData);
if (i >= 0) {
if (!((BusyMask *)pParam)->AddNum(i)) {
if (ShowLastError(MB_OKCANCEL|MB_ICONWARNING, "AddDeviceToBusyMask(%d)", i) == IDCANCEL)
return FALSE;
}
}
return TRUE;
}
static int AllocPortNum(InfFile &infFile, int num)
{
BusyMask busyMask;
DevProperties devProperties;
devProperties.pDevId = C0C_BUS_DEVICE_ID;
if (EnumDevices(infFile, &devProperties, NULL, AddDeviceToBusyMask, &busyMask) < 0)
return -1;
return busyMask.IsFreeNum(num) ? num : busyMask.GetFirstFreeNum();
}
int Install(InfFile &infFile, const char *pParametersA, const char *pParametersB, int num)
{
int i;
int res;
do {
res = IDCONTINUE;
i = AllocPortNum(infFile, num >= 0 ? num : 0);
if (i < 0)
goto err;
if (num >= 0 && num != i) {
res = ShowMsg(MB_CANCELTRYCONTINUE|MB_ICONWARNING,
"The identifiers " C0C_PREF_PORT_NAME_A "%d and "
C0C_PREF_PORT_NAME_B "%d are already used for other ports\n"
"so ports with identifiers " C0C_PREF_PORT_NAME_A "%d and "
C0C_PREF_PORT_NAME_B "%d will be installed instead.\n",
num, num, i, i);
}
} while (res == IDTRYAGAIN);
if (res != IDCONTINUE)
goto err;
if (!IsValidPortNum(i))
goto err;
for (int j = 0 ; j < 2 ; j++) {
char phPortName[20];
const char *pParameters;
pParameters = j ? pParametersB : pParametersA;
SNPRINTF(phPortName, sizeof(phPortName)/sizeof(phPortName[0]), "%s%d",
j ? C0C_PREF_PORT_NAME_B : C0C_PREF_PORT_NAME_A, i);
PortParameters portParameters(C0C_SERVICE, phPortName);
LONG err = portParameters.Load();
if (err == ERROR_SUCCESS) {
portParameters.ParseParametersStr(pParameters);
char portName[20];
portParameters.FillPortName(portName, sizeof(portName)/sizeof(portName[0]));
if (!IsValidPortName(portName, NULL))
goto err;
if (portParameters.Changed()) {
err = portParameters.Save();
if (err != ERROR_SUCCESS)
ShowError(MB_OK|MB_ICONWARNING, err, "portParameters.Save(%s)", phPortName);
}
} else {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -