Main Page | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

lib/WINBUILD/i_opencbm.c

Go to the documentation of this file.
00001 /*
00002  *      This program is free software; you can redistribute it and/or
00003  *      modify it under the terms of the GNU General Public License
00004  *      as published by the Free Software Foundation; either version
00005  *      2 of the License, or (at your option) any later version.
00006  *
00007  *  Copyright 1999-2001 Michael Klein <michael(dot)klein(at)puffin(dot)lb(dot)shuttle(dot)de>
00008  *  Copyright 2001-2004 Spiro Trikaliotis
00009  *
00010  *  Parts are Copyright
00011  *      Jouko Valta <jopi(at)stekt(dot)oulu(dot)fi>
00012  *      Andreas Boose <boose(at)linux(dot)rz(dot)fh-hannover(dot)de>
00013 */
00014 
00027 #include <windows.h>
00028 #include <windowsx.h>
00029 
00031 #define DBG_USERMODE
00032 
00034 #ifndef DBG_PROGNAME
00035     #define DBG_PROGNAME "OPENCBM.DLL"
00036 #endif // #ifndef DBG_PROGNAME
00037 
00038 #include "debug.h"
00039 
00040 #include <winioctl.h>
00041 #include "cbmioctl.h"
00042 
00043 #include <stdlib.h>
00044 #include <stddef.h>
00045 
00046 #include "i_opencbm.h"
00047 
00048 #include "version.h"
00049 #include "archlib.h"
00050 
00051 
00052 /*-------------------------------------------------------------------*/
00053 /*--------- REGISTRY FUNCTIONS --------------------------------------*/
00054 
00076 LONG
00077 RegGetDWORD(IN HKEY RegKey, IN char *SubKey, OUT LPDWORD Value)
00078 {
00079     DWORD valueLen;
00080     DWORD lpType;
00081     DWORD value;
00082     DWORD rc;
00083 
00084     FUNC_ENTER();
00085 
00086     FUNC_PARAM((DBG_PREFIX "Subkey = '%s'", SubKey));
00087 
00088     valueLen = sizeof(value);
00089 
00090     rc = RegQueryValueEx(RegKey, SubKey, NULL, &lpType, (LPBYTE)&value, &valueLen);
00091 
00092     DBG_ASSERT(valueLen == 4);
00093 
00094     if ((rc == ERROR_SUCCESS) && (valueLen == 4))
00095     {
00096         DBG_SUCCESS((DBG_PREFIX "RegGetDWORD"));
00097         *Value = value;
00098     }
00099     else
00100     {
00101         DBG_ERROR((DBG_PREFIX "RegGetDWORD failed, returning -1"));
00102         rc = -1;
00103     }
00104 
00105     FUNC_LEAVE_INT(rc);
00106 }
00107 
00108 
00122 static int
00123 cbm_get_default_port(VOID)
00124 {
00125     DWORD ret;
00126     HKEY regKey;
00127 
00128     FUNC_ENTER();
00129 
00130     DBG_PPORT((DBG_PREFIX "cbm_get_default_port()"));
00131 
00132     // Open a registry key to HKLM<%REGKEY_SERVICE%>
00133 
00134     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
00135                      CBM_REGKEY_SERVICE,
00136                      0,
00137                      KEY_QUERY_VALUE,
00138                      &regKey)
00139        )
00140     {
00141         DBG_WARN((DBG_PREFIX "RegOpenKeyEx() failed!"));
00142         FUNC_LEAVE_BOOL(FALSE);
00143     }
00144 
00145     // now, get the number of the port to use
00146 
00147     if (RegGetDWORD(regKey, CBM_REGKEY_SERVICE_DEFAULTLPT, &ret) != ERROR_SUCCESS)
00148     {
00149         DBG_WARN((DBG_PREFIX "No " CBM_REGKEY_SERVICE "\\" CBM_REGKEY_SERVICE_DEFAULTLPT 
00150             " value, setting 0."));
00151         ret = 0;
00152     }
00153 
00154     // We're done, close the registry handle.
00155 
00156     RegCloseKey(regKey);
00157 
00158     DBG_PPORT((DBG_PREFIX "RETURN: cbm_get_default_port() == %u", ret));
00159 
00160     FUNC_LEAVE_INT(ret);
00161 }
00162 
00163 #if DBG
00164 
00171 VOID
00172 cbm_i_get_debugging_flags(VOID)
00173 {
00174     DWORD ret;
00175     HKEY RegKey;
00176 
00177     FUNC_ENTER();
00178 
00179     // Open a registry key to HKLM<%REGKEY_SERVICE%>
00180 
00181     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
00182                      CBM_REGKEY_SERVICE,
00183                      0,
00184                      KEY_QUERY_VALUE,
00185                      &RegKey)
00186        )
00187     {
00188         DBG_WARN((DBG_PREFIX "RegOpenKeyEx() failed!"));
00189         FUNC_LEAVE();
00190     }
00191 
00192     // now, get the number of the port to use
00193 
00194     if (RegGetDWORD(RegKey, CBM_REGKEY_SERVICE_DLL_DEBUGFLAGS, &ret) != ERROR_SUCCESS)
00195     {
00196         DBG_WARN((DBG_PREFIX "No " CBM_REGKEY_SERVICE "\\" CBM_REGKEY_SERVICE_DLL_DEBUGFLAGS
00197             " value, leaving default."));
00198     }
00199     else
00200     {
00201         DbgFlags = ret;
00202     }
00203 
00204     // We're done, close the registry handle.
00205 
00206     RegCloseKey(RegKey);
00207 
00208     FUNC_LEAVE();
00209 }
00210 
00211 #endif // #if DBG
00212 
00229 const char *
00230 cbmarch_get_driver_name(int PortNumber)
00231 {
00233     static char driverName[] = "\\\\.\\opencbm0";
00234     char *ret;
00235 
00236     FUNC_ENTER();
00237 
00238     ret = NULL;
00239 
00244     if (PortNumber <= 10)
00245     {
00246         if (PortNumber == 0)
00247         {
00248             // PortNumber 0 has special meaning: Find out the default value
00249 
00250             PortNumber = cbm_get_default_port();
00251         }
00252 
00253         driverName[strlen(driverName)-1] = (PortNumber ? PortNumber-1 : 0) + '0';
00254         ret = driverName;
00255     }
00256 
00257     FUNC_LEAVE_STRING(ret);
00258 }
00259 
00280 int
00281 cbmarch_driver_open(CBM_FILE *HandleDevice, int PortNumber)
00282 {
00283     const char *driverName;
00284 
00285     FUNC_ENTER();
00286 
00287     // Get the name of the driver to be opened
00288 
00289     driverName = cbmarch_get_driver_name(PortNumber);
00290 
00291     if (driverName == NULL)
00292     {
00293         // there was a problem, thus, fail this call!
00294 
00295         *HandleDevice = INVALID_HANDLE_VALUE;
00296     }
00297     else 
00298     {
00299         // Open the device
00300 
00301         *HandleDevice = CreateFile(driverName,
00302             GENERIC_READ | GENERIC_WRITE, // we need read and write access
00303             0,
00304             NULL,
00305             OPEN_EXISTING,
00306             FILE_ATTRIBUTE_NORMAL,
00307             NULL);
00308     }
00309 
00310     DBG_ASSERT(*HandleDevice != INVALID_HANDLE_VALUE);
00311 
00312     FUNC_LEAVE_INT(*HandleDevice == INVALID_HANDLE_VALUE);
00313 }
00314 
00329 void
00330 cbmarch_driver_close(CBM_FILE HandleDevice)
00331 {
00332     FUNC_ENTER();
00333 
00334     DBG_ASSERT(HandleDevice != 0);
00335 
00336     CloseHandle(HandleDevice);
00337 
00338     FUNC_LEAVE();
00339 }
00340 
00381 BOOL 
00382 cbm_ioctl(IN CBM_FILE HandleDevice, IN DWORD ControlCode, 
00383 #if DBG
00384           IN char *TextControlCode, 
00385 #endif // #if DBG
00386           IN PVOID InBuffer, IN ULONG InBufferSize, OUT PVOID OutBuffer, IN ULONG OutBufferSize)
00387 {
00388     DWORD dwBytesReturned;
00389 
00390     BOOL returnValue;
00391 
00392     FUNC_ENTER();
00393 
00394     // Perform the IOCTL
00395 
00396     returnValue = DeviceIoControl(HandleDevice, ControlCode, InBuffer, InBufferSize,
00397         OutBuffer, OutBufferSize, &dwBytesReturned, NULL);
00398 
00399     // If an error occurred, output it (in the DEBUG version of this file
00400 
00401     if (!returnValue)
00402     {
00403         DBG_ERROR((DBG_PREFIX "%s: Error code = %u", TextControlCode, GetLastError()));
00404     }
00405     else
00406     {
00407         // Check if the number of bytes returned equals the wanted number
00408 
00409         if (dwBytesReturned != OutBufferSize) 
00410         {
00411             DBG_WARN((DBG_PREFIX "%s: OutBufferSize = %u, but dwBytesReturned = %u",
00412                 TextControlCode, OutBufferSize, dwBytesReturned));
00413         }
00414     }
00415 
00416     FUNC_LEAVE_BOOL(returnValue);
00417 }
00418 
00419 /*-------------------------------------------------------------------*/
00420 /*--------- DEVICE DRIVER HANDLING FUNCTIONS  -----------------------*/
00421 
00422 
00434 BOOL
00435 cbm_i_driver_start(VOID)
00436 {
00437     SC_HANDLE schManager;
00438     SC_HANDLE schService;
00439     DWORD err;
00440     BOOL ret;
00441 
00442     FUNC_ENTER();
00443 
00444     ret = TRUE;
00445 
00446     schManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
00447 
00448     if (schManager == NULL)
00449     {
00450        DBG_ERROR((DBG_PREFIX "Could not open service control manager!"));
00451        FUNC_LEAVE_BOOL(FALSE);
00452     }
00453 
00454     schService = OpenService(schManager, OPENCBM_DRIVERNAME, SERVICE_ALL_ACCESS);
00455 
00456     if (schService == NULL)
00457     {
00458         DBG_ERROR((DBG_PREFIX "OpenService (0x%02x)", GetLastError()));
00459         FUNC_LEAVE_BOOL(FALSE);
00460     }
00461 
00462     ret = StartService(schService, 0, NULL);
00463 
00464     if (ret)
00465     {
00466         DBG_SUCCESS((DBG_PREFIX "StartService"));
00467     }
00468     else
00469     {
00470         err = GetLastError();
00471 
00472         if (err == ERROR_SERVICE_ALREADY_RUNNING)
00473         {
00474             /* If the service is already running, don't treat it
00475              * as an error, but as a warning, and report success!
00476              */
00477 
00478             DBG_WARN((DBG_PREFIX "StartService, (ERROR_SERVICE_ALREADY_RUNNING)"));
00479 
00480             ret = TRUE;
00481         }
00482         else
00483         {
00484             DBG_ERROR((DBG_PREFIX "StartService (0x%02x)", err));
00485         }
00486     }
00487 
00488     CloseServiceHandle(schService);
00489 
00490     // Close the SCM: We don't need it anymore
00491 
00492     CloseServiceHandle(schManager);
00493 
00494     FUNC_LEAVE_BOOL(ret);
00495 }
00496 
00497 
00509 BOOL
00510 cbm_i_driver_stop(VOID)
00511 {
00512     SERVICE_STATUS  serviceStatus;
00513     SC_HANDLE schManager;
00514     SC_HANDLE schService;
00515     BOOL ret;
00516 
00517     FUNC_ENTER();
00518 
00519     schManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
00520 
00521     schService = OpenService(schManager, OPENCBM_DRIVERNAME, SERVICE_ALL_ACCESS);
00522 
00523     if (schManager == NULL)
00524     {
00525        DBG_ERROR((DBG_PREFIX "Could not open service control manager!"));
00526        FUNC_LEAVE_BOOL(FALSE);
00527     }
00528 
00529     if (schService == NULL)
00530     {
00531         DBG_ERROR((DBG_PREFIX "OpenService (0x%02x)", GetLastError()));
00532         FUNC_LEAVE_BOOL(FALSE);
00533     }
00534 
00535     ret = ControlService(schService, SERVICE_CONTROL_STOP, &serviceStatus);
00536 
00537     if (ret)
00538     {
00539         DBG_SUCCESS((DBG_PREFIX "ControlService"));
00540     }
00541     else
00542     {
00543         DBG_ERROR((DBG_PREFIX "ControlService (0x%02x)", GetLastError()));
00544     }
00545 
00546     CloseServiceHandle(schService);
00547 
00548     // Close the SCM: We don't need it anymore
00549 
00550     CloseServiceHandle(schManager);
00551 
00552     FUNC_LEAVE_BOOL(ret);
00553 }
00554 
00574 BOOL
00575 cbm_i_i_driver_install(OUT PULONG Buffer, IN ULONG BufferLen)
00576 {
00577     PCBMT_I_INSTALL_OUT outBuffer;
00578     CBM_FILE HandleDevice;
00579 
00580     FUNC_ENTER();
00581 
00582     DBG_ASSERT(Buffer != NULL);
00583     DBG_ASSERT(BufferLen >= sizeof(ULONG));
00584 
00585     outBuffer = (PCBMT_I_INSTALL_OUT) Buffer;
00586 
00587     DBG_ASSERT(outBuffer != NULL);
00588 
00589     if (cbmarch_driver_open(&HandleDevice, 0) == 0)
00590     {
00591         outBuffer->ErrorFlags = CBM_I_DRIVER_INSTALL_0_IOCTL_FAILED;
00592         cbm_ioctl(HandleDevice, CBMCTRL(I_INSTALL), NULL, 0, Buffer, BufferLen);
00593         cbmarch_driver_close(HandleDevice);
00594     }
00595     else
00596     {
00597         outBuffer->ErrorFlags = CBM_I_DRIVER_INSTALL_0_FAILED;
00598         DBG_ERROR((DBG_PREFIX "Driver could not be openend"));
00599     }
00600 
00601     // if there is room in the given buffer, set the dll version
00602 
00603     if (BufferLen >= sizeof(outBuffer->DllVersion) + offsetof(CBMT_I_INSTALL_OUT, DllVersion))
00604     {
00605         outBuffer->DllVersion =
00606             CBMT_I_INSTALL_OUT_MAKE_VERSION(CBM4WIN_VERSION_MAJOR, CBM4WIN_VERSION_MINOR,
00607                                             CBM4WIN_VERSION_SUBMINOR, CBM4WIN_VERSION_DEVEL);
00608     }
00609 
00610     // if there is even room for the dll version extension, set the dll version extension
00611 
00612     if (BufferLen >= sizeof(outBuffer->DllVersionEx) + offsetof(CBMT_I_INSTALL_OUT, DllVersionEx))
00613     {
00614         outBuffer->DllVersionEx =
00615             CBMT_I_INSTALL_OUT_MAKE_VERSION_EX(CBM4WIN_VERSION_PATCHLEVEL);
00616     }
00617 
00618     FUNC_LEAVE_INT(
00619         (  (outBuffer->ErrorFlags != CBM_I_DRIVER_INSTALL_0_IOCTL_FAILED)
00620         && (outBuffer->ErrorFlags != CBM_I_DRIVER_INSTALL_0_FAILED)
00621         ) ? FALSE : TRUE);
00622 }
00623 
00633 BOOL
00634 IsDriverStartedAutomatically(VOID)
00635 {
00636     DWORD ret;
00637     BOOL automaticStart;
00638     HKEY regKey;
00639 
00640     FUNC_ENTER();
00641 
00642     automaticStart = FALSE;
00643 
00644     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
00645                      CBM_REGKEY_SERVICE,
00646                      0,
00647                      KEY_QUERY_VALUE,
00648                      &regKey)
00649        )
00650     {
00651         DBG_WARN((DBG_PREFIX "RegOpenKeyEx() failed!"));
00652         FUNC_LEAVE_BOOL(FALSE);
00653     }
00654 
00655     // now, get the number of the port to use
00656 
00657     if (RegGetDWORD(regKey, "Start", &ret) != ERROR_SUCCESS)
00658     {
00659         DBG_ERROR((DBG_PREFIX "No " CBM_REGKEY_SERVICE "\\Start value!"));
00660     }
00661     else
00662     {
00663         if (ret == SERVICE_AUTO_START)
00664         {
00665             automaticStart = TRUE;
00666         }
00667     }
00668 
00669     // We're done, close the registry handle.
00670 
00671     RegCloseKey(regKey);
00672 
00673     FUNC_LEAVE_BOOL(automaticStart);
00674 }

Generated on Sun Apr 30 18:45:51 2006 for opencbm by  doxygen 1.4.2