From: Martin Ling Date: Sat, 28 Dec 2019 18:47:06 +0000 (+0100) Subject: windows: Use architecture-specific size limit for WriteFile calls. X-Git-Url: https://sigrok.org/gitweb/?p=libserialport.git;a=commitdiff_plain;h=b457865b8f42b68953bf2910dcc02d3fe27fc2a8 windows: Use architecture-specific size limit for WriteFile calls. --- diff --git a/Makefile.am b/Makefile.am index 3fa06ee..640b043 100644 --- a/Makefile.am +++ b/Makefile.am @@ -32,7 +32,7 @@ if LINUX libserialport_la_SOURCES += linux.c linux_termios.c linux_termios.h endif if WIN32 -libserialport_la_SOURCES += windows.c +libserialport_la_SOURCES += windows.c windows_ddk.c windows_ddk.h endif if MACOSX libserialport_la_SOURCES += macosx.c diff --git a/libserialport_internal.h b/libserialport_internal.h index 46c77a8..3f01b6d 100644 --- a/libserialport_internal.h +++ b/libserialport_internal.h @@ -47,6 +47,7 @@ static const GUID name = { l,w1,w2,{ b1,b2,b3,b4,b5,b6,b7,b8 } } #include #include +#include "windows_ddk.h" #else #include #include diff --git a/serialport.c b/serialport.c index d0618bb..74d46ee 100644 --- a/serialport.c +++ b/serialport.c @@ -793,6 +793,10 @@ SP_API enum sp_return sp_blocking_write(struct sp_port *port, const void *buf, RETURN_FAIL("SetCommTimeouts() failed"); } + /* Reduce count if it exceeds the WriteFile limit. */ + if (count > WRITEFILE_MAX_SIZE) + count = WRITEFILE_MAX_SIZE; + /* Start write. */ if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl)) { DEBUG("Write completed immediately"); @@ -921,6 +925,10 @@ SP_API enum sp_return sp_nonblocking_write(struct sp_port *port, RETURN_FAIL("SetCommTimeouts() failed"); } + /* Reduce count if it exceeds the WriteFile limit. */ + if (count > WRITEFILE_MAX_SIZE) + count = WRITEFILE_MAX_SIZE; + /* Copy data to our write buffer. */ buf_bytes = min(port->write_buf_size, count); memcpy(port->write_buf, buf, buf_bytes); diff --git a/windows_ddk.c b/windows_ddk.c new file mode 100644 index 0000000..34f6a56 --- /dev/null +++ b/windows_ddk.c @@ -0,0 +1,28 @@ +/* + * This file is part of the libserialport project. + * + * Copyright (C) 2019 Martin Ling + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +/* + * We can't include DDK headers in serialport.c because they conflict with + * user space headers. So this file exists to isolate the definitions which + * use the kernel declarations. + */ + +#include + +const size_t WRITEFILE_MAX_SIZE = ((65535 - sizeof(MDL)) / sizeof(ULONG_PTR)) * PAGE_SIZE; diff --git a/windows_ddk.h b/windows_ddk.h new file mode 100644 index 0000000..8e3e599 --- /dev/null +++ b/windows_ddk.h @@ -0,0 +1,25 @@ +/* + * This file is part of the libserialport project. + * + * Copyright (C) 2019 Martin Ling + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef LIBSERIALPORT_WINDOWS_DDK_H +#define LIBSERIALPORT_WINDOWS_DDK_H + +SP_PRIV extern const size_t WRITEFILE_MAX_SIZE; + +#endif