ffalcinelli / pydivert

A Python binding for WinDivert driver
GNU Lesser General Public License v3.0
202 stars 36 forks source link

Access Denied error on uninstall #18

Open ffalcinelli opened 7 years ago

ffalcinelli commented 7 years ago

Seems like driver needs to be unregistered before uninstalling the binding.

SYS files are still in use by the Windows Kernel, and trying to remove them results in an Access Denied error (WinError 5).

Successfully uninstalled pydivert-2.0.0
Exception:
Traceback (most recent call last):
  File "c:\program files (x86)\python35-32\lib\shutil.py", line 381, in _rmtree_unsafe
    os.unlink(fullname)
PermissionError: [WinError 5] Accesso negato: 'C:\\Users\\fabio\\AppData\\Local\\Temp\\pip-1vd8riwq-uninstall\\program files (x86)\\python35-32\\lib\\site-packages\\pydivert\\windivert_dll\\windivert64.sys'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\basecommand.py", line 215, in main
    status = self.run(options, args)
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\commands\uninstall.py", line 76, in run
    requirement_set.uninstall(auto_confirm=options.yes)
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\req\req_set.py", line 337, in uninstall
    req.commit_uninstall()
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\req\req_install.py", line 755, in commit_uninstall
    self.uninstalled.commit()
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\req\req_uninstall.py", line 142, in commit
    rmtree(self.save_dir)
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\_vendor\retrying.py", line 49, in wrapped_f
    return Retrying(*dargs, **dkw).call(f, *args, **kw)
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\_vendor\retrying.py", line 212, in call
    raise attempt.get()
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\_vendor\retrying.py", line 247, in get
    six.reraise(self.value[0], self.value[1], self.value[2])
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\_vendor\six.py", line 686, in reraise
    raise value
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\_vendor\retrying.py", line 200, in call
    attempt = Attempt(fn(*args, **kwargs), attempt_number, False)
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\utils\__init__.py", line 102, in rmtree
    onerror=rmtree_errorhandler)
  File "c:\program files (x86)\python35-32\lib\shutil.py", line 488, in rmtree
    return _rmtree_unsafe(path, onerror)
  File "c:\program files (x86)\python35-32\lib\shutil.py", line 378, in _rmtree_unsafe
    _rmtree_unsafe(fullname, onerror)
  File "c:\program files (x86)\python35-32\lib\shutil.py", line 378, in _rmtree_unsafe
    _rmtree_unsafe(fullname, onerror)
  File "c:\program files (x86)\python35-32\lib\shutil.py", line 378, in _rmtree_unsafe
    _rmtree_unsafe(fullname, onerror)
  File "c:\program files (x86)\python35-32\lib\shutil.py", line 378, in _rmtree_unsafe
    _rmtree_unsafe(fullname, onerror)
  File "c:\program files (x86)\python35-32\lib\shutil.py", line 378, in _rmtree_unsafe
    _rmtree_unsafe(fullname, onerror)
  File "c:\program files (x86)\python35-32\lib\shutil.py", line 378, in _rmtree_unsafe
    _rmtree_unsafe(fullname, onerror)
  File "c:\program files (x86)\python35-32\lib\shutil.py", line 383, in _rmtree_unsafe
    onerror(os.unlink, fullname, sys.exc_info())
  File "c:\program files (x86)\python35-32\lib\site-packages\pip\utils\__init__.py", line 114, in rmtree_errorhandler
    func(path)
PermissionError: [WinError 5] Accesso negato: 'C:\\Users\\fabio\\AppData\\Local\\Temp\\pip-1vd8riwq-uninstall\\program files (x86)\\python35-32\\lib\\site-packages\\pydivert\\windivert_dll\\windivert64.sys'

To delete those files, we must stop the service before using pip

sc stop WinDivert1.1

The WinDivert documentation states that is possible to remove SYS and DLL files and driver will be uninstalled at next reboot, or manually by typing

sc stop WinDivert1.1
sc delete WinDivert1.1
ffalcinelli commented 7 years ago

Since pip has the sole purpose to manage python package, the task to stop service in an uninstall hook is something would never be managed by pip itself, and should not even if an hacky way was available.

So, I think the best solution right now would be to demand this duty to the application or to the developer wanting to uninstall:

Maybe this needs to be reported in documentation, or readme

mhils commented 7 years ago

Yes, that should certainly be part of the PyDivert README/docs. This seems to be an issue in the WinDivert documentation as well:

To uninstall, simply delete the WinDivert.dll, WinDivert32.sys, and WinDivert64.sys files. If already running, the WinDivert driver will be automatically uninstalled during the next machine reboot.

@basil00, can you shed some light on this? :blush:

basil00 commented 7 years ago

The uninstaller should not stop the driver since other unrelated WinDivert applications may still be using it.

I was unable to reproduce the problem -- I tried deleting the .sys files that were still in use, and it worked as expected (tested with Win7, WinDivert1.2, and admin privileges). That is, the files were gone and the WinDivert service was still running.

mhils commented 7 years ago

Thanks for the super fast reply, @basil00! I can reproduce the issue with WinDivert 1.1 and Windows 10. What system are you on, @ffalcinelli?

ffalcinelli commented 7 years ago

I'm on Windows 10 too, and maybe it's related to it. This evening I'll be back and I'll try on a Windows 7 virtual machine and let you know.

I've not modified the readme nor documentation since the intended behaviour is as @basil00 stated.

Thank you both :wink:

ffalcinelli commented 7 years ago

Well seems like on a Windows 7 x86 virtual machine it works fine.

What I find really weird:

basil00 commented 7 years ago

So is this a Win10 issue, or a python+Win10 issue? (I do not have a Win10 test box handy)

mhils commented 7 years ago

This is a Windows 10 issue, unrelated of Python. I cannot delete WinDivert64.sys as long as WinDivert 1.1.8 is running. "access denied" -> sc stop -> "success"

basil00 commented 7 years ago

In that case it appears that Windows has changed its semantics regarding deleting .sys files that are currently running. This complicates the WinDivert uninstall process, since as mentioned earlier, stopping the WinDivert service is not correct either. Probably "delete-on-reboot" is needed.