codekingpro/portable-devtools
114k
1# Regedit - a Registry Editor for Python2 3import commctrl4import regutil5import win32api6import win32con7import win32ui8from pywin.mfc import dialog, docview, window9 10from . import hierlist11 12 13def SafeApply(fn, args, err_desc=""):14 try:15 fn(*args)16 return 117 except win32api.error as exc:18 msg = "Error " + err_desc + "\r\n\r\n" + exc.strerror19 win32ui.MessageBox(msg)20 return 021 22 23class SplitterFrame(window.MDIChildWnd):24 def __init__(self):25 # call base CreateFrame26 self.images = None27 window.MDIChildWnd.__init__(self)28 29 def OnCreateClient(self, cp, context):30 splitter = win32ui.CreateSplitter()31 doc = context.doc32 frame_rect = self.GetWindowRect()33 size = ((frame_rect[2] - frame_rect[0]), (frame_rect[3] - frame_rect[1]) // 2)34 sub_size = (size[0] // 3, size[1])35 splitter.CreateStatic(self, 1, 2)36 # CTreeControl view37 self.keysview = RegistryTreeView(doc)38 # CListControl view39 self.valuesview = RegistryValueView(doc)40 41 splitter.CreatePane(self.keysview, 0, 0, (sub_size))42 splitter.CreatePane(self.valuesview, 0, 1, (0, 0)) # size ignored.43 splitter.SetRowInfo(0, size[1], 0)44 # Setup items in the imagelist45 46 return 147 48 def OnItemDoubleClick(self, info, extra):49 (hwndFrom, idFrom, code) = info50 if idFrom == win32ui.AFX_IDW_PANE_FIRST:51 # Tree control52 return None53 elif idFrom == win32ui.AFX_IDW_PANE_FIRST + 1:54 item = self.keysview.SelectedItem()55 self.valuesview.EditValue(item)56 return 057 # List control58 else:59 return None # Pass it on60 61 def PerformItemSelected(self, item):62 return self.valuesview.UpdateForRegItem(item)63 64 def OnDestroy(self, msg):65 window.MDIChildWnd.OnDestroy(self, msg)66 if self.images:67 self.images.DeleteImageList()68 self.images = None69 70 71class RegistryTreeView(docview.TreeView):72 def OnInitialUpdate(self):73 rc = self._obj_.OnInitialUpdate()74 self.frame = self.GetParent().GetParent()75 self.hierList = hierlist.HierListWithItems(76 self.GetHLIRoot(), win32ui.IDB_HIERFOLDERS, win32ui.AFX_IDW_PANE_FIRST77 )78 self.hierList.HierInit(self.frame, self.GetTreeCtrl())79 self.hierList.SetStyle(80 commctrl.TVS_HASLINES | commctrl.TVS_LINESATROOT | commctrl.TVS_HASBUTTONS81 )82 self.hierList.PerformItemSelected = self.PerformItemSelected83 84 self.frame.HookNotify(self.frame.OnItemDoubleClick, commctrl.NM_DBLCLK)85 self.frame.HookNotify(self.OnItemRightClick, commctrl.NM_RCLICK)86 87 # self.HookMessage(self.OnItemRightClick, win32con.WM_RBUTTONUP)88 89 def GetHLIRoot(self):90 doc = self.GetDocument()91 regroot = doc.root92 subkey = doc.subkey93 return HLIRegistryKey(regroot, subkey, "Root")94 95 def OnItemRightClick(self, notify_data, extra):96 # First select the item we right-clicked on.97 pt = self.ScreenToClient(win32api.GetCursorPos())98 flags, hItem = self.HitTest(pt)99 if hItem == 0 or commctrl.TVHT_ONITEM & flags == 0:100 return None101 self.Select(hItem, commctrl.TVGN_CARET)102 103 menu = win32ui.CreatePopupMenu()104 menu.AppendMenu(win32con.MF_STRING | win32con.MF_ENABLED, 1000, "Add Key")105 menu.AppendMenu(win32con.MF_STRING | win32con.MF_ENABLED, 1001, "Add Value")106 menu.AppendMenu(win32con.MF_STRING | win32con.MF_ENABLED, 1002, "Delete Key")107 self.HookCommand(self.OnAddKey, 1000)108 self.HookCommand(self.OnAddValue, 1001)109 self.HookCommand(self.OnDeleteKey, 1002)110 menu.TrackPopupMenu(win32api.GetCursorPos()) # track at mouse position.111 return None112 113 def OnDeleteKey(self, command, code):114 hitem = self.hierList.GetSelectedItem()115 item = self.hierList.ItemFromHandle(hitem)116 msg = "Are you sure you wish to delete the key '%s'?" % (item.keyName,)117 id = win32ui.MessageBox(msg, None, win32con.MB_YESNO)118 if id != win32con.IDYES:119 return120 if SafeApply(121 win32api.RegDeleteKey, (item.keyRoot, item.keyName), "deleting registry key"122 ):123 # Get the items parent.124 try:125 hparent = self.GetParentItem(hitem)126 except win32ui.error:127 hparent = None128 self.hierList.Refresh(hparent)129 130 def OnAddKey(self, command, code):131 from pywin.mfc import dialog132 133 val = dialog.GetSimpleInput("New key name", "", "Add new key")134 if val is None:135 return # cancelled.136 hitem = self.hierList.GetSelectedItem()137 item = self.hierList.ItemFromHandle(hitem)138 if SafeApply(win32api.RegCreateKey, (item.keyRoot, item.keyName + "\\" + val)):139 self.hierList.Refresh(hitem)140 141 def OnAddValue(self, command, code):142 from pywin.mfc import dialog143 144 val = dialog.GetSimpleInput("New value", "", "Add new value")145 if val is None:146 return # cancelled.147 hitem = self.hierList.GetSelectedItem()148 item = self.hierList.ItemFromHandle(hitem)149 if SafeApply(150 win32api.RegSetValue, (item.keyRoot, item.keyName, win32con.REG_SZ, val)151 ):152 # Simply re-select the current item to refresh the right spitter.153 self.PerformItemSelected(item)154 155 # self.Select(hitem, commctrl.TVGN_CARET)156 157 def PerformItemSelected(self, item):158 return self.frame.PerformItemSelected(item)159 160 def SelectedItem(self):161 return self.hierList.ItemFromHandle(self.hierList.GetSelectedItem())162 163 def SearchSelectedItem(self):164 handle = self.hierList.GetChildItem(0)165 while 1:166 # print "State is", self.hierList.GetItemState(handle, -1)167 if self.hierList.GetItemState(handle, commctrl.TVIS_SELECTED):168 # print "Item is ", self.hierList.ItemFromHandle(handle)169 return self.hierList.ItemFromHandle(handle)170 handle = self.hierList.GetNextSiblingItem(handle)171 172 173class RegistryValueView(docview.ListView):174 def OnInitialUpdate(self):175 hwnd = self._obj_.GetSafeHwnd()176 style = win32api.GetWindowLong(hwnd, win32con.GWL_STYLE)177 win32api.SetWindowLong(178 hwnd,179 win32con.GWL_STYLE,180 (style & ~commctrl.LVS_TYPEMASK) | commctrl.LVS_REPORT,181 )182 183 itemDetails = (commctrl.LVCFMT_LEFT, 100, "Name", 0)184 self.InsertColumn(0, itemDetails)185 itemDetails = (commctrl.LVCFMT_LEFT, 500, "Data", 0)186 self.InsertColumn(1, itemDetails)187 188 def UpdateForRegItem(self, item):189 self.DeleteAllItems()190 hkey = win32api.RegOpenKey(item.keyRoot, item.keyName)191 try:192 valNum = 0193 ret = []194 while 1:195 try:196 res = win32api.RegEnumValue(hkey, valNum)197 except win32api.error:198 break199 name = res[0]200 if not name:201 name = "(Default)"202 self.InsertItem(valNum, name)203 self.SetItemText(valNum, 1, str(res[1]))204 valNum = valNum + 1205 finally:206 win32api.RegCloseKey(hkey)207 208 def EditValue(self, item):209 # Edit the current value210 class EditDialog(dialog.Dialog):211 def __init__(self, item):212 self.item = item213 dialog.Dialog.__init__(self, win32ui.IDD_LARGE_EDIT)214 215 def OnInitDialog(self):216 self.SetWindowText("Enter new value")217 self.GetDlgItem(win32con.IDCANCEL).ShowWindow(win32con.SW_SHOW)218 self.edit = self.GetDlgItem(win32ui.IDC_EDIT1)219 # Modify the edit windows style220 style = win32api.GetWindowLong(221 self.edit.GetSafeHwnd(), win32con.GWL_STYLE222 )223 style = style & (~win32con.ES_WANTRETURN)224 win32api.SetWindowLong(225 self.edit.GetSafeHwnd(), win32con.GWL_STYLE, style226 )227 self.edit.SetWindowText(str(self.item))228 self.edit.SetSel(-1)229 return dialog.Dialog.OnInitDialog(self)230 231 def OnDestroy(self, msg):232 self.newvalue = self.edit.GetWindowText()233 234 try:235 index = self.GetNextItem(-1, commctrl.LVNI_SELECTED)236 except win32ui.error:237 return # No item selected.238 239 if index == 0:240 keyVal = ""241 else:242 keyVal = self.GetItemText(index, 0)243 # Query for a new value.244 try:245 newVal = self.GetItemsCurrentValue(item, keyVal)246 except TypeError as details:247 win32ui.MessageBox(details)248 return249 250 d = EditDialog(newVal)251 if d.DoModal() == win32con.IDOK:252 try:253 self.SetItemsCurrentValue(item, keyVal, d.newvalue)254 except win32api.error as exc:255 win32ui.MessageBox("Error setting value\r\n\n%s" % exc.strerror)256 self.UpdateForRegItem(item)257 258 def GetItemsCurrentValue(self, item, valueName):259 hkey = win32api.RegOpenKey(item.keyRoot, item.keyName)260 try:261 val, type = win32api.RegQueryValueEx(hkey, valueName)262 if type != win32con.REG_SZ:263 raise TypeError("Only strings can be edited")264 return val265 finally:266 win32api.RegCloseKey(hkey)267 268 def SetItemsCurrentValue(self, item, valueName, value):269 # ** Assumes already checked is a string.270 hkey = win32api.RegOpenKey(271 item.keyRoot, item.keyName, 0, win32con.KEY_SET_VALUE272 )273 try:274 win32api.RegSetValueEx(hkey, valueName, 0, win32con.REG_SZ, value)275 finally:276 win32api.RegCloseKey(hkey)277 278 279class RegTemplate(docview.DocTemplate):280 def __init__(self):281 docview.DocTemplate.__init__(282 self, win32ui.IDR_PYTHONTYPE, None, SplitterFrame, None283 )284 285 # def InitialUpdateFrame(self, frame, doc, makeVisible=1):286 # self._obj_.InitialUpdateFrame(frame, doc, makeVisible) # call default handler.287 # frame.InitialUpdateFrame(doc, makeVisible)288 289 def OpenRegistryKey(290 self, root=None, subkey=None291 ): # Use this instead of OpenDocumentFile.292 # Look for existing open document293 if root is None:294 root = regutil.GetRootKey()295 if subkey is None:296 subkey = regutil.BuildDefaultPythonKey()297 for doc in self.GetDocumentList():298 if doc.root == root and doc.subkey == subkey:299 doc.GetFirstView().ActivateFrame()300 return doc301 # not found - new one.302 doc = RegDocument(self, root, subkey)303 frame = self.CreateNewFrame(doc)304 doc.OnNewDocument()305 self.InitialUpdateFrame(frame, doc, 1)306 return doc307 308 309class RegDocument(docview.Document):310 def __init__(self, template, root, subkey):311 docview.Document.__init__(self, template)312 self.root = root313 self.subkey = subkey314 self.SetTitle("Registry Editor: " + subkey)315 316 def OnOpenDocument(self, name):317 raise TypeError("This template can not open files")318 return 0319 320 321class HLIRegistryKey(hierlist.HierListItem):322 def __init__(self, keyRoot, keyName, userName):323 self.keyRoot = keyRoot324 self.keyName = keyName325 self.userName = userName326 hierlist.HierListItem.__init__(self)327 328 def __lt__(self, other):329 return self.name < other.name330 331 def __eq__(self, other):332 return (333 self.keyRoot == other.keyRoot334 and self.keyName == other.keyName335 and self.userName == other.userName336 )337 338 def __repr__(self):339 return "<%s with root=%s, key=%s>" % (340 self.__class__.__name__,341 self.keyRoot,342 self.keyName,343 )344 345 def GetText(self):346 return self.userName347 348 def IsExpandable(self):349 # All keys are expandable, even if they currently have zero children.350 return 1351 352 ## hkey = win32api.RegOpenKey(self.keyRoot, self.keyName)353 ## try:354 ## keys, vals, dt = win32api.RegQueryInfoKey(hkey)355 ## return (keys>0)356 ## finally:357 ## win32api.RegCloseKey(hkey)358 359 def GetSubList(self):360 hkey = win32api.RegOpenKey(self.keyRoot, self.keyName)361 win32ui.DoWaitCursor(1)362 try:363 keyNum = 0364 ret = []365 while 1:366 try:367 key = win32api.RegEnumKey(hkey, keyNum)368 except win32api.error:369 break370 ret.append(HLIRegistryKey(self.keyRoot, self.keyName + "\\" + key, key))371 keyNum = keyNum + 1372 finally:373 win32api.RegCloseKey(hkey)374 win32ui.DoWaitCursor(0)375 return ret376 377 378template = RegTemplate()379 380 381def EditRegistry(root=None, key=None):382 doc = template.OpenRegistryKey(root, key)383 384 385if __name__ == "__main__":386 EditRegistry()387 