Commit 8cb6ad8e by rfkelly0

dokan: add basic silent-install routine for dokan DLLs (not included)

parent 9c5c4d49
...@@ -173,13 +173,11 @@ MIN_FH = 100 ...@@ -173,13 +173,11 @@ MIN_FH = 100
class FSOperations(DokanOperations): class FSOperations(DokanOperations):
"""DokanOperations interface delegating all activities to an FS object.""" """DokanOperations interface delegating all activities to an FS object."""
def __init__(self, fs, on_init=None, on_unmount=None, fsname="Dokan FS", volname="Dokan Volume"): def __init__(self, fs, fsname="Dokan FS", volname="Dokan Volume"):
super(FSOperations,self).__init__() super(FSOperations,self).__init__()
self.fs = fs self.fs = fs
self.fsname = fsname self.fsname = fsname
self.volname = volname self.volname = volname
self._on_init = on_init
self._on_unmount = on_unmount
self._files_by_handle = {} self._files_by_handle = {}
self._files_lock = threading.Lock() self._files_lock = threading.Lock()
self._next_handle = MIN_FH self._next_handle = MIN_FH
...@@ -227,10 +225,6 @@ class FSOperations(DokanOperations): ...@@ -227,10 +225,6 @@ class FSOperations(DokanOperations):
return True return True
return False return False
def Unmount(self, info):
if self._on_unmount:
self._on_unmount()
@handle_fs_errors @handle_fs_errors
def CreateFile(self, path, access, sharing, disposition, flags, info): def CreateFile(self, path, access, sharing, disposition, flags, info):
path = normpath(path) path = normpath(path)
...@@ -691,7 +685,7 @@ def mount(fs, drive, foreground=False, ready_callback=None, unmount_callback=Non ...@@ -691,7 +685,7 @@ def mount(fs, drive, foreground=False, ready_callback=None, unmount_callback=Non
flags = kwds.pop("flags",0) flags = kwds.pop("flags",0)
FSOperationsClass = kwds.pop("FSOperationsClass",FSOperations) FSOperationsClass = kwds.pop("FSOperationsClass",FSOperations)
opts = libdokan.DOKAN_OPTIONS(drive[:1], numthreads, flags) opts = libdokan.DOKAN_OPTIONS(drive[:1], numthreads, flags)
ops = FSOperationsClass(fs, on_unmount=unmount_callback, **kwds) ops = FSOperationsClass(fs, **kwds)
if ready_callback: if ready_callback:
check_thread = threading.Thread(target=check_ready) check_thread = threading.Thread(target=check_ready)
check_thread.daemon = True check_thread.daemon = True
...@@ -699,6 +693,8 @@ def mount(fs, drive, foreground=False, ready_callback=None, unmount_callback=Non ...@@ -699,6 +693,8 @@ def mount(fs, drive, foreground=False, ready_callback=None, unmount_callback=Non
res = DokanMain(ctypes.byref(opts),ctypes.byref(ops.buffer)) res = DokanMain(ctypes.byref(opts),ctypes.byref(ops.buffer))
if res != DOKAN_SUCCESS: if res != DOKAN_SUCCESS:
raise OSError("Dokan failed with error: %d" % (res,)) raise OSError("Dokan failed with error: %d" % (res,))
if unmount_callback:
unmount_callback()
# Running the background, spawn a subprocess and wait for it # Running the background, spawn a subprocess and wait for it
# to be ready before returning. # to be ready before returning.
else: else:
......
import os
import shutil
import subprocess
import ctypes
kernel32 = ctypes.windll.kernel32
def GetSystemDirectory():
buf = ctypes.create_unicode_buffer(260)
if not kernel32.GetSystemDirectoryW(ctypes.byref(buf),260):
raise ctypes.WinError()
return buf.value
def _tag2vertup(tag):
bits = []
for bit in tag.split("-"):
for bit2 in bit.split("."):
try:
bits.append(int(bit2.strip()))
except ValueError:
pass
return tuple(bits)
def install_dokan(release_dir,vendorid="pyfilesystem"):
"""Install dokan from the given release directory."""
reltag = os.path.basename(release_dir)
newver = _tag2vertup(reltag)
sysdir = GetSystemDirectory()
pfdir = os.path.join(os.environ["PROGRAMFILES"],"Dokan")
# Is Dokan already installed, and is it safe to upgrade?
old_reltag = None
if os.path.exists(os.path.join(sysdir,"drivers","dokan.sys")):
for nm in os.listdir(pfdir):
if nm.startswith(vendorid):
old_reltag = nm[len(vendorid)+1:-4]
oldver = _tag2vertup(old_reltag)
if oldver >= newver:
raise OSError("dokan already at version " + reltag)
break
else:
raise OSError("dokan already installed from another source")
# Device what version to install based on windows version.
wver = sys.getwindowsversion()
if wver < (5,1):
raise OSError("windows is too old to install dokan")
if wver < (6,0):
wtyp = "wxp"
elif wver < (6,1):
wtyp = "wlh"
else:
wtyp = "win7"
srcdir = os.path.join(release_dir,wtyp)
# Terminate the existing install and remove it
if old_reltag:
uninstall_dokan(old_reltag)
# Copy new files to the appropriate place
if not os.path.exists(pfdir):
os.makedirs(pfdir)
f = open(os.path.join(pfdir,vendorid+"-"+reltag+".txt"),"wt")
try:
f.write("Dokan automatically installed by " + vendorid + "\n")
finally:
f.close()
shutil.copy2(os.path.join(srcdir,"dll","dokan.dll"),
os.path.join(sysdir,"dokan.dll"))
shutil.copy2(os.path.join(srcdir,"sys","dokan.sys"),
os.path.join(sysdir,"drivers","dokan.sys"))
shutil.copy2(os.path.join(srcdir,"mounter","mounter.exe"),
os.path.join(pfdir,"mounter.exe"))
shutil.copy2(os.path.join(srcdir,"dokanctrl","dokanctl.exe"),
os.path.join(pfdir,"dokanctl.exe"))
# Invoke dokanctl to install the drivers
_dokanctl(pfdir,"/i","a")
def uninstall_dokan(release_dir):
reltag = os.path.basename(release_dir)
newver = _tag2vertup(reltag)
sysdir = GetSystemDirectory()
pfdir = os.path.join(os.environ["PROGRAMFILES"],"Dokan")
if dokan_installed:
_dokanctl(pfdir,"/r","a")
os.unlink(os.path.join(sysdir,"drivers","dokan.sys"))
os.unlink(os.path.join(sysdir,"dokan.dll"))
for nm in os.listdir(pfdir):
os.unlink(os.path.join(pfdir,nm))
def _dokanctl(pfdir,*args):
dokanctl = os.path.join(pfdir,"dokanctl.exe")
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
p = subprocess.Popen([dokanctl]+list(args),startupinfo=startupinfo,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
if p.wait() != 0:
raise OSError("dokanctl failed: " + p.stdout.read())
if __name__ == "__main__":
import sys
install_dokan(sys.argv[1])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment