@@ -178,8 +178,7 @@ struct hid_device_ {
178
178
size_t input_report_length ;
179
179
USHORT feature_report_length ;
180
180
unsigned char * feature_buf ;
181
- void * last_error_str ;
182
- DWORD last_error_num ;
181
+ wchar_t * last_error_str ;
183
182
BOOL read_pending ;
184
183
char * read_buf ;
185
184
OVERLAPPED ol ;
@@ -198,7 +197,6 @@ static hid_device *new_hid_device()
198
197
dev -> feature_report_length = 0 ;
199
198
dev -> feature_buf = NULL ;
200
199
dev -> last_error_str = NULL ;
201
- dev -> last_error_num = 0 ;
202
200
dev -> read_pending = FALSE;
203
201
dev -> read_buf = NULL ;
204
202
memset (& dev -> ol , 0 , sizeof (dev -> ol ));
@@ -215,42 +213,101 @@ static void free_hid_device(hid_device *dev)
215
213
CloseHandle (dev -> ol .hEvent );
216
214
CloseHandle (dev -> write_ol .hEvent );
217
215
CloseHandle (dev -> device_handle );
218
- LocalFree (dev -> last_error_str );
216
+ free (dev -> last_error_str );
217
+ dev -> last_error_str = NULL ;
219
218
free (dev -> write_buf );
220
219
free (dev -> feature_buf );
221
220
free (dev -> read_buf );
222
221
hid_free_enumeration (dev -> device_info );
223
222
free (dev );
224
223
}
225
224
226
- static void register_error ( hid_device * dev , const char * op )
225
+ static void register_winapi_error_to_buffer ( wchar_t * * error_buffer , const WCHAR * op )
227
226
{
228
- WCHAR * ptr , * msg ;
229
- (void )op ;
230
- FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER |
231
- FORMAT_MESSAGE_FROM_SYSTEM |
232
- FORMAT_MESSAGE_IGNORE_INSERTS ,
227
+ if (!error_buffer )
228
+ return ;
229
+
230
+ free (* error_buffer );
231
+ * error_buffer = NULL ;
232
+
233
+ /* Only clear out error messages if NULL is passed into op */
234
+ if (!op ) {
235
+ return ;
236
+ }
237
+
238
+ WCHAR system_err_buf [1024 ];
239
+ DWORD error_code = GetLastError ();
240
+
241
+ DWORD system_err_len = FormatMessageW (
242
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS ,
233
243
NULL ,
234
- GetLastError () ,
244
+ error_code ,
235
245
MAKELANGID (LANG_NEUTRAL , SUBLANG_DEFAULT ),
236
- ( LPWSTR ) & msg , 0 /*sz*/ ,
246
+ system_err_buf , ARRAYSIZE ( system_err_buf ) ,
237
247
NULL );
238
248
249
+ DWORD op_len = (DWORD )wcslen (op );
250
+
251
+ DWORD op_prefix_len =
252
+ op_len
253
+ + 15 /*: (0x00000000) */
254
+ ;
255
+ DWORD msg_len =
256
+ + op_prefix_len
257
+ + system_err_len
258
+ ;
259
+
260
+ * error_buffer = (WCHAR * )calloc (msg_len + 1 , sizeof (WCHAR ));
261
+ WCHAR * msg = * error_buffer ;
262
+
263
+ if (!msg )
264
+ return ;
265
+
266
+ int printf_written = swprintf (msg , msg_len + 1 , L"%.*ls: (0x%08X) %.*ls" , op_len , op , error_code , system_err_len , system_err_buf );
267
+
268
+ if (printf_written < 0 )
269
+ {
270
+ /* Highly unlikely */
271
+ msg [0 ] = L'\0' ;
272
+ return ;
273
+ }
274
+
239
275
/* Get rid of the CR and LF that FormatMessage() sticks at the
240
276
end of the message. Thanks Microsoft! */
241
- ptr = msg ;
242
- while (* ptr ) {
243
- if (* ptr == L'\r' ) {
244
- * ptr = L'\0' ;
245
- break ;
246
- }
247
- ptr ++ ;
277
+ while (msg [msg_len - 1 ] == L'\r' || msg [msg_len - 1 ] == L'\n' || msg [msg_len - 1 ] == L' ' )
278
+ {
279
+ msg [msg_len - 1 ] = L'\0' ;
280
+ msg_len -- ;
281
+ }
282
+ }
283
+
284
+ static void register_winapi_error (hid_device * dev , const WCHAR * op )
285
+ {
286
+ if (!dev )
287
+ return ;
288
+
289
+ register_winapi_error_to_buffer (& dev -> last_error_str , op );
290
+ }
291
+
292
+ static void register_string_error_to_buffer (wchar_t * * error_buffer , const WCHAR * string_error )
293
+ {
294
+ if (!error_buffer )
295
+ return ;
296
+
297
+ free (* error_buffer );
298
+ * error_buffer = NULL ;
299
+
300
+ if (string_error ) {
301
+ * error_buffer = _wcsdup (string_error );
248
302
}
303
+ }
304
+
305
+ static void register_string_error (hid_device * dev , const WCHAR * string_error )
306
+ {
307
+ if (!dev )
308
+ return ;
249
309
250
- /* Store the message off in the Device entry so that
251
- the hid_error() function can pick it up. */
252
- LocalFree (dev -> last_error_str );
253
- dev -> last_error_str = msg ;
310
+ register_string_error_to_buffer (& dev -> last_error_str , string_error );
254
311
}
255
312
256
313
static HANDLE open_device (const wchar_t * path , BOOL open_rw )
@@ -656,6 +713,10 @@ HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsi
656
713
hid_device * handle = NULL ;
657
714
658
715
devs = hid_enumerate (vendor_id , product_id );
716
+ if (!devs ) {
717
+ return NULL ;
718
+ }
719
+
659
720
cur_dev = devs ;
660
721
while (cur_dev ) {
661
722
if (cur_dev -> vendor_id == vendor_id &&
@@ -759,7 +820,7 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *
759
820
unsigned char * buf ;
760
821
761
822
if (!data || (length == 0 )) {
762
- register_error (dev , "Zero length buffer" );
823
+ register_string_error (dev , L "Zero buffer/length " );
763
824
return function_result ;
764
825
}
765
826
@@ -786,7 +847,7 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *
786
847
if (!res ) {
787
848
if (GetLastError () != ERROR_IO_PENDING ) {
788
849
/* WriteFile() failed. Return error. */
789
- register_error (dev , "WriteFile" );
850
+ register_winapi_error (dev , L "WriteFile" );
790
851
goto end_of_function ;
791
852
}
792
853
overlapped = TRUE;
@@ -798,7 +859,7 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *
798
859
res = WaitForSingleObject (dev -> write_ol .hEvent , 1000 );
799
860
if (res != WAIT_OBJECT_0 ) {
800
861
/* There was a Timeout. */
801
- register_error (dev , "WriteFile /WaitForSingleObject Timeout " );
862
+ register_winapi_error (dev , L"hid_write /WaitForSingleObject" );
802
863
goto end_of_function ;
803
864
}
804
865
@@ -809,7 +870,7 @@ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *
809
870
}
810
871
else {
811
872
/* The Write operation failed. */
812
- register_error (dev , "WriteFile " );
873
+ register_winapi_error (dev , L"hid_write/GetOverlappedResult " );
813
874
goto end_of_function ;
814
875
}
815
876
}
@@ -840,6 +901,7 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char
840
901
if (GetLastError () != ERROR_IO_PENDING ) {
841
902
/* ReadFile() has failed.
842
903
Clean up and return error. */
904
+ register_winapi_error (dev , L"ReadFile" );
843
905
CancelIo (dev -> device_handle );
844
906
dev -> read_pending = FALSE;
845
907
goto end_of_function ;
@@ -886,10 +948,12 @@ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char
886
948
memcpy (data , dev -> read_buf , copy_len );
887
949
}
888
950
}
951
+ if (!res ) {
952
+ register_winapi_error (dev , L"hid_read_timeout/GetOverlappedResult" );
953
+ }
889
954
890
955
end_of_function :
891
956
if (!res ) {
892
- register_error (dev , "GetOverlappedResult" );
893
957
return -1 ;
894
958
}
895
959
@@ -933,7 +997,7 @@ int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const u
933
997
res = HidD_SetFeature (dev -> device_handle , (PVOID )buf , (DWORD ) length_to_send );
934
998
935
999
if (!res ) {
936
- register_error (dev , "HidD_SetFeature" );
1000
+ register_winapi_error (dev , L "HidD_SetFeature" );
937
1001
return -1 ;
938
1002
}
939
1003
@@ -957,7 +1021,7 @@ static int hid_get_report(hid_device *dev, DWORD report_type, unsigned char *dat
957
1021
if (!res ) {
958
1022
if (GetLastError () != ERROR_IO_PENDING ) {
959
1023
/* DeviceIoControl() failed. Return error. */
960
- register_error (dev , "Get Input/Feature Report DeviceIoControl" );
1024
+ register_winapi_error (dev , L "Get Input/Feature Report DeviceIoControl" );
961
1025
return -1 ;
962
1026
}
963
1027
}
@@ -967,7 +1031,7 @@ static int hid_get_report(hid_device *dev, DWORD report_type, unsigned char *dat
967
1031
res = GetOverlappedResult (dev -> device_handle , & ol , & bytes_returned , TRUE/*wait*/ );
968
1032
if (!res ) {
969
1033
/* The operation failed. */
970
- register_error (dev , "Get Input/Feature Report GetOverLappedResult" );
1034
+ register_winapi_error (dev , L "Get Input/Feature Report GetOverLappedResult" );
971
1035
return -1 ;
972
1036
}
973
1037
@@ -1004,8 +1068,17 @@ void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev)
1004
1068
1005
1069
int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string (hid_device * dev , wchar_t * string , size_t maxlen )
1006
1070
{
1007
- if (!dev -> device_info || !string || !maxlen )
1071
+ if (!dev -> device_info )
1072
+ {
1073
+ register_string_error (dev , L"NULL device/info" );
1074
+ return -1 ;
1075
+ }
1076
+
1077
+ if (!string || !maxlen )
1078
+ {
1079
+ register_string_error (dev , L"Zero buffer/length" );
1008
1080
return -1 ;
1081
+ }
1009
1082
1010
1083
wcsncpy (string , dev -> device_info -> manufacturer_string , maxlen );
1011
1084
string [maxlen ] = L'\0' ;
@@ -1015,8 +1088,18 @@ int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev
1015
1088
1016
1089
int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string (hid_device * dev , wchar_t * string , size_t maxlen )
1017
1090
{
1018
- if (!dev -> device_info || !string || !maxlen )
1091
+ if (!dev -> device_info )
1092
+ {
1093
+ register_string_error (dev , L"NULL device/info" );
1019
1094
return -1 ;
1095
+ }
1096
+
1097
+ if (!string || !maxlen )
1098
+ {
1099
+ register_string_error (dev , L"Zero buffer/length" );
1100
+ return -1 ;
1101
+ }
1102
+
1020
1103
1021
1104
wcsncpy (string , dev -> device_info -> product_string , maxlen );
1022
1105
string [maxlen ] = L'\0' ;
@@ -1026,8 +1109,18 @@ int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wch
1026
1109
1027
1110
int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string (hid_device * dev , wchar_t * string , size_t maxlen )
1028
1111
{
1029
- if (!dev -> device_info || !string || !maxlen )
1112
+ if (!dev -> device_info )
1113
+ {
1114
+ register_string_error (dev , L"NULL device/info" );
1030
1115
return -1 ;
1116
+ }
1117
+
1118
+ if (!string || !maxlen )
1119
+ {
1120
+ register_string_error (dev , L"Zero buffer/length" );
1121
+ return -1 ;
1122
+ }
1123
+
1031
1124
1032
1125
wcsncpy (string , dev -> device_info -> serial_number , maxlen );
1033
1126
string [maxlen ] = L'\0' ;
@@ -1041,7 +1134,7 @@ int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int
1041
1134
1042
1135
res = HidD_GetIndexedString (dev -> device_handle , string_index , string , sizeof (wchar_t ) * (DWORD ) MIN (maxlen , MAX_STRING_WCHARS ));
1043
1136
if (!res ) {
1044
- register_error (dev , "HidD_GetIndexedString" );
1137
+ register_winapi_error (dev , L "HidD_GetIndexedString" );
1045
1138
return -1 ;
1046
1139
}
1047
1140
@@ -1057,28 +1150,43 @@ int HID_API_EXPORT_CALL hid_winapi_get_container_id(hid_device *dev, GUID *conta
1057
1150
ULONG len ;
1058
1151
1059
1152
if (!container_id )
1153
+ {
1154
+ register_string_error (dev , L"Invalid Container ID" );
1060
1155
return -1 ;
1156
+ }
1061
1157
1062
1158
interface_path = hid_internal_UTF8toUTF16 (dev -> device_info -> path );
1063
1159
if (!interface_path )
1160
+ {
1161
+ register_string_error (dev , L"Path conversion failure" );
1064
1162
goto end ;
1163
+ }
1065
1164
1066
1165
/* Get the device id from interface path */
1067
1166
device_id = hid_internal_get_device_interface_property (interface_path , & DEVPKEY_Device_InstanceId , DEVPROP_TYPE_STRING );
1068
1167
if (!device_id )
1168
+ {
1169
+ register_string_error (dev , L"Failed to get device interface property InstanceId" );
1069
1170
goto end ;
1171
+ }
1070
1172
1071
1173
/* Open devnode from device id */
1072
1174
cr = CM_Locate_DevNodeW (& dev_node , (DEVINSTID_W )device_id , CM_LOCATE_DEVNODE_NORMAL );
1073
1175
if (cr != CR_SUCCESS )
1176
+ {
1177
+ register_string_error (dev , L"Failed to locate device node" );
1074
1178
goto end ;
1179
+ }
1075
1180
1076
1181
/* Get the container id from devnode */
1077
1182
len = sizeof (* container_id );
1078
1183
cr = CM_Get_DevNode_PropertyW (dev_node , & DEVPKEY_Device_ContainerId , & property_type , (PBYTE )container_id , & len , 0 );
1079
1184
if (cr == CR_SUCCESS && property_type != DEVPROP_TYPE_GUID )
1080
1185
cr = CR_FAILURE ;
1081
1186
1187
+ if (cr != CR_SUCCESS )
1188
+ register_string_error (dev , L"Failed to read ContainerId property from device node" );
1189
+
1082
1190
end :
1083
1191
free (interface_path );
1084
1192
free (device_id );
0 commit comments