FreeBASIC  0.91.0
tester.bas
Go to the documentation of this file.
1 /'
2  Small tool to test the fbportio driver. You can
3 '/
4 
5 #include "windows.bi"#include "windows.bi"
6 #include "win/winioctl.bi"#include "win/winioctl.bi"
7 #include "../fbportio.h"#include "../fbportio.h"
8 
9 #define INFO(message) print __FUNCTION__ & "(): " & message
10 #define APIFAILED(func) print_winapi_error(__FUNCTION__, func)
11 
12 sub print_winapi_error(byval parent as zstring ptr, byval func as zstring ptr)
13  dim as DWORD e = GetLastError()
14  print *parent & "(): " & *func & " failed, GetLastError(): &h" & hex(e) & " / " & e
15 
16  dim as zstring ptr p = NULL
17  if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM, _
18  NULL, _
19  e, _
20  0, _
21  cptr(LPTSTR, @p), _
22  0, _
23  NULL)) then
24  print *p
25  LocalFree(p)
26  end if
27 
28  end(1)
29 end sub
30 
31 sub delete_service(byval manager as SC_HANDLE)
32  dim as SC_HANDLE service = OpenService(manager, "fbportio", SERVICE_ALL_ACCESS)
33  if (service = NULL) then
34  APIFAILED("OpenService()")
35  end if
36 
37  INFO("Marking the fbportio service for deletion...")
38  INFO("(This will fail if the service is already marked for deletion)")
39  INFO("(If the service is running, it will be deleted after it stops)")
40 
41  if (DeleteService(service) = 0) then
42  APIFAILED("DeleteService()")
43  end if
44 
45  CloseServiceHandle(service)
46 end sub
47 
48 sub stop_service(byval manager as SC_HANDLE)
49  dim as SC_HANDLE service = OpenService(manager, "fbportio", SERVICE_ALL_ACCESS)
50  if (service = NULL) then
51  APIFAILED("OpenService()")
52  end if
53 
54  INFO("Stopping the fbportio service...")
55 
56  dim as SERVICE_STATUS status
57  if (ControlService(service, SERVICE_CONTROL_STOP, @status) = 0) then
58  APIFAILED("ControlService(SERVICE_CONTROL_STOP)")
59  end if
60 
61  CloseServiceHandle(service)
62 end sub
63 
65  INFO("Copying fbportio.sys into the system's driver directory...")
66 
67  dim as zstring * (MAX_PATH+1) filename
68  dim as integer needed = GetSystemDirectory(@filename, MAX_PATH)
69  if ((needed = 0) or (needed > MAX_PATH)) then
70  APIFAILED("GetSystemDirectory()")
71  end if
72 
73  filename += "\Drivers\fbportio.sys"
74 
75  if (CopyFile("fbportio.sys", filename, FALSE) = 0) then
76  APIFAILED("CopyFile()")
77  end if
78 end sub
79 
80 sub create_service(byval manager as SC_HANDLE)
81  INFO("Creating fbportio service...")
82 
83  dim as SC_HANDLE service = _
84  CreateService(manager, _
85  "fbportio", _
86  "fbportio", _
87  SERVICE_ALL_ACCESS, _
88  SERVICE_KERNEL_DRIVER, _
89  SERVICE_DEMAND_START, _
90  SERVICE_ERROR_NORMAL, _
91  "system32\drivers\fbportio.sys", _
92  NULL, _
93  NULL, _
94  NULL, _
95  NULL, _
96  NULL)
97 
98  if (service = NULL) then
99  APIFAILED("CreateService()")
100  end if
101 
102  CloseServiceHandle(service)
103 end sub
104 
105 sub start_service(byval manager as SC_HANDLE)
106  dim as SC_HANDLE service = OpenService(manager, "fbportio", SERVICE_ALL_ACCESS)
107  if (service = NULL) then
108  APIFAILED("OpenService()")
109  end if
110 
111  INFO("Starting fbportio service...")
112 
113  if (StartService(service, 0, NULL) = 0) then
114  APIFAILED("StartService()")
115  end if
116 
117  CloseServiceHandle(service)
118 end sub
119 
120 sub access_driver _
121  ( _
122  byval h as HANDLE, _
123  byval code as DWORD, _
124  byval pin as any ptr, _
125  byval insize as uinteger, _
126  byval pout as any ptr, _
127  byval outsize as uinteger _
128  )
129 
130  INFO("Accessing driver...")
131 
132  dim as DWORD outwritten = 0
133  if (DeviceIoControl(h, code, pin, insize, pout, outsize, @outwritten, NULL) = 0) then
134  APIFAILED("DeviceIoControl()")
135  end if
136 end sub
137 
139  INFO("Initializing driver...")
140 
141  static as integer initialized = FALSE
142  if (initialized) then
143  return
144  end if
145 
146  INFO("Opening '\\.\fbportio'...")
147 
148  dim as HANDLE driver = _
149  CreateFile("\\.\fbportio", _
150  GENERIC_READ or GENERIC_WRITE, _
151  0, _
152  NULL, _
153  OPEN_EXISTING, _
154  FILE_ATTRIBUTE_NORMAL, _
155  NULL)
156  if (driver = INVALID_HANDLE_VALUE) then
157  APIFAILED("CreateFile()")
158  end if
159 
160  INFO("Asking driver for version number...")
161  dim as WORD version = 0
162  access_driver(driver, IOCTL_GET_VERSION, NULL, 0, @version, 2)
163  if (version <> FBPORTIO_VERSION) then
164  INFO("Driver version mismatch, aborting...")
165  CloseHandle(driver)
166  end(1)
167  end if
168 
169  INFO("Asking driver to grant our pid i/o ports access...")
170  dim as DWORD pid = GetCurrentProcessId()
171  access_driver(driver, IOCTL_GRANT_IOPM, @pid, 4, NULL, 0)
172 
173  CloseHandle(driver)
174 
175  '' Give up our timeslice to ensure process kernel state is updated
176  Sleep(1)
177  initialized = TRUE
178 end sub
179 
180 sub write_driver(byval port as short, byval dat as byte)
181  INFO("Writing...")
182  '' __asm__ volatile("outb %0, %1" : : "a"(dat), "d"(port));
183  asm
184  mov al, [dat]
185  mov dx, [port]
186  out dx, al
187  end asm
188 end sub
189 
190 sub read_driver(byval port as short, byval pdat as byte ptr)
191  INFO("Reading...")
192  dim as byte dat = 0
193 
194  '' __asm__ volatile("inb %1, %0" : "=a"(value) : "d"(port));
195  asm
196  mov dx, [port]
197  in al, dx
198  mov [dat], al
199  end asm
200 
201  if (pdat) then
202  *pdat = dat
203  end if
204 end sub
205 
206 
207  INFO("Opening service control manager...")
208  dim as SC_HANDLE manager = OpenSCManager(NULL, NULL, GENERIC_ALL)
209  if (manager = NULL) then
210  APIFAILED("OpenSCManager()")
211  INFO("Opening service control manager in read only mode...")
212  manager = OpenSCManager(NULL, NULL, GENERIC_READ)
213  if (manager = NULL) then
214  APIFAILED("OpenSCManager()")
215  end(1)
216  end if
217  end if
218 
219  dim as integer show_help = (__FB_ARGC__ < 2)
220 
221  for i as integer = 1 to (__FB_ARGC__ - 1)
222  dim as zstring ptr arg = __FB_ARGV__[i]
223 
224  select case (*arg)
225  case "-h", "--help"
226  show_help = TRUE
227  exit for
228 
229  case "-i", "--install"
232 
233  case "-u", "--uninstall"
235 
236  case "-s", "--start"
238 
239  case "-e", "--stop"
241 
242  case "-w", "--write"
243  i += 2
244  if (i >= __FB_ARGC__) then exit for
245  dim as zstring ptr port = __FB_ARGV__[i-1]
246  dim as zstring ptr dat = __FB_ARGV__[i]
247  init_driver()
248  write_driver(valuint(*port), valuint(*dat))
249 
250  case "-r", "--read"
251  i += 1
252  if (i >= __FB_ARGC__) then exit for
253  dim as zstring ptr port = __FB_ARGV__[i]
254  dim as byte dat = 0
255  init_driver()
256  read_driver(valuint(*port), @dat)
257  print "Data recieved: " + str(dat)
258 
259  case else
260  print "Unexpected command line argument: '" + *arg + "'"
261  end(1)
262  end select
263  next
264 
265  if (manager) then
266  CloseServiceHandle(manager)
267  end if
268 
269  if (show_help) then
270  print "Options:"
271  print "-h, --help"
272  print "-i, --install"
273  print "-u, --uninstall"
274  print "-s, --start"
275  print "-e, --stop"
276  print "{-w|--write} <port> <data>"
277  print "{-r|--read} <port>"
278  end(1)
279  end if
280