Skip to content

Commit

Permalink
resolved #82
Browse files Browse the repository at this point in the history
  • Loading branch information
yamahubuki committed Jan 12, 2020
1 parent e4ac265 commit ad7d9d7
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 18 deletions.
69 changes: 69 additions & 0 deletions deviceCtrl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# -*- coding: utf-8 -*-
#Falcon device ctrl
#Copyright (C) 2020 Yukio Nozawa <personal@nyanchangames.com>
#Copyright (C) 2020 yamahubuki <itiro.ishino@gmail.com>
#Note: All comments except these top lines will be written in Japanese.

import win32file
import pywintypes
import ctypes
import re

import errorCodes

from simpleDialog import dialog
from logging import getLogger


log=getLogger("falcon.deviceCtrl")
falconHelper=ctypes.cdll.LoadLibrary("falconHelper.dll")
falconHelper.ejectDevice.argtypes=[ctypes.c_char_p]

def ejectDrive(driveLetter):

try:
deviceName=win32file.QueryDosDevice(driveLetter[0].upper()+":")
except pywintypes.error as e:
if e.winerror==2:
return errorCodes.FILE_NOT_FOUND
else:
dialog(_("エラー"),e.strerror)
#log.error(unknown error in"+e.funcname+". code="+e.winerror+" message="+e.strerror)
return errorCodes.UNKNOWN

deviceName=re.sub(r"\\Device\\([^\x00]+).*",r"\1",deviceName)

try:
handle=win32file.CreateFile(
"\\\\.\\"+deviceName,
win32file.GENERIC_WRITE | win32file.GENERIC_READ,
0, #クローズするまで他からはOPENできない
None, #セキュリティ関連の構造体
win32file.OPEN_EXISTING, #デバイスのOPENはこれじゃないとダメ
0,
None)
except pywintypes.error as e:
if e.winerror==32:
return errorCodes.ACCESS_DENIED
else:
dialog(_("エラー"),e.strerror)
#log.error(unknown error in"+e.funcname+". code="+e.winerror+" message="+e.strerror)
return errorCodes.UNKNOWN

#0x2D4808=IOCTL_STORAGE_EJECT_MEDIA
ret=win32file.DeviceIoControl(handle,0x2D4808,None,None)

handle.Close()

return errorCodes.OK


def EjectDevice(letter):
log.debug("Trying to eject drive %s..." % letter)
ret=falconHelper.ejectDevice(letter.encode('utf-8'))
if ret==0:
log.debug("Successfully ejected.")
return errorCodes.OK
else:
log.debug("Failed to eject device (Error code: %d)" % ret)
return errorCodes.UNKNOWN
16 changes: 10 additions & 6 deletions errorCodes.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
# -*- coding: utf-8 -*-
#Falcon common error codes
#Copyright (C) 2019 Yukio Nozawa <personal@nyanchangames.com>
#Copyright (C) 2020 yamahubuki <itiro.ishino@gmail.com>
#Note: All comments except these top lines will be written in Japanese.

"""
エラーコードは、Falconの全体で共通です。ここに書かれているもの以外のエラーコードを定義してはいけません。
"""

OK=0#成功(エラーなし)
NOT_SUPPORTED=1#サポートされていない呼び出し
BOUNDARY=2#協会に到達したためリジェクト
FILE_NOT_FOUND=3#ファイルが存在しない
PARSING_FAILED=4#パーシングエラー
FATAL=5#続行不可能なエラー
OK=0 #成功(エラーなし)
NOT_SUPPORTED=1 #サポートされていない呼び出し
BOUNDARY=2 #境界に到達したためリジェクト
FILE_NOT_FOUND=3 #ファイルが存在しない
PARSING_FAILED=4 #パーシングエラー
FATAL=5 #続行不可能なエラー
ACCESS_DENIED=6 #アクセス拒否


UNKNOWN=99999
10 changes: 0 additions & 10 deletions misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
log=getLogger("falcon.misc")

falconHelper=ctypes.cdll.LoadLibrary("falconHelper.dll")
falconHelper.ejectDevice.argtypes=[ctypes.c_char_p]

class Timer:
"""シンプルなタイマー。経過時間や処理時間を計測するのに使う。単位は秒で、float。"""
Expand Down Expand Up @@ -140,12 +139,3 @@ def GetExecutableState(path):
"""指定されたファイルパスが、実行可能ファイルであろうかどうかを調べて boolean で返す。"""
return os.path.splitext(path)[1].upper() in os.environ["pathext"].split(";")

def EjectDevice(letter):
log.debug("Trying to eject drive %s..." % letter)
ret=falconHelper.ejectDevice(letter.encode('utf-8'))
if ret==0:
log.debug("Successfully ejected.")
return True
else:
log.debug("Failed to eject device (Error code: %d)" % ret)
return False
6 changes: 6 additions & 0 deletions tabObjects.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ def GetFocusedItem(self):
"""現在フォーカスが当たっているアイテムのインデックス番号を取得する。"""
return self.hListCtrl.GetFocusedItem()

def GetFocusedElement(self):
"""現在フォーカスが当たっているアイテムをbrowsableObjectsで返す"""
if self.GetFocusedItem()<0:
return None
return self.listObject.GetElement(self.GetFocusedItem())

# 選択されているアイテムが1つ以上存在するか否か
def IsItemSelected(self):
return self.hListCtrl.GetSelectedItemCount()>0
Expand Down
37 changes: 35 additions & 2 deletions views/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import tabObjects
import menuItemsStore
import fileSystemManager
import deviceCtrl

import views.fonttest
import views.changeAttribute
Expand Down Expand Up @@ -181,6 +182,9 @@ def Apply(self,target,event):

#ツールメニューの中身
self.RegisterMenuCommand(self.hToolMenu,"TOOL_DIRCALC",_("フォルダ容量計算"))
self.RegisterMenuCommand(self.hToolMenu,"TOOL_EJECT_DRIVE",_("ドライブの取り外し"))
self.RegisterMenuCommand(self.hToolMenu,"TOOL_EJECT_DEVICE",_("デバイスの取り外し"))


#環境メニューの中身
self.RegisterMenuCommand(self.hEnvMenu,"ENV_TESTDIALOG",_("テストダイアログを表示"))
Expand Down Expand Up @@ -375,6 +379,35 @@ def OnMenuSelect(self,event):
if selected==menuItemsStore.getRef("TOOL_DIRCALC"):
self.parent.activeTab.DirCalc()
return
if selected==menuItemsStore.getRef("TOOL_EJECT_DRIVE"):
if self.parent.activeTab.listObject.__class__!=listObjects.DriveList:
return
if self.parent.activeTab.GetFocusedItem()<0:
return
ret=deviceCtrl.ejectDrive(self.parent.activeTab.GetFocusedElement().letter)
if ret==errorCodes.OK:
dialog(_("成功"),_("ドライブは安全に切断されました。"))
self.UpdateFilelist(False)
elif ret==errorCodes.FILE_NOT_FOUND:
dialog(_("エラー"),_("指定されたドライブが見つかりません。既に取り外しされた可能性があります。"))
elif ret==errorCodes.UNKNOWN:
#エラー表示はむこうでやってる
pass
elif errorCodes.ACCESS_DENIED:
dialog(_("エラー"),_("取り外しに失敗しました。")+_("このドライブは使用中の可能性があります。"))
return
if selected==menuItemsStore.getRef("TOOL_EJECT_DEVICE"):
if self.parent.activeTab.listObject.__class__!=listObjects.DriveList:
return
if self.parent.activeTab.GetFocusedItem()<0:
return
ret=deviceCtrl.EjectDevice(self.parent.activeTab.GetFocusedElement().letter)
if ret==errorCodes.OK:
dialog(_("成功"),_("デバイスは安全に取り外せる状態になりました。"))
self.UpdateFilelist(False)
elif ret==errorCodes.UNKNOWN:
dialog(_("エラー"),_("デバイスの取り外しに失敗しました。"))
return
if selected==menuItemsStore.getRef("ENV_TESTDIALOG"):
self.testdialog=views.test.View()
self.testdialog.Initialize()
Expand Down Expand Up @@ -458,6 +491,6 @@ def SortCycleAd(self):
t=self.parent.activeTab
t.SortCycleAd()

def UpdateFilelist(self):
ret=self.parent.activeTab.UpdateFilelist()
def UpdateFilelist(self,silence=True):
ret=self.parent.activeTab.UpdateFilelist(silence=silence)

0 comments on commit ad7d9d7

Please sign in to comment.