initial upload, directio/giveio.sys sources still missing
diff --git a/pyparallel/CHANGES.txt b/pyparallel/CHANGES.txt
new file mode 100644
index 0000000..9f88238
--- /dev/null
+++ b/pyparallel/CHANGES.txt
@@ -0,0 +1,2 @@
+Version 0.1     29 Jul 2002
+    added to CVS
diff --git a/pyparallel/LICENSE.txt b/pyparallel/LICENSE.txt
new file mode 100644
index 0000000..2b0e2d8
--- /dev/null
+++ b/pyparallel/LICENSE.txt
@@ -0,0 +1,61 @@
+Copyright (c) 2002 Chris Liechti <cliechti@gmx.net>;
+All Rights Reserved.
+
+This is the Python license. In short, you can use this product in
+commercial and non-commercial applications, modify it, redistribute it.
+A notification to the author when you use and/or modify it is welcome.
+
+
+TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING THIS SOFTWARE
+===================================================================
+
+LICENSE AGREEMENT
+-----------------
+
+1. This LICENSE AGREEMENT is between the copyright holder of this
+product, and the Individual or Organization ("Licensee") accessing
+and otherwise using this product in source or binary form and its
+associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement,
+the copyright holder hereby grants Licensee a nonexclusive,
+royalty-free, world-wide license to reproduce, analyze, test,
+perform and/or display publicly, prepare derivative works, distribute,
+and otherwise use this product alone or in any derivative version,
+provided, however, that copyright holders License Agreement and
+copyright holders notice of copyright are retained in this product
+alone or in any derivative version prepared by Licensee.
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates this product or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to this product.
+
+4. The copyright holder is making this product available to Licensee on
+an "AS IS" basis. THE COPYRIGHT HOLDER MAKES NO REPRESENTATIONS OR
+WARRANTIES, EXPRESS OR IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION,
+THE COPYRIGHT HOLDER MAKES NO AND DISCLAIMS ANY REPRESENTATION OR
+WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR
+THAT THE USE OF THIS PRODUCT WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. THE COPYRIGHT HOLDER SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER
+USERS OF THIS PRODUCT FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL
+DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE
+USING THIS PRODUCT, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE
+POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. Nothing in this License Agreement shall be deemed to create any
+relationship of agency, partnership, or joint venture between the
+copyright holder and Licensee. This License Agreement does not grant
+permission to use trademarks or trade names from the copyright holder
+in a trademark sense to endorse or promote products or services of
+Licensee, or any third party.
+
+8. By copying, installing or otherwise using this product, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
+
diff --git a/pyparallel/MANIFEST b/pyparallel/MANIFEST
new file mode 100644
index 0000000..72f39fd
--- /dev/null
+++ b/pyparallel/MANIFEST
@@ -0,0 +1,8 @@
+README.txt
+LICENSE.txt
+CHANGES.txt
+setup.py
+parallel\__init__.py
+parallel\_pyparallel.py
+examples\test.py
+
diff --git a/pyparallel/README.txt b/pyparallel/README.txt
new file mode 100644
index 0000000..e6e0734
--- /dev/null
+++ b/pyparallel/README.txt
@@ -0,0 +1,46 @@
+pyParallel
+--------
+This module capsulates the access for the parallel port. It provides backends
+for standard Python running on Windows, Linux, BSD and Jython.
+The module named "parallel" automaticaly selects the appropriate backend.
+
+It is released under a free software license, see LICENSE.txt for more
+details.
+
+Project Homepage: pyserial.sourceforge.net
+(C) 2002 Chris Liechti <cliechti@gmx.net>
+
+
+Features
+--------
+- same class based interface on all supported platforms
+- port numbering starts at zero, no need to know the platform dependant port
+  name in the user program
+- port name can be specified if access through numbering is inappropriate
+
+Requirements
+------------
+- Python 2.0 or newer (1.5.2 untested)
+- "Java Communications" (JavaComm) extension for Java/Jython
+
+
+Installation
+------------
+Extract files from the archive, open a shell/console in that directory and
+let Distutils do the rest: "python setup.py install"
+
+The files get installed in the "Lib/site-packages" directory in newer
+Python versions.
+
+
+Short introduction
+------------------
+>>> import parallel
+>>> p = parallel.Parallel()     #open LPT1
+>>> p.setData(0x55)
+
+References
+----------
+- Python: http://www.python.org
+
+- Jython: http://www.jython.org
diff --git a/pyparallel/examples/lcd.py b/pyparallel/examples/lcd.py
new file mode 100644
index 0000000..b56c2a5
--- /dev/null
+++ b/pyparallel/examples/lcd.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python
+# character LCD example for pyparallel
+#
+#(C) 2002 Chris Liechti <cliechti@gmx.net>
+# this is distributed under a free software license, see license.txt
+
+import sys, time
+sys.path.append('..')
+import parallel
+
+LCDON           = 0x01 #0x00000001 Switch on  display
+LCDOFF          = 0x08 #0x00001000 Switch off display
+LCDCLEAR        = 0x01 #0x00000001
+LCDLINE1        = 0x80 #0x10000000
+LCDLINE2        = 0xc0 #0x11000000
+LCDCURSORON     = 0x0f #0x00001111 turn on cursor blinking
+LCDCURSOROFF    = 0x0c #0x00001100 Disable cursor blinking. The cursor is hidden.
+LCDCGADRSET     = 0x40 #0b01000000
+LCDDDADRSET     = 0x80 #0b10000000
+LCD2LINES       = 0x28 #0b00101000 Set display mode to two lines.
+LCD8BITS        = 0x30 #0b00110000 select 8 Bit interface
+LCD4BITS        = 0x20 #0b00100000 select 4 Bit interface
+LCD_DATA_OFF    = 0x05 #0x00000101 mask used to clear the data lines
+
+LCD_RS          = 1<<1
+LCD_RW          = 1<<2
+LCD_E           = 1<<3
+LCD_D4          = 1<<4
+LCD_D5          = 1<<5
+LCD_D6          = 1<<6
+LCD_D7          = 1<<7
+
+
+class LCD:
+    def __init__(self):
+        self.p = parallel.Parallel()
+        self.data = 0
+        
+        self.out(0)                 #reset pins
+        time.sleep(0.050)           #wait more than 30ms
+        #send the reset sequece (3 times the same pattern)
+        self.out(LCD8BITS)          #set 8 bit interface
+        self.toggleE()              #toggle LCD_E, the enable pin
+        time.sleep(0.005)           #wait a bit
+        self.toggleE()              #toggle LCD_E, the enable pin
+        time.sleep(0.005)           #wait a bit
+        self.toggleE()              #toggle LCD_E, the enable pin
+        time.sleep(0.005)           #wait a bit
+        
+        self.out(LCD4BITS)          #now set up the 4 bit interface
+        self.toggleE()              #toggle LCD_E, the enable pin
+        time.sleep(0.002)           #wait until instr is finished
+        self.instr(LCD2LINES)    #set 2 lines display
+        self.instr(LCDCURSOROFF) #hide cursor
+        self.instr(LCDCLEAR)     #clear display
+
+    #my connector has the wrong pinorder....
+    #better swap them in software than to solder ;-)
+    def reveseout(self, x):
+        r = ((x & (1<<0) and 1) << 7) |\
+            ((x & (1<<1) and 1) << 6) |\
+            ((x & (1<<2) and 1) << 5) |\
+            ((x & (1<<3) and 1) << 4) |\
+            ((x & (1<<4) and 1) << 3) |\
+            ((x & (1<<5) and 1) << 2) |\
+            ((x & (1<<6) and 1) << 1) |\
+            ((x & (1<<7) and 1) << 0)
+        #print "%02x" % r, "%02x" %x
+        self.p.setData(r)
+        
+    def toggleE(self):
+        """toggle enable pin"""
+        self.data |= LCD_E;         #toggle LCD_E, the enable pin
+        self.reveseout(self.data)
+        self.data &= ~LCD_E;        #back to inactive position
+        self.reveseout(self.data)
+
+    def out(self, data):
+        """set data to LCD port"""
+        self.data = data
+        self.reveseout(self.data)
+
+    def instr(self, cmd):
+        """send instruction byte to LCD"""
+        self.out(cmd & 0xf0)        #output upper nibble
+        self.toggleE()              #toggle LCD_E, the enable pin
+        self.out((cmd << 4) & 0xf0) #and then the lower nibble
+        self.toggleE()              #toggle LCD_E, the enable pin
+        time.sleep(0.001)           #wait until instr is finished
+
+    def putc(self, c):
+        """send a data byte to the LCD"""
+        c = ord(c)
+        self.out((c & 0xf0) | LCD_RS) #output upper nibble
+        self.toggleE()              #toggle LCD_E, the enable pin
+        self.out(((c << 4) & 0xf0) | LCD_RS) #and then the lower nibble
+        self.toggleE()              #toggle LCD_E, the enable pin
+        time.sleep(0.001)           #wait until instr is finished
+
+    def write(self, str):
+        """write a string to the LCD"""
+        for c in str:
+            self.putc(c)            #write each character
+
+    def downloadFont(self, fontdata):
+        """Set the memory pointer and download a font"""
+        self.instr(LCDCGADRSET);
+        self.write(fontdata)
+        self.instr(LCDLINE1)        #just in case, set cursor to a visible pos
+
+if __name__ == '__main__':
+    lcd = LCD()
+    lcd.write("Hello World")
+    lcd.instr(LCDLINE2)
+    lcd.write("from Python")
+##    for c in map(chr,range(256)):
+##        lcd.instr(LCDLINE1)
+##        lcd.write(c)
+
+    
\ No newline at end of file
diff --git a/pyparallel/makefile b/pyparallel/makefile
new file mode 100644
index 0000000..182cf58
--- /dev/null
+++ b/pyparallel/makefile
@@ -0,0 +1,6 @@
+all:
+	./setup.py build --compiler=mingw32
+	cp build/lib.win32-2.2/_pyparallel.pyd ./parallel
+
+installer: all
+	./setup.py bdist_wininst
diff --git a/pyparallel/parallel/__init__.py b/pyparallel/parallel/__init__.py
new file mode 100644
index 0000000..6bcdf49
--- /dev/null
+++ b/pyparallel/parallel/__init__.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python 
+#portable parallel port access with python
+#this is a wrapper module for different platform implementations
+#
+# (C)2001-2002 Chris Liechti <cliechti@gmx.net>
+# this is distributed under a free software license, see license.txt
+
+import sys, os, string
+VERSION = string.split("$Revision: 1.1 $")[1]     #extract CVS version
+
+#chose an implementation, depending on os
+if os.name == 'nt': #sys.platform == 'win32':
+    from parallelwin32 import *
+elif os.name == 'posix':
+    from parallelposix import *
+elif os.name == 'java':
+    from paralleljava import *
+else:
+    raise "Sorry no implementation for your platform available."
+
+#no "mac" implementation. someone want's to write it? i have no access to a mac.
diff --git a/pyparallel/parallel/parallelwin32.py b/pyparallel/parallel/parallelwin32.py
new file mode 100644
index 0000000..7c10c3f
--- /dev/null
+++ b/pyparallel/parallel/parallelwin32.py
@@ -0,0 +1,122 @@
+#pyparallel driver for win32
+#see __init__.py
+#
+#(C) 2002 Chris Liechti <cliechti@gmx.net>
+# this is distributed under a free software license, see license.txt
+#
+# thanks to Dincer Aydin dinceraydin@altavista.net for his work on the
+# winioport module: www.geocities.com/dinceraydin/ the graphic below is
+# borrowed form him ;-)
+
+
+#    LPT1 = 0x0378 or 0x03BC
+#    LPT2 = 0x0278 or 0x0378
+#    LPT3 = 0x0278
+#
+#   Data Register (base + 0) ........ outputs
+#
+#     7 6 5 4 3 2 1 0
+#     . . . . . . . *  D0 ........... (pin 2), 1=High, 0=Low (true)
+#     . . . . . . * .  D1 ........... (pin 3), 1=High, 0=Low (true)
+#     . . . . . * . .  D2 ........... (pin 4), 1=High, 0=Low (true)
+#     . . . . * . . .  D3 ........... (pin 5), 1=High, 0=Low (true)
+#     . . . * . . . .  D4 ........... (pin 6), 1=High, 0=Low (true)
+#     . . * . . . . .  D5 ........... (pin 7), 1=High, 0=Low (true)
+#     . * . . . . . .  D6 ........... (pin 8), 1=High, 0=Low (true)
+#     * . . . . . . .  D7 ........... (pin 9), 1=High, 0=Low (true)
+#
+#   Status Register (base + 1) ...... inputs
+#
+#     7 6 5 4 3 2 1 0
+#     . . . . . * * *  Undefined
+#     . . . . * . . .  Error ........ (pin 15), high=1, low=0 (true)
+#     . . . * . . . .  Selected ..... (pin 13), high=1, low=0 (true)
+#     . . * . . . . .  No paper ..... (pin 12), high=1, low=0 (true)
+#     . * . . . . . .  Ack .......... (pin 10), high=1, low=0 (true)
+#     * . . . . . . .  Busy ......... (pin 11), high=0, low=1 (inverted)
+#
+#   ctrl Register (base + 2) ..... outputs
+#
+#     7 6 5 4 3 2 1 0
+#     . . . . . . . *  Strobe ....... (pin 1),  1=low, 0=high (inverted)
+#     . . . . . . * .  Auto Feed .... (pin 14), 1=low, 0=high (inverted)
+#     . . . . . * . .  Initialize ... (pin 16), 1=high, 0=low (true)
+#     . . . . * . . .  Select ....... (pin 17), 1=low, 0=high (inverted)
+#     * * * * . . . .  Unused
+
+LPT1 = 0
+LPT2 = 1
+
+LPT1_base = 0x0378
+LPT2_base = 0x0278
+
+import _pyparallel
+
+class Parallel:
+    def __init__(self, port = LPT1):
+        if port == LPT1:
+            self.dataRegAdr = LPT1_base
+        elif port == LPT1:
+            self.dataRegAdr = LPT2_base
+        else:
+            raise ValueError("No such port available - expecting a number")
+        self.statusRegAdr = self.dataRegAdr + 1
+        self.ctrlRegAdr   = self.dataRegAdr + 2
+
+    def setData(self, value):
+        _pyparallel.outp(self.dataRegAdr, value)
+
+    # control register output functions
+    def setDataStrobe(self, state):
+        """data strobe bit"""
+        if state == 0:
+            self.ctrlReg = self.ctrlReg |  0x01
+        else:
+            self.ctrlReg = self.ctrlReg & ~0x01
+        _pyparallel.outp(self.ctrlRegAdr, self.ctrlReg)
+
+    def setAutoFeed(self, state):
+        """auto feed bit"""
+        if state == 0:
+            self.ctrlReg = self.ctrlReg |  0x02
+        else:
+            self.ctrlReg = self.ctrlReg & ~0x02
+        _pyparallel.outp(self.ctrlRegAdr, self.ctrlReg)
+
+    def setInitOut(self, state):
+        """initialize bit"""
+        if state == 0:
+            self.ctrlReg = self.ctrlReg & ~0x04
+        else:
+            self.ctrlReg = self.ctrlReg |  0x04
+        _pyparallel.outp(self.ctrlRegAdr, self.ctrlReg)
+    
+    def setSelect(self, state):
+        """select bit"""
+        if state == 0:
+            self.ctrlReg = self.ctrlReg |  0x08
+        else:
+            self.ctrlReg = self.ctrlReg & ~0x08
+        _pyparallel.outp(self.ctrlRegAdr, self.ctrlReg)
+
+    def getInError(self):
+        """Error pin"""
+        return _pyparallel.inp(self.statusRegAdr) & 0x08 and 1
+
+    def gettInSelected(self):
+        """select pin"""
+        return _pyparallel.inp(self.statusRegAdr) & 0x10 and 1
+
+    def getInPaperOut(self):
+        """paper out pin"""
+        return _pyparallel.inp(self.statusRegAdr) & 0x20 and 1
+
+    def getInAcknowledge(self):
+        """Acknowledge pin"""
+        return _pyparallel.inp(self.statusRegAdr) & 0x40 and 1
+
+    def getInBusy(self):
+        """input from busy pin"""
+        return _pyparallel.inp(self.statusRegAdr)& 0x80 and 1
+
+
diff --git a/pyparallel/setup.py b/pyparallel/setup.py
new file mode 100644
index 0000000..64bda13
--- /dev/null
+++ b/pyparallel/setup.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+from distutils.core import setup, Extension
+
+setup (name = "pyparallel",
+    description="Python Parallel Port Extension",
+    version="0.1",
+    author="Chris Liechti",
+    author_email="cliechti@gmx.net",
+    url="http://pyserial.sourceforge.net/",
+    packages=['parallel'],
+    license="Python",
+    long_description="Python Parallel Port Extension for Win32, Linux, BSD",
+
+    ext_modules = [
+        Extension('_pyparallel',
+            sources=['src/win32/_pyparallel.c', 'src/win32/loaddrv.c'],
+        )
+    ]
+)
diff --git a/pyparallel/src/win32/_pyparallel.c b/pyparallel/src/win32/_pyparallel.c
new file mode 100644
index 0000000..7f906c5
--- /dev/null
+++ b/pyparallel/src/win32/_pyparallel.c
@@ -0,0 +1,91 @@
+// Parallel port extension for Win32
+// "inp" and "outp" are used to access the parallelport hardware
+// needs giveio.sys driver on NT/2k/XP
+//
+// (C) 2002 Chris Liechti <cliechti@gmx.net>
+// this is distributed under a free software license, see license.txt
+
+#include <Python.h>
+#include <windows.h>
+#include <conio.h>
+#include "loaddrv.h"
+
+#define DRIVERNAME      "giveio.sys"
+#define SERVICENAME     "giveio"
+
+/* module-functions */
+
+static PyObject*
+py_outp(PyObject *self, PyObject *args)
+{
+    int port, value;
+    if(!PyArg_ParseTuple(args, "ii", &port, &value))
+        return 0;
+    _outp(port, value);
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject*
+py_inp(PyObject *self, PyObject *args)
+{
+    int port, value;
+    if(!PyArg_ParseTuple(args, "i", &port))
+        return 0;
+    value = _inp(port);
+    return Py_BuildValue("i", value);
+}
+
+
+
+static PyMethodDef pypar_methods[] = {
+    {"outp",   py_outp,   METH_VARARGS},
+    {"inp",    py_inp,    METH_VARARGS},
+    {0, 0}
+};
+
+/* module entry-point (module-initialization) function */
+void init_pyparallel(void) {
+    int dwStatus;
+    //~ char buf[256];
+    OSVERSIONINFO vi;
+    
+    /* Create the module and add the functions */
+    PyObject *m = Py_InitModule("_pyparallel", pypar_methods);
+    
+    //detect OS, on NT,2k,XP the driver needs to be loaded
+    vi.dwOSVersionInfoSize = sizeof(vi);
+    GetVersionEx(&vi);
+    if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
+        HANDLE h;
+        //try to open driver
+        h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL,
+                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+        if (h == INVALID_HANDLE_VALUE) {
+            //failed, try to load sys file fom disk
+            dwStatus = LoadDriverInit();        //init loaddriver module
+            //~ printf("init %d\n", dwStatus);
+            //driver not running, try to start it
+            //~ dwStatus = getcwd(buf, sizeof buf);
+            //~ snprintf(buf, sizeof buf, "%s\\%s", buf, SERVICENAME);
+            //~ printf("path %d %s %s\n", dwStatus, buf, SERVICENAME);
+            //~ dwStatus = DriverInstall(buf, SERVICENAME);
+            //install the driver. this returns an error if already installed
+            //but who cares?
+            dwStatus = DriverInstall(DRIVERNAME, SERVICENAME);
+            dwStatus = DriverStart(SERVICENAME);//now start the driver
+            LoadDriverCleanup();                //close loaddriver module
+            //retry to open the file
+            h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL,
+                            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+            if (h == INVALID_HANDLE_VALUE) {
+                //if it fails again, then we have a problem... -> exception
+                PyErr_Format(PyExc_ImportError, "Couldn't access giveio device");
+            }
+        }
+        //close again immediately.
+        //the process is now tagged to have the rights it needs,
+        //the giveio driver remembers that
+        if (h != NULL) CloseHandle(h);          //close the driver's file
+    }
+}
diff --git a/pyparallel/src/win32/loaddrv.c b/pyparallel/src/win32/loaddrv.c
new file mode 100644
index 0000000..5149877
--- /dev/null
+++ b/pyparallel/src/win32/loaddrv.c
@@ -0,0 +1,103 @@
+// loaddrv.c - Dynamic driver install/start/stop/remove
+// original by Paula Tomlinson
+
+#include <windows.h>
+#include "loaddrv.h"
+
+SC_HANDLE hSCMan = NULL;
+
+DWORD LoadDriverInit(void) {
+    // connect to local service control manager
+    if ((hSCMan = OpenSCManager(NULL, NULL, 
+        SC_MANAGER_ALL_ACCESS)) == NULL) {
+        return -1;
+    }
+    return OKAY;
+}
+
+void LoadDriverCleanup(void) {
+    if (hSCMan != NULL) CloseServiceHandle(hSCMan);
+}
+
+DWORD DriverInstall(LPSTR lpPath, LPSTR lpDriver) {
+   BOOL dwStatus = OKAY;
+   SC_HANDLE hService = NULL;
+
+   // add to service control manager's database
+   if ((hService = CreateService(hSCMan, lpDriver, 
+      lpDriver, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER,
+      SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, lpPath, 
+      NULL, NULL, NULL, NULL, NULL)) == NULL) 
+   {
+         dwStatus = GetLastError();
+   } else {
+       CloseServiceHandle(hService);
+   }
+
+   return dwStatus;
+}
+
+DWORD DriverStart(LPSTR lpDriver) {
+   BOOL dwStatus = OKAY;
+   SC_HANDLE hService = NULL;
+
+   // get a handle to the service
+   if ((hService = OpenService(hSCMan, lpDriver, 
+      SERVICE_ALL_ACCESS)) != NULL) 
+   {
+      // start the driver
+      if (!StartService(hService, 0, NULL))
+         dwStatus = GetLastError();
+   } else {
+       dwStatus = GetLastError();
+   }
+
+   if (hService != NULL) {
+       CloseServiceHandle(hService);
+   }
+   return dwStatus;
+}
+
+DWORD DriverStop(LPSTR lpDriver) {
+   BOOL dwStatus = OKAY;
+   SC_HANDLE hService = NULL;
+   SERVICE_STATUS serviceStatus;
+
+   // get a handle to the service
+   if ((hService = OpenService(hSCMan, lpDriver, 
+      SERVICE_ALL_ACCESS)) != NULL) 
+   {
+      // stop the driver
+      if (!ControlService(hService, SERVICE_CONTROL_STOP,
+         &serviceStatus))
+            dwStatus = GetLastError();
+   } else {
+       dwStatus = GetLastError();
+   }
+
+   if (hService != NULL) {
+       CloseServiceHandle(hService);
+   }
+   return dwStatus;
+}
+
+DWORD DriverRemove(LPSTR lpDriver) {
+   BOOL dwStatus = OKAY;
+   SC_HANDLE hService = NULL;
+
+   // get a handle to the service
+   if ((hService = OpenService(hSCMan, lpDriver, 
+      SERVICE_ALL_ACCESS)) != NULL) 
+   {
+      // remove the driver
+      if (!DeleteService(hService))
+         dwStatus = GetLastError();
+   } else {
+       dwStatus = GetLastError();
+   }
+
+   if (hService != NULL) {
+       CloseServiceHandle(hService);
+   }
+   return dwStatus;
+}
diff --git a/pyparallel/src/win32/loaddrv.h b/pyparallel/src/win32/loaddrv.h
new file mode 100644
index 0000000..4f874da
--- /dev/null
+++ b/pyparallel/src/win32/loaddrv.h
@@ -0,0 +1,17 @@
+#ifndef LOADDRV_H
+#define LOADDRV_H
+
+#include <windows.h>
+
+#define OKAY                   0
+#define UNEXPECTED_ERROR       9999
+
+//prototypes
+DWORD LoadDriverInit(void);
+void LoadDriverCleanup(void);
+DWORD DriverInstall(LPSTR, LPSTR);
+DWORD DriverStart(LPSTR);
+DWORD DriverStop(LPSTR);
+DWORD DriverRemove(LPSTR);
+
+#endif //LOADDRV_H
\ No newline at end of file