OpenCBM
parport.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version
5  * 2 of the License, or (at your option) any later version.
6  *
7  * Copyright 2004, 2008, 2012 Spiro Trikaliotis
8  *
9  */
10 
20 #include <windows.h>
21 #include <stdio.h>
22 
23 // #include "instcbm.h"
24 #include "i_opencbm.h"
25 
26 #include <setupapi.h>
27 #include <cfgmgr32.h>
28 
29 #include <initguid.h>
30 #include <ntddpar.h>
31 
33 #define DBG_USERMODE
34 
36 #define DBG_PROGNAME "OPENCBM-XA1541.DLL"
37 
38 #include "debug.h"
39 
40 #include "libmisc.h"
41 
44 static void
45 output_error(void)
46 {
47  DWORD error = GetLastError();
48 
49  if (error)
50  {
51  DBG_ERROR((DBG_PREFIX "error: (0x%x) '%s'", error, cbmlibmisc_format_error_message(error)));
52  printf("error: (0x%x) '%s'\n", error, cbmlibmisc_format_error_message(error));
53  }
54 }
55 
60 typedef CMAPI CONFIGRET (*P_CM_Get_Device_ID_ExA)(
61  IN DEVINST dnDevInst, OUT PTCHAR Buffer, IN ULONG BufferLen,
62  IN ULONG ulFlags, IN HMACHINE hMachine);
63 
68 typedef WINSETUPAPI BOOL (*P_SetupDiGetDeviceInfoListDetailA)(
69  IN HDEVINFO DeviceInfoSet, OUT PSP_DEVINFO_LIST_DETAIL_DATA DeviceInfoSetDetailData);
70 
74 typedef
75 struct {
76 
79 
82 
85 
86 } SETUPAPI, *PSETUPAPI;
88 static VOID
89 FreeDynamicalAddresses(PSETUPAPI SetupApi)
90 {
91  FUNC_ENTER();
92 
93  DBG_ASSERT(SetupApi->HandleSetupApiDll != NULL);
94 
95  FreeLibrary(SetupApi->HandleSetupApiDll);
96 
97  DBGDO(memset(SetupApi, 0, sizeof(*SetupApi));)
98 
99  FUNC_LEAVE();
100 }
101 
103 #define GET_PROC_ADDRESS(_xxx) \
104  if (SetupApi && SetupApi->HandleSetupApiDll) \
105  { \
106  SetupApi->_xxx##_p = (P_##_xxx) GetProcAddress(SetupApi->HandleSetupApiDll, #_xxx); \
107  \
108  DBG_SUCCESS((DBG_PREFIX "p_CM_Get_Device_ID_Ex = %p", SetupApi->_xxx##_p)); \
109  \
110  if (SetupApi->_xxx##_p == NULL) \
111  { \
112  DBG_WARN((DBG_PREFIX "GetProcAddress(\"" #_xxx "\") FAILED!")); \
113  FreeDynamicalAddresses(SetupApi); \
114  } \
115  }
116 
117 static BOOLEAN
118 GetDynamicalAddresses(PSETUPAPI SetupApi)
119 {
120  FUNC_ENTER();
121 
122  DBG_ASSERT(SetupApi != NULL);
123  DBG_ASSERT(SetupApi->HandleSetupApiDll == NULL);
124  DBG_ASSERT(SetupApi->CM_Get_Device_ID_ExA_p == NULL);
125 
126  SetupApi->HandleSetupApiDll = LoadLibrary("SETUPAPI.DLL");
127 
128  DBG_SUCCESS((DBG_PREFIX "SetupApi->HandleSetupApiDll = %p",
129  SetupApi->HandleSetupApiDll));
130 
131  GET_PROC_ADDRESS(CM_Get_Device_ID_ExA);
132  GET_PROC_ADDRESS(SetupDiGetDeviceInfoListDetailA);
133 
134  FUNC_LEAVE_BOOLEAN(SetupApi->HandleSetupApiDll != NULL ? TRUE : FALSE);
135 }
136 
142 VOID
144 {
145  HDEVINFO hdevInfo;
146  SETUPAPI setupApi;
147 
148  FUNC_ENTER();
149 
150  DBGDO(memset(&setupApi, 0, sizeof(setupApi));)
151 
152  if (GetDynamicalAddresses(&setupApi))
153  {
154  DBG_ASSERT(setupApi.HandleSetupApiDll);
157 
158  // open all devices with a parallel port interface
159 
160  hdevInfo = SetupDiGetClassDevs(&GUID_PARALLEL_DEVICE, NULL, NULL,
161  DIGCF_DEVICEINTERFACE | DIGCF_PRESENT | DIGCF_PROFILE);
162 
163  if (hdevInfo != INVALID_HANDLE_VALUE)
164  {
165  SP_DEVINFO_DATA sdd;
166  unsigned i;
167 
168  // now, enumerate all parallel devices
169  for (i=0; ; i++)
170  {
171  char deviceId[MAX_DEVICE_ID_LEN];
172 
173  SP_DEVINFO_LIST_DETAIL_DATA sdld;
174 
175  sdld.cbSize = sizeof(sdld);
176 
177  if (!setupApi.SetupDiGetDeviceInfoListDetailA_p(hdevInfo, &sdld))
178  {
179  DBG_ERROR((DBG_PREFIX "SetupDiGetDeviceInfoListDetail FAILED!"));
180  printf("SetupDiGetDeviceInfoListDetail FAILED!\n");
181  }
182 
183 
184  sdd.cbSize = sizeof(sdd);
185 
186  if (SetupDiEnumDeviceInfo(hdevInfo, i, &sdd))
187  {
188  SP_DEVINSTALL_PARAMS devParams;
189  SP_PROPCHANGE_PARAMS spp;
190  HMACHINE machineHandle = { 0 };
191 
192  if (setupApi.CM_Get_Device_ID_ExA_p(sdd.DevInst, deviceId, MAX_DEVICE_ID_LEN,
193  0, machineHandle) != CR_SUCCESS)
194  {
195  deviceId[0] = 0;
196  }
197  DBG_SUCCESS((DBG_PREFIX "No. %u: Returned deviceId = '%s'", i, deviceId));
198 
199  spp.ClassInstallHeader.cbSize = sizeof(spp.ClassInstallHeader);
200  spp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
201  spp.StateChange = DICS_PROPCHANGE;
202  spp.Scope = DICS_FLAG_GLOBAL; // ignored
203  spp.HwProfile = 0;
204 
205  if (SetupDiSetClassInstallParams(hdevInfo, &sdd,
206  (PSP_CLASSINSTALL_HEADER) &spp, sizeof(spp)))
207  {
208  DBG_SUCCESS((DBG_PREFIX "SET CLASS INSTALL PARAMS WAS SUCCESSFULL!"));
209  }
210  else
211  {
212  DBG_ERROR((DBG_PREFIX "SET CLASS INSTALL PARAMS NOT SUCCESSFULL"));
213  printf("SET CLASS INSTALL PARAMS NOT SUCCESSFULL!\n");
214  output_error();
215  }
216 
217  if (SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hdevInfo, &sdd))
218  {
219  DBG_SUCCESS((DBG_PREFIX "CALL CLASS INSTALLER WAS SUCCESSFULL!"));
220  }
221  else
222  {
223  DBG_ERROR((DBG_PREFIX "CALL CLASS INSTALLER NOT SUCCESSFULL"));
224  printf("CALL CLASS INSTALLER NOT SUCCESSFULL!\n");
225  output_error();
226  }
227 
228  if (SetupDiGetDeviceInstallParams(hdevInfo, &sdd, &devParams))
229  {
230  if (devParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT))
231  {
232  DBG_ERROR((DBG_PREFIX "NEED REBOOT TO TAKE EFFECT!"));
233  printf("NEED REBOOT TO TAKE EFFECT!\n");
234  }
235  }
236  }
237  else
238  {
239  if (GetLastError() == ERROR_NO_MORE_ITEMS)
240  {
241  break;
242  }
243  }
244  }
245  }
246  else
247  {
248  DBG_ERROR((DBG_PREFIX "SetupDiGetClassDevs FAILED!"));
249  printf("SetupDiGetClassDevs FAILED!");
250  output_error();
251  }
252 
253  SetupDiDestroyDeviceInfoList(hdevInfo);
254 
255  FreeDynamicalAddresses(&setupApi);
256  }
257 
258  FUNC_LEAVE();
259 }
#define DBGDO(_xxx)
Definition: debug.h:409
Define makros for debugging purposes.
HMODULE HandleSetupApiDll
Definition: parport.c:78
VOID CbmParportRestart(VOID)
Restart the parallel port.
Definition: parport.c:143
P_CM_Get_Device_ID_ExA CM_Get_Device_ID_ExA_p
Definition: parport.c:81
#define FUNC_LEAVE_BOOLEAN(_xxx)
Definition: debug.h:356
#define FUNC_LEAVE()
Definition: debug.h:349
CMAPI CONFIGRET(* P_CM_Get_Device_ID_ExA)(IN DEVINST dnDevInst, OUT PTCHAR Buffer, IN ULONG BufferLen, IN ULONG ulFlags, IN HMACHINE hMachine)
Definition: parport.c:60
struct SETUPAPI * PSETUPAPI
#define DBG_ASSERT(_xxx)
Definition: debug.h:401
#define DBG_ERROR(_xxx)
Definition: debug.h:397
#define DBG_SUCCESS(_xxx)
Definition: debug.h:393
#define FUNC_ENTER()
Definition: debug.h:347
P_SetupDiGetDeviceInfoListDetailA SetupDiGetDeviceInfoListDetailA_p
Definition: parport.c:84
#define DBG_PREFIX
Definition: debug.h:320
#define GET_PROC_ADDRESS(_xxx)
Definition: parport.c:103
Internal API for opencbm installation.
Some functions for string handling.
char * cbmlibmisc_format_error_message(unsigned int ErrorNumber)
Format a returned error code into a string.
WINSETUPAPI BOOL(* P_SetupDiGetDeviceInfoListDetailA)(IN HDEVINFO DeviceInfoSet, OUT PSP_DEVINFO_LIST_DETAIL_DATA DeviceInfoSetDetailData)
Definition: parport.c:68