/*++ Copyright (c) Microsoft Corporation. All rights reserved. Module Name: devcon.cpp Abstract: Device Console command-line interface for managing devices @@BEGIN_DDKSPLIT Author: Jamie Hunter (JamieHun) Nov-30-2000 Revision History: @@END_DDKSPLIT --*/ #include "devcon.h" struct IdEntry { LPCTSTR String; // string looking for LPCTSTR Wild; // first wild character if any BOOL InstanceId; }; void FormatToStream(FILE * stream,DWORD fmt,...) /*++ Routine Description: Format text to stream using a particular msg-id fmt Used for displaying localizable messages Arguments: stream - file stream to output to, stdout or stderr fmt - message id ... - parameters %1... Return Value: none --*/ { va_list arglist; LPTSTR locbuffer = NULL; DWORD count; va_start(arglist, fmt); count = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE|FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, fmt, 0, // LANGID (LPTSTR) &locbuffer, 0, // minimum size of buffer &arglist); if(locbuffer) { if(count) { _fputts(locbuffer,stream); } LocalFree(locbuffer); } } void Padding(int pad) /*++ Routine Description: Insert padding into line before text Arguments: pad - number of padding tabs to insert Return Value: none --*/ { int c; for(c=0;c [...] = [...] where can either be @instance-id, or hardware-id and may contain wildcards is a class name Arguments: BaseName - name of executable Machine - name of machine to enumerate Flags - extra enumeration flags (eg DIGCF_PRESENT) argc/argv - remaining arguments on command line Callback - function to call for each hit Context - data to pass function for each hit Return Value: EXIT_xxxx --*/ { HDEVINFO devs = INVALID_HANDLE_VALUE; IdEntry * templ = NULL; DWORD err; int failcode = EXIT_FAIL; int retcode; int argIndex; DWORD devIndex; SP_DEVINFO_DATA devInfo; SP_DEVINFO_LIST_DETAIL_DATA devInfoListDetail; BOOL doSearch = FALSE; BOOL match; BOOL all = FALSE; GUID cls; DWORD numClass = 0; int skip = 0; if(!argc) { return EXIT_USAGE; } templ = new IdEntry[argc]; if(!templ) { goto final; } // // determine if a class is specified // if(argc>skip && argv[skip][0]==CLASS_PREFIX_CHAR && argv[skip][1]) { if(!SetupDiClassGuidsFromNameEx(argv[skip]+1,&cls,1,&numClass,Machine,NULL) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) { goto final; } if(!numClass) { failcode = EXIT_OK; goto final; } skip++; } if(argc>skip && argv[skip][0]==WILD_CHAR && !argv[skip][1]) { // // catch convinient case of specifying a single argument '*' // all = TRUE; skip++; } else if(argc<=skip) { // // at least one parameter, but no 's // all = TRUE; } // // determine if any instance id's were specified // // note, if = was specified with no id's // we'll mark it as not doSearch // but will go ahead and add them all // for(argIndex=skip;argIndex and hand off execution to command Arguments: argc/argv - parameters passed to executable Return Value: EXIT_xxxx --*/ { LPCTSTR cmd; LPCTSTR baseName; LPCTSTR machine = NULL; int dispIndex; int firstArg = 1; int retval = EXIT_USAGE; BOOL autoReboot = FALSE; // // syntax: // // [options] [-]command [ []] // // options: // -m: - remote // -r - auto reboot // baseName = _tcsrchr(argv[0],TEXT('\\')); if(!baseName) { baseName = argv[0]; } else { baseName = CharNext(baseName); } while((argc > firstArg) && ((argv[firstArg][0] == TEXT('-')) || (argv[firstArg][0] == TEXT('/')))) { if((argv[firstArg][1]==TEXT('m')) || (argv[firstArg][1]==TEXT('M'))) { if((argv[firstArg][2]!=TEXT(':')) || (argv[firstArg][3]==TEXT('\0'))) { // // don't recognize this switch // break; } machine = argv[firstArg]+3; } else if((argv[firstArg][1]==TEXT('r')) || (argv[firstArg][1]==TEXT('R'))) { if((argv[firstArg][2]!=TEXT('\0')) ) { // // don't recognize this switch // break; } else { autoReboot = TRUE; } } else { // // don't recognize this switch // break; } firstArg++; } if((argc-firstArg) < 1) { // // after switches, must at least be command // Usage(baseName); return EXIT_USAGE; } cmd = argv[firstArg]; if((cmd[0]==TEXT('-')) || (cmd[0]==TEXT('/'))) { // // command may begin '-' or '/' // eg, people might do devcon -help // cmd = CharNext(cmd); } firstArg++; for(dispIndex = 0;DispatchTable[dispIndex].cmd;dispIndex++) { if(lstrcmpi(cmd,DispatchTable[dispIndex].cmd)==0) { retval = DispatchTable[dispIndex].func(baseName,machine,argc-firstArg,argv+firstArg); switch(retval) { case EXIT_USAGE: CommandUsage(baseName,DispatchTable[dispIndex].cmd); break; case EXIT_REBOOT: if(autoReboot) { Reboot(); } break; case EXIT_OK: break; default: Failure(baseName,DispatchTable[dispIndex].cmd); break; } return retval; } } Usage(baseName); return EXIT_USAGE; }