/* DLL helper for COM/LPT port enabling/disabling (here, for VB.NET usage)
* Intended for XENON AIL software to cope with frequent communication error no. 4 to OWIS PS10 stepper motor controller
* h#s, TU Chemnitz, project PT-PIESA, 120210
*/
#include <windows.h>
#include <setupapi.h>
#include <cfgmgr32.h>
#include <devguid.h>
#define elemof(x) (sizeof(x)/sizeof(*(x)))
#define nobreak
// action code:
// 0: query port activation state, return TRUE when enabled, FALSE otherwise
// 1: enable (DICS_ENABLE)
// 2: disable (DICS_DISABLE)
// 3: flip state
// return value:
// 0 = failure (configmanager error, or port not found)
// 1 = enabled
// 2 = disabled
EXTERN_C int enableportW(PWSTR portname, int action) {
int ret=0;
HDEVINFO Devs=SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS,NULL,0,DIGCF_PRESENT);
SP_DEVINFO_DATA devInfo;
devInfo.cbSize=sizeof(devInfo);
for (int j=0; SetupDiEnumDeviceInfo(Devs,j,&devInfo); j++) {
HKEY hKey;
TCHAR val[16];
DWORD valsize=sizeof(val);
if (!CM_Open_DevNode_Key(devInfo.DevInst,KEY_QUERY_VALUE,0,RegDisposition_OpenExisting,&hKey,CM_REGISTRY_HARDWARE)) {
if (!RegQueryValueEx(hKey,L"PortName",NULL,NULL,(LPBYTE)val,&valsize)
&& !lstrcmpi(val,portname)) {
DWORD status,problem;
switch (action) {
case 0:
case 3: {
if (CM_Get_DevNode_Status(&status,&problem,devInfo.DevInst,0)) break;
if (status&DN_HAS_PROBLEM && problem!=CM_PROB_DISABLED) break;
if (action) action = status&DN_HAS_PROBLEM ? DICS_ENABLE : DICS_DISABLE;
else{
ret=status&DN_HAS_PROBLEM ? DICS_DISABLE : DICS_ENABLE;
break;
}
}nobreak;
default: {
SP_PROPCHANGE_PARAMS pcp;
pcp.ClassInstallHeader.cbSize=sizeof(pcp.ClassInstallHeader);
pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
pcp.StateChange = action;
pcp.Scope = DICS_FLAG_CONFIGSPECIFIC;
pcp.HwProfile = 0;
if (SetupDiSetClassInstallParams(Devs,&devInfo,&pcp.ClassInstallHeader,sizeof(pcp)) &&
SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,Devs,&devInfo)) {
ret=action;
}
}
}
}
RegCloseKey(hKey);
}
}
SetupDiDestroyDeviceInfoList(Devs);
return ret;
}
EXTERN_C int enableportA(PCSTR s,int action) {
WCHAR s2[16];
MultiByteToWideChar(CP_ACP,0,s,-1,s2,elemof(s2));
return enableportW(s2,action);
}
// switch given port off, then on, silently
// For calling by rundll32.dll
EXTERN_C void cycleW(HWND hwnd, HINSTANCE hinst, LPWSTR cmdline, int nCmdShow) {
enableportW(cmdline,DICS_DISABLE) && enableportW(cmdline,DICS_ENABLE);
}
EXTERN_C int _DllMainCRTStartup(HMODULE hLib,DWORD dwReason,DWORD) {
switch (dwReason) {
case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hLib);
}
return TRUE;
}
Detected encoding: UTF-8 | 0
|