Skip to content

Commit

Permalink
Address review comments.
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelDCurran committed May 31, 2019
1 parent 009f31b commit c4569d6
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 13 deletions.
2 changes: 1 addition & 1 deletion nvdaHelper/local/oleUtils.cpp
Expand Up @@ -26,7 +26,7 @@ HRESULT getOleClipboardText(IDataObject* dataObject, BSTR* text) {
FORMATETC format={CF_UNICODETEXT,nullptr,DVASPECT_CONTENT,-1,TYMED_HGLOBAL};
STGMEDIUM medium={0};
HRESULT res=dataObject->GetData(&format,&medium);
if(res!=S_OK) {
if(FAILED(res)) {
LOG_DEBUGWARNING(L"IDataObject::getData failed with error "<<res);
return res;
}
Expand Down
2 changes: 1 addition & 1 deletion source/NVDAObjects/window/edit.py
Expand Up @@ -586,7 +586,7 @@ def _getEmbeddedObjectLabel(self,embedRangeObj):
# As a final fallback (e.g. could not get display model text for Outlook Express), use the embedded object's user type (e.g. "recipient").
try:
oleObj=o.QueryInterface(oleTypes.IOleObject)
label="bad" #oleObj.GetUserType(1)
label=oleObj.GetUserType(1)
except comtypes.COMError:
pass
return label
Expand Down
26 changes: 26 additions & 0 deletions source/winKernel.py
Expand Up @@ -334,8 +334,19 @@ def DuplicateHandle(sourceProcessHandle, sourceHandle, targetProcessHandle, desi
GMEM_MOVEABLE=2

class HGLOBAL(HANDLE):
"""
A class for the HGLOBAL Windows handle type.
This class can auto-free the handle when it goes out of scope,
and also contains a classmethod for alloc,
And a context manager compatible method for locking.
"""

def __init__(self,h,autoFree=True):
"""
@param h: the raw Windows HGLOBAL handle
@param autoFree: True by default, the handle will automatically be freed with GlobalFree
when this object goes out of scope.
"""
super(HGLOBAL,self).__init__(h)
self._autoFree=autoFree

Expand All @@ -345,15 +356,30 @@ def __del__(self):

@classmethod
def alloc(cls,flags,size):
"""
Allocates global memory with GlobalAlloc
providing it as an instance of this class.
This method Takes the same arguments as GlobalAlloc.
"""
h=windll.kernel32.GlobalAlloc(flags,size)
return cls(h)

@contextlib.contextmanager
def lock(self):
"""
Used as a context manager,
This method locks the global memory with GlobalLock,
providing the usable memory address to the body of the 'with' statement.
When the body completes, GlobalUnlock is automatically called.
"""
try:
yield windll.kernel32.GlobalLock(self)
finally:
windll.kernel32.GlobalUnlock(self)

def forget(self):
"""
Sets this HGLOBAL value to NULL, forgetting the existing value.
Necessary if you pass this HGLOBAL to an API that takes ownership and therefore will handle freeing itself.
"""
self.value=None
24 changes: 13 additions & 11 deletions source/winUser.py
Expand Up @@ -627,29 +627,30 @@ def openClipboard(hwndOwner=None):
Use as the expression of a 'with' statement, and CloseClipboard will automatically be called at the end.
"""
if not windll.user32.OpenClipboard(hwndOwner):
raise RuntimeError("OpenClipboard failed")
raise ctypes.WinError()
try:
yield
finally:
windll.user32.CloseClipboard()

def emptyClipboard():
windll.user32.EmptyClipboard()
if not windll.user32.EmptyClipboard():
raise ctypes.WinError()

def getClipboardData(format):
# We only support unicode text for now
if format!=CF_UNICODETEXT:
raise ValueError("Unsupported format")
# Fetch the data from the clipboard as a global memory handle
h=windll.user32.GetClipboardData(format)
if h:
# Lock the global memory while we fetch the unicode string
# But make sure not to free the memory accidentally -- it is not ours
h=winKernel.HGLOBAL(h,autoFree=False)
with h.lock() as addr:
if addr:
# Read the string from the local memory address
return wstring_at(addr)
if not h:
raise ctypes.WinError()
# Lock the global memory while we fetch the unicode string
# But make sure not to free the memory accidentally -- it is not ours
h=winKernel.HGLOBAL(h,autoFree=False)
with h.lock() as addr:
# Read the string from the local memory address
return wstring_at(addr)

def setClipboardData(format,data):
# For now only unicode is a supported format
Expand All @@ -665,6 +666,7 @@ def setClipboardData(format,data):
buf=(c_wchar*bufLen).from_address(addr)
buf.value=text
# Set the clipboard data with the global memory
windll.user32.SetClipboardData(format,h)
if not windll.user32.SetClipboardData(format,h):
raise ctypes.WinError()
# NULL the global memory handle so that it is not freed at the end of scope as the clipboard now has it.
h.forget()

0 comments on commit c4569d6

Please sign in to comment.