|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386 |
- # Regedit - a Registry Editor for Python
-
- import commctrl
- import regutil
- import win32api
- import win32con
- import win32ui
- from pywin.mfc import dialog, docview, window
-
- from . import hierlist
-
-
- def SafeApply(fn, args, err_desc=""):
- try:
- fn(*args)
- return 1
- except win32api.error as exc:
- msg = "Error " + err_desc + "\r\n\r\n" + exc.strerror
- win32ui.MessageBox(msg)
- return 0
-
-
- class SplitterFrame(window.MDIChildWnd):
- def __init__(self):
- # call base CreateFrame
- self.images = None
- window.MDIChildWnd.__init__(self)
-
- def OnCreateClient(self, cp, context):
- splitter = win32ui.CreateSplitter()
- doc = context.doc
- frame_rect = self.GetWindowRect()
- size = ((frame_rect[2] - frame_rect[0]), (frame_rect[3] - frame_rect[1]) // 2)
- sub_size = (size[0] // 3, size[1])
- splitter.CreateStatic(self, 1, 2)
- # CTreeControl view
- self.keysview = RegistryTreeView(doc)
- # CListControl view
- self.valuesview = RegistryValueView(doc)
-
- splitter.CreatePane(self.keysview, 0, 0, (sub_size))
- splitter.CreatePane(self.valuesview, 0, 1, (0, 0)) # size ignored.
- splitter.SetRowInfo(0, size[1], 0)
- # Setup items in the imagelist
-
- return 1
-
- def OnItemDoubleClick(self, info, extra):
- (hwndFrom, idFrom, code) = info
- if idFrom == win32ui.AFX_IDW_PANE_FIRST:
- # Tree control
- return None
- elif idFrom == win32ui.AFX_IDW_PANE_FIRST + 1:
- item = self.keysview.SelectedItem()
- self.valuesview.EditValue(item)
- return 0
- # List control
- else:
- return None # Pass it on
-
- def PerformItemSelected(self, item):
- return self.valuesview.UpdateForRegItem(item)
-
- def OnDestroy(self, msg):
- window.MDIChildWnd.OnDestroy(self, msg)
- if self.images:
- self.images.DeleteImageList()
- self.images = None
-
-
- class RegistryTreeView(docview.TreeView):
- def OnInitialUpdate(self):
- rc = self._obj_.OnInitialUpdate()
- self.frame = self.GetParent().GetParent()
- self.hierList = hierlist.HierListWithItems(
- self.GetHLIRoot(), win32ui.IDB_HIERFOLDERS, win32ui.AFX_IDW_PANE_FIRST
- )
- self.hierList.HierInit(self.frame, self.GetTreeCtrl())
- self.hierList.SetStyle(
- commctrl.TVS_HASLINES | commctrl.TVS_LINESATROOT | commctrl.TVS_HASBUTTONS
- )
- self.hierList.PerformItemSelected = self.PerformItemSelected
-
- self.frame.HookNotify(self.frame.OnItemDoubleClick, commctrl.NM_DBLCLK)
- self.frame.HookNotify(self.OnItemRightClick, commctrl.NM_RCLICK)
-
- # self.HookMessage(self.OnItemRightClick, win32con.WM_RBUTTONUP)
-
- def GetHLIRoot(self):
- doc = self.GetDocument()
- regroot = doc.root
- subkey = doc.subkey
- return HLIRegistryKey(regroot, subkey, "Root")
-
- def OnItemRightClick(self, notify_data, extra):
- # First select the item we right-clicked on.
- pt = self.ScreenToClient(win32api.GetCursorPos())
- flags, hItem = self.HitTest(pt)
- if hItem == 0 or commctrl.TVHT_ONITEM & flags == 0:
- return None
- self.Select(hItem, commctrl.TVGN_CARET)
-
- menu = win32ui.CreatePopupMenu()
- menu.AppendMenu(win32con.MF_STRING | win32con.MF_ENABLED, 1000, "Add Key")
- menu.AppendMenu(win32con.MF_STRING | win32con.MF_ENABLED, 1001, "Add Value")
- menu.AppendMenu(win32con.MF_STRING | win32con.MF_ENABLED, 1002, "Delete Key")
- self.HookCommand(self.OnAddKey, 1000)
- self.HookCommand(self.OnAddValue, 1001)
- self.HookCommand(self.OnDeleteKey, 1002)
- menu.TrackPopupMenu(win32api.GetCursorPos()) # track at mouse position.
- return None
-
- def OnDeleteKey(self, command, code):
- hitem = self.hierList.GetSelectedItem()
- item = self.hierList.ItemFromHandle(hitem)
- msg = "Are you sure you wish to delete the key '%s'?" % (item.keyName,)
- id = win32ui.MessageBox(msg, None, win32con.MB_YESNO)
- if id != win32con.IDYES:
- return
- if SafeApply(
- win32api.RegDeleteKey, (item.keyRoot, item.keyName), "deleting registry key"
- ):
- # Get the items parent.
- try:
- hparent = self.GetParentItem(hitem)
- except win32ui.error:
- hparent = None
- self.hierList.Refresh(hparent)
-
- def OnAddKey(self, command, code):
- from pywin.mfc import dialog
-
- val = dialog.GetSimpleInput("New key name", "", "Add new key")
- if val is None:
- return # cancelled.
- hitem = self.hierList.GetSelectedItem()
- item = self.hierList.ItemFromHandle(hitem)
- if SafeApply(win32api.RegCreateKey, (item.keyRoot, item.keyName + "\\" + val)):
- self.hierList.Refresh(hitem)
-
- def OnAddValue(self, command, code):
- from pywin.mfc import dialog
-
- val = dialog.GetSimpleInput("New value", "", "Add new value")
- if val is None:
- return # cancelled.
- hitem = self.hierList.GetSelectedItem()
- item = self.hierList.ItemFromHandle(hitem)
- if SafeApply(
- win32api.RegSetValue, (item.keyRoot, item.keyName, win32con.REG_SZ, val)
- ):
- # Simply re-select the current item to refresh the right spitter.
- self.PerformItemSelected(item)
-
- # self.Select(hitem, commctrl.TVGN_CARET)
-
- def PerformItemSelected(self, item):
- return self.frame.PerformItemSelected(item)
-
- def SelectedItem(self):
- return self.hierList.ItemFromHandle(self.hierList.GetSelectedItem())
-
- def SearchSelectedItem(self):
- handle = self.hierList.GetChildItem(0)
- while 1:
- # print "State is", self.hierList.GetItemState(handle, -1)
- if self.hierList.GetItemState(handle, commctrl.TVIS_SELECTED):
- # print "Item is ", self.hierList.ItemFromHandle(handle)
- return self.hierList.ItemFromHandle(handle)
- handle = self.hierList.GetNextSiblingItem(handle)
-
-
- class RegistryValueView(docview.ListView):
- def OnInitialUpdate(self):
- hwnd = self._obj_.GetSafeHwnd()
- style = win32api.GetWindowLong(hwnd, win32con.GWL_STYLE)
- win32api.SetWindowLong(
- hwnd,
- win32con.GWL_STYLE,
- (style & ~commctrl.LVS_TYPEMASK) | commctrl.LVS_REPORT,
- )
-
- itemDetails = (commctrl.LVCFMT_LEFT, 100, "Name", 0)
- self.InsertColumn(0, itemDetails)
- itemDetails = (commctrl.LVCFMT_LEFT, 500, "Data", 0)
- self.InsertColumn(1, itemDetails)
-
- def UpdateForRegItem(self, item):
- self.DeleteAllItems()
- hkey = win32api.RegOpenKey(item.keyRoot, item.keyName)
- try:
- valNum = 0
- ret = []
- while 1:
- try:
- res = win32api.RegEnumValue(hkey, valNum)
- except win32api.error:
- break
- name = res[0]
- if not name:
- name = "(Default)"
- self.InsertItem(valNum, name)
- self.SetItemText(valNum, 1, str(res[1]))
- valNum = valNum + 1
- finally:
- win32api.RegCloseKey(hkey)
-
- def EditValue(self, item):
- # Edit the current value
- class EditDialog(dialog.Dialog):
- def __init__(self, item):
- self.item = item
- dialog.Dialog.__init__(self, win32ui.IDD_LARGE_EDIT)
-
- def OnInitDialog(self):
- self.SetWindowText("Enter new value")
- self.GetDlgItem(win32con.IDCANCEL).ShowWindow(win32con.SW_SHOW)
- self.edit = self.GetDlgItem(win32ui.IDC_EDIT1)
- # Modify the edit windows style
- style = win32api.GetWindowLong(
- self.edit.GetSafeHwnd(), win32con.GWL_STYLE
- )
- style = style & (~win32con.ES_WANTRETURN)
- win32api.SetWindowLong(
- self.edit.GetSafeHwnd(), win32con.GWL_STYLE, style
- )
- self.edit.SetWindowText(str(self.item))
- self.edit.SetSel(-1)
- return dialog.Dialog.OnInitDialog(self)
-
- def OnDestroy(self, msg):
- self.newvalue = self.edit.GetWindowText()
-
- try:
- index = self.GetNextItem(-1, commctrl.LVNI_SELECTED)
- except win32ui.error:
- return # No item selected.
-
- if index == 0:
- keyVal = ""
- else:
- keyVal = self.GetItemText(index, 0)
- # Query for a new value.
- try:
- newVal = self.GetItemsCurrentValue(item, keyVal)
- except TypeError as details:
- win32ui.MessageBox(details)
- return
-
- d = EditDialog(newVal)
- if d.DoModal() == win32con.IDOK:
- try:
- self.SetItemsCurrentValue(item, keyVal, d.newvalue)
- except win32api.error as exc:
- win32ui.MessageBox("Error setting value\r\n\n%s" % exc.strerror)
- self.UpdateForRegItem(item)
-
- def GetItemsCurrentValue(self, item, valueName):
- hkey = win32api.RegOpenKey(item.keyRoot, item.keyName)
- try:
- val, type = win32api.RegQueryValueEx(hkey, valueName)
- if type != win32con.REG_SZ:
- raise TypeError("Only strings can be edited")
- return val
- finally:
- win32api.RegCloseKey(hkey)
-
- def SetItemsCurrentValue(self, item, valueName, value):
- # ** Assumes already checked is a string.
- hkey = win32api.RegOpenKey(
- item.keyRoot, item.keyName, 0, win32con.KEY_SET_VALUE
- )
- try:
- win32api.RegSetValueEx(hkey, valueName, 0, win32con.REG_SZ, value)
- finally:
- win32api.RegCloseKey(hkey)
-
-
- class RegTemplate(docview.DocTemplate):
- def __init__(self):
- docview.DocTemplate.__init__(
- self, win32ui.IDR_PYTHONTYPE, None, SplitterFrame, None
- )
-
- # def InitialUpdateFrame(self, frame, doc, makeVisible=1):
- # self._obj_.InitialUpdateFrame(frame, doc, makeVisible) # call default handler.
- # frame.InitialUpdateFrame(doc, makeVisible)
-
- def OpenRegistryKey(
- self, root=None, subkey=None
- ): # Use this instead of OpenDocumentFile.
- # Look for existing open document
- if root is None:
- root = regutil.GetRootKey()
- if subkey is None:
- subkey = regutil.BuildDefaultPythonKey()
- for doc in self.GetDocumentList():
- if doc.root == root and doc.subkey == subkey:
- doc.GetFirstView().ActivateFrame()
- return doc
- # not found - new one.
- doc = RegDocument(self, root, subkey)
- frame = self.CreateNewFrame(doc)
- doc.OnNewDocument()
- self.InitialUpdateFrame(frame, doc, 1)
- return doc
-
-
- class RegDocument(docview.Document):
- def __init__(self, template, root, subkey):
- docview.Document.__init__(self, template)
- self.root = root
- self.subkey = subkey
- self.SetTitle("Registry Editor: " + subkey)
-
- def OnOpenDocument(self, name):
- raise TypeError("This template can not open files")
- return 0
-
-
- class HLIRegistryKey(hierlist.HierListItem):
- def __init__(self, keyRoot, keyName, userName):
- self.keyRoot = keyRoot
- self.keyName = keyName
- self.userName = userName
- hierlist.HierListItem.__init__(self)
-
- def __lt__(self, other):
- return self.name < other.name
-
- def __eq__(self, other):
- return (
- self.keyRoot == other.keyRoot
- and self.keyName == other.keyName
- and self.userName == other.userName
- )
-
- def __repr__(self):
- return "<%s with root=%s, key=%s>" % (
- self.__class__.__name__,
- self.keyRoot,
- self.keyName,
- )
-
- def GetText(self):
- return self.userName
-
- def IsExpandable(self):
- # All keys are expandable, even if they currently have zero children.
- return 1
-
- ## hkey = win32api.RegOpenKey(self.keyRoot, self.keyName)
- ## try:
- ## keys, vals, dt = win32api.RegQueryInfoKey(hkey)
- ## return (keys>0)
- ## finally:
- ## win32api.RegCloseKey(hkey)
-
- def GetSubList(self):
- hkey = win32api.RegOpenKey(self.keyRoot, self.keyName)
- win32ui.DoWaitCursor(1)
- try:
- keyNum = 0
- ret = []
- while 1:
- try:
- key = win32api.RegEnumKey(hkey, keyNum)
- except win32api.error:
- break
- ret.append(HLIRegistryKey(self.keyRoot, self.keyName + "\\" + key, key))
- keyNum = keyNum + 1
- finally:
- win32api.RegCloseKey(hkey)
- win32ui.DoWaitCursor(0)
- return ret
-
-
- template = RegTemplate()
-
-
- def EditRegistry(root=None, key=None):
- doc = template.OpenRegistryKey(root, key)
-
-
- if __name__ == "__main__":
- EditRegistry()
|