-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GetOverlappedResult implementation #115
Merged
Merged
Changes from 9 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
c02d634
Initial code for GetOverlappedResult
exvito a1757dd
Fix WriteFile result checking in the async case
exvito bc61e17
Preliminary work on GetOverlappedResult test
exvito 3cd2e6d
Fix internal CFFI/C type in GetOverlappedResult
exvito 7fc4b28
lint - Missing final newline in kernel32/__init__.py
exvito dc9f0bc
One GetOverlappedResult test in place - WriteFile
exvito cd84b6b
GetOverlappedResult - Fix silly text/bytes conversion mistake
exvito 57d80a2
GetOverlappedResult adjustments following review
exvito 9cd217e
Fix GetOverlappedResult WriteFile tests per MSDN docs
exvito 9635977
Merge remote-tracking branch 'upstream/master' into get-ov-result
exvito 2288d5d
Improved GetOverlappedResult error_check and WriteFile test
exvito 4842a58
Removed unused import in GetOverlappedResult wrapper
exvito File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
""" | ||
Overlapped | ||
---------- | ||
|
||
A module containing Windows functions for working with OVERLAPPED objects. | ||
""" | ||
|
||
from pywincffi.core import dist | ||
from pywincffi.core.checks import NON_ZERO, input_check, error_check | ||
from pywincffi.exceptions import WindowsAPIError | ||
from pywincffi.wintypes import HANDLE, OVERLAPPED, wintype_to_cdata | ||
|
||
|
||
def GetOverlappedResult(hFile, lpOverlapped, bWait): | ||
""" | ||
Retrieves the results of an overlapped operation on the specified file, | ||
named pipe, or communications device. To specify a timeout interval or | ||
wait on an alertable thread, use GetOverlappedResultEx. | ||
|
||
.. seealso:: | ||
|
||
https://msdn.microsoft.com/en-us/library/ms683209 | ||
|
||
:param pywincffi.wintypes.HANDLE hFile: | ||
A handle to the file, named pipe, or communications device. | ||
This is the same handle that was specified when the overlapped | ||
operation was started by a call to the ReadFile, WriteFile, | ||
ConnectNamedPipe, TransactNamedPipe, DeviceIoControl, or WaitCommEvent | ||
function. | ||
|
||
:param pywincffi.wintypes.OVERLAPPED lpOverlapped: | ||
The an OVERLAPPED object that was specified when the overlapped | ||
operation was started | ||
|
||
:param bool bWait: | ||
If this parameter is TRUE, and the Internal member of the lpOverlapped | ||
structure is STATUS_PENDING, the function does not return until the | ||
operation has been completed. If this parameter is FALSE and the | ||
operation is still pending, the function returns FALSE and the | ||
GetLastError function returns ERROR_IO_INCOMPLETE | ||
|
||
:returns: | ||
The number of bytes that were actually transferred by a read or write | ||
operation. For a TransactNamedPipe operation, this is the number of | ||
bytes that were read from the pipe. For a DeviceIoControl operation, | ||
this is the number of bytes of output data returned by the device | ||
driver. For a ConnectNamedPipe or WaitCommEvent operation, this value | ||
is undefined. | ||
""" | ||
input_check("hFile", hFile, HANDLE) | ||
input_check("lpOverlapped", lpOverlapped, OVERLAPPED) | ||
input_check("bWait", bWait, allowed_values=(True, False)) | ||
|
||
ffi, library = dist.load() | ||
|
||
lpNumberOfBytesTransferred = ffi.new("DWORD[1]") | ||
|
||
result = library.GetOverlappedResult( | ||
wintype_to_cdata(hFile), | ||
wintype_to_cdata(lpOverlapped), | ||
lpNumberOfBytesTransferred, | ||
ffi.cast("BOOL", bWait), | ||
) | ||
|
||
try: | ||
error_check("GetOverlappedResult", result, NON_ZERO) | ||
except WindowsAPIError as error: | ||
if error.errno != library.ERROR_ALREADY_EXISTS: | ||
raise | ||
|
||
return int(lpNumberOfBytesTransferred[0]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import os | ||
import shutil | ||
import tempfile | ||
|
||
from six import text_type | ||
|
||
from pywincffi.dev.testutil import TestCase | ||
|
||
from pywincffi.core import dist | ||
|
||
from pywincffi.kernel32 import ( | ||
CreateFile, WriteFile, CloseHandle, CreateEvent, GetOverlappedResult) | ||
from pywincffi.wintypes import OVERLAPPED | ||
|
||
|
||
class TestOverlappedWriteFile(TestCase): | ||
""" | ||
Tests for :func:`pywincffi.kernel32.GetOverlappedResult` | ||
""" | ||
def test_overlapped_write_file(self): | ||
# Test outline: | ||
# - Create a temp dir. | ||
# - CreateFile for writing with FILE_FLAG_OVERLAPPED. | ||
# - WriteFile in overlapped mode. | ||
# - Use GetOverlappedResult to wait for IO completion. | ||
|
||
temp_dir = tempfile.mkdtemp(prefix="pywincffi-test-ovr-") | ||
self.addCleanup(shutil.rmtree, temp_dir, ignore_errors=True) | ||
|
||
filename = text_type(os.path.join(temp_dir, "overlapped-write-file")) | ||
file_contents = b"hello overlapped world" | ||
|
||
_, lib = dist.load() | ||
handle = CreateFile( | ||
lpFileName=filename, | ||
dwDesiredAccess=lib.GENERIC_WRITE, | ||
dwCreationDisposition=lib.CREATE_NEW, | ||
dwFlagsAndAttributes=lib.FILE_FLAG_OVERLAPPED, | ||
) | ||
|
||
# Prepare overlapped write | ||
ovr = OVERLAPPED() | ||
ovr.hEvent = CreateEvent(bManualReset=True, bInitialState=False) | ||
|
||
# Go for overlapped WriteFile. Should result in: | ||
# - num_bytes_written == 0 | ||
# - GetLastError() == ERROR_IO_PENDING | ||
|
||
# HOWEVER, https://msdn.microsoft.com/en-us/library/aa365683 states: | ||
# "Further, the WriteFile function will sometimes return TRUE with a | ||
# GetLastError value of ERROR_SUCCESS, even though it is using an | ||
# asynchronous handle (which can also return FALSE with | ||
# ERROR_IO_PENDING). | ||
# Test strategy: | ||
# - Disregard WriteFile return result. | ||
# - Assert GetLastError is either ERROR_IO_PENDING or ERROR_SUCCESS. | ||
# - Later validate that the correct number of bytes was written. | ||
|
||
_ = WriteFile(handle, file_contents, lpOverlapped=ovr) | ||
error_code, _ = self.GetLastError() | ||
self.assertIn(error_code, (lib.ERROR_IO_PENDING, 0)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interestingly, I merged some code yesterday you could use here: https://github.com/opalmer/pywincffi/blob/master/pywincffi/dev/testutil.py#L295 Basically, replace assertIn and SetLastError with: self.maybe_assert_last_error(lib.ERROR_IO_PENDING) |
||
|
||
# Reset last error so that TestCase cleanups don't error out. | ||
self.SetLastError(0) | ||
|
||
# Block until async write is completed. | ||
num_bytes_written = GetOverlappedResult(handle, ovr, bWait=True) | ||
self.assertEqual(num_bytes_written, len(file_contents)) | ||
|
||
CloseHandle(handle) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have not checked the tests yet, but you might be missing coverage here. The reason I think this might be the case is because there's a cleanup step in the tests which callsGetLastError()
to see there are any unhandled errors that need to be reset:https://github.com/opalmer/pywincffi/blob/master/pywincffi/dev/testutil.py#L222Looking at your test results, that check does not appear to be failing.And of course had I read your description first before doing the code review, I would have seen this was in fact covered. Sorry!