📄 cmds.cpp
字号:
int cmdUpdate(LPCTSTR BaseName,LPCTSTR Machine,int argc,TCHAR* argv[])
/*++
Routine Description:
UPDATE
update driver for existing device(s)
Arguments:
BaseName - name of executable
Machine - machine name, must be NULL
argc/argv - remaining parameters
Return Value:
EXIT_xxxx
--*/
{
HMODULE newdevMod = NULL;
int failcode = EXIT_FAIL;
UpdateDriverForPlugAndPlayDevicesProto UpdateFn;
BOOL reboot = FALSE;
LPCTSTR hwid = NULL;
LPCTSTR inf = NULL;
DWORD flags = 0;
DWORD res;
TCHAR InfPath[MAX_PATH];
if(Machine) {
//
// must be local machine
//
return EXIT_USAGE;
}
if(argc<2) {
//
// at least HWID required
//
return EXIT_USAGE;
}
inf = argv[0];
if(!inf[0]) {
return EXIT_USAGE;
}
hwid = argv[1];
if(!hwid[0]) {
return EXIT_USAGE;
}
//
// Inf must be a full pathname
//
res = GetFullPathName(inf,MAX_PATH,InfPath,NULL);
if((res >= MAX_PATH) || (res == 0)) {
//
// inf pathname too long
//
return EXIT_FAIL;
}
if(GetFileAttributes(InfPath)==(DWORD)(-1)) {
//
// inf doesn't exist
//
return EXIT_FAIL;
}
inf = InfPath;
flags |= INSTALLFLAG_FORCE;
//
// make use of UpdateDriverForPlugAndPlayDevices
//
newdevMod = LoadLibrary(TEXT("newdev.dll"));
if(!newdevMod) {
goto final;
}
UpdateFn = (UpdateDriverForPlugAndPlayDevicesProto)GetProcAddress(newdevMod,UPDATEDRIVERFORPLUGANDPLAYDEVICES);
if(!UpdateFn)
{
goto final;
}
FormatToStream(stdout,inf ? MSG_UPDATE_INF : MSG_UPDATE,hwid,inf);
if(!UpdateFn(NULL,hwid,inf,flags,&reboot)) {
goto final;
}
FormatToStream(stdout,MSG_UPDATE_OK);
failcode = reboot ? EXIT_REBOOT : EXIT_OK;
final:
if(newdevMod) {
FreeLibrary(newdevMod);
}
return failcode;
}
int cmdInstall(LPCTSTR BaseName,LPCTSTR Machine,int argc,TCHAR* argv[])
/*++
Routine Description:
INSTALL
install a device manually
Arguments:
BaseName - name of executable
Machine - machine name, must be NULL
argc/argv - remaining parameters
Return Value:
EXIT_xxxx
--*/
{
HDEVINFO DeviceInfoSet = INVALID_HANDLE_VALUE;
SP_DEVINFO_DATA DeviceInfoData;
GUID ClassGUID;
TCHAR ClassName[MAX_CLASS_NAME_LEN];
TCHAR hwIdList[LINE_LEN+4];
TCHAR InfPath[MAX_PATH];
DWORD err;
int failcode = EXIT_FAIL;
BOOL reboot = FALSE;
LPCTSTR hwid = NULL;
LPCTSTR inf = NULL;
DWORD flags = 0;
DWORD len;
if(Machine) {
//
// must be local machine
//
return EXIT_USAGE;
}
if(argc<2) {
//
// at least HWID required
//
return EXIT_USAGE;
}
inf = argv[0];
if(!inf[0]) {
return EXIT_USAGE;
}
hwid = argv[1];
if(!hwid[0]) {
return EXIT_USAGE;
}
//
// Inf must be a full pathname
//
if(GetFullPathName(inf,MAX_PATH,InfPath,NULL) >= MAX_PATH) {
//
// inf pathname too long
//
return EXIT_FAIL;
}
//
// List of hardware ID's must be double zero-terminated
//
ZeroMemory(hwIdList,sizeof(hwIdList));
lstrcpyn(hwIdList,hwid,LINE_LEN);
//
// Use the INF File to extract the Class GUID.
//
if (!SetupDiGetINFClass(InfPath,&ClassGUID,ClassName,sizeof(ClassName)/sizeof(ClassName[0]),0))
{
goto final;
}
//
// Create the container for the to-be-created Device Information Element.
//
DeviceInfoSet = SetupDiCreateDeviceInfoList(&ClassGUID,0);
if(DeviceInfoSet == INVALID_HANDLE_VALUE)
{
goto final;
}
//
// Now create the element.
// Use the Class GUID and Name from the INF file.
//
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if (!SetupDiCreateDeviceInfo(DeviceInfoSet,
ClassName,
&ClassGUID,
NULL,
0,
DICD_GENERATE_ID,
&DeviceInfoData))
{
goto final;
}
//
// Add the HardwareID to the Device's HardwareID property.
//
if(!SetupDiSetDeviceRegistryProperty(DeviceInfoSet,
&DeviceInfoData,
SPDRP_HARDWAREID,
(LPBYTE)hwIdList,
(lstrlen(hwIdList)+1+1)*sizeof(TCHAR)))
{
goto final;
}
//
// Transform the registry element into an actual devnode
// in the PnP HW tree.
//
if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE,
DeviceInfoSet,
&DeviceInfoData))
{
goto final;
}
FormatToStream(stdout,MSG_INSTALL_UPDATE);
//
// update the driver for the device we just created
//
failcode = cmdUpdate(BaseName,Machine,argc,argv);
final:
if (DeviceInfoSet != INVALID_HANDLE_VALUE) {
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
}
return failcode;
}
int cmdUpdateNI(LPCTSTR BaseName,LPCTSTR Machine,int argc,TCHAR* argv[])
/*++
Routine Description:
UPDATE (non interactive version)
update driver for existing device(s)
Arguments:
BaseName - name of executable
Machine - machine name, must be NULL
argc/argv - remaining parameters
Return Value:
EXIT_xxxx
--*/
{
//
// turn off interactive mode while doing the update
//
HMODULE setupapiMod = NULL;
SetupSetNonInteractiveModeProto SetNIFn;
int res;
BOOL prev;
setupapiMod = LoadLibrary(TEXT("setupapi.dll"));
if(!setupapiMod) {
return cmdUpdate(BaseName,Machine,argc,argv);
}
SetNIFn = (SetupSetNonInteractiveModeProto)GetProcAddress(setupapiMod,SETUPSETNONINTERACTIVEMODE);
if(!SetNIFn)
{
FreeLibrary(setupapiMod);
return cmdUpdate(BaseName,Machine,argc,argv);
}
prev = SetNIFn(TRUE);
res = cmdUpdate(BaseName,Machine,argc,argv);
SetNIFn(prev);
FreeLibrary(setupapiMod);
return res;
}
int RemoveCallback(HDEVINFO Devs,PSP_DEVINFO_DATA DevInfo,DWORD Index,LPVOID Context)
/*++
Routine Description:
Callback for use by Remove
Invokes DIF_REMOVE
uses SetupDiCallClassInstaller so cannot be done for remote devices
Don't use CM_xxx API's, they bypass class/co-installers and this is bad.
Arguments:
Devs )_ uniquely identify the device
DevInfo )
Index - index of device
Context - GenericContext
Return Value:
EXIT_xxxx
--*/
{
SP_REMOVEDEVICE_PARAMS rmdParams;
GenericContext *pControlContext = (GenericContext*)Context;
SP_DEVINSTALL_PARAMS devParams;
LPCTSTR action = NULL;
//
// need hardware ID before trying to remove, as we wont have it after
//
TCHAR devID[MAX_DEVICE_ID_LEN];
LPTSTR desc;
BOOL b = TRUE;
SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail;
devInfoListDetail.cbSize = sizeof(devInfoListDetail);
if((!SetupDiGetDeviceInfoListDetail(Devs,&devInfoListDetail)) ||
(CM_Get_Device_ID_Ex(DevInfo->DevInst,devID,MAX_DEVICE_ID_LEN,0,devInfoListDetail.RemoteMachineHandle)!=CR_SUCCESS)) {
//
// skip this
//
return EXIT_OK;
}
rmdParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
rmdParams.ClassInstallHeader.InstallFunction = DIF_REMOVE;
rmdParams.Scope = DI_REMOVEDEVICE_GLOBAL;
rmdParams.HwProfile = 0;
if(!SetupDiSetClassInstallParams(Devs,DevInfo,&rmdParams.ClassInstallHeader,sizeof(rmdParams)) ||
!SetupDiCallClassInstaller(DIF_REMOVE,Devs,DevInfo)) {
//
// failed to invoke DIF_REMOVE
//
action = pControlContext->strFail;
} else {
//
// see if device needs reboot
//
devParams.cbSize = sizeof(devParams);
if(SetupDiGetDeviceInstallParams(Devs,DevInfo,&devParams) && (devParams.Flags & (DI_NEEDRESTART|DI_NEEDREBOOT))) {
//
// reboot required
//
action = pControlContext->strReboot;
pControlContext->reboot = TRUE;
} else {
//
// appears to have succeeded
//
action = pControlContext->strSuccess;
}
pControlContext->count++;
}
_tprintf(TEXT("%-60s: %s\n"),devID,action);
return EXIT_OK;
}
int cmdRemove(LPCTSTR BaseName,LPCTSTR Machine,int argc,TCHAR* argv[])
/*++
Routine Description:
REMOVE
remove devices
Arguments:
BaseName - name of executable
Machine - machine name, must be NULL
argc/argv - remaining parameters
Return Value:
EXIT_xxxx
--*/
{
GenericContext context;
TCHAR strRemove[80];
TCHAR strReboot[80];
TCHAR strFail[80];
int failcode = EXIT_FAIL;
if(!argc) {
//
// arguments required
//
return EXIT_USAGE;
}
if(Machine) {
//
// must be local machine as we need to involve class/co installers
//
return EXIT_USAGE;
}
if(!LoadString(NULL,IDS_REMOVED,strRemove,ARRAYSIZE(strRemove))) {
return EXIT_FAIL;
}
if(!LoadString(NULL,IDS_REMOVED_REBOOT,strReboot,ARRAYSIZE(strReboot))) {
return EXIT_FAIL;
}
if(!LoadString(NULL,IDS_REMOVE_FAILED,strFail,ARRAYSIZE(strFail))) {
return EXIT_FAIL;
}
context.reboot = FALSE;
context.count = 0;
context.strReboot = strReboot;
context.strSuccess = strRemove;
context.strFail = strFail;
failcode = EnumerateDevices(BaseName,Machine,DIGCF_PRESENT,argc,argv,RemoveCallback,&context);
if(failcode == EXIT_OK) {
if(!context.count) {
FormatToStream(stdout,MSG_REMOVE_TAIL_NONE);
} else if(!context.reboot) {
FormatToStream(stdout,MSG_REMOVE_TAIL,context.count);
} else {
FormatToStream(stdout,MSG_REMOVE_TAIL_REBOOT,context.count);
failcode = EXIT_REBOOT;
}
}
return failcode;
}
int cmdRescan(LPCTSTR BaseName,LPCTSTR Machine,int argc,TCHAR* argv[])
/*++
Routine Description:
RESCAN
rescan for new devices
Arguments:
BaseName - name of executable
Machine - machine name, must be NULL
argc/argv - remaining parameters
Return Value:
EXIT_xxxx
--*/
{
//
// reenumerate from the root of the devnode tree
// totally CM based
//
int failcode = EXIT_FAIL;
HMACHINE machineHandle = NULL;
DEVINST devRoot;
if(Machine) {
if(CM_Connect_Machine(Machine,&machineHandle) != CR_SUCCESS) {
return failcode;
}
}
if(CM_Locate_DevNode_Ex(&devRoot,NULL,CM_LOCATE_DEVNODE_NORMAL,machineHandle) != CR_SUCCESS) {
goto final;
}
FormatToStream(stdout,Machine ? MSG_RESCAN : MSG_RESCAN_LOCAL);
if(CM_Reenumerate_DevNode_Ex(devRoot, 0, machineHandle) != CR_SUCCESS) {
goto final;
}
FormatToStream(stdout,MSG_RESCAN_OK);
failcode = EXIT_OK;
final:
if(machineHandle) {
CM_Disconnect_Machine(machineHandle);
}
return failcode;
}
int cmdClassFilter(LPCTSTR BaseName,LPCTSTR Machine,int argc,TCHAR* argv[])
/*++
Routine Description:
CLASSFILTER <name> <type> <subcmds>
Allows tweaking of class filters
Useful for filter driver development and for Product Support
<subcmds> is a list of the following:
@service - sets 'after' to the first match of service after 'after'
(reset to -1 after any other command)
!service - deletes first match of 'service' after 'after'
-service - insert new service directly prior to 'after', or at start
+service - insert new service directly after 'after', or at end
if no <subcmds> given, list the services
Arguments:
BaseName - name of executable
Machine - if non-NULL, remote machine
argc/argv - remaining parameters - list of class names
Return Value:
EXIT_xxxx
--*/
{
int failcode = EXIT_FAIL;
int argIndex;
DWORD numGuids;
GUID guid;
LPTSTR regval = NULL;
HKEY hk = (HKEY)INVALID_HANDLE_VALUE;
LPTSTR * multiVal = NULL;
int after;
bool modified = false;
int span;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -