Source file: /~heha/hs/maus32.zip/PnP/cycleport.cpp

/* 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: ASCII (7 bit)2