Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hid/hidp.c | 5 +++-- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 4 ---- 2 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index 59f18276b38..6261c3c2f68 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -96,13 +96,14 @@ static NTSTATUS enum_value_caps( WINE_HIDP_PREPARSED_DATA *preparsed, HIDP_REPOR { const struct hid_value_caps *caps, *caps_end; NTSTATUS status; + BOOL incompatible = FALSE; LONG remaining = *count;
for (status = get_value_caps_range( preparsed, report_type, report_len, &caps, &caps_end ); status == HIDP_STATUS_SUCCESS && caps != caps_end; caps++) { if (!match_value_caps( caps, filter )) continue; - if (filter->report_id && caps->report_id != filter->report_id) continue; + if (filter->report_id && caps->report_id != filter->report_id) incompatible = TRUE; else if (filter->array && (caps->is_range || caps->report_count <= 1)) return HIDP_STATUS_NOT_VALUE_ARRAY; else if (remaining-- > 0) status = callback( caps, user ); } @@ -111,7 +112,7 @@ static NTSTATUS enum_value_caps( WINE_HIDP_PREPARSED_DATA *preparsed, HIDP_REPOR if (status != HIDP_STATUS_SUCCESS) return status;
*count -= remaining; - if (*count == 0) return HIDP_STATUS_USAGE_NOT_FOUND; + if (*count == 0) return incompatible ? HIDP_STATUS_INCOMPATIBLE_REPORT_ID : HIDP_STATUS_USAGE_NOT_FOUND; if (remaining < 0) return HIDP_STATUS_BUFFER_TOO_SMALL; return HIDP_STATUS_SUCCESS; } diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 432bc168259..753957a8ac6 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -2292,14 +2292,12 @@ static void test_hidp(HANDLE file, int report_id) status = HidP_SetUsageValue(HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, preparsed_data, report, caps.FeatureReportByteLength); - todo_wine_if(!report_id) ok(status == (report_id ? HIDP_STATUS_SUCCESS : HIDP_STATUS_INCOMPATIBLE_REPORT_ID), "HidP_SetUsageValue returned %#x\n", status); report[0] = 2; status = HidP_SetUsageValue(HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, preparsed_data, report, caps.FeatureReportByteLength); - todo_wine ok(status == HIDP_STATUS_INCOMPATIBLE_REPORT_ID, "HidP_SetUsageValue returned %#x\n", status); report[0] = report_id; status = HidP_SetUsageValue(HidP_Feature, HID_USAGE_PAGE_ORDINAL, 0xdead, 3, HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, @@ -2330,13 +2328,11 @@ static void test_hidp(HANDLE file, int report_id) report[0] = 1 - report_id; status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, &value, preparsed_data, report, caps.FeatureReportByteLength); - todo_wine_if(!report_id) ok(status == (report_id ? HIDP_STATUS_SUCCESS : HIDP_STATUS_INCOMPATIBLE_REPORT_ID), "HidP_GetUsageValue returned %#x\n", status); report[0] = 2; status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, &value, preparsed_data, report, caps.FeatureReportByteLength); - todo_wine ok(status == HIDP_STATUS_INCOMPATIBLE_REPORT_ID, "HidP_GetUsageValue returned %#x\n", status); report[0] = report_id; status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_ORDINAL, 0xdead, 3, &value,
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hid/hidp.c | 32 +++++++++++++++--------------- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 1 - 2 files changed, 16 insertions(+), 17 deletions(-)
diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index 6261c3c2f68..afd69281f0d 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -679,24 +679,24 @@ NTSTATUS WINAPI HidP_GetUsagesEx( HIDP_REPORT_TYPE report_type, USHORT collectio return status; }
-ULONG WINAPI HidP_MaxDataListLength(HIDP_REPORT_TYPE ReportType, PHIDP_PREPARSED_DATA PreparsedData) +static NTSTATUS count_data( const struct hid_value_caps *caps, void *user ) { - WINE_HIDP_PREPARSED_DATA *data = (WINE_HIDP_PREPARSED_DATA *)PreparsedData; - TRACE("(%i, %p)\n", ReportType, PreparsedData); - if (data->magic != HID_MAGIC) - return 0; + if (caps->is_range || HID_VALUE_CAPS_IS_BUTTON( caps )) *(ULONG *)user += caps->report_count; + else *(ULONG *)user += 1; + return HIDP_STATUS_SUCCESS; +}
- switch(ReportType) - { - case HidP_Input: - return data->caps.NumberInputDataIndices; - case HidP_Output: - return data->caps.NumberOutputDataIndices; - case HidP_Feature: - return data->caps.NumberFeatureDataIndices; - default: - return 0; - } +ULONG WINAPI HidP_MaxDataListLength( HIDP_REPORT_TYPE report_type, PHIDP_PREPARSED_DATA preparsed_data ) +{ + WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct caps_filter filter = {}; + USHORT limit = -1; + ULONG count = 0; + + TRACE( "report_type %d, preparsed_data %p.\n", report_type, preparsed_data ); + + enum_value_caps( preparsed, report_type, 0, &filter, count_data, &count, &limit ); + return count; }
NTSTATUS WINAPI HidP_GetData(HIDP_REPORT_TYPE ReportType, HIDP_DATA *DataList, ULONG *DataLength, diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 753957a8ac6..101366bf50b 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -2229,7 +2229,6 @@ static void test_hidp(HANDLE file, int report_id) value = HidP_MaxDataListLength(HidP_Feature + 1, preparsed_data); ok(value == 0, "HidP_MaxDataListLength(HidP_Feature + 1) returned %d, expected %d\n", value, 0); value = HidP_MaxDataListLength(HidP_Input, preparsed_data); - todo_wine ok(value == 50, "HidP_MaxDataListLength(HidP_Input) returned %d, expected %d\n", value, 50); value = HidP_MaxDataListLength(HidP_Output, preparsed_data); ok(value == 0, "HidP_MaxDataListLength(HidP_Output) returned %d, expected %d\n", value, 0);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=93192
Your paranoid android.
=== w8 (32 bit report) ===
ntoskrnl.exe: driver.c:759: Test failed: got 0
=== w1064_tsign (64 bit report) ===
ntoskrnl.exe: driver.c:272: Test failed: Got unexpected test_load_image_notify_count 0.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hid/hidp.c | 157 ++++++++++------------------- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 41 ++++---- 2 files changed, 73 insertions(+), 125 deletions(-)
diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index afd69281f0d..94dc4212067 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -155,44 +155,6 @@ static void copy_bits( unsigned char *dst, const unsigned char *src, int count, *dst = (bits & mask) | (*dst & ~mask); }
-static NTSTATUS get_report_data(BYTE *report, INT reportLength, INT startBit, INT valueSize, PULONG value) -{ - - if ((startBit + valueSize) / 8 > reportLength) - return HIDP_STATUS_INVALID_REPORT_LENGTH; - - if (valueSize == 1) - { - ULONG byte_index = startBit / 8; - ULONG bit_index = startBit - (byte_index * 8); - INT mask = (1 << bit_index); - *value = !!(report[byte_index] & mask); - } - else - { - ULONG remaining_bits = valueSize; - ULONG byte_index = startBit / 8; - ULONG bit_index = startBit % 8; - ULONG data = 0; - ULONG shift = 0; - while (remaining_bits) - { - ULONG copy_bits = 8 - bit_index; - if (remaining_bits < copy_bits) - copy_bits = remaining_bits; - - data |= ((report[byte_index] >> bit_index) & ((1 << copy_bits) - 1)) << shift; - - shift += copy_bits; - bit_index = 0; - byte_index++; - remaining_bits -= copy_bits; - } - *value = data; - } - return HIDP_STATUS_SUCCESS; -} - NTSTATUS WINAPI HidP_GetButtonCaps( HIDP_REPORT_TYPE report_type, HIDP_BUTTON_CAPS *caps, USHORT *caps_count, PHIDP_PREPARSED_DATA preparsed_data ) { @@ -207,14 +169,7 @@ NTSTATUS WINAPI HidP_GetCaps( PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *ca
if (preparsed->magic != HID_MAGIC) return HIDP_STATUS_INVALID_PREPARSED_DATA;
- *caps = preparsed->caps; - caps->NumberInputButtonCaps = preparsed->new_caps.NumberInputButtonCaps; - caps->NumberOutputButtonCaps = preparsed->new_caps.NumberOutputButtonCaps; - caps->NumberFeatureButtonCaps = preparsed->new_caps.NumberFeatureButtonCaps; - caps->NumberInputValueCaps = preparsed->new_caps.NumberInputValueCaps; - caps->NumberOutputValueCaps = preparsed->new_caps.NumberOutputValueCaps; - caps->NumberFeatureValueCaps = preparsed->new_caps.NumberFeatureValueCaps; - + *caps = preparsed->new_caps; return HIDP_STATUS_SUCCESS; }
@@ -699,79 +654,71 @@ ULONG WINAPI HidP_MaxDataListLength( HIDP_REPORT_TYPE report_type, PHIDP_PREPARS return count; }
-NTSTATUS WINAPI HidP_GetData(HIDP_REPORT_TYPE ReportType, HIDP_DATA *DataList, ULONG *DataLength, - PHIDP_PREPARSED_DATA PreparsedData,CHAR *Report, ULONG ReportLength) +struct find_all_data_params { - WINE_HIDP_PREPARSED_DATA *data = (WINE_HIDP_PREPARSED_DATA*)PreparsedData; - WINE_HID_ELEMENT *elems = HID_ELEMS(data); - WINE_HID_REPORT *report = NULL; - USHORT r_count = 0; - int i,uCount = 0; - NTSTATUS rc; - - TRACE("(%i, %p, %p(%i), %p, %p, %i)\n", ReportType, DataList, DataLength, - DataLength?*DataLength:0, PreparsedData, Report, ReportLength); - - if (data->magic != HID_MAGIC) - return 0; - - if (ReportType != HidP_Input && ReportType != HidP_Output && ReportType != HidP_Feature) - return HIDP_STATUS_INVALID_REPORT_TYPE; - - r_count = data->reportCount[ReportType]; - report = &data->reports[data->reportIdx[ReportType][(BYTE)Report[0]]]; + HIDP_DATA *data; + HIDP_DATA *data_end; + char *report_buf; +};
- if (!r_count || (report->reportID && report->reportID != Report[0])) - return HIDP_STATUS_REPORT_DOES_NOT_EXIST; +static NTSTATUS find_all_data( const struct hid_value_caps *caps, void *user ) +{ + struct find_all_data_params *params = user; + HIDP_DATA *data = params->data, *data_end = params->data_end; + ULONG bit, last, bit_count = caps->bit_size * caps->report_count; + char *report_buf = params->report_buf;
- for (i = 0; i < report->elementCount; i++) + if (!caps->bit_size) return HIDP_STATUS_SUCCESS; + if (caps->bit_size == 1) { - WINE_HID_ELEMENT *element = &elems[report->elementIdx + i]; - if (element->caps.BitSize == 1) + for (bit = caps->start_bit, last = bit + caps->usage_max - caps->usage_min; bit <= last; bit++) { - int k; - for (k=0; k < element->bitCount; k++) + if (!(report_buf[bit / 8] & (1 << (bit % 8)))) continue; + if (data < data_end) { - UINT v = 0; - NTSTATUS rc = get_report_data((BYTE*)Report, ReportLength, - element->valueStartBit + k, 1, &v); - if (rc != HIDP_STATUS_SUCCESS) - return rc; - if (v) - { - if (uCount < *DataLength) - { - DataList[uCount].DataIndex = element->caps.Range.DataIndexMin + k; - DataList[uCount].On = v; - } - uCount++; - } + data->DataIndex = caps->data_index_min + bit - caps->start_bit; + data->On = 1; } + data++; } - else + } + else if (caps->report_count == 1) + { + if (data < data_end) { - if (uCount < *DataLength) - { - UINT v; - NTSTATUS rc = get_report_data((BYTE*)Report, ReportLength, - element->valueStartBit, element->bitCount, &v); - if (rc != HIDP_STATUS_SUCCESS) - return rc; - DataList[uCount].DataIndex = element->caps.NotRange.DataIndex; - DataList[uCount].RawValue = v; - } - uCount++; + data->DataIndex = caps->data_index_min; + data->RawValue = 0; + if ((bit_count + 7) / 8 > sizeof(data->RawValue)) return HIDP_STATUS_BUFFER_TOO_SMALL; + copy_bits( (void *)&data->RawValue, (void *)report_buf, bit_count, -caps->start_bit ); } + data++; }
- if (*DataLength < uCount) - rc = HIDP_STATUS_BUFFER_TOO_SMALL; - else - rc = HIDP_STATUS_SUCCESS; + params->data = data; + return HIDP_STATUS_SUCCESS; +} + +NTSTATUS WINAPI HidP_GetData( HIDP_REPORT_TYPE report_type, HIDP_DATA *data, ULONG *data_len, + PHIDP_PREPARSED_DATA preparsed_data, char *report_buf, ULONG report_len ) +{ + struct find_all_data_params params = {.data = data, .data_end = data + *data_len, .report_buf = report_buf}; + WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct caps_filter filter = {}; + NTSTATUS status; + USHORT limit = -1;
- *DataLength = uCount; + TRACE( "report_type %d, data %p, data_len %p, preparsed_data %p, report_buf %p, report_len %u.\n", + report_type, data, data_len, preparsed_data, report_buf, report_len );
- return rc; + if (!report_len) return HIDP_STATUS_INVALID_REPORT_LENGTH; + + filter.report_id = report_buf[0]; + status = enum_value_caps( preparsed, report_type, report_len, &filter, find_all_data, ¶ms, &limit ); + *data_len = params.data - data; + if (status != HIDP_STATUS_SUCCESS) return status; + + if (params.data > params.data_end) return HIDP_STATUS_BUFFER_TOO_SMALL; + return HIDP_STATUS_SUCCESS; }
NTSTATUS WINAPI HidP_GetLinkCollectionNodes(HIDP_LINK_COLLECTION_NODE *LinkCollectionNode, diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 101366bf50b..f9bb9e87cda 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1500,6 +1500,26 @@ static void test_pnp_driver(struct testsign_context *ctx) (val).member, (exp).member) #define check_member(val, exp, fmt, member) check_member_(__FILE__, __LINE__, val, exp, fmt, member)
+#define check_hidp_caps(a, b) check_hidp_caps_(__LINE__, a, b) +static inline void check_hidp_caps_(int line, HIDP_CAPS *caps, const HIDP_CAPS *exp) +{ + check_member_(__FILE__, line, *caps, *exp, "%04x", Usage); + check_member_(__FILE__, line, *caps, *exp, "%04x", UsagePage); + check_member_(__FILE__, line, *caps, *exp, "%d", InputReportByteLength); + check_member_(__FILE__, line, *caps, *exp, "%d", OutputReportByteLength); + check_member_(__FILE__, line, *caps, *exp, "%d", FeatureReportByteLength); + check_member_(__FILE__, line, *caps, *exp, "%d", NumberLinkCollectionNodes); + check_member_(__FILE__, line, *caps, *exp, "%d", NumberInputButtonCaps); + check_member_(__FILE__, line, *caps, *exp, "%d", NumberInputValueCaps); + check_member_(__FILE__, line, *caps, *exp, "%d", NumberInputDataIndices); + check_member_(__FILE__, line, *caps, *exp, "%d", NumberOutputButtonCaps); + check_member_(__FILE__, line, *caps, *exp, "%d", NumberOutputValueCaps); + check_member_(__FILE__, line, *caps, *exp, "%d", NumberOutputDataIndices); + check_member_(__FILE__, line, *caps, *exp, "%d", NumberFeatureButtonCaps); + check_member_(__FILE__, line, *caps, *exp, "%d", NumberFeatureValueCaps); + check_member_(__FILE__, line, *caps, *exp, "%d", NumberFeatureDataIndices); +} + #define check_hidp_link_collection_node(a, b) check_hidp_link_collection_node_(__LINE__, a, b) static inline void check_hidp_link_collection_node_(int line, HIDP_LINK_COLLECTION_NODE *node, const HIDP_LINK_COLLECTION_NODE *exp) @@ -1827,23 +1847,7 @@ static void test_hidp(HANDLE file, int report_id) ok(status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetCaps returned %#x\n", status); status = HidP_GetCaps(preparsed_data, &caps); ok(status == HIDP_STATUS_SUCCESS, "HidP_GetCaps returned %#x\n", status); - check_member(caps, expect_hidp_caps[report_id], "%04x", Usage); - check_member(caps, expect_hidp_caps[report_id], "%04x", UsagePage); - check_member(caps, expect_hidp_caps[report_id], "%d", InputReportByteLength); - check_member(caps, expect_hidp_caps[report_id], "%d", OutputReportByteLength); - check_member(caps, expect_hidp_caps[report_id], "%d", FeatureReportByteLength); - check_member(caps, expect_hidp_caps[report_id], "%d", NumberLinkCollectionNodes); - check_member(caps, expect_hidp_caps[report_id], "%d", NumberInputButtonCaps); - check_member(caps, expect_hidp_caps[report_id], "%d", NumberInputValueCaps); - todo_wine - check_member(caps, expect_hidp_caps[report_id], "%d", NumberInputDataIndices); - check_member(caps, expect_hidp_caps[report_id], "%d", NumberOutputButtonCaps); - check_member(caps, expect_hidp_caps[report_id], "%d", NumberOutputValueCaps); - check_member(caps, expect_hidp_caps[report_id], "%d", NumberOutputDataIndices); - check_member(caps, expect_hidp_caps[report_id], "%d", NumberFeatureButtonCaps); - check_member(caps, expect_hidp_caps[report_id], "%d", NumberFeatureValueCaps); - todo_wine - check_member(caps, expect_hidp_caps[report_id], "%d", NumberFeatureDataIndices); + check_hidp_caps(&caps, &expect_hidp_caps[report_id]);
collection_count = 0; status = HidP_GetLinkCollectionNodes(collections, &collection_count, preparsed_data); @@ -2238,7 +2242,6 @@ static void test_hidp(HANDLE file, int report_id) value = 1; status = HidP_GetData(HidP_Input, data, &value, preparsed_data, report, caps.InputReportByteLength); ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetData returned %#x\n", status); - todo_wine ok(value == 9, "got data count %d, expected %d\n", value, 9); memset(data, 0, sizeof(data)); status = HidP_GetData(HidP_Input, data, &value, preparsed_data, report, caps.InputReportByteLength); @@ -2246,9 +2249,7 @@ static void test_hidp(HANDLE file, int report_id) for (i = 0; i < ARRAY_SIZE(expect_data); ++i) { winetest_push_context("data[%d]", i); - todo_wine_if(i >= 4) check_member(data[i], expect_data[i], "%d", DataIndex); - todo_wine_if(i == 6 || i == 7 || i == 8) check_member(data[i], expect_data[i], "%d", RawValue); winetest_pop_context(); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=93193
Your paranoid android.
=== w8 (32 bit report) ===
ntoskrnl.exe: driver.c:272: Test failed: Got unexpected test_load_image_notify_count 0.
=== debiant2 (32 bit Japanese:Japan report) ===
ntoskrnl.exe: ntoskrnl: Timeout
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hid/hidp.c | 44 ++++++++++++++++++---------------- dlls/hidclass.sys/descriptor.c | 29 ++++------------------ include/wine/hid.h | 14 +---------- 3 files changed, 30 insertions(+), 57 deletions(-)
diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index 94dc4212067..750dbce9f26 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -721,33 +721,37 @@ NTSTATUS WINAPI HidP_GetData( HIDP_REPORT_TYPE report_type, HIDP_DATA *data, ULO return HIDP_STATUS_SUCCESS; }
-NTSTATUS WINAPI HidP_GetLinkCollectionNodes(HIDP_LINK_COLLECTION_NODE *LinkCollectionNode, - ULONG *LinkCollectionNodeLength, PHIDP_PREPARSED_DATA PreparsedData) +NTSTATUS WINAPI HidP_GetLinkCollectionNodes( HIDP_LINK_COLLECTION_NODE *nodes, ULONG *nodes_len, PHIDP_PREPARSED_DATA preparsed_data ) { - WINE_HIDP_PREPARSED_DATA *data = (WINE_HIDP_PREPARSED_DATA*)PreparsedData; - WINE_HID_LINK_COLLECTION_NODE *nodes = HID_NODES(data); - ULONG i; + WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct hid_value_caps *caps = HID_COLLECTION_VALUE_CAPS( preparsed ); + ULONG i, count, capacity = *nodes_len;
- TRACE("(%p, %p, %p)\n", LinkCollectionNode, LinkCollectionNodeLength, PreparsedData); + TRACE( "nodes %p, nodes_len %p, preparsed_data %p.\n", nodes, nodes_len, preparsed_data );
- if (data->magic != HID_MAGIC) - return HIDP_STATUS_INVALID_PREPARSED_DATA; + if (preparsed->magic != HID_MAGIC) return HIDP_STATUS_INVALID_PREPARSED_DATA;
- if (*LinkCollectionNodeLength < data->caps.NumberLinkCollectionNodes) - return HIDP_STATUS_BUFFER_TOO_SMALL; + if (capacity < preparsed->caps.NumberLinkCollectionNodes) return HIDP_STATUS_BUFFER_TOO_SMALL; + count = *nodes_len = preparsed->caps.NumberLinkCollectionNodes;
- for (i = 0; i < data->caps.NumberLinkCollectionNodes; ++i) + for (i = 0; i < count; ++i) { - LinkCollectionNode[i].LinkUsage = nodes[i].LinkUsage; - LinkCollectionNode[i].LinkUsagePage = nodes[i].LinkUsagePage; - LinkCollectionNode[i].Parent = nodes[i].Parent; - LinkCollectionNode[i].NumberOfChildren = nodes[i].NumberOfChildren; - LinkCollectionNode[i].NextSibling = nodes[i].NextSibling; - LinkCollectionNode[i].FirstChild = nodes[i].FirstChild; - LinkCollectionNode[i].CollectionType = nodes[i].CollectionType; - LinkCollectionNode[i].IsAlias = nodes[i].IsAlias; + nodes[i].LinkUsagePage = caps[i].usage_page; + nodes[i].LinkUsage = caps[i].usage_min; + nodes[i].Parent = caps[i].link_collection; + nodes[i].CollectionType = caps[i].bit_field; + nodes[i].IsAlias = 0; + nodes[i].FirstChild = 0; + nodes[i].NextSibling = 0; + nodes[i].NumberOfChildren = 0; + + if (i > 0) + { + nodes[i].NextSibling = nodes[nodes[i].Parent].FirstChild; + nodes[nodes[i].Parent].FirstChild = i; + nodes[nodes[i].Parent].NumberOfChildren++; + } } - *LinkCollectionNodeLength = data->caps.NumberLinkCollectionNodes;
return HIDP_STATUS_SUCCESS; } diff --git a/dlls/hidclass.sys/descriptor.c b/dlls/hidclass.sys/descriptor.c index 3b4455a0b88..986912990a7 100644 --- a/dlls/hidclass.sys/descriptor.c +++ b/dlls/hidclass.sys/descriptor.c @@ -834,7 +834,6 @@ static void preparse_collection(const struct collection *root, const struct coll static WINE_HIDP_PREPARSED_DATA *build_preparsed_data( struct collection *base_collection, struct hid_parser_state *state ) { - WINE_HID_LINK_COLLECTION_NODE *nodes; WINE_HIDP_PREPARSED_DATA *data; struct hid_value_caps *caps; unsigned int report_count; @@ -843,7 +842,6 @@ static WINE_HIDP_PREPARSED_DATA *build_preparsed_data( struct collection *base_c
struct preparse_ctx ctx; unsigned int element_off; - unsigned int nodes_offset;
memset(&ctx, 0, sizeof(ctx)); create_preparse_ctx(base_collection, &ctx); @@ -853,10 +851,8 @@ static WINE_HIDP_PREPARSED_DATA *build_preparsed_data( struct collection *base_c element_off = FIELD_OFFSET(WINE_HIDP_PREPARSED_DATA, reports[report_count]); size = element_off + (ctx.elem_count * sizeof(WINE_HID_ELEMENT));
- nodes_offset = size; - size += state->caps.NumberLinkCollectionNodes * sizeof(WINE_HID_LINK_COLLECTION_NODE); - - caps_len = state->caps.NumberInputValueCaps + state->caps.NumberOutputValueCaps + state->caps.NumberFeatureValueCaps; + caps_len = state->caps.NumberInputValueCaps + state->caps.NumberOutputValueCaps + + state->caps.NumberFeatureValueCaps + state->caps.NumberLinkCollectionNodes; caps_off = size; size += caps_len * sizeof(*caps);
@@ -866,7 +862,6 @@ static WINE_HIDP_PREPARSED_DATA *build_preparsed_data( struct collection *base_c data->caps = state->caps; data->new_caps = state->caps; data->elementOffset = element_off; - data->nodesOffset = nodes_offset;
data->value_caps_offset = caps_off; data->value_caps_count[HidP_Input] = state->caps.NumberInputValueCaps; @@ -878,23 +873,6 @@ static WINE_HIDP_PREPARSED_DATA *build_preparsed_data( struct collection *base_c data->caps.NumberFeatureValueCaps = data->caps.NumberFeatureButtonCaps = data->caps.NumberFeatureDataIndices = 0; preparse_collection(base_collection, base_collection, data, &ctx);
- nodes = HID_NODES( data ); - for (i = 0; i < data->caps.NumberLinkCollectionNodes; ++i) - { - nodes[i].LinkUsagePage = state->collections[i].usage_page; - nodes[i].LinkUsage = state->collections[i].usage_min; - nodes[i].Parent = state->collections[i].link_collection; - nodes[i].CollectionType = state->collections[i].bit_field; - nodes[i].IsAlias = 0; - - if (i > 0) - { - nodes[i].NextSibling = nodes[nodes[i].Parent].FirstChild; - nodes[nodes[i].Parent].FirstChild = i; - nodes[nodes[i].Parent].NumberOfChildren++; - } - } - /* fixup value vs button vs filler counts */
caps = HID_INPUT_VALUE_CAPS( data ); @@ -929,6 +907,9 @@ static WINE_HIDP_PREPARSED_DATA *build_preparsed_data( struct collection *base_c data->new_caps.NumberFeatureButtonCaps = button; data->new_caps.NumberFeatureValueCaps -= filler + button;
+ caps = HID_COLLECTION_VALUE_CAPS( data ); + memcpy( caps, state->collections, data->new_caps.NumberLinkCollectionNodes * sizeof(*caps) ); + return data; }
diff --git a/include/wine/hid.h b/include/wine/hid.h index 8d1d6d4d104..b15b26474a0 100644 --- a/include/wine/hid.h +++ b/include/wine/hid.h @@ -81,17 +81,6 @@ typedef struct __WINE_HID_REPORT DWORD elementIdx; } WINE_HID_REPORT;
-typedef struct __WINE_HID_LINK_COLLECTION_NODE { - USAGE LinkUsage; - USAGE LinkUsagePage; - USHORT Parent; - USHORT NumberOfChildren; - USHORT NextSibling; - USHORT FirstChild; - BYTE CollectionType; - BYTE IsAlias; -} WINE_HID_LINK_COLLECTION_NODE; - typedef struct __WINE_HIDP_PREPARSED_DATA { DWORD magic; @@ -100,7 +89,6 @@ typedef struct __WINE_HIDP_PREPARSED_DATA HIDP_CAPS new_caps;
DWORD elementOffset; - DWORD nodesOffset; DWORD reportCount[3]; BYTE reportIdx[3][256];
@@ -113,10 +101,10 @@ typedef struct __WINE_HIDP_PREPARSED_DATA #define HID_OUTPUT_REPORTS(d) ((d)->reports + (d)->reportCount[0]) #define HID_FEATURE_REPORTS(d) ((d)->reports + (d)->reportCount[0] + (d)->reportCount[1]) #define HID_ELEMS(d) ((WINE_HID_ELEMENT*)((BYTE*)(d) + (d)->elementOffset)) -#define HID_NODES(d) ((WINE_HID_LINK_COLLECTION_NODE*)((BYTE*)(d) + (d)->nodesOffset))
#define HID_INPUT_VALUE_CAPS(d) ((struct hid_value_caps*)((char *)(d) + (d)->value_caps_offset)) #define HID_OUTPUT_VALUE_CAPS(d) (HID_INPUT_VALUE_CAPS(d) + (d)->value_caps_count[0]) #define HID_FEATURE_VALUE_CAPS(d) (HID_OUTPUT_VALUE_CAPS(d) + (d)->value_caps_count[1]) +#define HID_COLLECTION_VALUE_CAPS(d) (HID_FEATURE_VALUE_CAPS(d) + (d)->value_caps_count[2])
#endif /* __WINE_PARSE_H */
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hid/hidp.c | 2 +- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index 750dbce9f26..6a9fba6e425 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -731,8 +731,8 @@ NTSTATUS WINAPI HidP_GetLinkCollectionNodes( HIDP_LINK_COLLECTION_NODE *nodes, U
if (preparsed->magic != HID_MAGIC) return HIDP_STATUS_INVALID_PREPARSED_DATA;
- if (capacity < preparsed->caps.NumberLinkCollectionNodes) return HIDP_STATUS_BUFFER_TOO_SMALL; count = *nodes_len = preparsed->caps.NumberLinkCollectionNodes; + if (capacity < count) return HIDP_STATUS_BUFFER_TOO_SMALL;
for (i = 0; i < count; ++i) { diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index f9bb9e87cda..a3c2a303a59 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1852,7 +1852,6 @@ static void test_hidp(HANDLE file, int report_id) collection_count = 0; status = HidP_GetLinkCollectionNodes(collections, &collection_count, preparsed_data); ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetLinkCollectionNodes returned %#x\n", status); - todo_wine ok(collection_count == caps.NumberLinkCollectionNodes, "got %d collection nodes, expected %d\n", collection_count, caps.NumberLinkCollectionNodes); collection_count = ARRAY_SIZE(collections);