diff --git a/.gitignore b/.gitignore index 048900e28..a479f336d 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,7 @@ CMakeLists.txt.user # doxgen output doxygen/html/ + +# Visual Studio Code + CMake +.vscode/ +build/ diff --git a/windows/hid.c b/windows/hid.c index dacfb9192..1e27f10a4 100644 --- a/windows/hid.c +++ b/windows/hid.c @@ -20,12 +20,6 @@ https://github.com/libusb/hidapi . ********************************************************/ -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) -/* Do not warn about wcsncpy usage. - https://docs.microsoft.com/cpp/c-runtime-library/security-features-in-the-crt */ -#define _CRT_SECURE_NO_WARNINGS -#endif - #ifdef __cplusplus extern "C" { #endif @@ -66,6 +60,16 @@ typedef LONG NTSTATUS; #include #include +/* MSVC secure CRT (VS2005+) provides swprintf_s/wcsncpy_s. + Older MSVC and GCC/MinGW/Cygwin use the classic variants. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#define HIDAPI_SWPRINTF swprintf_s +#define HIDAPI_WCSNCPY(dest, dest_count, src) wcsncpy_s((dest), (dest_count), (src), _TRUNCATE) +#else +#define HIDAPI_SWPRINTF swprintf +#define HIDAPI_WCSNCPY(dest, dest_count, src) wcsncpy((dest), (src), (dest_count)) +#endif + #ifdef MIN #undef MIN #endif @@ -286,7 +290,8 @@ static void register_winapi_error_to_buffer(wchar_t **error_buffer, const WCHAR if (!msg) return; - int printf_written = swprintf(msg, msg_len + 1, L"%.*ls: (0x%08X) %.*ls", (int)op_len, op, error_code, (int)system_err_len, system_err_buf); + int printf_written = HIDAPI_SWPRINTF(msg, msg_len + 1, L"%.*ls: (0x%08X) %.*ls", (int)op_len, op, error_code, (int)system_err_len, system_err_buf); + msg[msg_len] = L'\0'; if (printf_written < 0) { @@ -1432,7 +1437,7 @@ int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev return -1; } - wcsncpy(string, dev->device_info->manufacturer_string, maxlen); + HIDAPI_WCSNCPY(string, maxlen, dev->device_info->manufacturer_string); string[maxlen - 1] = L'\0'; register_string_error(dev, NULL); @@ -1452,7 +1457,7 @@ int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wch return -1; } - wcsncpy(string, dev->device_info->product_string, maxlen); + HIDAPI_WCSNCPY(string, maxlen, dev->device_info->product_string); string[maxlen - 1] = L'\0'; register_string_error(dev, NULL); @@ -1472,7 +1477,7 @@ int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *de return -1; } - wcsncpy(string, dev->device_info->serial_number, maxlen); + HIDAPI_WCSNCPY(string, maxlen, dev->device_info->serial_number); string[maxlen - 1] = L'\0'; register_string_error(dev, NULL); diff --git a/windows/hidapi_descriptor_reconstruct.h b/windows/hidapi_descriptor_reconstruct.h index 4b8ca83fb..6471204b2 100644 --- a/windows/hidapi_descriptor_reconstruct.h +++ b/windows/hidapi_descriptor_reconstruct.h @@ -19,12 +19,6 @@ #ifndef HIDAPI_DESCRIPTOR_RECONSTRUCT_H__ #define HIDAPI_DESCRIPTOR_RECONSTRUCT_H__ -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) -/* Do not warn about wcsncpy usage. - https://docs.microsoft.com/cpp/c-runtime-library/security-features-in-the-crt */ -#define _CRT_SECURE_NO_WARNINGS -#endif - #include "hidapi_winapi.h" #ifdef _MSC_VER diff --git a/windows/test/hid_report_reconstructor_test.c b/windows/test/hid_report_reconstructor_test.c index a7adeb54d..65e6d0088 100644 --- a/windows/test/hid_report_reconstructor_test.c +++ b/windows/test/hid_report_reconstructor_test.c @@ -9,13 +9,40 @@ #include #include +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#define HIDAPI_SSCANF sscanf_s +#define HIDAPI_FSCANF fscanf_s +#define HIDAPI_SCANSET_SIZE(buf) , (unsigned)_countof(buf) +#else +#define HIDAPI_SSCANF sscanf +#define HIDAPI_FSCANF fscanf +#define HIDAPI_SCANSET_SIZE(buf) +#endif + +#define sscanf HIDAPI_SSCANF + +static const char* hidapi_strerror_compat(int errnum, char* buf, size_t buf_size) +{ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + if (strerror_s(buf, buf_size, errnum) == 0) { + return buf; + } + return "Unknown error"; +#else + (void)buf; + (void)buf_size; + return strerror(errnum); +#endif +} + static hidp_preparsed_data * alloc_preparsed_data_from_file(char* filename) { FILE* file; errno_t err = fopen_s(&file, filename, "r"); if (err != 0) { - fprintf(stderr, "ERROR: Couldn't open file '%s' for reading: %s\n", filename, strerror(err)); + char err_buf[128]; + fprintf(stderr, "ERROR: Couldn't open file '%s' for reading: %s\n", filename, hidapi_strerror_compat((int)err, err_buf, sizeof(err_buf))); return NULL; } @@ -49,8 +76,8 @@ static hidp_preparsed_data * alloc_preparsed_data_from_file(char* filename) if (sscanf(line, "dev->product_id = 0x%04hX\n", &product_id)) continue; if (sscanf(line, "dev->usage_page = 0x%04hX\n", &usage_page)) continue; if (sscanf(line, "dev->usage = 0x%04hX\n", &usage)) continue; - if (sscanf(line, "dev->manufacturer_string = \"%127[^\"\n]", manufacturer_string)) continue; - if (sscanf(line, "dev->product_string = \"%127[^\"\n]", product_string)) continue; + if (sscanf(line, "dev->manufacturer_string = \"%127[^\"\n]", manufacturer_string HIDAPI_SCANSET_SIZE(manufacturer_string))) continue; + if (sscanf(line, "dev->product_string = \"%127[^\"\n]", product_string HIDAPI_SCANSET_SIZE(product_string))) continue; if (sscanf(line, "dev->release_number = 0x%04hX\n", &release_number)) continue; if (sscanf(line, "dev->interface_number = %d\n", &interface_number)) continue; // if (sscanf(line, "dev->path = \"%127[^\"]\n", path)) continue; @@ -456,14 +483,15 @@ static BOOLEAN read_hex_data_from_text_file(const char *filename, unsigned char FILE* file = NULL; errno_t err = fopen_s(&file, filename, "r"); if (err != 0) { - fprintf(stderr, "ERROR: Couldn't open file '%s' for reading: %s\n", filename, strerror(err)); + char err_buf[128]; + fprintf(stderr, "ERROR: Couldn't open file '%s' for reading: %s\n", filename, hidapi_strerror_compat((int)err, err_buf, sizeof(err_buf))); return FALSE; } BOOLEAN result = TRUE; unsigned int val; char buf[16]; - while (fscanf(file, "%15s", buf) == 1) { + while (HIDAPI_FSCANF(file, "%15s", buf HIDAPI_SCANSET_SIZE(buf)) == 1) { if (sscanf(buf, "0x%X", &val) != 1) { fprintf(stderr, "Invalid HEX text ('%s') file, got %s\n", filename, buf); result = FALSE;