阅读:10548回复:26
用setup api安装modem成功后,在拨号连接里无法使用
我用setup api安装modem成功了,设备管理器可以正常看到这个modem,也可以正常检测,但在拨号连接里就是无法使用,老是提示找不到modem。如果我用硬件向导装modem就可以用。是不是modem驱动安装完还要在注册表登记什么?大虾指教啊,江湖救急!
|
|
最新喜欢:kb219 |
沙发#
发布于:2003-08-16 17:09
我的msn : ma13910206425@hotmail.com
|
|
|
板凳#
发布于:2003-08-17 00:32
痛苦挣扎后几个小时终于解决了。原来我是在modem安装完后再修改注册表键AttachTo使Modem绑在一个端口上,后来发现这是不行的,因为Modem安装过程中有一个向RAS注册的过程,必须在这个过程之前设置好AttachTo。但在SetupDiCallClassInstaller(DIF_INSTALLDEVICE,)之前AttachTo所在的主键还没有生成,没办法设置AttachTo,最后写了一个CoInstaller了事。
|
|
地板#
发布于:2003-08-18 14:09
to gzytom
可否把你的CoInstaller部分代码发给我参考一下,我在这儿遇到的问题和你的很相似,谢谢! 我的mail: EricGaoxp@hotmail.com |
|
|
地下室#
发布于:2003-08-18 16:41
to gzytom 其实很简单,在安装前我把需要绑定的端口名称放在注册表某个地方下(我这里用的是HKCR\\Environment\\MDMCOM),然后在CoInstaller里读出这个值。用共享内存或者其他什么方式也可以的,不过我觉得用注册表方便。 DWORD CALLBACK ModemCoInstallProc ( DI_FUNCTION InstallFunction, HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PCOINSTALLER_CONTEXT_DATA Context ) { if(InstallFunction == DIF_INSTALLDEVICE) { char szInstanceID[255]; char buffer[1024]; DWORD cbData; HKEY hKey; char szComPort[10] = { 0 }; if(RegOpenKey(HKEY_CURRENT_USER , \"Environment\" , &hKey)==ERROR_SUCCESS) { cbData = sizeof(szComPort); if(RegQueryValueEx(hKey , \"MDMCOM\" , NULL , NULL , (LPBYTE)szComPort , &cbData)==ERROR_SUCCESS) { if(SetupDiGetDeviceInstanceId(DeviceInfoSet , DeviceInfoData , szInstanceID , 1024 , NULL)) { if(GetOsType() < OS_NT4) strcpy(buffer , \"System\\\\CurrentControlSet\\\\Services\\\\Class\\\\\"); else strcpy(buffer , \"SYSTEM\\\\CurrentControlSet\\\\Control\\\\Class\\\\\"); cbData = 1024 - strlen(buffer); if(RegQueryDeviceProperty(szInstanceID , NULL , \"Driver\" , NULL , (PBYTE)(buffer + strlen(buffer)), &cbData)==ERROR_SUCCESS) { if(RegOpenKey(HKEY_LOCAL_MACHINE, buffer,&hKey)==ERROR_SUCCESS) { RegSetValueEx(hKey , \"AttachedTo\", 0 , REG_SZ , (LPBYTE)szComPort , strlen(szComPort)); RegCloseKey(hKey); } } } } RegCloseKey(hKey); } } return NO_ERROR; } [编辑 - 8/18/03 by gzytom] |
|
5楼#
发布于:2003-08-19 08:54
可不可以把你的所有代码发给我,我还是不是很明白,呵呵,我是新手,刚接触这方面不到一个星期,或者你可以上msn吗,我的msn是
:EricGaoxp@hotmail.com |
|
|
6楼#
发布于:2003-08-21 19:17
我也想解决这样的问题,请问如何将CoInstaller如何将你的回调结合在一起了,没玩过CoInstaller,请指点!
|
|
7楼#
发布于:2003-08-22 12:22
可不可以把你的所有代码发给我,我还是不是很明白,呵呵,我是新手,刚接触这方面不到一个星期,或者你可以上msn吗,我的msn是 哈哈,我也是新手啊。代码我基本都贴出来了啊。 |
|
8楼#
发布于:2003-08-22 12:24
我也想解决这样的问题,请问如何将CoInstaller如何将你的回调结合在一起了,没玩过CoInstaller,请指点! 看不大懂你的意思:(。CoInstaller是有系统调用的。在INF文件注册后就可以。不过98不能用,郁闷。 |
|
9楼#
发布于:2003-08-22 13:41
to gzytom :
98下确实是不能用,因为setupapi.dll使用了一些NTDLL.DLL的函数导 入,98下没有的,即使拷过来也不能用。 我的意思就是怎么让这个回调函数于你的主程序组合在一起。我想要实现运行这个程序后,就可以指定串口和INF文件,自动安装标准33K的调制解调器。无需用户在去选择和干预。 不知能不能给你的主程序也拿出来让大家学习学习。 下面是DDK下根据指定的INF和HardWareID来自动安装驱动的函数例程,请问如何将它和你的回调组合在一起使用,达到上述目的? BOOL InstallRootEnumDriver(IN LPTSTR HardwareId, IN LPTSTR InfFile,OUT PBOOL RebootRequest OPTIONAL) { HDEVINFO DeviceInfoSet=0; SP_DEVINFO_DATA DeviceInfoData; GUID ClassGUID; TCHAR ClassName[MAX_CLASS_NAME_LEN]; DWORD err; if (!SetupDiGetINFClass(InfFile,&ClassGUID,ClassName,sizeof(ClassName),0)) { return DisplayError(TEXT(\"SetupDiINFClass\")); } DeviceInfoSet=SetupDiCreateDeviceInfoList(&ClassGUID,0); if (DeviceInfoSet==INVALID_HANDLE_VALUE) { return DisplayError(TEXT(\"SetupCreateDeviceInfoList\")); } DeviceInfoData.cbSize=sizeof(SP_DEVINFO_DATA); if (!SetupDiCreateDeviceInfo(DeviceInfoSet,ClassName,&ClassGUID,NULL,0, DICD_GENERATE_ID,&DeviceInfoData)) { DisplayError(TEXT(\"CreateDeviceInfo\")); goto cleanup_DeviceInfo; } if(!SetupDiSetDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, SPDRP_HARDWAREID, (LPBYTE)HardwareId, (lstrlen(HardwareId)+1+1)*sizeof(TCHAR))) { DisplayError(TEXT(\"SetDeviceRegistryProperty\")); goto cleanup_DeviceInfo; } if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, DeviceInfoSet, &DeviceInfoData)) { DisplayError(TEXT(\"CallClassInstaller(REGISTERDEVICE)\")); goto cleanup_DeviceInfo; } // // The element is now registered. We must explicitly remove the // device using DIF_REMOVE, if we encounter any failure from now on. // // // Install the Driver. // if (!UpdateDriverForPlugAndPlayDevices(0, HardwareId, InfFile, INSTALLFLAG_FORCE, RebootRequest)) { DWORD err = GetLastError(); DisplayError(TEXT(\"UpdateDriverForPlugAndPlayDevices\")); if (!SetupDiCallClassInstaller( DIF_REMOVE, DeviceInfoSet, &DeviceInfoData)) { DisplayError(TEXT(\"CallClassInstaller(REMOVE)\")); } SetLastError(err); } // // Cleanup. // cleanup_DeviceInfo: err = GetLastError(); SetupDiDestroyDeviceInfoList(DeviceInfoSet); SetLastError(err); return err == NO_ERROR; } |
|
10楼#
发布于:2003-08-22 14:53
to gzytom : 哦,我明白你的意思了。98下也有setupapi.dll,而且好像还没有什么函数不可以用吧?DDK下那个例子除了一个函数不能用:UpdateDriverForPlugAndPlayDevices,它是在newdev.dll里的,其他都可以用。其实这个UpdateDriverForPlugAndPlayDevices也可以用SetupDiXX类函数替代。下面是我的主程序的一个片断,仿照DDK写的,98下可以有条件的正常运行(见我后面的解释): BOOL FindExistingDevice(IN LPGUID lpGUID , IN LPCTSTR lpszHardwareID , OUT LPTSTR lpszInstanceID OPTIONAL) { HDEVINFO hdi = NULL; SP_DEVINFO_DATA hDev = { 0 } ; hDev.cbSize = sizeof(SP_DEVINFO_DATA); DWORD dwEnumIndex; char buffer[1024]; DWORD cbData; BOOL fFound = FALSE; try { if((hdi = SetupDiGetClassDevs(lpGUID , NULL , NULL , 0))==NULL) throw STException(\"SetupDiGetClassDevs\"); dwEnumIndex = 0; while(SetupDiEnumDeviceInfo(hdi , dwEnumIndex++ , &hDev)) { if(SetupDiGetDeviceRegistryProperty(hdi , &hDev , SPDRP_HARDWAREID , NULL , (PBYTE)buffer , 1024 , &cbData)) { char *p; for (p=buffer;*p&&(p<&buffer[cbData]);p+=strlen(p)+sizeof(char)) { if (stricmp(lpszHardwareID,p)==0) { printf(\"Found! [%s]\\n\",p); if(!SetupDiGetDeviceInstanceId(hdi , &hDev , buffer , 1024 , NULL)) throw STException(\"SetupDiGetDeviceInstanceId\"); if(lpszInstanceID!=NULL) strcpy(lpszInstanceID , buffer); fFound = TRUE; break; } } if(fFound) break; } } } catch(STException &e) { LogMessage(\"%s failed , err = %x.\\n\" , e.getMessage() , GetLastError()); } if(hdi != NULL) SetupDiDestroyDeviceInfoList(hdi); return fFound; } int InstallRootEnumeratedDriver(IN LPGUID lpGUID, IN LPCTSTR lpszHardwareID , IN LPCTSTR lpszDescription, IN LPCTSTR lpszInfName OPTIONAL, OUT LPTSTR lpszInstanceID OPTIONAL, OUT LPBOOL pfNeedReboot OPTIONAL ) { int ret = ERROR_SUCCESS; DWORD dwEnumIndex; char szClassName[100]; HDEVINFO hdi = NULL; SP_DEVINFO_DATA hDev = { 0 } ; SP_DEVINSTALL_PARAMS hInstParam = { 0 } ; SP_DRVINFO_DATA hDrv = { 0 } ; hDev.cbSize = sizeof(SP_DEVINFO_DATA); hInstParam.cbSize = sizeof(SP_DEVINSTALL_PARAMS); hDrv.cbSize = sizeof(SP_DRVINFO_DATA); try { //检测设备是否已经安装 if(FindExistingDevice(lpGUID , lpszHardwareID , lpszInstanceID)) return ERROR_SUCCESS; if(!SetupDiClassNameFromGuid(lpGUID , szClassName , sizeof(szClassName) ,NULL)) throw STException(\"SetupDiCreateDeviceInfoList\"); if((hdi = SetupDiCreateDeviceInfoList(lpGUID , NULL))==NULL) throw STException(\"SetupDiCreateDeviceInfoList\"); //创建新设备信息。如果设备已经存在,有异常产生 if(!SetupDiCreateDeviceInfo(hdi , szClassName, lpGUID , lpszDescription, NULL , DICD_GENERATE_ID , &hDev)) throw STException(\"SetupDiCreateDeviceInfo\"); if(!SetupDiGetDeviceInstanceId(hdi , &hDev ,lpszInstanceID , MAX_PATH , NULL)) throw STException(\"SetupDiGetDeviceInstanceId\"); //获得设备安装参数 if(!SetupDiGetDeviceInstallParams(hdi , &hDev , &hInstParam)) throw STException(\"SetupDiGetDeviceInstallParams\"); //修改参数 if(lpszInfName!=NULL && strlen(lpszInfName)!=0) { DWORD fattr = GetFileAttributes(lpszInfName); if(fattr == -1) throw STException(\"GetFileAttributes\"); if(!(fattr & FILE_ATTRIBUTE_DIRECTORY)) hInstParam.Flags = hInstParam.Flags | DI_ENUMSINGLEINF; strcpy(hInstParam.DriverPath , lpszInfName); } hInstParam.FlagsEx = hInstParam.FlagsEx | DI_FLAGSEX_ALLOWEXCLUDEDDRVS; //设置设备安装参数 if(!SetupDiSetDeviceInstallParams(hdi, &hDev , &hInstParam)) throw STException(\"SetupDiSetDeviceInstallParams\"); //获得设备驱动信息列表 if(!SetupDiBuildDriverInfoList(hdi, &hDev , SPDIT_CLASSDRIVER)) throw STException(\"SetupDiBuildDriverInfoList\"); //获得设备的驱动程序 dwEnumIndex = 0; while(SetupDiEnumDriverInfo(hdi , &hDev , SPDIT_CLASSDRIVER , dwEnumIndex++ , &hDrv)) { if(stricmp(hDrv.Description , lpszDescription)==0) break; } //选定这个驱动程序 if(!SetupDiSetSelectedDriver(hdi , &hDev , &hDrv)) throw STException(\"SetupDiSetSelectedDriver\"); //注册设备 if(!SetupDiRegisterDeviceInfo(hdi , &hDev , 0 , NULL , NULL , NULL)) throw STException(\"SetupDiRegisterDeviceInfo\"); //注册Co-Installer if(!SetupDiRegisterCoDeviceInstallers(hdi , &hDev)) throw STException(\"SetupDiRegisterCoDeviceInstallers\"); //安装设备 if(!SetupDiCallClassInstaller(DIF_INSTALLDEVICE , hdi , &hDev)) throw STException(\"SetupDiInstallDevice\"); if(pfNeedReboot!=NULL) { if(SetupDiGetDeviceInstallParams(hdi , &hDev , &hInstParam)) *pfNeedReboot = ((hInstParam.Flags & DI_NEEDRESTART) || (hInstParam.Flags & DI_NEEDREBOOT)); else pfNeedReboot = FALSE; } } catch(STException &e) { ret = GetLastError(); //反注册设备 if(hDev.DevInst != 0) SetupDiRemoveDevice(hdi , &hDev); LogMessage(\"%s failed , err = %x.\\n\" , e.getMessage() , ret); } if(hdi!=NULL) SetupDiDestroyDeviceInfoList(hdi); return ret; } int InstallSuntekModem(LPCTSTR lpszComName) { int ret = ERROR_SUCCESS; char szInfPath[ MAX_PATH ] = { 0 }; char szInstanceID[ MAX_PATH ] = { 0 }; char szHardwareID[ MAX_PATH ] = { 0 }; char szDeviceDesc[ MAX_PATH ] = { 0 }; char buffer[1024]; HKEY hKey = NULL; HINF hInf = NULL; INFCONTEXT hContext; DWORD cbData; GetWindowsDirectory(szInfPath , MAX_PATH); strcat(szInfPath , \"\\\\inf\\\\xxxx.inf\"); hInf = SetupOpenInfFile(szInfPath , NULL , INF_STYLE_WIN4 , NULL); if(hInf != INVALID_HANDLE_VALUE) { if(SetupFindFirstLine(hInf , \"Manufacturer\" , NULL , &hContext)) { if(SetupGetStringField(&hContext , 1 , buffer , sizeof(buffer) , NULL)) { if(SetupFindFirstLine(hInf , buffer , NULL , &hContext)) { //获得设备描述 SetupGetStringField(&hContext , 0 , szDeviceDesc , sizeof(szDeviceDesc) , NULL); //获得HardwareID SetupGetStringField(&hContext , 2, szHardwareID , sizeof(szHardwareID) , NULL); } } } SetupCloseInfFile(hInf); if(RegCreateKey(HKEY_CURRENT_USER , \"Environment\" , &hKey)==ERROR_SUCCESS) RegSetValueEx(hKey , \"MDMCOM\" , 0 , REG_SZ , (LPBYTE)lpszComName , strlen(lpszComName)); if((ret = InstallRootEnumeratedDriver((LPGUID)&GUID_MODEM , szHardwareID , szDeviceDesc, szInfPath , szInstanceID , NULL))!=ERROR_SUCCESS) return ret; if(hKey!=NULL) { RegDeleteValue(hKey , \"MDMCOM\"); RegCloseKey(hKey); } } return ret; } 上面的代码结合我先前贴出的CoInstaller可以在2k/xp下完整地解决安装Modem 的问题。在98下有两个问题,一个是对某些设备的驱动在运行到SetupDiCreateDeviceInfo时会弹出新硬件安装的wizard,十分讨厌。不过好像Modem没有。解决办法也不难,对于会弹出wizard的设备,可以通过直接写注册表完成创建过程(也幸好98下可以直接修改enum)。 第二是98下不支持Co-Installer,实在不知道怎么及时地设置Attach键值,以致装完后拨号网络认不出Modem, 需要重启后才认。这是我目前没办法解决的。望哪位大虾可以指点迷津。 [编辑 - 8/22/03 by gzytom] |
|
11楼#
发布于:2003-08-25 18:27
十分感谢你的回信。
GUID_MODEM是指Modem的Guid还是你的MODEM的GUID呢? 另外安装的这个MODEM是内MODEM还是虚拟MODEM |
|
12楼#
发布于:2003-08-25 20:40
十分感谢你的回信。 Modem得GUID。虚拟Modem。 |
|
13楼#
发布于:2003-08-26 09:05
/*
Copyright (c) Microsoft Corporation. All rights reserved. Created By : Rohit Raina Creation Date : May 27, 2001 */ #include <stdio.h> #include <tchar.h> #include <windows.h> #include <newdev.h> #include <devguid.h> #include <setupapi.h> #include <cfgmgr32.h> #include <windef.h> #include <stdlib.h> #include <ras.h> #define MAX_CLASS_NAME_LEN 32 #define MAX__DESC 256 TCHAR chComPort[10]; TCHAR chFriendlyName[256]; void DisplayError(TCHAR * ErrorName) { DWORD Err = GetLastError(); LPVOID lpMessageBuffer = NULL; if (FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, Err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMessageBuffer, 0, NULL )) _tprintf(_T(\"%s FAILURE: %s\\n\"),ErrorName,(TCHAR *)lpMessageBuffer); else _tprintf(_T(\"%s FAILURE: (0x%08x)\\n\"),ErrorName,Err); if (lpMessageBuffer) LocalFree( lpMessageBuffer ); // Free system buffer SetLastError(Err); return; } BOOL GetFriendlyName(LPTSTR HardwareId) { HDEVINFO DeviceInfoSet; SP_DEVINFO_DATA DeviceInfoData; DWORD i,err; BOOL Found; // // Create a Device Information Set with all present devices. // DeviceInfoSet = SetupDiGetClassDevs(NULL, // All Classes 0, 0, DIGCF_ALLCLASSES | DIGCF_PRESENT ); // All devices present on system if (DeviceInfoSet == INVALID_HANDLE_VALUE) { DisplayError(_T(\"GetClassDevs(All Present Devices)\")) ; return FALSE; } _tprintf(_T(\"\\n\\nSearch for Device ID: [%s]\\n\\n\"),HardwareId); // // Enumerate through all Devices. // Found = FALSE; i = err = 0; DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); //for (i=0;SetupDiEnumDeviceInfo(DeviceInfoSet,i,&DeviceInfoData);i++) while ( !Found && SetupDiEnumDeviceInfo(DeviceInfoSet, i++, &DeviceInfoData)) { DWORD DataT; LPTSTR p,buffer = NULL; DWORD buffersize = 1024; // // We won\'t know the size of the HardwareID buffer until we call // this function. So call it with a null to begin with, and then // use the required buffer size to Alloc the nessicary space. // Keep calling we have success or an unknown failure. // while (!SetupDiGetDeviceRegistryProperty( DeviceInfoSet, &DeviceInfoData, SPDRP_HARDWAREID, &DataT, (PBYTE)buffer, 1024, &buffersize)) { if (GetLastError() == ERROR_INVALID_DATA) { // // May be a Legacy Device with no HardwareID. Continue. // break; } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { // // We need to change the buffer size. // if (buffer) LocalFree(buffer); buffer = (char *)LocalAlloc(LPTR,buffersize); } else { // // Unknown Failure. // DisplayError(_T(\"GetDeviceRegistryProperty\")); err = 1; break; } } if (GetLastError() == ERROR_INVALID_DATA) continue; if( err) break; // // Compare each entry in the buffer multi-sz list with our HardwareID. // for (p=buffer;*p&&(p<&buffer[buffersize]);p+=lstrlen(p)+sizeof(TCHAR)) { _tprintf(_T(\"Comparing device ID: [%s]\\n\"),p); if (!_tcscmp(HardwareId,p)) { _tprintf(_T(\"Found! [%s]\\n\"),p); Found = TRUE; break; } } if (buffer) LocalFree(buffer); //if (Found) break; } if(Found) { DWORD dwData, dwBufferSize; if(!SetupDiGetDeviceRegistryProperty( DeviceInfoSet, &DeviceInfoData, SPDRP_FRIENDLYNAME, &dwData, (PBYTE)chFriendlyName, 256, &dwBufferSize)) return FALSE; } if (GetLastError() != NO_ERROR) { DisplayError(_T(\"EnumDeviceInfo\")); } // // Cleanup. // err = GetLastError(); SetupDiDestroyDeviceInfoList(DeviceInfoSet); SetLastError(err); return err == NO_ERROR; } BOOL WriteToRegistry(LPTSTR FrendlyName) { TCHAR chBirdFriendlyNameReg[] = \"Bird_AD3C0BDD-F9A9-488b-AEA2-5CA08CF506B0_Class\\\\BirdModem\"; HKEY hBirdKey; //TCHAR szFriendlyNam[] = \"BirdModem\"; //DWORD dwType, dwSize; // TCHAR szReturn[256]; LONG lReturn = RegOpenKeyEx(HKEY_CLASSES_ROOT, chBirdFriendlyNameReg, 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hBirdKey); if(lReturn != ERROR_SUCCESS) { lReturn = RegCreateKey(HKEY_CLASSES_ROOT, chBirdFriendlyNameReg, &hBirdKey); if(lReturn != ERROR_SUCCESS) return FALSE; lReturn = RegSetValueEx(hBirdKey, (LPCTSTR)\"Modem FriendlyName\", 0, REG_SZ, (const byte *)chFriendlyName, 256); if(lReturn != ERROR_SUCCESS) return FALSE; } RegCloseKey(hBirdKey); //lReturn = RegOpenKey(hBirdKey, ) return TRUE; } BOOL GetAvailablePort() { HKEY hKeyClass; TCHAR strKey[] = \"HARDWARE\\\\DEVICEMAP\\\\SERIALCOMM\"; TCHAR szPortNum[10]; TCHAR szReturn[10]; DWORD dwSize; DWORD dwType; TCHAR strSubKey[256]; LONG lReturn = RegOpenKey(HKEY_LOCAL_MACHINE, strKey, &hKeyClass); if(lReturn != ERROR_SUCCESS) return FALSE; for(int i = 0; i < 5; i++) { //strcpy(strSubKey, strKey); _itoa(i, szPortNum, 10); strcpy(strSubKey, \"\\\\Device\\\\Serial\"); strcat(strSubKey, szPortNum); lReturn = RegQueryValueEx(hKeyClass, strSubKey, NULL, &dwType, (BYTE*)szReturn, &dwSize); if(lReturn != ERROR_SUCCESS) break; else { if(strcmp(szReturn, \"COM1\") == 0 || strcmp(szReturn, \"COM2\") == 0) continue; else strcpy(chComPort, szReturn); } } RegCloseKey(hKeyClass); return TRUE; } BOOL PortExists(TCHAR* szPortName) /*++ Routine Description: This routine checks if the port name supplied is a valid one or not Arguments: szPortName - Supplies a string containing a port name (like COM1, COM2) Return Value: The function returns TRUE if it finds a match for port name, otherwise it returns a FALSE. --*/ { TCHAR szDevDesc[MAX__DESC]; BOOL match = FALSE; // GUID const CLASS_GUID = GUID_DEVCLASS_PORTS; GUID const CLASS_GUID = {0x4d36e978L, 0xe325, 0x11ce, {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}}; HDEVINFO hDevInfo; hDevInfo = SetupDiGetClassDevs((LPGUID)&CLASS_GUID, NULL, NULL, DIGCF_PRESENT); if ( INVALID_HANDLE_VALUE != hDevInfo) { SP_DEVINFO_DATA devInfoElem; int index = 0; devInfoElem.cbSize = sizeof(SP_DEVINFO_DATA); while ( SetupDiEnumDeviceInfo(hDevInfo, index++, &devInfoElem)) { HKEY hKeyDev = SetupDiOpenDevRegKey(hDevInfo, &devInfoElem, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); if (INVALID_HANDLE_VALUE != hKeyDev) { WORD length = sizeof(szDevDesc); if(ERROR_SUCCESS == RegQueryValueEx(hKeyDev, _T((const char *)\"PortName\"), NULL, NULL, (unsigned char *)szDevDesc, (LPDWORD)&length) ) { RegCloseKey(hKeyDev); printf(\"\\t\\tComparing : %s\\twith\\t%s\\n\", szPortName, szDevDesc); if (! _tcsicmp(szPortName, szDevDesc)) { match = TRUE; break; } } } } // while SetupDiDestroyDeviceInfoList(hDevInfo); } return match; } BOOL RegisterModem( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdevData, IN LPCTSTR pszPort) /*++ Routine Description: This routine registers a modem device and writes \"AttachedTo\" string to registry -- this value represents the Port to which Modem is attached. Arguments: hdi -- Device Info Set -- containing the modem Device Info element. pdevData -- Pointer the the modem device information element. szPortName -- Supplies a string containing port name the modem is to be attached to (like COM1, COM2). Return Value: The function returns TRUE if it was able to register the modem and write the \"AttachedTo\" string to registry, otherwise it returns a FALSE. Note : Once the device is registered using SetupDiRegisterDeviceInfo(...), we need to remove it explicitly in case of an error here after -- may be call SetupDiCallClassInstaller(...) with a DIF_REMOVE function. --*/ { BOOL bRet; SP_DRVINFO_DATA drvData; DWORD nErr = NO_ERROR; DWORD dwRet; TCHAR const c_szAttachedTo[] = _T(\"AttachedTo\"); HKEY hKeyDev; bRet = FALSE; if( !SetupDiRegisterDeviceInfo(hdi, pdevData, 0, NULL, NULL, NULL) ) { DisplayError(\"Register Device 1\\n\"); return bRet; } hKeyDev = SetupDiOpenDevRegKey(hdi, pdevData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS); //// This call fails.... if( (INVALID_HANDLE_VALUE == hKeyDev) && ( ERROR_KEY_DOES_NOT_EXIST == GetLastError()) ) { hKeyDev = SetupDiCreateDevRegKey(hdi, pdevData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL); if( INVALID_HANDLE_VALUE == hKeyDev ) { DisplayError(_T(\"SetupDi Open+Create DevRegKey failed: \")); return FALSE; } } else { DisplayError(_T(\"Can not open DriverKey: \")); return FALSE; } if (ERROR_SUCCESS != (dwRet = RegSetValueEx (hKeyDev, c_szAttachedTo, 0, REG_SZ, (PBYTE)pszPort, (lstrlen(pszPort)+1)*sizeof(TCHAR)))) { DisplayError(_T(\"RegSetValueEx :\")); SetLastError (dwRet); bRet = FALSE; } RegCloseKey (hKeyDev); /* if(!SetupDiBuildDriverInfoList(hdi, pdevData, SPDIT_CLASSDRIVER)) return FALSE; //获得设备的驱动程序 DWORD dwEnumIndex = 0; while(SetupDiEnumDriverInfo(hdi , pdevData , SPDIT_CLASSDRIVER , dwEnumIndex++ , &drvData)) { if(stricmp(drvData.Description , \"标准 33600 bps 调制解调器\")==0) break; } //选定这个驱动程序 if(!SetupDiSetSelectedDriver(hdi , pdevData , &drvData)) return false; */ if( !SetupDiRegisterDeviceInfo(hdi, pdevData, 0, NULL, NULL, NULL) ) { DisplayError(_T(\"Register Device 2\")); return FALSE; } if ( !SetupDiGetSelectedDriver(hdi, pdevData, &drvData)) { DisplayError(_T(\"SetupDiGetSelectedDriver Failed: \")); } return TRUE; } BOOL FindExistingDevice(IN LPTSTR HardwareId) /*++ Routine Description: This routine finds an existing devnode if present. Arguments: HardwareIdList - Supplies a string containing a hardware ID to be associated with the device. Return Value: The function returns TRUE if it is successful. Otherwise it returns FALSE and the logged error can be retrieved with a call to GetLastError. The most common error will be ERROR_NO_MORE_ITEMS, which means the function could not find a devnode with the HardwareID. --*/ { HDEVINFO DeviceInfoSet; SP_DEVINFO_DATA DeviceInfoData; DWORD i,err; BOOL Found; // // Create a Device Information Set with all present devices. // DeviceInfoSet = SetupDiGetClassDevs(NULL, // All Classes 0, 0, DIGCF_ALLCLASSES | DIGCF_PRESENT ); // All devices present on system if (DeviceInfoSet == INVALID_HANDLE_VALUE) { DisplayError(_T(\"GetClassDevs(All Present Devices)\")) ; return FALSE; } _tprintf(_T(\"\\n\\nSearch for Device ID: [%s]\\n\\n\"),HardwareId); // // Enumerate through all Devices. // Found = FALSE; i = err = 0; DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); //for (i=0;SetupDiEnumDeviceInfo(DeviceInfoSet,i,&DeviceInfoData);i++) while ( !Found && SetupDiEnumDeviceInfo(DeviceInfoSet, i++, &DeviceInfoData)) { DWORD DataT; LPTSTR p,buffer = NULL; DWORD buffersize = 1024; // // We won\'t know the size of the HardwareID buffer until we call // this function. So call it with a null to begin with, and then // use the required buffer size to Alloc the nessicary space. // Keep calling we have success or an unknown failure. // while (!SetupDiGetDeviceRegistryProperty( DeviceInfoSet, &DeviceInfoData, SPDRP_HARDWAREID, &DataT, (PBYTE)buffer, 1024, &buffersize)) { if (GetLastError() == ERROR_INVALID_DATA) { // // May be a Legacy Device with no HardwareID. Continue. // break; } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { // // We need to change the buffer size. // if (buffer) LocalFree(buffer); buffer = (char *)LocalAlloc(LPTR,buffersize); } else { // // Unknown Failure. // DisplayError(_T(\"GetDeviceRegistryProperty\")); err = 1; break; } } if (GetLastError() == ERROR_INVALID_DATA) continue; if( err) break; // // Compare each entry in the buffer multi-sz list with our HardwareID. // for (p=buffer;*p&&(p<&buffer[buffersize]);p+=lstrlen(p)+sizeof(TCHAR)) { _tprintf(_T(\"Comparing device ID: [%s]\\n\"),p); if (!_tcscmp(HardwareId,p)) { _tprintf(_T(\"Found! [%s]\\n\"),p); Found = TRUE; break; } } if (buffer) LocalFree(buffer); //if (Found) break; } if (GetLastError() != NO_ERROR) { DisplayError(_T(\"EnumDeviceInfo\")); } // // Cleanup. // err = GetLastError(); SetupDiDestroyDeviceInfoList(DeviceInfoSet); SetLastError(err); return err == NO_ERROR; } BOOL InstallRootEnumeratedDriver(IN LPTSTR HardwareId, IN LPTSTR INFFile, IN LPTSTR MdmPort, OUT PBOOL RebootRequired OPTIONAL ) /*++ Routine Description: This routine creates and installs a new root-enumerated devnode. Arguments: HardwareIdList - Supplies a multi-sz list containing one or more hardware IDs to be associated with the device. These are necessary in order to match up with an INF driver node when we go to do the device installation. InfFile - Supplies the full path to the INF File to be used when installing this device. RebootRequired - Optionally, supplies the address of a boolean that is set, upon successful return, to indicate whether or not a reboot is required to bring the newly-installed device on-line. Return Value: The function returns TRUE if it is successful. Otherwise it returns FALSE and the logged error can be retrieved with a call to GetLastError. --*/ { HDEVINFO DeviceInfoSet = 0; SP_DEVINFO_DATA DeviceInfoData; GUID ClassGUID; TCHAR ClassName[MAX_CLASS_NAME_LEN]; DWORD err; // HKEY hKeyDev; BOOL Remove = FALSE; // // Use the INF File to extract the Class GUID. // if (!SetupDiGetINFClass(INFFile,&ClassGUID,ClassName,sizeof(ClassName),0)) { DisplayError(_T(\"GetINFClass\")); return FALSE; } // // Create the container for the to-be-created Device Information Element. // DeviceInfoSet = SetupDiCreateDeviceInfoList(&ClassGUID,0); if(DeviceInfoSet == INVALID_HANDLE_VALUE) { DisplayError(_T(\"CreateDeviceInfoList\")); return FALSE; } do { // // 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)) { DisplayError(_T(\"CreateDeviceInfo\")); break; } // // Add the HardwareID to the Device\'s HardwareID property. // if(!SetupDiSetDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, SPDRP_HARDWAREID, (LPBYTE)HardwareId, (lstrlen(HardwareId)+1+1)*sizeof(TCHAR))) { DisplayError(_T(\"SetDeviceRegistryProperty\")); break; } if ( !RegisterModem(DeviceInfoSet, &DeviceInfoData, MdmPort) ) { Remove = TRUE; break; } // // Install the Driver. // if (!UpdateDriverForPlugAndPlayDevices(0, HardwareId, INFFile, INSTALLFLAG_FORCE, RebootRequired)) { DisplayError(_T(\"UpdateDriverForPlugAndPlayDevices\")); Remove = TRUE; break; } } while (FALSE); if(Remove) { //Delete Device Instance that was registered using SetupDiRegisterDeviceInfo // May through an error if Device not registered -- who cares?? SetupDiCallClassInstaller( DIF_REMOVE, DeviceInfoSet, &DeviceInfoData); } // // Cleanup. // err = GetLastError(); SetupDiDestroyDeviceInfoList(DeviceInfoSet); SetLastError(err); return (err == NO_ERROR && !Remove); } void addRasDail() { //创建电话簿 char * lpszEntry = \"DOEASY\"; char * lpszDeviceType = \"modem\"; char * lpszPhoneNumber = \"*99***1#\"; char * lpszPhoneBook = NULL; char lpszDeviceName[MAX__DESC]; //find BIRD_USB Registy alias if( GetFriendlyName( _TEXT(\"mdmgen336\")) ){ strcpy( lpszDeviceName, chFriendlyName ); } if(RasValidateEntryName(lpszPhoneBook, lpszEntry) != ERROR_ALREADY_EXISTS)//检测拨号网络是否存在 { RASENTRY rasEntry; ZeroMemory(&rasEntry, sizeof(rasEntry)); rasEntry.dwSize = sizeof(rasEntry); strcpy(rasEntry.szLocalPhoneNumber,lpszPhoneNumber); rasEntry.dwfNetProtocols = RASNP_NetBEUI; rasEntry.dwFramingProtocol = RASNP_Ip;//设置为TcpIP协议 strcpy(rasEntry.szDeviceType, lpszDeviceType); strcpy(rasEntry.szDeviceName, lpszDeviceName); DWORD dwRV = RasSetEntryProperties(lpszPhoneBook, lpszEntry, &rasEntry,sizeof(rasEntry), NULL, 0); } // return \"DOEASY\"; } int __cdecl _tmain(int argc, _TCHAR **argv, _TCHAR **envp) /*++ Routine Discription: Entry point to install.exe. Parse the command line, call subroutines. Arguments: Standard console \'c\' application arguments. argv[1] - Full path of INF file. argv[2] - PnP HardwareID of device. Return Value: Standard Console ERRORLEVEL values: 0 - Install Successfull, no reboot required. 1 - Install Successfull, reboot required. 2 - Install Failure. --*/ { WIN32_FIND_DATA FindFileData; BOOL RebootRequired = 0; // Must be cleared. // // Verify the Arguments. // char szInfPath[256]; GetWindowsDirectory(szInfPath , MAX_PATH); strcat(szInfPath , \"\\\\inf\\\\mdmgen.inf\"); GetAvailablePort(); argv[1] = new char[256]; argv[2] = new char[256]; strcpy(argv[1] , szInfPath); strcpy(argv[2], chComPort); argv[3] = \"mdmgen336\"; /* if (argc != 4) { _tprintf(\"usage: %s <INF_File> COMP <Hardware_ID>\\n\", argv[0]); return 2; // Install Failure } */ if(!PortExists(argv[2])) { _tprintf(_T(\"\\nInvalid Port... exiting\")); return 2; // Invalid Port supplied } if (FindFirstFile(argv[1],&FindFileData)==INVALID_HANDLE_VALUE) { _tprintf(_T(\" File not found.\\n\")); _tprintf(_T(\"usage: install <INF_File> COMP <Hardware_ID>\\n\")); return 2; // Install Failure } // // if this device allready exists // if (FindExistingDevice(argv[3])) { // // No Need to Create a Device Node, just update the current devnode. // if (!UpdateDriverForPlugAndPlayDevices(0, // No Window Handle argv[3], // Hardware ID argv[1], // FileName INSTALLFLAG_FORCE, &RebootRequired)) { DisplayError(_T(\"UpdateDriverForPlugAndPlayDevices\")); return 2; // Install Failure } } else { if (GetLastError()!= ERROR_NO_MORE_ITEMS) { // // An unknown failure from FindExistingDevice() // return 2; // Install Failure } // // Driver Does not exist, Create and call the API. // HardwareID must be a multi-sz string, which argv[2] is. // if (!InstallRootEnumeratedDriver(argv[3], // HardwareID argv[1], // FileName argv[2], // Modem Port &RebootRequired)) { if(GetFriendlyName(argv[3])) { WriteToRegistry(chFriendlyName); addRasDail(); } return 2; // Install Failure } } _tprintf(_T(\"Driver Installed successfully.\\n\")); if (RebootRequired) { _tprintf(_T(\"(Reboot Required)\\n\")); return 1; // Install Success, reboot required. } return 0; // Install Success, no reboot required. } 以上代码是安装一个标准的336Modem,运行的前提是必须有一个COM存在,可以在xp和2k下运行! |
|
|
14楼#
发布于:2003-08-26 10:11
to:gzytom,EricGaoxp
谢谢俩位的慷慨解囊,不知你们是用在什么MODEM上的?我是用在CDMA MODEM上的。 gzytom你的代码我试过,我将GUIDMODEM代入的是MODEM的ClassGUID {4D36E96D-E325-11CE-BFC1-08002BE10318}。但是在运行到SetupDiClassNameFromGuid函数时报了一个错误0xe0000206。不知为什么,另外不知你coinstall这方面是在那学的,这方面的资料很少,大部分是E文的。 EricGaoxp你的代码我试一试再说。 |
|
15楼#
发布于:2003-08-26 12:29
to:gzytom,EricGaoxp 我的也是CDMA Modem啊,//hand,呵呵。0xe0000206是指不合法的 类。怎么你的机子连Modem的类都没有。自己用写注册表方法手工添加应该也行的。不过我想不会的,是不是你的DEFINE_GUID写错了?coinstall不是很复杂的东西,msdn就有,不过e文是肯定的了。EricGaoxp的代码就可以不使用coinstaller了,一直没考虑过SetupDiCreateDevRegKey这个函数,原来有这个妙用。 |
|
16楼#
发布于:2003-08-26 12:55
原来都是用在CDMA MODEM上的呀!有缘有缘
MODEM的ClassGuid不是4D36E96D-E325-11CE-BFC1-08002BE10318吗 我用DEFINE_GUID(GUID_MODEM,0x4D36E96D,0x0e325,0x11ce,0xbfc1,0x08,0x00,0x2b,0xe1,0x03,0x18); 写的有什么错误吗? 另外你不知你用过DDK下的那个例子程序(通过.inf安装驱动程序)在调用UpdateDriverForPlugAndPlayDevices时在WIN2000下返回0xe0000203,但在XP返回0,这个ERROR又是什么意思? gzytom 其实在2000下可以设置Enum权限,然后修改它的键值(98可直接修怍),不用通过setupapi |
|
17楼#
发布于:2003-08-26 14:27
原来都是用在CDMA MODEM上的呀!有缘有缘 你写错了吧,应该是DEFINE_GUID (GUID_MODEM , 0x4D36E96D, 0xE325, 0x11CE,0xBF,0xC1,0x08,0x00,0x2B,0xE1,0x03,0x18); 0xe0000203是没有选择驱动,是不是你的INF不正确。0就是成功拉。 是不是用RegSetKeySecurity?我没用过这个函数。 |
|
18楼#
发布于:2003-08-26 14:50
//注册表权限调整使EvenyOne可写可读
//AllowRegKeyForEveryone (HKEY_LOCAL_MACHINE,\'system\\currentcontrolset\\enum\'); function AllowRegKeyForEveryone(Key: HKEY; Path: string): Boolean; var WidePath: PWideChar; Len: Integer; begin case Key of HKEY_LOCAL_MACHINE: Path := \'MACHINE\\\' + Path; HKEY_CURRENT_USER: Path := \'CURRENT_USER\\\' + Path; HKEY_CLASSES_ROOT: Path := \'CLASSES_ROOT\\\' + Path; HKEY_USERS: Path := \'USERS\\\' + Path; end; Len := (Length(Path)+1)*SizeOf(WideChar); GetMem(WidePath,Len); MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, PChar(Path), -1, WidePath, Len); Result := SetNamedSecurityInfoW(PChar(WidePath),SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, nil, nil, nil, nil) = ERROR_SUCCESS; FreeMem(WidePath); end; |
|
19楼#
发布于:2003-08-30 11:41
看了各位大侠的帖子,感触颇深。我现在在做GPRS MODEM,用了一根USB数据线连接手机,在PC机上虚拟了一个串口,现在软件编写完成,可是MODEM的添加却仍然需要用户手动添加,非常麻烦。我们自己做了一个MODEM的inf文件,不知道怎么在setup过程中就把MODEM添加到USB数据线虚拟的那个串口上去。
|
|
|
上一页
下一页