Am einfachsten und präzisesten Weg verwenden NT Api NtReadFile und überprüfen Sie den endgültigen Status der Operation. Zeitüberschreitung < => iosb.Status == STATUS_TIMEOUT. kernel32 api Readfile - verlorene Daten für diesen Status (STATUS_TIMEOUT), weil es nur für STATUS_PENDING überprüfen und 0> Status
für synchrone Arbeit können Code wie folgt verwendet werden:
void SyncTest(POBJECT_ATTRIBUTES poa)
{
HANDLE hFile;
IO_STATUS_BLOCK iosb;
NTSTATUS status = NtOpenFile(&hFile, FILE_ALL_ACCESS, poa, &iosb, FILE_SHARE_VALID_FLAGS, FILE_SYNCHRONOUS_IO_NONALERT);
if (0 <= status)
{
SERIAL_TIMEOUTS st = { 4000, 1, 0, 1, 0 };
status = NtDeviceIoControlFile(hFile, 0, 0, 0, &iosb, IOCTL_SERIAL_SET_TIMEOUTS, &st, sizeof(st), 0, 0);
DbgPrint("time %x[%x,%p]\n", status, iosb.Status, iosb.Information);
if (0 <= status)
{
UCHAR buf[256];
status = NtReadFile(hFile, 0, 0, 0, &iosb, buf, sizeof(buf), 0, 0);
DbgPrint("read %x [%x,%p]\n", status, iosb.Status, iosb.Information);
//assert(status == iosb.Status);
if (status == STATUS_TIMEOUT)
{
DbgPrint("timeout\n");
}
}
NtClose(hFile);
}
}
für asynchrone:
class __declspec(novtable) IoObject
{
friend class UserIrp;
protected:
HANDLE _hFile;
private:
LONG _dwRef;
protected:
virtual ~IoObject()
{
if (_hFile) NtClose(_hFile);
}
virtual void OnIoComplete(NTSTATUS status, ULONG_PTR Information, ULONG code, PVOID pv) = 0;
public:
NTSTATUS BindIoCompletion();
void AddRef()
{
InterlockedIncrement(&_dwRef);
}
void Release()
{
if (!InterlockedDecrement(&_dwRef)) delete this;
}
IoObject()
{
_hFile = 0;
_dwRef = 1;
}
};
class UserIrp : public IO_STATUS_BLOCK
{
friend IoObject;
IoObject* _pObj;
PVOID _pv;
LONG _dwRef;
ULONG _code;
static VOID WINAPI OnComplete(NTSTATUS Status, ULONG_PTR Information, UserIrp* This)
{
This->_pObj->OnIoComplete(Status, Information, This->_code, This->_pv);
This->Release();
}
~UserIrp()
{
_pObj->Release();
}
public:
NTSTATUS CheckStatus(NTSTATUS status)
{
if (NT_ERROR(status))
{
OnComplete(status, Information, this);
}
return status;
}
void AddRef()
{
InterlockedIncrement(&_dwRef);
}
void Release()
{
if (!InterlockedDecrement(&_dwRef)) delete this;
}
UserIrp(IoObject* pObj, ULONG code, PVOID pv) : _pObj(pObj), _dwRef(1), _code(code), _pv(pv)
{
pObj->AddRef();
}
};
NTSTATUS IoObject::BindIoCompletion()
{
return RtlSetIoCompletionCallback(_hFile, (LPOVERLAPPED_COMPLETION_ROUTINE)UserIrp::OnComplete, 0);
}
class MySerial : public IoObject
{
void OnIoComplete(NTSTATUS status, ULONG_PTR Information, ULONG code, PVOID pv)
{
DbgPrint("OnIoComplete(%x, %p, %.4s, %p)\n", status, Information, &code, pv);
switch (code)
{
case 'time':
if (0 <= status)
{
if (PUCHAR buf = new UCHAR[256])
{
if (UserIrp* Irp = new UserIrp(this, 'read', buf))
{
static LARGE_INTEGER ByteOffset;
status = Irp->CheckStatus(NtReadFile(_hFile, 0, 0, Irp, Irp, buf, 256, &ByteOffset, 0));
DbgPrint("read begin = %x\n", status);
return ;
}
delete buf;
}
}
break;
case 'read':
DbgPrint("read end(%x, %p)\n", status, Information);
if (status == STATUS_TIMEOUT)
{
DbgPrint("timeout\n");
}
delete pv;
break;
}
}
virtual ~MySerial()
{
DbgPrint("--MySerial<%p>\n", this);
}
public:
MySerial()
{
DbgPrint("++MySerial<%p>\n", this);
}
NTSTATUS Open(POBJECT_ATTRIBUTES poa)
{
IO_STATUS_BLOCK iosb;
return NtOpenFile(&_hFile, FILE_ALL_ACCESS, poa, &iosb, FILE_SHARE_VALID_FLAGS, 0);
}
NTSTATUS SetTimeouts(ULONG ms)
{
if (UserIrp* Irp = new UserIrp(this, 'time', 0))
{
SERIAL_TIMEOUTS st = { ms, 1, 0, 1, 0 };
return Irp->CheckStatus(ZwDeviceIoControlFile(_hFile, 0, 0, Irp, Irp, IOCTL_SERIAL_SET_TIMEOUTS, &st, sizeof(st), 0, 0));
}
return STATUS_INSUFFICIENT_RESOURCES;
}
};
void AsyncTest(POBJECT_ATTRIBUTES poa)
{
if (MySerial* p = new MySerial)
{
if (0 <= p->Open(poa) && 0 <= p->BindIoCompletion())
{
NTSTATUS status = p->SetTimeouts(4000);
DbgPrint("set timeout=%x\n", status);
}
p->Release();
}
}
Hat es irgendwelche Bytes übertragen? – EJP
* Wenn ReadFile true zurückgibt, aber der dwRead-Parameter 0 ergibt, [...] schließe ich, dass die ReadFile-Funktion ein Zeitlimit haben muss * - für eine serielle Schnittstelle halte ich dies für eine sichere Schlussfolgerung. Wenn es irgendeinen anderen Grund gäbe, wäre der Anruf fehlgeschlagen. –
OK, ich werde das in meinem Programm verwenden. Zu diesem Zeitpunkt habe ich nur den USB-UART-Konverter an meinen Laptop angeschlossen, am anderen Ende des Konverters befindet sich kein Gerät, so dass Daten eingelesen werden. – quantum231