Wine-devel
Threads by month
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
August 2021
- 78 participants
- 929 discussions
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/gdi32/enhmfdrv/enhmetafiledrv.h | 1 -
dlls/gdi32/enhmfdrv/init.c | 2 +-
dlls/gdi32/enhmfdrv/objects.c | 18 ++++++++----------
dlls/gdi32/gdi_private.h | 2 ++
dlls/gdi32/gdidc.c | 18 ++++++++++++++++++
dlls/gdi32/metafile.c | 2 +-
dlls/gdi32/mfdrv/init.c | 2 +-
dlls/gdi32/mfdrv/metafiledrv.h | 1 -
dlls/gdi32/mfdrv/objects.c | 20 +++++++++-----------
dlls/gdi32/palette.c | 28 ++--------------------------
10 files changed, 42 insertions(+), 52 deletions(-)
2
1
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/gdi32/enhmfdrv/enhmetafiledrv.h | 2 -
dlls/gdi32/enhmfdrv/init.c | 4 +-
dlls/gdi32/enhmfdrv/objects.c | 90 +++++++------
dlls/gdi32/gdi_private.h | 1 +
dlls/gdi32/objects.c | 3 +
dlls/gdi32/tests/metafile.c | 191 +++++++++++++++++++++++++++
6 files changed, 247 insertions(+), 44 deletions(-)
2
1
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/gdi32/dc.c | 2 +-
dlls/gdi32/gdi_private.h | 1 +
dlls/gdi32/mfdrv/init.c | 11 ++-
dlls/gdi32/mfdrv/metafiledrv.h | 7 +-
dlls/gdi32/mfdrv/objects.c | 81 ++++++++++++------
dlls/gdi32/objects.c | 2 +
dlls/gdi32/tests/metafile.c | 151 +++++++++++++++++++++++++++++++++
include/ntgdi.h | 1 +
8 files changed, 219 insertions(+), 37 deletions(-)
2
1
[PATCH 1/5] gdi32: Handle deletion of objects associated with metafile without accessing kernel objects.
by Jacek Caban 09 Aug '21
by Jacek Caban 09 Aug '21
09 Aug '21
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/gdi32/enhmfdrv/enhmetafiledrv.h | 1 -
dlls/gdi32/enhmfdrv/init.c | 2 +-
dlls/gdi32/enhmfdrv/objects.c | 28 +++--
dlls/gdi32/gdi_private.h | 4 +
dlls/gdi32/gdidc.c | 2 +-
dlls/gdi32/gdiobj.c | 77 --------------
dlls/gdi32/mfdrv/init.c | 2 +-
dlls/gdi32/mfdrv/metafiledrv.h | 1 -
dlls/gdi32/mfdrv/objects.c | 30 +++---
dlls/gdi32/ntgdi_private.h | 9 --
dlls/gdi32/objects.c | 148 +++++++++++++++++++++++++++
11 files changed, 183 insertions(+), 121 deletions(-)
2
1
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/d3d10/d3d10_private.h | 1 +
dlls/d3d10/effect.c | 19 +++-
dlls/d3d10/tests/effect.c | 181 ++++++++++++++++---------------------
3 files changed, 95 insertions(+), 106 deletions(-)
diff --git a/dlls/d3d10/d3d10_private.h b/dlls/d3d10/d3d10_private.h
index 8d48231d971..fc4d50004af 100644
--- a/dlls/d3d10/d3d10_private.h
+++ b/dlls/d3d10/d3d10_private.h
@@ -188,6 +188,7 @@ struct d3d10_effect_variable
char *name;
char *semantic;
+ char *value;
DWORD buffer_offset;
DWORD annotation_count;
DWORD flag;
diff --git a/dlls/d3d10/effect.c b/dlls/d3d10/effect.c
index 86ef50aac01..18aed7b52de 100644
--- a/dlls/d3d10/effect.c
+++ b/dlls/d3d10/effect.c
@@ -1330,12 +1330,28 @@ static HRESULT parse_fx10_variable_head(const char *data, size_t data_size,
static HRESULT parse_fx10_annotation(const char *data, size_t data_size,
const char **ptr, struct d3d10_effect_variable *a)
{
+ DWORD offset;
HRESULT hr;
if (FAILED(hr = parse_fx10_variable_head(data, data_size, ptr, a)))
return hr;
- skip_dword_unknown("annotation", ptr, 1);
+ read_dword(ptr, &offset);
+ TRACE("Annotation value is at offset %#x.\n", offset);
+
+ switch (a->type->basetype)
+ {
+ case D3D10_SVT_STRING:
+ if (!fx10_copy_string(data, data_size, offset, &a->value))
+ {
+ ERR("Failed to copy name.\n");
+ return E_OUTOFMEMORY;
+ }
+ break;
+
+ default:
+ FIXME("Unhandled object type %#x.\n", a->type->basetype);
+ }
/* mark the variable as annotation */
a->flag = D3D10_EFFECT_VARIABLE_ANNOTATION;
@@ -2744,6 +2760,7 @@ static void d3d10_effect_variable_destroy(struct d3d10_effect_variable *v)
heap_free(v->name);
heap_free(v->semantic);
+ heap_free(v->value);
if (v->annotations)
{
for (i = 0; i < v->annotation_count; ++i)
diff --git a/dlls/d3d10/tests/effect.c b/dlls/d3d10/tests/effect.c
index fc0b8180b97..871bf78cc27 100644
--- a/dlls/d3d10/tests/effect.c
+++ b/dlls/d3d10/tests/effect.c
@@ -1161,7 +1161,7 @@ static void test_effect_variable_element(void)
* test_effect_variable_type_class
*/
#if 0
-cbuffer cb <String s = "STRING";>
+cbuffer cb <String s = "STRING"; String s2 = "STRING"; >
{
float f;
vector <int, 2> i;
@@ -1186,109 +1186,60 @@ GeometryShader gs[2];
PixelShader ps;
VertexShader vs[1];
#endif
-static DWORD fx_test_evtc[] = {
-0x43425844, 0xc04c50cb, 0x0afeb4ef, 0xbb93f346,
-0x97a29499, 0x00000001, 0x00000659, 0x00000001,
-0x00000024, 0x30315846, 0x0000062d, 0xfeff1001,
-0x00000001, 0x00000004, 0x00000011, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x000003d9,
-0x00000000, 0x00000008, 0x00000001, 0x00000001,
-0x00000001, 0x00000001, 0x00000001, 0x00000001,
-0x00000004, 0x00000000, 0x00000000, 0x53006263,
-0x6e697274, 0x00070067, 0x00020000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00010000,
-0x00730000, 0x49525453, 0x6600474e, 0x74616f6c,
-0x00003300, 0x00000100, 0x00000000, 0x00000400,
-0x00001000, 0x00000400, 0x00090900, 0x69006600,
-0x0032746e, 0x00000057, 0x00000001, 0x00000000,
-0x00000008, 0x00000010, 0x00000008, 0x00001112,
-0x69750069, 0x7832746e, 0x007a0033, 0x00010000,
-0x00000000, 0x00280000, 0x00300000, 0x00180000,
-0x5a1b0000, 0x00750000, 0x6c6f6f62, 0x00337832,
-0x000000a0, 0x00000001, 0x00000000, 0x0000001c,
-0x00000020, 0x00000018, 0x00001a23, 0x6c420062,
-0x53646e65, 0x65746174, 0x0000c600, 0x00000200,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000200, 0x656c6200, 0x4400646e, 0x68747065,
-0x6e657453, 0x536c6963, 0x65746174, 0x0000f300,
-0x00000200, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000300, 0x70656400, 0x74736874,
-0x69636e65, 0x6152006c, 0x72657473, 0x72657a69,
-0x74617453, 0x012e0065, 0x00020000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00040000,
-0x61720000, 0x53007473, 0x6c706d61, 0x74537265,
-0x00657461, 0x0000015f, 0x00000002, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000015,
-0x006d6173, 0x646e6552, 0x61547265, 0x74656772,
-0x77656956, 0x00018c00, 0x00000200, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00001300,
-0x76747200, 0x70654400, 0x74536874, 0x69636e65,
-0x6569566c, 0x01bd0077, 0x00020000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00140000,
-0x73640000, 0x65540076, 0x72757478, 0x00443165,
-0x000001ee, 0x00000002, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x0000000a, 0x54003174,
-0x75747865, 0x44316572, 0x61727241, 0x02170079,
-0x00020000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x000b0000, 0x31740000, 0x65540061,
-0x72757478, 0x00443265, 0x00000246, 0x00000002,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x0000000c, 0x54003274, 0x75747865, 0x44326572,
-0x6f00534d, 0x02000002, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x0e000000, 0x74000000,
-0x736d6432, 0x78655400, 0x65727574, 0x72414432,
-0x00796172, 0x0000029d, 0x00000002, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x0000000d,
-0x00613274, 0x74786554, 0x32657275, 0x41534d44,
-0x79617272, 0x0002cc00, 0x00000200, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000f00,
-0x64327400, 0x0061736d, 0x74786554, 0x33657275,
-0x03000044, 0x00020000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00100000, 0x33740000,
-0x78655400, 0x65727574, 0x65627543, 0x00032900,
-0x00000200, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00001100, 0x00717400, 0x6d6f6547,
-0x79727465, 0x64616853, 0x54007265, 0x02000003,
-0x02000000, 0x00000000, 0x00000000, 0x00000000,
-0x07000000, 0x67000000, 0x69500073, 0x536c6578,
-0x65646168, 0x03820072, 0x00020000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00050000,
-0x73700000, 0x72655600, 0x53786574, 0x65646168,
-0x03ad0072, 0x00020000, 0x00010000, 0x00000000,
-0x00000000, 0x00000000, 0x00060000, 0x73760000,
-0x00000400, 0x00006000, 0x00000000, 0x00000400,
-0xffffff00, 0x000001ff, 0x00002a00, 0x00000e00,
-0x00002c00, 0x00005500, 0x00003900, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00007800, 0x00005c00, 0x00000000, 0x00000400,
-0x00000000, 0x00000000, 0x00000000, 0x00009e00,
-0x00008200, 0x00000000, 0x00001000, 0x00000000,
-0x00000000, 0x00000000, 0x0000c400, 0x0000a800,
-0x00000000, 0x00004000, 0x00000000, 0x00000000,
-0x00000000, 0x0000ed00, 0x0000d100, 0x00000000,
-0xffffff00, 0x000000ff, 0x00000000, 0x00012100,
-0x00010500, 0x00000000, 0xffffff00, 0x000000ff,
-0x00000000, 0x00015a00, 0x00013e00, 0x00000000,
-0xffffff00, 0x000000ff, 0x00000000, 0x00018800,
-0x00016c00, 0x00000000, 0xffffff00, 0x000000ff,
-0x00000000, 0x0001b900, 0x00019d00, 0x00000000,
-0xffffff00, 0x000000ff, 0x0001ea00, 0x0001ce00,
-0x00000000, 0xffffff00, 0x000000ff, 0x00021400,
-0x0001f800, 0x00000000, 0xffffff00, 0x000000ff,
-0x00024200, 0x00022600, 0x00000000, 0xffffff00,
-0x000000ff, 0x00026c00, 0x00025000, 0x00000000,
-0xffffff00, 0x000000ff, 0x00029700, 0x00027b00,
-0x00000000, 0xffffff00, 0x000000ff, 0x0002c800,
-0x0002ac00, 0x00000000, 0xffffff00, 0x000000ff,
-0x0002f900, 0x0002dd00, 0x00000000, 0xffffff00,
-0x000000ff, 0x00032600, 0x00030a00, 0x00000000,
-0xffffff00, 0x000000ff, 0x00035100, 0x00033500,
-0x00000000, 0xffffff00, 0x000000ff, 0x00037f00,
-0x00036300, 0x00000000, 0xffffff00, 0x000000ff,
-0x00000000, 0x00000000, 0x0003aa00, 0x00038e00,
-0x00000000, 0xffffff00, 0x000000ff, 0x00000000,
-0x0003d600, 0x0003ba00, 0x00000000, 0xffffff00,
-0x000000ff, 0x00000000, 0x00000000,
+static DWORD fx_test_evtc[] =
+{
+0x43425844, 0x16ff7a62, 0x6eb690dc, 0x60dd5ba4, 0x903b0ce7, 0x00000001, 0x00000668, 0x00000001,
+0x00000024, 0x30315846, 0x0000063c, 0xfeff1001, 0x00000001, 0x00000004, 0x00000011, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x000003dc, 0x00000000, 0x00000008, 0x00000001, 0x00000001,
+0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000004, 0x00000000, 0x00000000, 0x53006263,
+0x6e697274, 0x00070067, 0x00020000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010000,
+0x00730000, 0x49525453, 0x7300474e, 0x6c660032, 0x0074616f, 0x00000036, 0x00000001, 0x00000000,
+0x00000004, 0x00000010, 0x00000004, 0x00000909, 0x6e690066, 0x5a003274, 0x01000000, 0x00000000,
+0x08000000, 0x10000000, 0x08000000, 0x12000000, 0x69000011, 0x6e697500, 0x33783274, 0x00007d00,
+0x00000100, 0x00000000, 0x00002800, 0x00003000, 0x00001800, 0x005a1b00, 0x62007500, 0x326c6f6f,
+0xa3003378, 0x01000000, 0x00000000, 0x1c000000, 0x20000000, 0x18000000, 0x23000000, 0x6200001a,
+0x656c4200, 0x7453646e, 0x00657461, 0x000000c9, 0x00000002, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000002, 0x6e656c62, 0x65440064, 0x53687470, 0x636e6574, 0x74536c69, 0x00657461,
+0x000000f6, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x74706564,
+0x65747368, 0x6c69636e, 0x73615200, 0x69726574, 0x5372657a, 0x65746174, 0x00013100, 0x00000200,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000400, 0x73617200, 0x61530074, 0x656c706d,
+0x61745372, 0x62006574, 0x02000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x15000000,
+0x73000000, 0x52006d61, 0x65646e65, 0x72615472, 0x56746567, 0x00776569, 0x0000018f, 0x00000002,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000013, 0x00767472, 0x74706544, 0x65745368,
+0x6c69636e, 0x77656956, 0x0001c000, 0x00000200, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00001400, 0x76736400, 0x78655400, 0x65727574, 0xf1004431, 0x02000001, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x0a000000, 0x74000000, 0x65540031, 0x72757478, 0x41443165, 0x79617272,
+0x00021a00, 0x00000200, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000b00, 0x61317400,
+0x78655400, 0x65727574, 0x49004432, 0x02000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x0c000000, 0x74000000, 0x65540032, 0x72757478, 0x4d443265, 0x02720053, 0x00020000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x000e0000, 0x32740000, 0x00736d64, 0x74786554, 0x32657275,
+0x72724144, 0xa0007961, 0x02000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0d000000,
+0x74000000, 0x54006132, 0x75747865, 0x44326572, 0x7241534d, 0x00796172, 0x000002cf, 0x00000002,
+0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x6d643274, 0x54006173, 0x75747865,
+0x44336572, 0x00030300, 0x00000200, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00001000,
+0x00337400, 0x74786554, 0x43657275, 0x00656275, 0x0000032c, 0x00000002, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000011, 0x47007174, 0x656d6f65, 0x53797274, 0x65646168, 0x03570072,
+0x00020000, 0x00020000, 0x00000000, 0x00000000, 0x00000000, 0x00070000, 0x73670000, 0x78695000,
+0x68536c65, 0x72656461, 0x00038500, 0x00000200, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000500, 0x00737000, 0x74726556, 0x68537865, 0x72656461, 0x0003b000, 0x00000200, 0x00000100,
+0x00000000, 0x00000000, 0x00000000, 0x00000600, 0x00737600, 0x00000004, 0x00000060, 0x00000000,
+0x00000004, 0xffffffff, 0x00000002, 0x0000002a, 0x0000000e, 0x0000002c, 0x00000033, 0x0000000e,
+0x0000002c, 0x00000058, 0x0000003c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x0000007b, 0x0000005f, 0x00000000, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x000000a1,
+0x00000085, 0x00000000, 0x00000010, 0x00000000, 0x00000000, 0x00000000, 0x000000c7, 0x000000ab,
+0x00000000, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0x000000f0, 0x000000d4, 0x00000000,
+0xffffffff, 0x00000000, 0x00000000, 0x00000124, 0x00000108, 0x00000000, 0xffffffff, 0x00000000,
+0x00000000, 0x0000015d, 0x00000141, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x0000018b,
+0x0000016f, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x000001bc, 0x000001a0, 0x00000000,
+0xffffffff, 0x00000000, 0x000001ed, 0x000001d1, 0x00000000, 0xffffffff, 0x00000000, 0x00000217,
+0x000001fb, 0x00000000, 0xffffffff, 0x00000000, 0x00000245, 0x00000229, 0x00000000, 0xffffffff,
+0x00000000, 0x0000026f, 0x00000253, 0x00000000, 0xffffffff, 0x00000000, 0x0000029a, 0x0000027e,
+0x00000000, 0xffffffff, 0x00000000, 0x000002cb, 0x000002af, 0x00000000, 0xffffffff, 0x00000000,
+0x000002fc, 0x000002e0, 0x00000000, 0xffffffff, 0x00000000, 0x00000329, 0x0000030d, 0x00000000,
+0xffffffff, 0x00000000, 0x00000354, 0x00000338, 0x00000000, 0xffffffff, 0x00000000, 0x00000382,
+0x00000366, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x000003ad, 0x00000391,
+0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x000003d9, 0x000003bd, 0x00000000, 0xffffffff,
+0x00000000, 0x00000000,
};
static BOOL is_valid_check(BOOL a, BOOL b)
@@ -1382,6 +1333,7 @@ static void check_as(ID3D10EffectVariable *variable)
static void test_effect_variable_type_class(void)
{
+ ID3D10EffectStringVariable *string_var;
ID3D10Effect *effect;
ID3D10EffectConstantBuffer *constantbuffer, *null_buffer, *parent;
ID3D10EffectVariable *variable;
@@ -1392,6 +1344,7 @@ static void test_effect_variable_type_class(void)
ULONG refcount;
HRESULT hr;
unsigned int variable_nr = 0;
+ const char *str1, *str2;
if (!(device = create_device()))
{
@@ -1413,7 +1366,7 @@ static void test_effect_variable_type_class(void)
ok(strcmp(vd.Name, "cb") == 0, "Name is \"%s\", expected \"cb\"\n", vd.Name);
ok(vd.Semantic == NULL, "Semantic is \"%s\", expected NULL\n", vd.Semantic);
ok(vd.Flags == 0, "Type is %u, expected 0\n", vd.Flags);
- ok(vd.Annotations == 1, "Elements is %u, expected 1\n", vd.Annotations);
+ ok(vd.Annotations == 2, "Elements is %u, expected 1\n", vd.Annotations);
ok(vd.BufferOffset == 0, "Members is %u, expected 0\n", vd.BufferOffset);
ok(vd.ExplicitBindPoint == 0, "ExplicitBindPoint is %u, expected 0\n", vd.ExplicitBindPoint);
@@ -1469,6 +1422,24 @@ static void test_effect_variable_type_class(void)
ok(td.UnpackedSize == 0x0, "UnpackedSize is %#x, expected 0x0\n", td.UnpackedSize);
ok(td.Stride == 0x0, "Stride is %#x, expected 0x0\n", td.Stride);
+ string_var = variable->lpVtbl->AsString(variable);
+ hr = string_var->lpVtbl->GetString(string_var, &str1);
+todo_wine
+ ok(SUCCEEDED(hr), "GetString failed %#x.\n", hr);
+ if (SUCCEEDED(hr))
+ ok(!strcmp(str1, "STRING"), "Unexpected value %s.\n", str1);
+
+ variable = constantbuffer->lpVtbl->GetAnnotationByIndex(constantbuffer, 1);
+ string_var = variable->lpVtbl->AsString(variable);
+ hr = string_var->lpVtbl->GetString(string_var, &str2);
+todo_wine
+ ok(SUCCEEDED(hr), "GetString failed %#x.\n", hr);
+ if (SUCCEEDED(hr))
+ {
+ ok(str2 != str1, "Unexpected string pointer.\n");
+ ok(!strcmp(str2, "STRING"), "Unexpected value %s.\n", str1);
+ }
+
/* check float f */
variable = constantbuffer->lpVtbl->GetMemberByIndex(constantbuffer, variable_nr++);
hr = variable->lpVtbl->GetDesc(variable, &vd);
--
2.30.2
1
2
[PATCH 1/5] xinput1_3: Consistently name struct xinput_controller variable.
by Rémi Bernon 09 Aug '21
by Rémi Bernon 09 Aug '21
09 Aug '21
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/xinput1_3/main.c | 134 +++++++++++++++++++++---------------------
1 file changed, 67 insertions(+), 67 deletions(-)
diff --git a/dlls/xinput1_3/main.c b/dlls/xinput1_3/main.c
index 248f8f796e5..25f3b0f0407 100644
--- a/dlls/xinput1_3/main.c
+++ b/dlls/xinput1_3/main.c
@@ -240,18 +240,18 @@ static BOOL VerifyGamepad(PHIDP_PREPARSED_DATA preparsed, XINPUT_CAPABILITIES *x
return TRUE;
}
-static DWORD HID_set_state(struct xinput_controller *device, XINPUT_VIBRATION *state)
+static DWORD HID_set_state(struct xinput_controller *controller, XINPUT_VIBRATION *state)
{
- struct hid_platform_private *private = device->platform_private;
+ struct hid_platform_private *private = controller->platform_private;
char *output_report_buf = private->output_report_buf;
ULONG output_report_len = private->caps.OutputReportByteLength;
- if (device->caps.Flags & XINPUT_CAPS_FFB_SUPPORTED)
+ if (controller->caps.Flags & XINPUT_CAPS_FFB_SUPPORTED)
{
- device->vibration.wLeftMotorSpeed = state->wLeftMotorSpeed;
- device->vibration.wRightMotorSpeed = state->wRightMotorSpeed;
+ controller->vibration.wLeftMotorSpeed = state->wLeftMotorSpeed;
+ controller->vibration.wRightMotorSpeed = state->wRightMotorSpeed;
- if (device->enabled)
+ if (controller->enabled)
{
memset(output_report_buf, 0, output_report_len);
output_report_buf[0] = /* report id */ 0;
@@ -395,16 +395,16 @@ static void HID_find_gamepads(void)
LeaveCriticalSection(&xinput_crit);
}
-static void remove_gamepad(struct xinput_controller *device)
+static void remove_gamepad(struct xinput_controller *controller)
{
- EnterCriticalSection(&device->crit);
+ EnterCriticalSection(&controller->crit);
- if (device->platform_private)
+ if (controller->platform_private)
{
- struct hid_platform_private *private = device->platform_private;
+ struct hid_platform_private *private = controller->platform_private;
- controller_disable(device);
- device->platform_private = NULL;
+ controller_disable(controller);
+ controller->platform_private = NULL;
CloseHandle(private->device);
free(private->input_report_buf[0]);
@@ -414,7 +414,7 @@ static void remove_gamepad(struct xinput_controller *device)
free(private);
}
- LeaveCriticalSection(&device->crit);
+ LeaveCriticalSection(&controller->crit);
}
static void HID_destroy_gamepads(void)
@@ -433,9 +433,9 @@ static BYTE scale_byte(LONG value, const struct axis_info *axis)
return (((ULONGLONG)(value - axis->min)) * 0xff) / axis->range;
}
-static void HID_update_state(struct xinput_controller *device, XINPUT_STATE *state)
+static void HID_update_state(struct xinput_controller *controller, XINPUT_STATE *state)
{
- struct hid_platform_private *private = device->platform_private;
+ struct hid_platform_private *private = controller->platform_private;
int i;
char **report_buf = private->input_report_buf, *tmp;
ULONG report_len = private->caps.InputReportByteLength;
@@ -445,14 +445,14 @@ static void HID_update_state(struct xinput_controller *device, XINPUT_STATE *sta
ULONG button_length, hat_value;
LONG value;
- if (!device->enabled) return;
+ if (!controller->enabled) return;
if (!HidD_GetInputReport(private->device, report_buf[0], report_len))
{
if (GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == ERROR_INVALID_HANDLE)
{
EnterCriticalSection(&xinput_crit);
- remove_gamepad(device);
+ remove_gamepad(controller);
LeaveCriticalSection(&xinput_crit);
}
else ERR("Failed to get input report, HidD_GetInputReport failed with error %u\n", GetLastError());
@@ -461,27 +461,27 @@ static void HID_update_state(struct xinput_controller *device, XINPUT_STATE *sta
if (memcmp(report_buf[0], report_buf[1], report_len) != 0)
{
- device->state.dwPacketNumber++;
+ controller->state.dwPacketNumber++;
button_length = ARRAY_SIZE(buttons);
status = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, buttons, &button_length, private->preparsed, report_buf[0], report_len);
if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetUsages HID_USAGE_PAGE_BUTTON returned %#x\n", status);
- device->state.Gamepad.wButtons = 0;
+ controller->state.Gamepad.wButtons = 0;
for (i = 0; i < button_length; i++)
{
switch (buttons[i])
{
- case 1: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_A; break;
- case 2: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_B; break;
- case 3: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_X; break;
- case 4: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_Y; break;
- case 5: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_SHOULDER; break;
- case 6: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_SHOULDER; break;
- case 7: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_BACK; break;
- case 8: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_START; break;
- case 9: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_THUMB; break;
- case 10: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_THUMB; break;
- case 11: device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_GUIDE; break;
+ case 1: controller->state.Gamepad.wButtons |= XINPUT_GAMEPAD_A; break;
+ case 2: controller->state.Gamepad.wButtons |= XINPUT_GAMEPAD_B; break;
+ case 3: controller->state.Gamepad.wButtons |= XINPUT_GAMEPAD_X; break;
+ case 4: controller->state.Gamepad.wButtons |= XINPUT_GAMEPAD_Y; break;
+ case 5: controller->state.Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_SHOULDER; break;
+ case 6: controller->state.Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_SHOULDER; break;
+ case 7: controller->state.Gamepad.wButtons |= XINPUT_GAMEPAD_BACK; break;
+ case 8: controller->state.Gamepad.wButtons |= XINPUT_GAMEPAD_START; break;
+ case 9: controller->state.Gamepad.wButtons |= XINPUT_GAMEPAD_LEFT_THUMB; break;
+ case 10: controller->state.Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_THUMB; break;
+ case 11: controller->state.Gamepad.wButtons |= XINPUT_GAMEPAD_GUIDE; break;
}
}
@@ -496,81 +496,81 @@ static void HID_update_state(struct xinput_controller *device, XINPUT_STATE *sta
case 0:
break;
case 1:
- device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_UP;
+ controller->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_UP;
break;
case 2:
- device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_UP | XINPUT_GAMEPAD_DPAD_RIGHT;
+ controller->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_UP | XINPUT_GAMEPAD_DPAD_RIGHT;
break;
case 3:
- device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_RIGHT;
+ controller->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_RIGHT;
break;
case 4:
- device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_RIGHT | XINPUT_GAMEPAD_DPAD_DOWN;
+ controller->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_RIGHT | XINPUT_GAMEPAD_DPAD_DOWN;
break;
case 5:
- device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN;
+ controller->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN;
break;
case 6:
- device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN | XINPUT_GAMEPAD_DPAD_LEFT;
+ controller->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN | XINPUT_GAMEPAD_DPAD_LEFT;
break;
case 7:
- device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT;
+ controller->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT;
break;
case 8:
- device->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT | XINPUT_GAMEPAD_DPAD_UP;
+ controller->state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT | XINPUT_GAMEPAD_DPAD_UP;
break;
}
}
status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, &value, private->preparsed, report_buf[0], report_len);
if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetScaledUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_X returned %#x\n", status);
- else device->state.Gamepad.sThumbLX = scale_short(value, &private->lx);
+ else controller->state.Gamepad.sThumbLX = scale_short(value, &private->lx);
status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Y, &value, private->preparsed, report_buf[0], report_len);
if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetScaledUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_Y returned %#x\n", status);
- else device->state.Gamepad.sThumbLY = -scale_short(value, &private->ly) - 1;
+ else controller->state.Gamepad.sThumbLY = -scale_short(value, &private->ly) - 1;
status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RX, &value, private->preparsed, report_buf[0], report_len);
if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetScaledUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_RX returned %#x\n", status);
- else device->state.Gamepad.sThumbRX = scale_short(value, &private->rx);
+ else controller->state.Gamepad.sThumbRX = scale_short(value, &private->rx);
status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RY, &value, private->preparsed, report_buf[0], report_len);
if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetScaledUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_RY returned %#x\n", status);
- else device->state.Gamepad.sThumbRY = -scale_short(value, &private->ry) - 1;
+ else controller->state.Gamepad.sThumbRY = -scale_short(value, &private->ry) - 1;
status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RZ, &value, private->preparsed, report_buf[0], report_len);
if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetScaledUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_RZ returned %#x\n", status);
- else device->state.Gamepad.bRightTrigger = scale_byte(value, &private->rtrigger);
+ else controller->state.Gamepad.bRightTrigger = scale_byte(value, &private->rtrigger);
status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, &value, private->preparsed, report_buf[0], report_len);
if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetScaledUsageValue HID_USAGE_PAGE_GENERIC / HID_USAGE_GENERIC_Z returned %#x\n", status);
- else device->state.Gamepad.bLeftTrigger = scale_byte(value, &private->ltrigger);
+ else controller->state.Gamepad.bLeftTrigger = scale_byte(value, &private->ltrigger);
}
tmp = report_buf[0];
report_buf[0] = report_buf[1];
report_buf[1] = tmp;
- memcpy(state, &device->state, sizeof(*state));
+ memcpy(state, &controller->state, sizeof(*state));
}
-static BOOL verify_and_lock_device(struct xinput_controller *device)
+static BOOL verify_and_lock_device(struct xinput_controller *controller)
{
- if (!device->platform_private) return FALSE;
+ if (!controller->platform_private) return FALSE;
- EnterCriticalSection(&device->crit);
+ EnterCriticalSection(&controller->crit);
- if (!device->platform_private)
+ if (!controller->platform_private)
{
- LeaveCriticalSection(&device->crit);
+ LeaveCriticalSection(&controller->crit);
return FALSE;
}
return TRUE;
}
-static void unlock_device(struct xinput_controller *device)
+static void unlock_device(struct xinput_controller *controller)
{
- LeaveCriticalSection(&device->crit);
+ LeaveCriticalSection(&controller->crit);
}
BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
@@ -768,7 +768,7 @@ static BOOL trigger_is_on(const BYTE value)
static DWORD check_for_keystroke(const DWORD index, XINPUT_KEYSTROKE *keystroke)
{
- struct xinput_controller *device = &controllers[index];
+ struct xinput_controller *controller = &controllers[index];
const XINPUT_GAMEPAD *cur;
DWORD ret = ERROR_EMPTY;
int i;
@@ -795,26 +795,26 @@ static DWORD check_for_keystroke(const DWORD index, XINPUT_KEYSTROKE *keystroke)
/* note: guide button does not send an event */
};
- if (!verify_and_lock_device(device)) return ERROR_DEVICE_NOT_CONNECTED;
+ if (!verify_and_lock_device(controller)) return ERROR_DEVICE_NOT_CONNECTED;
- cur = &device->state.Gamepad;
+ cur = &controller->state.Gamepad;
/*** buttons ***/
for (i = 0; i < ARRAY_SIZE(buttons); ++i)
{
- if ((cur->wButtons & buttons[i].mask) ^ (device->last_keystroke.wButtons & buttons[i].mask))
+ if ((cur->wButtons & buttons[i].mask) ^ (controller->last_keystroke.wButtons & buttons[i].mask))
{
keystroke->VirtualKey = buttons[i].vk;
keystroke->Unicode = 0; /* unused */
if (cur->wButtons & buttons[i].mask)
{
keystroke->Flags = XINPUT_KEYSTROKE_KEYDOWN;
- device->last_keystroke.wButtons |= buttons[i].mask;
+ controller->last_keystroke.wButtons |= buttons[i].mask;
}
else
{
keystroke->Flags = XINPUT_KEYSTROKE_KEYUP;
- device->last_keystroke.wButtons &= ~buttons[i].mask;
+ controller->last_keystroke.wButtons &= ~buttons[i].mask;
}
keystroke->UserIndex = index;
keystroke->HidCode = 0;
@@ -824,45 +824,45 @@ static DWORD check_for_keystroke(const DWORD index, XINPUT_KEYSTROKE *keystroke)
}
/*** triggers ***/
- if (trigger_is_on(cur->bLeftTrigger) ^ trigger_is_on(device->last_keystroke.bLeftTrigger))
+ if (trigger_is_on(cur->bLeftTrigger) ^ trigger_is_on(controller->last_keystroke.bLeftTrigger))
{
keystroke->VirtualKey = VK_PAD_LTRIGGER;
keystroke->Unicode = 0; /* unused */
keystroke->Flags = trigger_is_on(cur->bLeftTrigger) ? XINPUT_KEYSTROKE_KEYDOWN : XINPUT_KEYSTROKE_KEYUP;
keystroke->UserIndex = index;
keystroke->HidCode = 0;
- device->last_keystroke.bLeftTrigger = cur->bLeftTrigger;
+ controller->last_keystroke.bLeftTrigger = cur->bLeftTrigger;
ret = ERROR_SUCCESS;
goto done;
}
- if (trigger_is_on(cur->bRightTrigger) ^ trigger_is_on(device->last_keystroke.bRightTrigger))
+ if (trigger_is_on(cur->bRightTrigger) ^ trigger_is_on(controller->last_keystroke.bRightTrigger))
{
keystroke->VirtualKey = VK_PAD_RTRIGGER;
keystroke->Unicode = 0; /* unused */
keystroke->Flags = trigger_is_on(cur->bRightTrigger) ? XINPUT_KEYSTROKE_KEYDOWN : XINPUT_KEYSTROKE_KEYUP;
keystroke->UserIndex = index;
keystroke->HidCode = 0;
- device->last_keystroke.bRightTrigger = cur->bRightTrigger;
+ controller->last_keystroke.bRightTrigger = cur->bRightTrigger;
ret = ERROR_SUCCESS;
goto done;
}
/*** joysticks ***/
ret = check_joystick_keystroke(index, keystroke, &cur->sThumbLX, &cur->sThumbLY,
- &device->last_keystroke.sThumbLX,
- &device->last_keystroke.sThumbLY, VK_PAD_LTHUMB_UP);
+ &controller->last_keystroke.sThumbLX,
+ &controller->last_keystroke.sThumbLY, VK_PAD_LTHUMB_UP);
if (ret == ERROR_SUCCESS)
goto done;
ret = check_joystick_keystroke(index, keystroke, &cur->sThumbRX, &cur->sThumbRY,
- &device->last_keystroke.sThumbRX,
- &device->last_keystroke.sThumbRY, VK_PAD_RTHUMB_UP);
+ &controller->last_keystroke.sThumbRX,
+ &controller->last_keystroke.sThumbRY, VK_PAD_RTHUMB_UP);
if (ret == ERROR_SUCCESS)
goto done;
done:
- unlock_device(device);
+ unlock_device(controller);
return ret;
}
--
2.32.0
1
4
09 Aug '21
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/iphlpapi/ifenum.c | 671 +---------------------------------
dlls/iphlpapi/ifenum.h | 42 ---
dlls/iphlpapi/iphlpapi_main.c | 647 ++++++++++++--------------------
3 files changed, 233 insertions(+), 1127 deletions(-)
diff --git a/dlls/iphlpapi/ifenum.c b/dlls/iphlpapi/ifenum.c
index 8108c7ff8c2..9cb576f86fd 100644
--- a/dlls/iphlpapi/ifenum.c
+++ b/dlls/iphlpapi/ifenum.c
@@ -122,7 +122,7 @@ static BOOL isLoopbackInterface(int fd, const char *name)
/* The comments say MAX_ADAPTER_NAME is required, but really only IF_NAMESIZE
* bytes are necessary.
*/
-char *getInterfaceNameByIndex(IF_INDEX index, char *name)
+static char *getInterfaceNameByIndex(IF_INDEX index, char *name)
{
return if_indextoname(index, name);
}
@@ -146,7 +146,7 @@ DWORD getInterfaceIndexByName(const char *name, IF_INDEX *index)
return ret;
}
-BOOL isIfIndexLoopback(ULONG idx)
+static BOOL isIfIndexLoopback(ULONG idx)
{
BOOL ret = FALSE;
char name[IFNAMSIZ];
@@ -394,670 +394,3 @@ DWORD get_interface_indices( BOOL skip_loopback, InterfaceIndexTable **table )
}
#endif
-static DWORD getInterfaceBCastAddrByName(const char *name)
-{
- DWORD ret = INADDR_ANY;
-
- if (name) {
- int fd = socket(PF_INET, SOCK_DGRAM, 0);
-
- if (fd != -1) {
- struct ifreq ifr;
-
- lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
- if (ioctl(fd, SIOCGIFBRDADDR, &ifr) == 0)
- memcpy(&ret, ifr.ifr_addr.sa_data + 2, sizeof(DWORD));
- close(fd);
- }
- }
- return ret;
-}
-
-static DWORD getInterfaceMaskByName(const char *name)
-{
- DWORD ret = INADDR_NONE;
-
- if (name) {
- int fd = socket(PF_INET, SOCK_DGRAM, 0);
-
- if (fd != -1) {
- struct ifreq ifr;
-
- lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
- if (ioctl(fd, SIOCGIFNETMASK, &ifr) == 0)
- memcpy(&ret, ifr.ifr_addr.sa_data + 2, sizeof(DWORD));
- close(fd);
- }
- }
- return ret;
-}
-
-#if defined (SIOCGIFHWADDR) && defined (HAVE_STRUCT_IFREQ_IFR_HWADDR)
-static DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr,
- PDWORD type)
-{
- DWORD ret;
- int fd;
-
- if (!name || !len || !addr || !type)
- return ERROR_INVALID_PARAMETER;
-
- fd = socket(PF_INET, SOCK_DGRAM, 0);
- if (fd != -1) {
- struct ifreq ifr;
-
- memset(&ifr, 0, sizeof(struct ifreq));
- lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
- if ((ioctl(fd, SIOCGIFHWADDR, &ifr)))
- ret = ERROR_INVALID_DATA;
- else {
- unsigned int addrLen;
-
- switch (ifr.ifr_hwaddr.sa_family)
- {
-#ifdef ARPHRD_LOOPBACK
- case ARPHRD_LOOPBACK:
- addrLen = 0;
- *type = MIB_IF_TYPE_LOOPBACK;
- break;
-#endif
-#ifdef ARPHRD_ETHER
- case ARPHRD_ETHER:
- addrLen = ETH_ALEN;
- *type = MIB_IF_TYPE_ETHERNET;
- break;
-#endif
-#ifdef ARPHRD_FDDI
- case ARPHRD_FDDI:
- addrLen = ETH_ALEN;
- *type = MIB_IF_TYPE_FDDI;
- break;
-#endif
-#ifdef ARPHRD_IEEE802
- case ARPHRD_IEEE802: /* 802.2 Ethernet && Token Ring, guess TR? */
- addrLen = ETH_ALEN;
- *type = MIB_IF_TYPE_TOKENRING;
- break;
-#endif
-#ifdef ARPHRD_IEEE802_TR
- case ARPHRD_IEEE802_TR: /* also Token Ring? */
- addrLen = ETH_ALEN;
- *type = MIB_IF_TYPE_TOKENRING;
- break;
-#endif
-#ifdef ARPHRD_SLIP
- case ARPHRD_SLIP:
- addrLen = 0;
- *type = MIB_IF_TYPE_SLIP;
- break;
-#endif
-#ifdef ARPHRD_PPP
- case ARPHRD_PPP:
- addrLen = 0;
- *type = MIB_IF_TYPE_PPP;
- break;
-#endif
- default:
- addrLen = 0;
- *type = MIB_IF_TYPE_OTHER;
- }
- if (addrLen > *len) {
- ret = ERROR_INSUFFICIENT_BUFFER;
- *len = addrLen;
- }
- else {
- if (addrLen > 0)
- memcpy(addr, ifr.ifr_hwaddr.sa_data, addrLen);
- /* zero out remaining bytes for broken implementations */
- memset(addr + addrLen, 0, *len - addrLen);
- *len = addrLen;
- ret = NO_ERROR;
- }
- }
- close(fd);
- }
- else
- ret = ERROR_NO_MORE_FILES;
- return ret;
-}
-#elif defined (SIOCGARP)
-static DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr,
- PDWORD type)
-{
- DWORD ret;
- int fd;
-
- if (!name || !len || !addr || !type)
- return ERROR_INVALID_PARAMETER;
-
- fd = socket(PF_INET, SOCK_DGRAM, 0);
- if (fd != -1) {
- if (isLoopbackInterface(fd, name)) {
- *type = MIB_IF_TYPE_LOOPBACK;
- memset(addr, 0, *len);
- *len = 0;
- ret=NOERROR;
- }
- else {
- struct arpreq arp;
- struct sockaddr_in *saddr;
- struct ifreq ifr;
-
- /* get IP addr */
- lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
- ioctl(fd, SIOCGIFADDR, &ifr);
- memset(&arp, 0, sizeof(struct arpreq));
- arp.arp_pa.sa_family = AF_INET;
- saddr = (struct sockaddr_in *)&arp; /* proto addr is first member */
- saddr->sin_family = AF_INET;
- memcpy(&saddr->sin_addr.s_addr, ifr.ifr_addr.sa_data + 2, sizeof(DWORD));
- if ((ioctl(fd, SIOCGARP, &arp)))
- ret = ERROR_INVALID_DATA;
- else {
- /* FIXME: heh: who said it was ethernet? */
- int addrLen = ETH_ALEN;
-
- if (addrLen > *len) {
- ret = ERROR_INSUFFICIENT_BUFFER;
- *len = addrLen;
- }
- else {
- if (addrLen > 0)
- memcpy(addr, &arp.arp_ha.sa_data[0], addrLen);
- /* zero out remaining bytes for broken implementations */
- memset(addr + addrLen, 0, *len - addrLen);
- *len = addrLen;
- *type = MIB_IF_TYPE_ETHERNET;
- ret = NO_ERROR;
- }
- }
- }
- close(fd);
- }
- else
- ret = ERROR_NO_MORE_FILES;
-
- return ret;
-}
-#elif defined (HAVE_SYS_SYSCTL_H) && defined (HAVE_NET_IF_DL_H)
-static DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr,
- PDWORD type)
-{
- DWORD ret;
- struct if_msghdr *ifm;
- struct sockaddr_dl *sdl;
- u_char *p, *buf;
- size_t mibLen;
- int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 };
- unsigned addrLen;
- BOOL found = FALSE;
-
- if (!name || !len || !addr || !type)
- return ERROR_INVALID_PARAMETER;
-
- if (sysctl(mib, 6, NULL, &mibLen, NULL, 0) < 0)
- return ERROR_NO_MORE_FILES;
-
- buf = HeapAlloc(GetProcessHeap(), 0, mibLen);
- if (!buf)
- return ERROR_NOT_ENOUGH_MEMORY;
-
- if (sysctl(mib, 6, buf, &mibLen, NULL, 0) < 0) {
- HeapFree(GetProcessHeap(), 0, buf);
- return ERROR_NO_MORE_FILES;
- }
-
- ret = ERROR_INVALID_DATA;
- for (p = buf; !found && p < buf + mibLen; p += ifm->ifm_msglen) {
- ifm = (struct if_msghdr *)p;
- sdl = (struct sockaddr_dl *)(ifm + 1);
-
- if (ifm->ifm_type != RTM_IFINFO || (ifm->ifm_addrs & RTA_IFP) == 0)
- continue;
-
- if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 ||
- memcmp(sdl->sdl_data, name, max(sdl->sdl_nlen, strlen(name))) != 0)
- continue;
-
- found = TRUE;
- addrLen = min(MAX_INTERFACE_PHYSADDR, sdl->sdl_alen);
- if (addrLen > *len) {
- ret = ERROR_INSUFFICIENT_BUFFER;
- *len = addrLen;
- }
- else {
- if (addrLen > 0)
- memcpy(addr, LLADDR(sdl), addrLen);
- /* zero out remaining bytes for broken implementations */
- memset(addr + addrLen, 0, *len - addrLen);
- *len = addrLen;
-#if defined(HAVE_NET_IF_TYPES_H)
- switch (sdl->sdl_type)
- {
- case IFT_ETHER:
- *type = MIB_IF_TYPE_ETHERNET;
- break;
- case IFT_FDDI:
- *type = MIB_IF_TYPE_FDDI;
- break;
- case IFT_ISO88024: /* Token Bus */
- *type = MIB_IF_TYPE_TOKENRING;
- break;
- case IFT_ISO88025: /* Token Ring */
- *type = MIB_IF_TYPE_TOKENRING;
- break;
- case IFT_PPP:
- *type = MIB_IF_TYPE_PPP;
- break;
- case IFT_SLIP:
- *type = MIB_IF_TYPE_SLIP;
- break;
- case IFT_LOOP:
- *type = MIB_IF_TYPE_LOOPBACK;
- break;
- default:
- *type = MIB_IF_TYPE_OTHER;
- }
-#else
- /* default if we don't know */
- *type = MIB_IF_TYPE_ETHERNET;
-#endif
- ret = NO_ERROR;
- }
- }
- HeapFree(GetProcessHeap(), 0, buf);
- return ret;
-}
-#endif
-
-DWORD getInterfacePhysicalByIndex(IF_INDEX index, PDWORD len, PBYTE addr,
- PDWORD type)
-{
- char nameBuf[IF_NAMESIZE];
- char *name = getInterfaceNameByIndex(index, nameBuf);
-
- if (name)
- return getInterfacePhysicalByName(name, len, addr, type);
- else
- return ERROR_INVALID_DATA;
-}
-
-DWORD getInterfaceMtuByName(const char *name, PDWORD mtu)
-{
- DWORD ret;
- int fd;
-
- if (!name)
- return ERROR_INVALID_PARAMETER;
- if (!mtu)
- return ERROR_INVALID_PARAMETER;
-
- fd = socket(PF_INET, SOCK_DGRAM, 0);
- if (fd != -1) {
- struct ifreq ifr;
-
- lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
- if ((ioctl(fd, SIOCGIFMTU, &ifr)))
- ret = ERROR_INVALID_DATA;
- else {
-#ifndef __sun
- *mtu = ifr.ifr_mtu;
-#else
- *mtu = ifr.ifr_metric;
-#endif
- ret = NO_ERROR;
- }
- close(fd);
- }
- else
- ret = ERROR_NO_MORE_FILES;
- return ret;
-}
-
-DWORD getInterfaceStatusByName(const char *name, INTERNAL_IF_OPER_STATUS *status)
-{
- DWORD ret;
- int fd;
-
- if (!name)
- return ERROR_INVALID_PARAMETER;
- if (!status)
- return ERROR_INVALID_PARAMETER;
-
- fd = socket(PF_INET, SOCK_DGRAM, 0);
- if (fd != -1) {
- struct ifreq ifr;
-
- lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
- if ((ioctl(fd, SIOCGIFFLAGS, &ifr)))
- ret = ERROR_INVALID_DATA;
- else {
- if (ifr.ifr_flags & IFF_UP)
- *status = MIB_IF_OPER_STATUS_OPERATIONAL;
- else
- *status = MIB_IF_OPER_STATUS_NON_OPERATIONAL;
- ret = NO_ERROR;
- }
- close(fd);
- }
- else
- ret = ERROR_NO_MORE_FILES;
- return ret;
-}
-
-static DWORD getIPAddrRowByName(PMIB_IPADDRROW ipAddrRow, const char *ifName,
- const struct sockaddr *sa)
-{
- DWORD ret, bcast;
-
- ret = getInterfaceIndexByName(ifName, &ipAddrRow->dwIndex);
- memcpy(&ipAddrRow->dwAddr, sa->sa_data + 2, sizeof(DWORD));
- ipAddrRow->dwMask = getInterfaceMaskByName(ifName);
- /* the dwBCastAddr member isn't the broadcast address, it indicates whether
- * the interface uses the 1's broadcast address (1) or the 0's broadcast
- * address (0).
- */
- bcast = getInterfaceBCastAddrByName(ifName);
- ipAddrRow->dwBCastAddr = (bcast & ipAddrRow->dwMask) ? 1 : 0;
- /* FIXME: hardcoded reasm size, not sure where to get it */
- ipAddrRow->dwReasmSize = 65535;
- ipAddrRow->unused1 = 0;
- /* wType is a bit field composed of MIB_IPADDR_* flags. Windows <= XP seems
- * to like returning undocumented values 0x20 + 0x02 but for our current
- * needs returning MIB_IPADDR_PRIMARY is enough.
- */
- ipAddrRow->wType = MIB_IPADDR_PRIMARY;
- return ret;
-}
-
-#if defined(HAVE_IFADDRS_H) && defined(HAVE_GETIFADDRS)
-
-/* Counts the IPv4 addresses in the system using the return value from
- * getifaddrs, returning the count.
- */
-static DWORD countIPv4Addresses(struct ifaddrs *ifa)
-{
- DWORD numAddresses = 0;
-
- for (; ifa; ifa = ifa->ifa_next)
- if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET)
- numAddresses++;
- return numAddresses;
-}
-
-DWORD getNumIPAddresses(void)
-{
- DWORD numAddresses = 0;
- struct ifaddrs *ifa;
-
- if (!getifaddrs(&ifa))
- {
- numAddresses = countIPv4Addresses(ifa);
- freeifaddrs(ifa);
- }
- return numAddresses;
-}
-
-DWORD getIPAddrTable(PMIB_IPADDRTABLE *ppIpAddrTable, HANDLE heap, DWORD flags)
-{
- DWORD ret;
-
- if (!ppIpAddrTable)
- ret = ERROR_INVALID_PARAMETER;
- else
- {
- struct ifaddrs *ifa;
-
- if (!getifaddrs(&ifa))
- {
- DWORD size = sizeof(MIB_IPADDRTABLE);
- DWORD numAddresses = countIPv4Addresses(ifa);
-
- if (numAddresses > 1)
- size += (numAddresses - 1) * sizeof(MIB_IPADDRROW);
- *ppIpAddrTable = HeapAlloc(heap, flags, size);
- if (*ppIpAddrTable)
- {
- DWORD i = 0;
- struct ifaddrs *ifp;
-
- ret = NO_ERROR;
- (*ppIpAddrTable)->dwNumEntries = numAddresses;
- for (ifp = ifa; !ret && ifp; ifp = ifp->ifa_next)
- {
- if (!ifp->ifa_addr || ifp->ifa_addr->sa_family != AF_INET)
- continue;
-
- ret = getIPAddrRowByName(&(*ppIpAddrTable)->table[i], ifp->ifa_name,
- ifp->ifa_addr);
- i++;
- }
- if (ret)
- HeapFree(GetProcessHeap(), 0, *ppIpAddrTable);
- }
- else
- ret = ERROR_OUTOFMEMORY;
- freeifaddrs(ifa);
- }
- else
- ret = ERROR_INVALID_PARAMETER;
- }
- return ret;
-}
-
-ULONG v6addressesFromIndex(IF_INDEX index, SOCKET_ADDRESS **addrs, ULONG *num_addrs, SOCKET_ADDRESS **masks)
-{
- struct ifaddrs *ifa;
- ULONG ret;
-
- if (!getifaddrs(&ifa))
- {
- struct ifaddrs *p;
- ULONG n;
- char name[IFNAMSIZ];
-
- getInterfaceNameByIndex(index, name);
- for (p = ifa, n = 0; p; p = p->ifa_next)
- if (p->ifa_addr && p->ifa_addr->sa_family == AF_INET6 &&
- !strcmp(name, p->ifa_name))
- n++;
- if (n)
- {
- *addrs = HeapAlloc(GetProcessHeap(), 0, n * (sizeof(SOCKET_ADDRESS) +
- sizeof(struct WS_sockaddr_in6)));
- *masks = HeapAlloc(GetProcessHeap(), 0, n * (sizeof(SOCKET_ADDRESS) +
- sizeof(struct WS_sockaddr_in6)));
- if (*addrs && *masks)
- {
- struct WS_sockaddr_in6 *next_addr = (struct WS_sockaddr_in6 *)(
- (BYTE *)*addrs + n * sizeof(SOCKET_ADDRESS));
- struct WS_sockaddr_in6 *mask_addr = (struct WS_sockaddr_in6 *)(
- (BYTE *)*masks + n * sizeof(SOCKET_ADDRESS));
-
- for (p = ifa, n = 0; p; p = p->ifa_next)
- {
- if (p->ifa_addr && p->ifa_addr->sa_family == AF_INET6 &&
- !strcmp(name, p->ifa_name))
- {
- struct sockaddr_in6 *addr = (struct sockaddr_in6 *)p->ifa_addr;
- struct sockaddr_in6 *mask = (struct sockaddr_in6 *)p->ifa_netmask;
-
- next_addr->sin6_family = WS_AF_INET6;
- next_addr->sin6_port = addr->sin6_port;
- next_addr->sin6_flowinfo = addr->sin6_flowinfo;
- memcpy(&next_addr->sin6_addr, &addr->sin6_addr,
- sizeof(next_addr->sin6_addr));
- next_addr->sin6_scope_id = addr->sin6_scope_id;
- (*addrs)[n].lpSockaddr = (LPSOCKADDR)next_addr;
- (*addrs)[n].iSockaddrLength = sizeof(struct WS_sockaddr_in6);
- next_addr++;
-
- mask_addr->sin6_family = WS_AF_INET6;
- mask_addr->sin6_port = mask->sin6_port;
- mask_addr->sin6_flowinfo = mask->sin6_flowinfo;
- memcpy(&mask_addr->sin6_addr, &mask->sin6_addr,
- sizeof(mask_addr->sin6_addr));
- mask_addr->sin6_scope_id = mask->sin6_scope_id;
- (*masks)[n].lpSockaddr = (LPSOCKADDR)mask_addr;
- (*masks)[n].iSockaddrLength = sizeof(struct WS_sockaddr_in6);
- mask_addr++;
- n++;
- }
- }
- *num_addrs = n;
- ret = ERROR_SUCCESS;
- }
- else
- {
- HeapFree(GetProcessHeap(), 0, *addrs);
- HeapFree(GetProcessHeap(), 0, *masks);
- ret = ERROR_OUTOFMEMORY;
- }
- }
- else
- {
- *addrs = NULL;
- *num_addrs = 0;
- *masks = NULL;
- ret = ERROR_SUCCESS;
- }
- freeifaddrs(ifa);
- }
- else
- ret = ERROR_NO_DATA;
- return ret;
-}
-
-#else
-
-/* Enumerates the IP addresses in the system using SIOCGIFCONF, returning
- * the count to you in *pcAddresses. It also returns to you the struct ifconf
- * used by the call to ioctl, so that you may process the addresses further.
- * Free ifc->ifc_buf using HeapFree.
- * Returns NO_ERROR on success, something else on failure.
- */
-static DWORD enumIPAddresses(PDWORD pcAddresses, struct ifconf *ifc)
-{
- DWORD ret;
- int fd;
-
- fd = socket(PF_INET, SOCK_DGRAM, 0);
- if (fd != -1) {
- int ioctlRet = 0;
- DWORD guessedNumAddresses = 0, numAddresses = 0;
- caddr_t ifPtr;
- int lastlen;
-
- ret = NO_ERROR;
- ifc->ifc_len = 0;
- ifc->ifc_buf = NULL;
- /* there is no way to know the interface count beforehand,
- so we need to loop again and again upping our max each time
- until returned is constant across 2 calls */
- do {
- lastlen = ifc->ifc_len;
- HeapFree(GetProcessHeap(), 0, ifc->ifc_buf);
- if (guessedNumAddresses == 0)
- guessedNumAddresses = INITIAL_INTERFACES_ASSUMED;
- else
- guessedNumAddresses *= 2;
- ifc->ifc_len = sizeof(struct ifreq) * guessedNumAddresses;
- ifc->ifc_buf = HeapAlloc(GetProcessHeap(), 0, ifc->ifc_len);
- ioctlRet = ioctl(fd, SIOCGIFCONF, ifc);
- } while ((ioctlRet == 0) && (ifc->ifc_len != lastlen));
-
- if (ioctlRet == 0) {
- ifPtr = ifc->ifc_buf;
- while (ifPtr && (char *)ifPtr < ifc->ifc_buf + ifc->ifc_len) {
- struct ifreq *ifr = (struct ifreq *)ifPtr;
-
- if (ifr->ifr_addr.sa_family == AF_INET)
- numAddresses++;
-
- ifPtr = (char *)ifPtr + ifreq_len((struct ifreq *)ifPtr);
- }
- }
- else
- ret = ERROR_INVALID_PARAMETER; /* FIXME: map from errno to Win32 */
- if (!ret)
- *pcAddresses = numAddresses;
- else
- {
- HeapFree(GetProcessHeap(), 0, ifc->ifc_buf);
- ifc->ifc_buf = NULL;
- }
- close(fd);
- }
- else
- ret = ERROR_NO_SYSTEM_RESOURCES;
- return ret;
-}
-
-DWORD getNumIPAddresses(void)
-{
- DWORD numAddresses = 0;
- struct ifconf ifc;
-
- if (!enumIPAddresses(&numAddresses, &ifc))
- HeapFree(GetProcessHeap(), 0, ifc.ifc_buf);
- return numAddresses;
-}
-
-DWORD getIPAddrTable(PMIB_IPADDRTABLE *ppIpAddrTable, HANDLE heap, DWORD flags)
-{
- DWORD ret;
-
- if (!ppIpAddrTable)
- ret = ERROR_INVALID_PARAMETER;
- else
- {
- DWORD numAddresses = 0;
- struct ifconf ifc;
-
- ret = enumIPAddresses(&numAddresses, &ifc);
- if (!ret)
- {
- DWORD size = sizeof(MIB_IPADDRTABLE);
-
- if (numAddresses > 1)
- size += (numAddresses - 1) * sizeof(MIB_IPADDRROW);
- *ppIpAddrTable = HeapAlloc(heap, flags, size);
- if (*ppIpAddrTable) {
- DWORD i = 0;
- caddr_t ifPtr;
-
- ret = NO_ERROR;
- (*ppIpAddrTable)->dwNumEntries = numAddresses;
- ifPtr = ifc.ifc_buf;
- while (!ret && ifPtr && (char *)ifPtr < ifc.ifc_buf + ifc.ifc_len) {
- struct ifreq *ifr = (struct ifreq *)ifPtr;
-
- ifPtr = (char *)ifPtr + ifreq_len(ifr);
-
- if (ifr->ifr_addr.sa_family != AF_INET)
- continue;
-
- ret = getIPAddrRowByName(&(*ppIpAddrTable)->table[i], ifr->ifr_name,
- &ifr->ifr_addr);
- i++;
- }
- if (ret)
- HeapFree(GetProcessHeap(), 0, *ppIpAddrTable);
- }
- else
- ret = ERROR_OUTOFMEMORY;
- HeapFree(GetProcessHeap(), 0, ifc.ifc_buf);
- }
- }
- return ret;
-}
-
-ULONG v6addressesFromIndex(IF_INDEX index, SOCKET_ADDRESS **addrs, ULONG *num_addrs, SOCKET_ADDRESS **masks)
-{
- *addrs = NULL;
- *num_addrs = 0;
- *masks = NULL;
- return ERROR_SUCCESS;
-}
-
-#endif
diff --git a/dlls/iphlpapi/ifenum.h b/dlls/iphlpapi/ifenum.h
index d0143eaaf69..710b493ad36 100644
--- a/dlls/iphlpapi/ifenum.h
+++ b/dlls/iphlpapi/ifenum.h
@@ -44,8 +44,6 @@
#define MAX_INTERFACE_PHYSADDR 8
#define MAX_INTERFACE_DESCRIPTION 256
-BOOL isIfIndexLoopback(ULONG idx) DECLSPEC_HIDDEN;
-
/* A table of interface indexes, see get_interface_indices(). */
typedef struct _InterfaceIndexTable {
DWORD numIndexes;
@@ -59,50 +57,10 @@ DWORD get_interface_indices( BOOL skip_loopback, InterfaceIndexTable **table ) D
/* ByName/ByIndex versions of various getter functions. */
-/* can be used as quick check to see if you've got a valid index, returns NULL
- * if not. Overwrites your buffer, which should be at least of size
- * MAX_ADAPTER_NAME.
- */
-char *getInterfaceNameByIndex(IF_INDEX index, char *name) DECLSPEC_HIDDEN;
-
/* Fills index with the index of name, if found. Returns
* ERROR_INVALID_PARAMETER if name or index is NULL, ERROR_INVALID_DATA if name
* is not found, and NO_ERROR on success.
*/
DWORD getInterfaceIndexByName(const char *name, IF_INDEX *index) DECLSPEC_HIDDEN;
-/* Gets a few physical characteristics of a device: MAC addr len, MAC addr,
- * and type as one of the MIB_IF_TYPEs.
- * len's in-out: on in, needs to say how many bytes are available in addr,
- * which to be safe should be MAX_INTERFACE_PHYSADDR. On out, it's how many
- * bytes were set, or how many were required if addr isn't big enough.
- * Returns ERROR_INVALID_PARAMETER if name, len, addr, or type is NULL.
- * Returns ERROR_INVALID_DATA if name/index isn't valid.
- * Returns ERROR_INSUFFICIENT_BUFFER if addr isn't large enough for the
- * physical address; *len will contain the required size.
- * May return other errors, e.g. ERROR_OUTOFMEMORY or ERROR_NO_MORE_FILES,
- * if internal errors occur.
- * Returns NO_ERROR on success.
- */
-DWORD getInterfacePhysicalByIndex(IF_INDEX index, PDWORD len, PBYTE addr,
- PDWORD type) DECLSPEC_HIDDEN;
-
-DWORD getNumIPAddresses(void) DECLSPEC_HIDDEN;
-
-/* Gets the configured IP addresses for the system, and sets *ppIpAddrTable to
- * a table of them allocated from heap, or NULL if out of memory. Returns
- * NO_ERROR on success, something else on failure. Note there may be more than
- * one IP address may exist per interface.
- */
-DWORD getIPAddrTable(PMIB_IPADDRTABLE *ppIpAddrTable, HANDLE heap, DWORD flags) DECLSPEC_HIDDEN;
-
-/* Returns the IPv6 addresses for a particular interface index.
- * Returns NO_ERROR on success, something else on failure.
- */
-ULONG v6addressesFromIndex(IF_INDEX index, SOCKET_ADDRESS **addrs, ULONG *num_addrs,
- SOCKET_ADDRESS **masks) DECLSPEC_HIDDEN;
-
-DWORD getInterfaceMtuByName(const char *name, PDWORD mtu) DECLSPEC_HIDDEN;
-DWORD getInterfaceStatusByName(const char *name, INTERNAL_IF_OPER_STATUS *status) DECLSPEC_HIDDEN;
-
#endif /* ndef WINE_IFENUM_H_ */
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index 22e17e06757..2700ecd3172 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -109,6 +109,15 @@ DWORD WINAPI ConvertStringToGuidW( const WCHAR *str, GUID *guid )
return RtlNtStatusToDosError( RtlGUIDFromString( &ustr, guid ) );
}
+static void if_counted_string_copy( WCHAR *dst, unsigned int len, IF_COUNTED_STRING *src )
+{
+ unsigned int copy = src->Length;
+
+ if (copy >= len * sizeof(WCHAR)) copy = 0;
+ memcpy( dst, src->String, copy );
+ memset( (char *)dst + copy, 0, len * sizeof(WCHAR) - copy );
+}
+
/******************************************************************
* AddIPAddress (IPHLPAPI.@)
*
@@ -913,129 +922,6 @@ void adapters_addresses_copy( IP_ADAPTER_ADDRESSES *dst, IP_ADAPTER_ADDRESSES *s
}
}
-static DWORD typeFromMibType(DWORD mib_type)
-{
- switch (mib_type)
- {
- case MIB_IF_TYPE_ETHERNET: return IF_TYPE_ETHERNET_CSMACD;
- case MIB_IF_TYPE_TOKENRING: return IF_TYPE_ISO88025_TOKENRING;
- case MIB_IF_TYPE_PPP: return IF_TYPE_PPP;
- case MIB_IF_TYPE_LOOPBACK: return IF_TYPE_SOFTWARE_LOOPBACK;
- default: return IF_TYPE_OTHER;
- }
-}
-
-static NET_IF_CONNECTION_TYPE connectionTypeFromMibType(DWORD mib_type)
-{
- switch (mib_type)
- {
- case MIB_IF_TYPE_PPP: return NET_IF_CONNECTION_DEMAND;
- case MIB_IF_TYPE_SLIP: return NET_IF_CONNECTION_DEMAND;
- default: return NET_IF_CONNECTION_DEDICATED;
- }
-}
-
-static ULONG v4addressesFromIndex(IF_INDEX index, DWORD **addrs, ULONG *num_addrs, DWORD **masks)
-{
- ULONG ret, i, j;
- MIB_IPADDRTABLE *at;
-
- *num_addrs = 0;
- if ((ret = getIPAddrTable(&at, GetProcessHeap(), 0))) return ret;
- for (i = 0; i < at->dwNumEntries; i++)
- {
- if (at->table[i].dwIndex == index) (*num_addrs)++;
- }
- if (!(*addrs = HeapAlloc(GetProcessHeap(), 0, *num_addrs * sizeof(DWORD))))
- {
- HeapFree(GetProcessHeap(), 0, at);
- return ERROR_OUTOFMEMORY;
- }
- if (!(*masks = HeapAlloc(GetProcessHeap(), 0, *num_addrs * sizeof(DWORD))))
- {
- HeapFree(GetProcessHeap(), 0, *addrs);
- HeapFree(GetProcessHeap(), 0, at);
- return ERROR_OUTOFMEMORY;
- }
- for (i = 0, j = 0; i < at->dwNumEntries; i++)
- {
- if (at->table[i].dwIndex == index)
- {
- (*addrs)[j] = at->table[i].dwAddr;
- (*masks)[j] = at->table[i].dwMask;
- j++;
- }
- }
- HeapFree(GetProcessHeap(), 0, at);
- return ERROR_SUCCESS;
-}
-
-static char *debugstr_ipv4(const in_addr_t *in_addr, char *buf)
-{
- const BYTE *addrp;
- char *p = buf;
-
- for (addrp = (const BYTE *)in_addr;
- addrp - (const BYTE *)in_addr < sizeof(*in_addr);
- addrp++)
- {
- if (addrp == (const BYTE *)in_addr + sizeof(*in_addr) - 1)
- sprintf(p, "%d", *addrp);
- else
- p += sprintf(p, "%d.", *addrp);
- }
- return buf;
-}
-
-static ULONG count_v4_gateways(DWORD index, PMIB_IPFORWARDTABLE routeTable)
-{
- DWORD i, num_gateways = 0;
-
- for (i = 0; i < routeTable->dwNumEntries; i++)
- {
- if (routeTable->table[i].dwForwardIfIndex == index &&
- routeTable->table[i].u1.ForwardType == MIB_IPROUTE_TYPE_INDIRECT)
- num_gateways++;
- }
- return num_gateways;
-}
-
-static DWORD mask_v4_to_prefix(DWORD m)
-{
-#ifdef HAVE___BUILTIN_POPCOUNT
- return __builtin_popcount(m);
-#else
- m -= m >> 1 & 0x55555555;
- m = (m & 0x33333333) + (m >> 2 & 0x33333333);
- return ((m + (m >> 4)) & 0x0f0f0f0f) * 0x01010101 >> 24;
-#endif
-}
-
-static DWORD mask_v6_to_prefix(SOCKET_ADDRESS *m)
-{
- const IN6_ADDR *mask = &((struct WS_sockaddr_in6 *)m->lpSockaddr)->sin6_addr;
- DWORD ret = 0, i;
-
- for (i = 0; i < 8; i++)
- ret += mask_v4_to_prefix(mask->u.Word[i]);
- return ret;
-}
-
-static PMIB_IPFORWARDROW findIPv4Gateway(DWORD index,
- PMIB_IPFORWARDTABLE routeTable)
-{
- DWORD i;
- PMIB_IPFORWARDROW row = NULL;
-
- for (i = 0; !row && i < routeTable->dwNumEntries; i++)
- {
- if (routeTable->table[i].dwForwardIfIndex == index &&
- routeTable->table[i].u1.ForwardType == MIB_IPROUTE_TYPE_INDIRECT)
- row = &routeTable->table[i];
- }
- return row;
-}
-
static BOOL sockaddr_is_loopback( SOCKADDR *sock )
{
if (sock->sa_family == WS_AF_INET)
@@ -1067,308 +953,211 @@ static BOOL unicast_is_dns_eligible( IP_ADAPTER_UNICAST_ADDRESS *uni )
!sockaddr_is_linklocal( uni->Address.lpSockaddr );
}
-static void fill_unicast_addr_data(IP_ADAPTER_ADDRESSES *aa, IP_ADAPTER_UNICAST_ADDRESS *ua)
+static DWORD unicast_addresses_alloc( IP_ADAPTER_ADDRESSES *aa, ULONG family, ULONG flags )
{
- /* Actually this information should be read somewhere from the system
- * but it doesn't matter much for the bugs found so far.
- * This information is required for DirectPlay8 games. */
- if (aa->IfType != IF_TYPE_SOFTWARE_LOOPBACK)
- {
- ua->PrefixOrigin = IpPrefixOriginDhcp;
- ua->SuffixOrigin = IpSuffixOriginDhcp;
- }
- else
- {
- ua->PrefixOrigin = IpPrefixOriginManual;
- ua->SuffixOrigin = IpSuffixOriginManual;
- }
-
- /* The address is not duplicated in the network */
- ua->DadState = IpDadStatePreferred;
-
- /* Some address life time values, required even for non-dhcp addresses */
- ua->ValidLifetime = 60000;
- ua->PreferredLifetime = 60000;
- ua->LeaseLifetime = 60000;
-
- if (unicast_is_dns_eligible( ua )) ua->u.s.Flags |= IP_ADAPTER_ADDRESS_DNS_ELIGIBLE;
-}
-
-static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index,
- IP_ADAPTER_ADDRESSES *aa, char **ptr)
-{
- ULONG ret = ERROR_SUCCESS, i, j, num_v4addrs = 0, num_v4_gateways = 0, num_v6addrs = 0;
- DWORD *v4addrs = NULL, *v4masks = NULL;
- SOCKET_ADDRESS *v6addrs = NULL, *v6masks = NULL;
- PMIB_IPFORWARDTABLE routeTable = NULL;
- BOOL output_gateways;
- char name[IF_NAMESIZE], *src;
- WCHAR *dst;
- DWORD buflen, type;
- INTERNAL_IF_OPER_STATUS status;
- NET_LUID luid;
- GUID guid;
+ struct nsi_ipv4_unicast_key *key4;
+ struct nsi_ipv6_unicast_key *key6;
+ struct nsi_ip_unicast_rw *rw;
+ struct nsi_ip_unicast_dynamic *dyn;
+ struct nsi_ip_unicast_static *stat;
+ IP_ADAPTER_UNICAST_ADDRESS *addr, **next;
+ DWORD err, count, i, key_size = (family == WS_AF_INET) ? sizeof(*key4) : sizeof(*key6);
+ DWORD sockaddr_size = (family == WS_AF_INET) ? sizeof(SOCKADDR_IN) : sizeof(SOCKADDR_IN6);
+ NET_LUID *luid;
+ void *key;
- if ((flags & GAA_FLAG_INCLUDE_ALL_GATEWAYS) || !(flags & GAA_FLAG_SKIP_UNICAST))
- {
- ret = AllocateAndGetIpForwardTableFromStack(&routeTable, FALSE, GetProcessHeap(), 0);
- if (ret) return ret;
- num_v4_gateways = count_v4_gateways(index, routeTable);
- }
- output_gateways = (flags & GAA_FLAG_INCLUDE_ALL_GATEWAYS) && (family == WS_AF_INET || family == WS_AF_UNSPEC);
+ err = NsiAllocateAndGetTable( 1, ip_module_id( family ), NSI_IP_UNICAST_TABLE, &key, key_size,
+ (void **)&rw, sizeof(*rw), (void **)&dyn, sizeof(*dyn),
+ (void **)&stat, sizeof(*stat), &count, 0 );
+ if (err) return err;
- if (family == WS_AF_INET)
- {
- ret = v4addressesFromIndex(index, &v4addrs, &num_v4addrs, &v4masks);
- }
- else if (family == WS_AF_INET6)
- {
- ret = v6addressesFromIndex(index, &v6addrs, &num_v6addrs, &v6masks);
- }
- else if (family == WS_AF_UNSPEC)
- {
- ret = v4addressesFromIndex(index, &v4addrs, &num_v4addrs, &v4masks);
- if (!ret) ret = v6addressesFromIndex(index, &v6addrs, &num_v6addrs, &v6masks);
- }
- else
- {
- FIXME("address family %u unsupported\n", family);
- ret = ERROR_NO_DATA;
- }
- if (ret)
- {
- HeapFree(GetProcessHeap(), 0, v4addrs);
- HeapFree(GetProcessHeap(), 0, v4masks);
- HeapFree(GetProcessHeap(), 0, v6addrs);
- HeapFree(GetProcessHeap(), 0, v6masks);
- HeapFree(GetProcessHeap(), 0, routeTable);
- return ret;
- }
- if (1)
+ while (aa)
{
- memset(aa, 0, sizeof(IP_ADAPTER_ADDRESSES));
- aa->u.s.Length = sizeof(IP_ADAPTER_ADDRESSES);
- aa->u.s.IfIndex = index;
-
- ConvertInterfaceIndexToLuid(index, &luid);
- ConvertInterfaceLuidToGuid(&luid, &guid);
- ConvertGuidToStringA( &guid, *ptr, CHARS_IN_GUID );
- aa->AdapterName = *ptr;
- *ptr += (CHARS_IN_GUID + 1) & ~1;
+ for (next = &aa->FirstUnicastAddress; *next; next = &(*next)->Next)
+ ;
- getInterfaceNameByIndex(index, name);
- if (!(flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
- {
- aa->FriendlyName = (WCHAR *)*ptr;
- for (src = name, dst = (WCHAR *)*ptr; *src; src++, dst++)
- *dst = *src;
- *dst++ = 0;
- *ptr = (char *)dst;
- }
- aa->Description = (WCHAR *)ptr;
- for (src = name, dst = (WCHAR *)*ptr; *src; src++, dst++)
- *dst = *src;
- *dst++ = 0;
- *ptr = (char *)dst;
-
- TRACE("%s: %d IPv4 addresses, %d IPv6 addresses:\n", name, num_v4addrs,
- num_v6addrs);
-
- buflen = MAX_INTERFACE_PHYSADDR;
- getInterfacePhysicalByIndex(index, &buflen, aa->PhysicalAddress, &type);
- aa->PhysicalAddressLength = buflen;
- aa->IfType = typeFromMibType(type);
- aa->ConnectionType = connectionTypeFromMibType(type);
- ConvertInterfaceIndexToLuid( index, &aa->Luid );
-
- if (output_gateways && num_v4_gateways)
- {
- PMIB_IPFORWARDROW adapterRow;
-
- if ((adapterRow = findIPv4Gateway(index, routeTable)))
- {
- PIP_ADAPTER_GATEWAY_ADDRESS gw;
- PSOCKADDR_IN sin;
-
- gw = heap_alloc( sizeof(IP_ADAPTER_GATEWAY_ADDRESS) + sizeof(SOCKADDR_IN) );
- aa->FirstGatewayAddress = gw;
-
- gw->u.s.Length = sizeof(IP_ADAPTER_GATEWAY_ADDRESS);
- sin = (PSOCKADDR_IN)(gw + 1);
- sin->sin_family = WS_AF_INET;
- sin->sin_port = 0;
- memcpy(&sin->sin_addr, &adapterRow->dwForwardNextHop,
- sizeof(DWORD));
- gw->Address.lpSockaddr = (LPSOCKADDR)sin;
- gw->Address.iSockaddrLength = sizeof(SOCKADDR_IN);
- gw->Next = NULL;
- }
- }
- if (num_v4addrs && !(flags & GAA_FLAG_SKIP_UNICAST))
+ for (i = 0; i < count; i++)
{
- IP_ADAPTER_UNICAST_ADDRESS *ua;
- struct WS_sockaddr_in *sa;
- aa->u1.s1.Ipv4Enabled = TRUE;
- ua = aa->FirstUnicastAddress = heap_alloc_zero( sizeof(IP_ADAPTER_UNICAST_ADDRESS) + sizeof(SOCKADDR_IN) );
- for (i = 0; i < num_v4addrs; i++)
+ key4 = (struct nsi_ipv4_unicast_key *)key + i;
+ key6 = (struct nsi_ipv6_unicast_key *)key + i;
+ luid = (family == WS_AF_INET) ? &key4->luid : &key6->luid;
+ if (luid->Value != aa->Luid.Value) continue;
+ addr = heap_alloc_zero( sizeof(*addr) + sockaddr_size );
+ if (!addr)
{
- char addr_buf[16];
-
- memset(ua, 0, sizeof(IP_ADAPTER_UNICAST_ADDRESS));
- ua->u.s.Length = sizeof(IP_ADAPTER_UNICAST_ADDRESS);
- ua->Address.iSockaddrLength = sizeof(struct sockaddr_in);
- ua->Address.lpSockaddr = (SOCKADDR *)(ua + 1);
-
- sa = (struct WS_sockaddr_in *)ua->Address.lpSockaddr;
- sa->sin_family = WS_AF_INET;
- sa->sin_addr.S_un.S_addr = v4addrs[i];
- sa->sin_port = 0;
- TRACE("IPv4 %d/%d: %s\n", i + 1, num_v4addrs,
- debugstr_ipv4(&sa->sin_addr.S_un.S_addr, addr_buf));
- fill_unicast_addr_data(aa, ua);
-
- ua->OnLinkPrefixLength = mask_v4_to_prefix(v4masks[i]);
-
- if (i < num_v4addrs - 1)
- {
- ua->Next = heap_alloc_zero( sizeof(IP_ADAPTER_UNICAST_ADDRESS) + sizeof(SOCKADDR_IN) );
- ua = ua->Next;
- }
+ err = ERROR_NOT_ENOUGH_MEMORY;
+ goto err;
}
- }
- if (num_v6addrs && !(flags & GAA_FLAG_SKIP_UNICAST))
- {
- IP_ADAPTER_UNICAST_ADDRESS *ua;
- struct WS_sockaddr_in6 *sa;
-
- aa->u1.s1.Ipv6Enabled = TRUE;
- if (aa->FirstUnicastAddress)
+ addr->u.s.Length = sizeof(*addr);
+ addr->Address.lpSockaddr = (SOCKADDR *)(addr + 1);
+ addr->Address.iSockaddrLength = sockaddr_size;
+ addr->Address.lpSockaddr->sa_family = family;
+ if (family == WS_AF_INET)
{
- for (ua = aa->FirstUnicastAddress; ua->Next; ua = ua->Next)
- ;
- ua->Next = heap_alloc_zero( sizeof(IP_ADAPTER_UNICAST_ADDRESS) + sizeof(SOCKADDR_IN6) );
- ua = ua->Next;
+ SOCKADDR_IN *in = (SOCKADDR_IN *)addr->Address.lpSockaddr;
+ in->sin_addr = key4->addr;
}
else
- ua = aa->FirstUnicastAddress = heap_alloc_zero( sizeof(IP_ADAPTER_UNICAST_ADDRESS) + sizeof(SOCKADDR_IN6) );
- for (i = 0; i < num_v6addrs; i++)
{
- char addr_buf[46];
-
- memset(ua, 0, sizeof(IP_ADAPTER_UNICAST_ADDRESS));
- ua->u.s.Length = sizeof(IP_ADAPTER_UNICAST_ADDRESS);
- ua->Address.iSockaddrLength = v6addrs[i].iSockaddrLength;
- ua->Address.lpSockaddr = (SOCKADDR *)(ua + 1);
-
- sa = (struct WS_sockaddr_in6 *)ua->Address.lpSockaddr;
- memcpy(sa, v6addrs[i].lpSockaddr, sizeof(*sa));
- TRACE("IPv6 %d/%d: %s\n", i + 1, num_v6addrs,
- debugstr_ipv6(sa, addr_buf));
- fill_unicast_addr_data(aa, ua);
-
- ua->OnLinkPrefixLength = mask_v6_to_prefix(&v6masks[i]);
-
- if (i < num_v6addrs - 1)
- {
- ua->Next = heap_alloc_zero( sizeof(IP_ADAPTER_UNICAST_ADDRESS) + sizeof(SOCKADDR_IN6) );
- ua = ua->Next;
- }
+ SOCKADDR_IN6 *in6 = (SOCKADDR_IN6 *)addr->Address.lpSockaddr;
+ in6->sin6_addr = key6->addr;
+ in6->sin6_scope_id = dyn[i].scope_id;
}
+ addr->PrefixOrigin = rw[i].prefix_origin;
+ addr->SuffixOrigin = rw[i].suffix_origin;
+ addr->DadState = dyn[i].dad_state;
+ addr->ValidLifetime = rw[i].valid_lifetime;
+ addr->PreferredLifetime = rw[i].preferred_lifetime;
+ addr->LeaseLifetime = rw[i].valid_lifetime; /* FIXME */
+ addr->OnLinkPrefixLength = rw[i].on_link_prefix;
+ if (unicast_is_dns_eligible( addr )) addr->u.s.Flags |= IP_ADAPTER_ADDRESS_DNS_ELIGIBLE;
+
+ *next = addr;
+ next = &addr->Next;
}
- if (num_v4addrs && (flags & GAA_FLAG_INCLUDE_PREFIX))
- {
- IP_ADAPTER_PREFIX *prefix;
+ aa = aa->Next;
+ }
- prefix = aa->FirstPrefix = heap_alloc_zero( sizeof(*prefix) + sizeof(SOCKADDR_IN) );
- for (i = 0; i < num_v4addrs; i++)
- {
- char addr_buf[16];
- struct WS_sockaddr_in *sa;
+err:
+ NsiFreeTable( key, rw, dyn, stat );
+ return err;
+}
- prefix->u.s.Length = sizeof(*prefix);
- prefix->u.s.Flags = 0;
- prefix->Next = NULL;
- prefix->Address.iSockaddrLength = sizeof(struct sockaddr_in);
- prefix->Address.lpSockaddr = (SOCKADDR *)(prefix + 1);
+static DWORD gateway_and_prefix_addresses_alloc( IP_ADAPTER_ADDRESSES *aa, ULONG family, ULONG flags )
+{
+ struct nsi_ipv4_forward_key *key4;
+ struct nsi_ipv6_forward_key *key6;
+ IP_ADAPTER_GATEWAY_ADDRESS *gw, **gw_next;
+ IP_ADAPTER_PREFIX *prefix, **prefix_next;
+ DWORD err, count, i, prefix_len, key_size = (family == WS_AF_INET) ? sizeof(*key4) : sizeof(*key6);
+ DWORD sockaddr_size = (family == WS_AF_INET) ? sizeof(SOCKADDR_IN) : sizeof(SOCKADDR_IN6);
+ SOCKADDR_INET sockaddr;
+ NET_LUID *luid;
+ void *key;
- sa = (struct WS_sockaddr_in *)prefix->Address.lpSockaddr;
- sa->sin_family = WS_AF_INET;
- sa->sin_addr.S_un.S_addr = v4addrs[i] & v4masks[i];
- sa->sin_port = 0;
+ err = NsiAllocateAndGetTable( 1, ip_module_id( family ), NSI_IP_FORWARD_TABLE, &key, key_size,
+ NULL, 0, NULL, 0, NULL, 0, &count, 0 );
+ if (err) return err;
- prefix->PrefixLength = mask_v4_to_prefix(v4masks[i]);
+ while (aa)
+ {
+ for (gw_next = &aa->FirstGatewayAddress; *gw_next; gw_next = &(*gw_next)->Next)
+ ;
+ for (prefix_next = &aa->FirstPrefix; *prefix_next; prefix_next = &(*prefix_next)->Next)
+ ;
- TRACE("IPv4 network: %s/%u\n",
- debugstr_ipv4((const in_addr_t *)&sa->sin_addr.S_un.S_addr, addr_buf),
- prefix->PrefixLength);
+ for (i = 0; i < count; i++)
+ {
+ key4 = (struct nsi_ipv4_forward_key *)key + i;
+ key6 = (struct nsi_ipv6_forward_key *)key + i;
+ luid = (family == WS_AF_INET) ? &key4->luid : &key6->luid;
+ if (luid->Value != aa->Luid.Value) continue;
- if (i < num_v4addrs - 1)
+ if (flags & GAA_FLAG_INCLUDE_ALL_GATEWAYS)
+ {
+ memset( &sockaddr, 0, sizeof(sockaddr) );
+ if (family == WS_AF_INET)
{
- prefix->Next = heap_alloc_zero( sizeof(*prefix) + sizeof(SOCKADDR_IN) );
- prefix = prefix->Next;
+ if (key4->next_hop.WS_s_addr != 0)
+ {
+ sockaddr.si_family = family;
+ sockaddr.Ipv4.sin_addr = key4->next_hop;
+ }
+ }
+ else
+ {
+ static const IN6_ADDR zero;
+ if (memcmp( &key6->next_hop, &zero, sizeof(zero) ))
+ {
+ sockaddr.si_family = family;
+ sockaddr.Ipv6.sin6_addr = key6->next_hop;
+ }
}
- }
- }
- if (num_v6addrs && (flags & GAA_FLAG_INCLUDE_PREFIX))
- {
- IP_ADAPTER_PREFIX *prefix;
- if (aa->FirstPrefix)
- {
- for (prefix = aa->FirstPrefix; prefix->Next; prefix = prefix->Next)
- ;
- prefix->Next = heap_alloc_zero( sizeof(*prefix) + sizeof(SOCKADDR_IN6) );
- prefix = prefix->Next;
+ if (sockaddr.si_family)
+ {
+ gw = heap_alloc_zero( sizeof(*gw) + sockaddr_size );
+ if (!gw)
+ {
+ err = ERROR_NOT_ENOUGH_MEMORY;
+ goto err;
+ }
+ gw->u.s.Length = sizeof(*gw);
+ gw->Address.lpSockaddr = (SOCKADDR *)(gw + 1);
+ gw->Address.iSockaddrLength = sockaddr_size;
+ memcpy( gw->Address.lpSockaddr, &sockaddr, sockaddr_size );
+ *gw_next = gw;
+ gw_next = &gw->Next;
+ }
}
- else
- prefix = aa->FirstPrefix = heap_alloc_zero( sizeof(*prefix) + sizeof(SOCKADDR_IN6) );
- for (i = 0; i < num_v6addrs; i++)
+
+ if (flags & GAA_FLAG_INCLUDE_PREFIX)
{
- char addr_buf[46];
- struct WS_sockaddr_in6 *sa;
- const IN6_ADDR *addr, *mask;
-
- prefix->u.s.Length = sizeof(*prefix);
- prefix->u.s.Flags = 0;
- prefix->Next = NULL;
- prefix->Address.iSockaddrLength = sizeof(struct sockaddr_in6);
- prefix->Address.lpSockaddr = (SOCKADDR *)(prefix + 1);
-
- sa = (struct WS_sockaddr_in6 *)prefix->Address.lpSockaddr;
- sa->sin6_family = WS_AF_INET6;
- sa->sin6_port = 0;
- sa->sin6_flowinfo = 0;
- addr = &((struct WS_sockaddr_in6 *)v6addrs[i].lpSockaddr)->sin6_addr;
- mask = &((struct WS_sockaddr_in6 *)v6masks[i].lpSockaddr)->sin6_addr;
- for (j = 0; j < 8; j++) sa->sin6_addr.u.Word[j] = addr->u.Word[j] & mask->u.Word[j];
- sa->sin6_scope_id = 0;
-
- prefix->PrefixLength = mask_v6_to_prefix(&v6masks[i]);
-
- TRACE("IPv6 network: %s/%u\n", debugstr_ipv6(sa, addr_buf), prefix->PrefixLength);
-
- if (i < num_v6addrs - 1)
+ memset( &sockaddr, 0, sizeof(sockaddr) );
+ if (family == WS_AF_INET)
+ {
+ if (!key4->next_hop.WS_s_addr)
+ {
+ sockaddr.si_family = family;
+ sockaddr.Ipv4.sin_addr = key4->prefix;
+ prefix_len = key4->prefix_len;
+ }
+ }
+ else
{
- prefix->Next = heap_alloc_zero( sizeof(*prefix) + sizeof(SOCKADDR_IN6) );
- prefix = prefix->Next;
+ static const IN6_ADDR zero;
+ if (!memcmp( &key6->next_hop, &zero, sizeof(zero) ))
+ {
+ sockaddr.si_family = family;
+ sockaddr.Ipv6.sin6_addr = key6->prefix;
+ prefix_len = key6->prefix_len;
+ }
+ }
+
+ if (sockaddr.si_family)
+ {
+ prefix = heap_alloc_zero( sizeof(*prefix) + sockaddr_size );
+ if (!prefix)
+ {
+ err = ERROR_NOT_ENOUGH_MEMORY;
+ goto err;
+ }
+ prefix->u.s.Length = sizeof(*prefix);
+ prefix->Address.lpSockaddr = (SOCKADDR *)(prefix + 1);
+ prefix->Address.iSockaddrLength = sockaddr_size;
+ memcpy( prefix->Address.lpSockaddr, &sockaddr, sockaddr_size );
+ prefix->PrefixLength = prefix_len;
+ *prefix_next = prefix;
+ prefix_next = &prefix->Next;
}
}
}
+ aa = aa->Next;
+ }
- getInterfaceMtuByName(name, &aa->Mtu);
+err:
+ NsiFreeTable( key, NULL, NULL, NULL );
+ return err;
+}
- getInterfaceStatusByName(name, &status);
- if (status == MIB_IF_OPER_STATUS_OPERATIONAL) aa->OperStatus = IfOperStatusUp;
- else if (status == MIB_IF_OPER_STATUS_NON_OPERATIONAL) aa->OperStatus = IfOperStatusDown;
- else aa->OperStatus = IfOperStatusUnknown;
+static DWORD call_families( DWORD (*fn)( IP_ADAPTER_ADDRESSES *aa, ULONG family, ULONG flags ),
+ IP_ADAPTER_ADDRESSES *aa, ULONG family, ULONG flags )
+{
+ DWORD err;
+
+ if (family != WS_AF_INET)
+ {
+ err = fn( aa, WS_AF_INET6, flags );
+ if (err) return err;
}
- HeapFree(GetProcessHeap(), 0, routeTable);
- HeapFree(GetProcessHeap(), 0, v6addrs);
- HeapFree(GetProcessHeap(), 0, v6masks);
- HeapFree(GetProcessHeap(), 0, v4addrs);
- HeapFree(GetProcessHeap(), 0, v4masks);
- return ERROR_SUCCESS;
+
+ if (family != WS_AF_INET6)
+ {
+ err = fn( aa, WS_AF_INET, flags );
+ if (err) return err;
+ }
+ return err;
}
static DWORD dns_servers_query_code( ULONG family )
@@ -1461,20 +1250,21 @@ err:
static DWORD adapters_addresses_alloc( ULONG family, ULONG flags, IP_ADAPTER_ADDRESSES **info )
{
IP_ADAPTER_ADDRESSES *aa;
+ NET_LUID *luids;
+ struct nsi_ndis_ifinfo_rw *rw;
+ struct nsi_ndis_ifinfo_dynamic *dyn;
+ struct nsi_ndis_ifinfo_static *stat;
DWORD err, i, count, needed;
+ GUID guid;
char *str_ptr;
- InterfaceIndexTable *table;
- get_interface_indices( FALSE, &table );
- if (!table || !table->numIndexes)
- {
- HeapFree(GetProcessHeap(), 0, table);
- return ERROR_NO_DATA;
- }
- count = table->numIndexes;
+ err = NsiAllocateAndGetTable( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, (void **)&luids, sizeof(*luids),
+ (void **)&rw, sizeof(*rw), (void **)&dyn, sizeof(*dyn),
+ (void **)&stat, sizeof(*stat), &count, 0 );
+ if (err) return err;
- needed = count * (sizeof(*aa) + ((CHARS_IN_GUID + 1) & ~1) + sizeof(IF_COUNTED_STRING));
- if (!(flags & GAA_FLAG_SKIP_FRIENDLY_NAME)) needed += count * sizeof(IF_COUNTED_STRING);
+ needed = count * (sizeof(*aa) + ((CHARS_IN_GUID + 1) & ~1) + sizeof(stat->descr.String));
+ if (!(flags & GAA_FLAG_SKIP_FRIENDLY_NAME)) needed += count * sizeof(rw->alias.String);
aa = heap_alloc_zero( needed );
if (!aa)
@@ -1486,18 +1276,52 @@ static DWORD adapters_addresses_alloc( ULONG family, ULONG flags, IP_ADAPTER_ADD
str_ptr = (char *)(aa + count);
for (i = 0; i < count; i++)
{
- if ((err = adapterAddressesFromIndex(family, flags, table->indexes[i], aa + i, &str_ptr)))
+ aa[i].u.s.Length = sizeof(*aa);
+ aa[i].u.s.IfIndex = stat[i].if_index;
+ if (i < count - 1) aa[i].Next = aa + i + 1;
+ ConvertInterfaceLuidToGuid( luids + i, &guid );
+ ConvertGuidToStringA( &guid, str_ptr, CHARS_IN_GUID );
+ aa[i].AdapterName = str_ptr;
+ str_ptr += (CHARS_IN_GUID + 1) & ~1;
+ if_counted_string_copy( (WCHAR *)str_ptr, ARRAY_SIZE(stat[i].descr.String), &stat[i].descr );
+ aa[i].Description = (WCHAR *)str_ptr;
+ str_ptr += sizeof(stat[i].descr.String);
+ if (!(flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
{
- HeapFree(GetProcessHeap(), 0, table);
- return err;
+ if_counted_string_copy( (WCHAR *)str_ptr, ARRAY_SIZE(rw[i].alias.String), &rw[i].alias );
+ aa[i].FriendlyName = (WCHAR *)str_ptr;
+ str_ptr += sizeof(rw[i].alias.String);
}
- if (i < count - 1) aa[i].Next = aa + i + 1;
+ aa[i].PhysicalAddressLength = rw->phys_addr.Length;
+ if (aa[i].PhysicalAddressLength > sizeof(aa[i].PhysicalAddress)) aa[i].PhysicalAddressLength = 0;
+ memcpy( aa[i].PhysicalAddress, rw->phys_addr.Address, aa[i].PhysicalAddressLength );
+ aa[i].Mtu = dyn[i].mtu;
+ aa[i].IfType = stat[i].type;
+ aa[i].OperStatus = dyn[i].oper_status;
+ aa[i].TransmitLinkSpeed = dyn[i].xmit_speed;
+ aa[i].ReceiveLinkSpeed = dyn[i].rcv_speed;
+ aa[i].Luid = luids[i];
+ aa[i].NetworkGuid = rw[i].network_guid;
+ aa[i].ConnectionType = stat[i].conn_type;
+ }
+
+ if (!(flags & GAA_FLAG_SKIP_UNICAST))
+ {
+ err = call_families( unicast_addresses_alloc, aa, family, flags );
+ if (err) goto err;
+ }
+
+ if (flags & (GAA_FLAG_INCLUDE_ALL_GATEWAYS | GAA_FLAG_INCLUDE_PREFIX))
+ {
+ err = call_families( gateway_and_prefix_addresses_alloc, aa, family, flags );
+ if (err) goto err;
}
err = dns_info_alloc( aa, family, flags );
+ if (err) goto err;
err:
- HeapFree(GetProcessHeap(), 0, table);
+ NsiFreeTable( luids, rw, dyn, stat );
if (!err) *info = aa;
else adapters_addresses_free( aa );
return err;
@@ -1861,15 +1685,6 @@ err:
return err;
}
-static void if_counted_string_copy( WCHAR *dst, unsigned int len, IF_COUNTED_STRING *src )
-{
- unsigned int copy = src->Length;
-
- if (copy >= len * sizeof(WCHAR)) copy = 0;
- memcpy( dst, src->String, copy );
- memset( (char *)dst + copy, 0, len * sizeof(WCHAR) - copy );
-}
-
static void if_row2_fill( MIB_IF_ROW2 *row, struct nsi_ndis_ifinfo_rw *rw, struct nsi_ndis_ifinfo_dynamic *dyn,
struct nsi_ndis_ifinfo_static *stat )
{
--
2.23.0
1
0
[PATCH 3/4] iphlpapi: Mark non-loopback, non-linklocal addresses as dns eligible.
by Huw Davies 09 Aug '21
by Huw Davies 09 Aug '21
09 Aug '21
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/iphlpapi/iphlpapi_main.c | 35 +++++++++++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index dbe4a12afe8..22e17e06757 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -1036,6 +1036,37 @@ static PMIB_IPFORWARDROW findIPv4Gateway(DWORD index,
return row;
}
+static BOOL sockaddr_is_loopback( SOCKADDR *sock )
+{
+ if (sock->sa_family == WS_AF_INET)
+ {
+ SOCKADDR_IN *sin = (SOCKADDR_IN *)sock;
+ return (sin->sin_addr.WS_s_addr & 0xff) == 127;
+ }
+ else if (sock->sa_family == WS_AF_INET6)
+ {
+ SOCKADDR_IN6 *sin6 = (SOCKADDR_IN6 *)sock;
+ return WS_IN6_IS_ADDR_LOOPBACK( &sin6->sin6_addr );
+ }
+ return FALSE;
+}
+
+static BOOL sockaddr_is_linklocal( SOCKADDR *sock )
+{
+ if (sock->sa_family == WS_AF_INET6)
+ {
+ SOCKADDR_IN6 *sin6 = (SOCKADDR_IN6 *)sock;
+ return WS_IN6_IS_ADDR_LINKLOCAL( &sin6->sin6_addr );
+ }
+ return FALSE;
+}
+
+static BOOL unicast_is_dns_eligible( IP_ADAPTER_UNICAST_ADDRESS *uni )
+{
+ return !sockaddr_is_loopback( uni->Address.lpSockaddr ) &&
+ !sockaddr_is_linklocal( uni->Address.lpSockaddr );
+}
+
static void fill_unicast_addr_data(IP_ADAPTER_ADDRESSES *aa, IP_ADAPTER_UNICAST_ADDRESS *ua)
{
/* Actually this information should be read somewhere from the system
@@ -1059,6 +1090,8 @@ static void fill_unicast_addr_data(IP_ADAPTER_ADDRESSES *aa, IP_ADAPTER_UNICAST_
ua->ValidLifetime = 60000;
ua->PreferredLifetime = 60000;
ua->LeaseLifetime = 60000;
+
+ if (unicast_is_dns_eligible( ua )) ua->u.s.Flags |= IP_ADAPTER_ADDRESS_DNS_ELIGIBLE;
}
static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index,
@@ -1186,8 +1219,6 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
ua->u.s.Length = sizeof(IP_ADAPTER_UNICAST_ADDRESS);
ua->Address.iSockaddrLength = sizeof(struct sockaddr_in);
ua->Address.lpSockaddr = (SOCKADDR *)(ua + 1);
- if (num_v4_gateways)
- ua->u.s.Flags |= IP_ADAPTER_ADDRESS_DNS_ELIGIBLE;
sa = (struct WS_sockaddr_in *)ua->Address.lpSockaddr;
sa->sin_family = WS_AF_INET;
--
2.23.0
1
0
[PATCH 2/4] iphlpapi: Rewrite GetAdaptersAddresses() to first alloc and then copy the info.
by Huw Davies 09 Aug '21
by Huw Davies 09 Aug '21
09 Aug '21
This refractoring is necessary to simplify implementing it on top of nsi.
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/iphlpapi/iphlpapi_main.c | 502 ++++++++++++++++++++--------------
1 file changed, 300 insertions(+), 202 deletions(-)
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index 6a934f926d1..dbe4a12afe8 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -760,6 +760,159 @@ err:
return err;
}
+static void address_entry_free( void *ptr, ULONG offset, void *ctxt )
+{
+ heap_free( ptr );
+}
+
+static void address_entry_size( void *ptr, ULONG offset, void *ctxt )
+{
+ IP_ADAPTER_DNS_SERVER_ADDRESS *src_addr = ptr; /* all list types are super-sets of this type */
+ ULONG *total = (ULONG *)ctxt, align = sizeof(ULONGLONG) - 1;
+
+ *total = (*total + src_addr->u.s.Length + src_addr->Address.iSockaddrLength + align) & ~align;
+}
+
+struct address_entry_copy_params
+{
+ IP_ADAPTER_ADDRESSES *src, *dst;
+ char *ptr;
+ void *next;
+ ULONG cur_offset;
+};
+
+static void address_entry_copy( void *ptr, ULONG offset, void *ctxt )
+{
+ struct address_entry_copy_params *params = ctxt;
+ IP_ADAPTER_DNS_SERVER_ADDRESS *src_addr = ptr; /* all list types are super-sets of this type */
+ IP_ADAPTER_DNS_SERVER_ADDRESS *dst_addr = (IP_ADAPTER_DNS_SERVER_ADDRESS *)params->ptr;
+ ULONG align = sizeof(ULONGLONG) - 1;
+
+ memcpy( dst_addr, src_addr, src_addr->u.s.Length );
+ params->ptr += src_addr->u.s.Length;
+ dst_addr->Address.lpSockaddr = (SOCKADDR *)params->ptr;
+ memcpy( dst_addr->Address.lpSockaddr, src_addr->Address.lpSockaddr, src_addr->Address.iSockaddrLength );
+ params->ptr += (src_addr->Address.iSockaddrLength + align) & ~align;
+
+ if (params->cur_offset != offset) /* new list */
+ {
+ params->next = (BYTE *)params->dst + offset;
+ params->cur_offset = offset;
+ }
+ *(IP_ADAPTER_DNS_SERVER_ADDRESS **)params->next = dst_addr;
+ params->next = &dst_addr->Next;
+}
+
+static void address_lists_iterate( IP_ADAPTER_ADDRESSES *aa, void (*fn)(void *entry, ULONG offset, void *ctxt), void *ctxt )
+{
+ IP_ADAPTER_UNICAST_ADDRESS *uni;
+ IP_ADAPTER_DNS_SERVER_ADDRESS *dns;
+ IP_ADAPTER_GATEWAY_ADDRESS *gw;
+ IP_ADAPTER_PREFIX *prefix;
+ void *next;
+
+ for (uni = aa->FirstUnicastAddress; uni; uni = next)
+ {
+ next = uni->Next;
+ fn( uni, FIELD_OFFSET( IP_ADAPTER_ADDRESSES, FirstUnicastAddress ), ctxt );
+ }
+
+ for (dns = aa->FirstDnsServerAddress; dns; dns = next)
+ {
+ next = dns->Next;
+ fn( dns, FIELD_OFFSET( IP_ADAPTER_ADDRESSES, FirstDnsServerAddress ), ctxt );
+ }
+
+ for (gw = aa->FirstGatewayAddress; gw; gw = next)
+ {
+ next = gw->Next;
+ fn( gw, FIELD_OFFSET( IP_ADAPTER_ADDRESSES, FirstGatewayAddress ), ctxt );
+ }
+
+ for (prefix = aa->FirstPrefix; prefix; prefix = next)
+ {
+ next = prefix->Next;
+ fn( prefix, FIELD_OFFSET( IP_ADAPTER_ADDRESSES, FirstPrefix ), ctxt );
+ }
+}
+
+void adapters_addresses_free( IP_ADAPTER_ADDRESSES *info )
+{
+ IP_ADAPTER_ADDRESSES *aa;
+
+ for (aa = info; aa; aa = aa->Next)
+ {
+ address_lists_iterate( aa, address_entry_free, NULL );
+
+ heap_free( aa->DnsSuffix );
+ }
+ heap_free( info );
+}
+
+ULONG adapters_addresses_size( IP_ADAPTER_ADDRESSES *info )
+{
+ IP_ADAPTER_ADDRESSES *aa;
+ ULONG size = 0, align = sizeof(ULONGLONG) - 1;
+
+ for (aa = info; aa; aa = aa->Next)
+ {
+ size += sizeof(*aa) + ((strlen( aa->AdapterName ) + 1 + 1) & ~1);
+ size += (strlenW( aa->Description ) + 1 + strlenW( aa->DnsSuffix ) + 1) * sizeof(WCHAR);
+ if (aa->FriendlyName) size += (strlenW(aa->FriendlyName) + 1) * sizeof(WCHAR);
+ size = (size + align) & ~align;
+ address_lists_iterate( aa, address_entry_size, &size );
+ }
+ return size;
+}
+
+void adapters_addresses_copy( IP_ADAPTER_ADDRESSES *dst, IP_ADAPTER_ADDRESSES *src )
+{
+ char *ptr;
+ DWORD len, align = sizeof(ULONGLONG) - 1;
+ struct address_entry_copy_params params;
+
+ while (src)
+ {
+ ptr = (char *)(dst + 1);
+ *dst = *src;
+ dst->AdapterName = ptr;
+ len = strlen( src->AdapterName ) + 1;
+ memcpy( dst->AdapterName, src->AdapterName, len );
+ ptr += (len + 1) & ~1;
+ dst->Description = (WCHAR *)ptr;
+ len = (strlenW( src->Description ) + 1) * sizeof(WCHAR);
+ memcpy( dst->Description, src->Description, len );
+ ptr += len;
+ dst->DnsSuffix = (WCHAR *)ptr;
+ len = (strlenW( src->DnsSuffix ) + 1) * sizeof(WCHAR);
+ memcpy( dst->DnsSuffix, src->DnsSuffix, len );
+ ptr += len;
+ if (src->FriendlyName)
+ {
+ dst->FriendlyName = (WCHAR *)ptr;
+ len = (strlenW( src->FriendlyName ) + 1) * sizeof(WCHAR);
+ memcpy( dst->FriendlyName, src->FriendlyName, len );
+ ptr += len;
+ }
+ ptr = (char *)(((UINT_PTR)ptr + align) & ~align);
+
+ params.src = src;
+ params.dst = dst;
+ params.ptr = ptr;
+ params.next = NULL;
+ params.cur_offset = ~0u;
+ address_lists_iterate( src, address_entry_copy, ¶ms );
+ ptr = params.ptr;
+
+ if (src->Next)
+ {
+ dst->Next = (IP_ADAPTER_ADDRESSES *)ptr;
+ dst = dst->Next;
+ }
+ src = src->Next;
+ }
+}
+
static DWORD typeFromMibType(DWORD mib_type)
{
switch (mib_type)
@@ -909,13 +1062,19 @@ static void fill_unicast_addr_data(IP_ADAPTER_ADDRESSES *aa, IP_ADAPTER_UNICAST_
}
static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index,
- IP_ADAPTER_ADDRESSES *aa, ULONG *size)
+ IP_ADAPTER_ADDRESSES *aa, char **ptr)
{
- ULONG ret = ERROR_SUCCESS, i, j, num_v4addrs = 0, num_v4_gateways = 0, num_v6addrs = 0, total_size;
+ ULONG ret = ERROR_SUCCESS, i, j, num_v4addrs = 0, num_v4_gateways = 0, num_v6addrs = 0;
DWORD *v4addrs = NULL, *v4masks = NULL;
SOCKET_ADDRESS *v6addrs = NULL, *v6masks = NULL;
PMIB_IPFORWARDTABLE routeTable = NULL;
BOOL output_gateways;
+ char name[IF_NAMESIZE], *src;
+ WCHAR *dst;
+ DWORD buflen, type;
+ INTERNAL_IF_OPER_STATUS status;
+ NET_LUID luid;
+ GUID guid;
if ((flags & GAA_FLAG_INCLUDE_ALL_GATEWAYS) || !(flags & GAA_FLAG_SKIP_UNICAST))
{
@@ -953,61 +1112,32 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
return ret;
}
- total_size = sizeof(IP_ADAPTER_ADDRESSES);
- total_size += CHARS_IN_GUID;
- total_size += IF_NAMESIZE * sizeof(WCHAR);
- if (!(flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
- total_size += IF_NAMESIZE * sizeof(WCHAR);
- if (flags & GAA_FLAG_INCLUDE_PREFIX)
- {
- total_size += sizeof(IP_ADAPTER_PREFIX) * num_v4addrs;
- total_size += sizeof(IP_ADAPTER_PREFIX) * num_v6addrs;
- total_size += sizeof(struct sockaddr_in) * num_v4addrs;
- for (i = 0; i < num_v6addrs; i++)
- total_size += v6masks[i].iSockaddrLength;
- }
- total_size += sizeof(IP_ADAPTER_UNICAST_ADDRESS) * num_v4addrs;
- total_size += sizeof(struct sockaddr_in) * num_v4addrs;
- if (output_gateways)
- total_size += (sizeof(IP_ADAPTER_GATEWAY_ADDRESS) + sizeof(SOCKADDR_IN)) * num_v4_gateways;
- total_size += sizeof(IP_ADAPTER_UNICAST_ADDRESS) * num_v6addrs;
- total_size += sizeof(SOCKET_ADDRESS) * num_v6addrs;
- for (i = 0; i < num_v6addrs; i++)
- total_size += v6addrs[i].iSockaddrLength;
-
- if (aa && *size >= total_size)
- {
- char name[IF_NAMESIZE], *ptr = (char *)aa + sizeof(IP_ADAPTER_ADDRESSES), *src;
- WCHAR *dst;
- DWORD buflen, type;
- INTERNAL_IF_OPER_STATUS status;
- NET_LUID luid;
- GUID guid;
-
+ if (1)
+ {
memset(aa, 0, sizeof(IP_ADAPTER_ADDRESSES));
aa->u.s.Length = sizeof(IP_ADAPTER_ADDRESSES);
aa->u.s.IfIndex = index;
ConvertInterfaceIndexToLuid(index, &luid);
ConvertInterfaceLuidToGuid(&luid, &guid);
- ConvertGuidToStringA( &guid, ptr, CHARS_IN_GUID );
- aa->AdapterName = ptr;
- ptr += CHARS_IN_GUID;
+ ConvertGuidToStringA( &guid, *ptr, CHARS_IN_GUID );
+ aa->AdapterName = *ptr;
+ *ptr += (CHARS_IN_GUID + 1) & ~1;
getInterfaceNameByIndex(index, name);
if (!(flags & GAA_FLAG_SKIP_FRIENDLY_NAME))
{
- aa->FriendlyName = (WCHAR *)ptr;
- for (src = name, dst = (WCHAR *)ptr; *src; src++, dst++)
+ aa->FriendlyName = (WCHAR *)*ptr;
+ for (src = name, dst = (WCHAR *)*ptr; *src; src++, dst++)
*dst = *src;
*dst++ = 0;
- ptr = (char *)dst;
+ *ptr = (char *)dst;
}
aa->Description = (WCHAR *)ptr;
- for (src = name, dst = (WCHAR *)ptr; *src; src++, dst++)
+ for (src = name, dst = (WCHAR *)*ptr; *src; src++, dst++)
*dst = *src;
*dst++ = 0;
- ptr = (char *)dst;
+ *ptr = (char *)dst;
TRACE("%s: %d IPv4 addresses, %d IPv6 addresses:\n", name, num_v4addrs,
num_v6addrs);
@@ -1028,12 +1158,11 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
PIP_ADAPTER_GATEWAY_ADDRESS gw;
PSOCKADDR_IN sin;
- gw = (PIP_ADAPTER_GATEWAY_ADDRESS)ptr;
+ gw = heap_alloc( sizeof(IP_ADAPTER_GATEWAY_ADDRESS) + sizeof(SOCKADDR_IN) );
aa->FirstGatewayAddress = gw;
gw->u.s.Length = sizeof(IP_ADAPTER_GATEWAY_ADDRESS);
- ptr += sizeof(IP_ADAPTER_GATEWAY_ADDRESS);
- sin = (PSOCKADDR_IN)ptr;
+ sin = (PSOCKADDR_IN)(gw + 1);
sin->sin_family = WS_AF_INET;
sin->sin_port = 0;
memcpy(&sin->sin_addr, &adapterRow->dwForwardNextHop,
@@ -1041,7 +1170,6 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
gw->Address.lpSockaddr = (LPSOCKADDR)sin;
gw->Address.iSockaddrLength = sizeof(SOCKADDR_IN);
gw->Next = NULL;
- ptr += sizeof(SOCKADDR_IN);
}
}
if (num_v4addrs && !(flags & GAA_FLAG_SKIP_UNICAST))
@@ -1049,7 +1177,7 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
IP_ADAPTER_UNICAST_ADDRESS *ua;
struct WS_sockaddr_in *sa;
aa->u1.s1.Ipv4Enabled = TRUE;
- ua = aa->FirstUnicastAddress = (IP_ADAPTER_UNICAST_ADDRESS *)ptr;
+ ua = aa->FirstUnicastAddress = heap_alloc_zero( sizeof(IP_ADAPTER_UNICAST_ADDRESS) + sizeof(SOCKADDR_IN) );
for (i = 0; i < num_v4addrs; i++)
{
char addr_buf[16];
@@ -1057,7 +1185,7 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
memset(ua, 0, sizeof(IP_ADAPTER_UNICAST_ADDRESS));
ua->u.s.Length = sizeof(IP_ADAPTER_UNICAST_ADDRESS);
ua->Address.iSockaddrLength = sizeof(struct sockaddr_in);
- ua->Address.lpSockaddr = (SOCKADDR *)((char *)ua + ua->u.s.Length);
+ ua->Address.lpSockaddr = (SOCKADDR *)(ua + 1);
if (num_v4_gateways)
ua->u.s.Flags |= IP_ADAPTER_ADDRESS_DNS_ELIGIBLE;
@@ -1071,10 +1199,9 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
ua->OnLinkPrefixLength = mask_v4_to_prefix(v4masks[i]);
- ptr += ua->u.s.Length + ua->Address.iSockaddrLength;
if (i < num_v4addrs - 1)
{
- ua->Next = (IP_ADAPTER_UNICAST_ADDRESS *)ptr;
+ ua->Next = heap_alloc_zero( sizeof(IP_ADAPTER_UNICAST_ADDRESS) + sizeof(SOCKADDR_IN) );
ua = ua->Next;
}
}
@@ -1089,11 +1216,11 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
{
for (ua = aa->FirstUnicastAddress; ua->Next; ua = ua->Next)
;
- ua->Next = (IP_ADAPTER_UNICAST_ADDRESS *)ptr;
- ua = (IP_ADAPTER_UNICAST_ADDRESS *)ptr;
+ ua->Next = heap_alloc_zero( sizeof(IP_ADAPTER_UNICAST_ADDRESS) + sizeof(SOCKADDR_IN6) );
+ ua = ua->Next;
}
else
- ua = aa->FirstUnicastAddress = (IP_ADAPTER_UNICAST_ADDRESS *)ptr;
+ ua = aa->FirstUnicastAddress = heap_alloc_zero( sizeof(IP_ADAPTER_UNICAST_ADDRESS) + sizeof(SOCKADDR_IN6) );
for (i = 0; i < num_v6addrs; i++)
{
char addr_buf[46];
@@ -1101,7 +1228,7 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
memset(ua, 0, sizeof(IP_ADAPTER_UNICAST_ADDRESS));
ua->u.s.Length = sizeof(IP_ADAPTER_UNICAST_ADDRESS);
ua->Address.iSockaddrLength = v6addrs[i].iSockaddrLength;
- ua->Address.lpSockaddr = (SOCKADDR *)((char *)ua + ua->u.s.Length);
+ ua->Address.lpSockaddr = (SOCKADDR *)(ua + 1);
sa = (struct WS_sockaddr_in6 *)ua->Address.lpSockaddr;
memcpy(sa, v6addrs[i].lpSockaddr, sizeof(*sa));
@@ -1111,10 +1238,9 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
ua->OnLinkPrefixLength = mask_v6_to_prefix(&v6masks[i]);
- ptr += ua->u.s.Length + ua->Address.iSockaddrLength;
if (i < num_v6addrs - 1)
{
- ua->Next = (IP_ADAPTER_UNICAST_ADDRESS *)ptr;
+ ua->Next = heap_alloc_zero( sizeof(IP_ADAPTER_UNICAST_ADDRESS) + sizeof(SOCKADDR_IN6) );
ua = ua->Next;
}
}
@@ -1123,7 +1249,7 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
{
IP_ADAPTER_PREFIX *prefix;
- prefix = aa->FirstPrefix = (IP_ADAPTER_PREFIX *)ptr;
+ prefix = aa->FirstPrefix = heap_alloc_zero( sizeof(*prefix) + sizeof(SOCKADDR_IN) );
for (i = 0; i < num_v4addrs; i++)
{
char addr_buf[16];
@@ -1133,7 +1259,7 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
prefix->u.s.Flags = 0;
prefix->Next = NULL;
prefix->Address.iSockaddrLength = sizeof(struct sockaddr_in);
- prefix->Address.lpSockaddr = (SOCKADDR *)((char *)prefix + prefix->u.s.Length);
+ prefix->Address.lpSockaddr = (SOCKADDR *)(prefix + 1);
sa = (struct WS_sockaddr_in *)prefix->Address.lpSockaddr;
sa->sin_family = WS_AF_INET;
@@ -1146,10 +1272,9 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
debugstr_ipv4((const in_addr_t *)&sa->sin_addr.S_un.S_addr, addr_buf),
prefix->PrefixLength);
- ptr += prefix->u.s.Length + prefix->Address.iSockaddrLength;
if (i < num_v4addrs - 1)
{
- prefix->Next = (IP_ADAPTER_PREFIX *)ptr;
+ prefix->Next = heap_alloc_zero( sizeof(*prefix) + sizeof(SOCKADDR_IN) );
prefix = prefix->Next;
}
}
@@ -1162,11 +1287,11 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
{
for (prefix = aa->FirstPrefix; prefix->Next; prefix = prefix->Next)
;
- prefix->Next = (IP_ADAPTER_PREFIX *)ptr;
- prefix = (IP_ADAPTER_PREFIX *)ptr;
+ prefix->Next = heap_alloc_zero( sizeof(*prefix) + sizeof(SOCKADDR_IN6) );
+ prefix = prefix->Next;
}
else
- prefix = aa->FirstPrefix = (IP_ADAPTER_PREFIX *)ptr;
+ prefix = aa->FirstPrefix = heap_alloc_zero( sizeof(*prefix) + sizeof(SOCKADDR_IN6) );
for (i = 0; i < num_v6addrs; i++)
{
char addr_buf[46];
@@ -1177,7 +1302,7 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
prefix->u.s.Flags = 0;
prefix->Next = NULL;
prefix->Address.iSockaddrLength = sizeof(struct sockaddr_in6);
- prefix->Address.lpSockaddr = (SOCKADDR *)((char *)prefix + prefix->u.s.Length);
+ prefix->Address.lpSockaddr = (SOCKADDR *)(prefix + 1);
sa = (struct WS_sockaddr_in6 *)prefix->Address.lpSockaddr;
sa->sin6_family = WS_AF_INET6;
@@ -1192,10 +1317,9 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
TRACE("IPv6 network: %s/%u\n", debugstr_ipv6(sa, addr_buf), prefix->PrefixLength);
- ptr += prefix->u.s.Length + prefix->Address.iSockaddrLength;
if (i < num_v6addrs - 1)
{
- prefix->Next = (IP_ADAPTER_PREFIX *)ptr;
+ prefix->Next = heap_alloc_zero( sizeof(*prefix) + sizeof(SOCKADDR_IN6) );
prefix = prefix->Next;
}
}
@@ -1208,7 +1332,6 @@ static ULONG adapterAddressesFromIndex(ULONG family, ULONG flags, IF_INDEX index
else if (status == MIB_IF_OPER_STATUS_NON_OPERATIONAL) aa->OperStatus = IfOperStatusDown;
else aa->OperStatus = IfOperStatusUnknown;
}
- *size = total_size;
HeapFree(GetProcessHeap(), 0, routeTable);
HeapFree(GetProcessHeap(), 0, v6addrs);
HeapFree(GetProcessHeap(), 0, v6masks);
@@ -1224,97 +1347,92 @@ static DWORD dns_servers_query_code( ULONG family )
return DnsConfigDnsServersUnspec;
}
-static ULONG get_dns_server_addresses( ULONG family, IP_ADAPTER_DNS_SERVER_ADDRESS *address, ULONG *len )
+static DWORD dns_info_alloc( IP_ADAPTER_ADDRESSES *aa, ULONG family, ULONG flags )
{
char buf[FIELD_OFFSET(DNS_ADDR_ARRAY, AddrArray[3])];
- DNS_ADDR_ARRAY *servers = (DNS_ADDR_ARRAY *)buf;
- DWORD err, num, i, needed, array_len = sizeof(buf);
+ IP_ADAPTER_DNS_SERVER_ADDRESS *dns, **next;
DWORD query = dns_servers_query_code( family );
- SOCKADDR_INET *out_addrs;
+ DWORD err, i, size, attempt, sockaddr_len;
+ WCHAR name[MAX_ADAPTER_NAME_LENGTH + 1];
+ DNS_ADDR_ARRAY *servers;
+ DNS_TXT_DATAW *search;
- for (;;)
+ while (aa)
{
- err = DnsQueryConfig( query, 0, NULL, NULL, servers, &array_len );
- if (err != ERROR_SUCCESS && err != ERROR_MORE_DATA) goto err;
- num = (array_len - FIELD_OFFSET(DNS_ADDR_ARRAY, AddrArray[0])) / sizeof(DNS_ADDR);
- needed = num * (sizeof(IP_ADAPTER_DNS_SERVER_ADDRESS) + sizeof(*out_addrs));
- if (!address || *len < needed)
+ MultiByteToWideChar( CP_ACP, 0, aa->AdapterName, -1, name, ARRAY_SIZE(name) );
+ if (!(flags & GAA_FLAG_SKIP_DNS_SERVER))
{
- *len = needed;
- err = ERROR_BUFFER_OVERFLOW;
- goto err;
+ servers = (DNS_ADDR_ARRAY *)buf;
+ for (attempt = 0; attempt < 5; attempt++)
+ {
+ err = DnsQueryConfig( query, 0, name, NULL, servers, &size );
+ if (err != ERROR_MORE_DATA) break;
+ if (servers != (DNS_ADDR_ARRAY *)buf) heap_free( servers );
+ servers = heap_alloc( size );
+ if (!servers)
+ {
+ err = ERROR_NOT_ENOUGH_MEMORY;
+ break;
+ }
+ }
+ if (!err)
+ {
+ next = &aa->FirstDnsServerAddress;
+ for (i = 0; i < servers->AddrCount; i++)
+ {
+ sockaddr_len = servers->AddrArray[i].Data.DnsAddrUserDword[0];
+ if (sockaddr_len > sizeof(servers->AddrArray[i].MaxSa))
+ sockaddr_len = sizeof(servers->AddrArray[i].MaxSa);
+ dns = heap_alloc_zero( sizeof(*dns) + sockaddr_len );
+ if (!dns)
+ {
+ err = ERROR_NOT_ENOUGH_MEMORY;
+ break;
+ }
+ dns->u.s.Length = sizeof(*dns);
+ dns->Address.lpSockaddr = (SOCKADDR *)(dns + 1);
+ dns->Address.iSockaddrLength = sockaddr_len;
+ memcpy( dns->Address.lpSockaddr, servers->AddrArray[i].MaxSa, sockaddr_len );
+ *next = dns;
+ next = &dns->Next;
+ }
+ }
+ if (servers != (DNS_ADDR_ARRAY *)buf) heap_free( servers );
+ if (err) goto err;
}
- if (!err) break;
- if ((char *)servers != buf) heap_free( servers );
- servers = heap_alloc( array_len );
- if (!servers)
+ aa->DnsSuffix = heap_alloc( MAX_DNS_SUFFIX_STRING_LENGTH * sizeof(WCHAR) );
+ if (!aa->DnsSuffix)
{
err = ERROR_NOT_ENOUGH_MEMORY;
goto err;
}
- }
-
- *len = needed;
- out_addrs = (SOCKADDR_INET *)(address + num);
- for (i = 0; i < num; i++)
- {
- address[i].u.s.Length = sizeof(*address);
- address[i].u.s.Reserved = 0;
- address[i].Next = NULL;
- address[i].Address.iSockaddrLength = servers->AddrArray[i].Data.DnsAddrUserDword[0];
- if (address[i].Address.iSockaddrLength > sizeof(*out_addrs))
- address[i].Address.iSockaddrLength = 0;
- address[i].Address.lpSockaddr = (SOCKADDR *)(out_addrs + i);
- memcpy( out_addrs + i, servers->AddrArray[i].MaxSa, address[i].Address.iSockaddrLength );
- memset( (BYTE *)(out_addrs + i) + address[i].Address.iSockaddrLength, 0,
- sizeof(*out_addrs) - address[i].Address.iSockaddrLength );
- if (i) address[i - 1].Next = address + i;
- }
- err = ERROR_SUCCESS;
-
-err:
- if ((char *)servers != buf) heap_free( servers );
- return err;
-}
-
-static ULONG get_dns_suffix(WCHAR *suffix, ULONG *len)
-{
- DWORD err, list_len = 0, needed = 1;
- DNS_TXT_DATAW *search = NULL;
+ aa->DnsSuffix[0] = '\0';
- if (suffix && *len > 0) *suffix = '\0';
-
- err = DnsQueryConfig( DnsConfigSearchList, 0, NULL, NULL, NULL, &list_len );
- if (err) goto err;
-
- search = heap_alloc( list_len );
- err = DnsQueryConfig( DnsConfigSearchList, 0, NULL, NULL, search, &list_len );
- if (err || !search->dwStringCount) goto err;
+ if (!DnsQueryConfig( DnsConfigSearchList, 0, name, NULL, NULL, &size ) &&
+ (search = heap_alloc( size )))
+ {
+ if (!DnsQueryConfig( DnsConfigSearchList, 0, name, NULL, search, &size ) &&
+ search->dwStringCount && strlenW( search->pStringArray[0] ) < MAX_DNS_SUFFIX_STRING_LENGTH)
+ {
+ strcpyW( aa->DnsSuffix, search->pStringArray[0] );
+ }
+ heap_free( search );
+ }
- needed = (strlenW( search->pStringArray[0] ) + 1) * sizeof(WCHAR);
- if (!suffix || *len < needed)
- {
- err = ERROR_INSUFFICIENT_BUFFER;
- goto err;
+ aa = aa->Next;
}
- memcpy( suffix, search->pStringArray[0], needed );
err:
- *len = needed;
- heap_free( search );
return err;
}
-ULONG WINAPI DECLSPEC_HOTPATCH GetAdaptersAddresses(ULONG family, ULONG flags, PVOID reserved,
- PIP_ADAPTER_ADDRESSES aa, PULONG buflen)
+static DWORD adapters_addresses_alloc( ULONG family, ULONG flags, IP_ADAPTER_ADDRESSES **info )
{
+ IP_ADAPTER_ADDRESSES *aa;
+ DWORD err, i, count, needed;
+ char *str_ptr;
InterfaceIndexTable *table;
- ULONG i, size, dns_server_size = 0, dns_suffix_size, total_size, ret = ERROR_NO_DATA;
-
- TRACE("(%d, %08x, %p, %p, %p)\n", family, flags, reserved, aa, buflen);
-
- if (!buflen) return ERROR_INVALID_PARAMETER;
get_interface_indices( FALSE, &table );
if (!table || !table->numIndexes)
@@ -1322,82 +1440,62 @@ ULONG WINAPI DECLSPEC_HOTPATCH GetAdaptersAddresses(ULONG family, ULONG flags, P
HeapFree(GetProcessHeap(), 0, table);
return ERROR_NO_DATA;
}
- total_size = 0;
- for (i = 0; i < table->numIndexes; i++)
- {
- size = 0;
- if ((ret = adapterAddressesFromIndex(family, flags, table->indexes[i], NULL, &size)))
- {
- HeapFree(GetProcessHeap(), 0, table);
- return ret;
- }
- total_size += size;
- }
- if (!(flags & GAA_FLAG_SKIP_DNS_SERVER))
+ count = table->numIndexes;
+
+ needed = count * (sizeof(*aa) + ((CHARS_IN_GUID + 1) & ~1) + sizeof(IF_COUNTED_STRING));
+ if (!(flags & GAA_FLAG_SKIP_FRIENDLY_NAME)) needed += count * sizeof(IF_COUNTED_STRING);
+
+ aa = heap_alloc_zero( needed );
+ if (!aa)
{
- /* Since DNS servers aren't really per adapter, get enough space for a
- * single copy of them.
- */
- get_dns_server_addresses( family, NULL, &dns_server_size );
- total_size += dns_server_size;
+ err = ERROR_NOT_ENOUGH_MEMORY;
+ goto err;
}
- /* Since DNS suffix also isn't really per adapter, get enough space for a
- * single copy of it.
- */
- get_dns_suffix(NULL, &dns_suffix_size);
- total_size += dns_suffix_size;
- if (aa && *buflen >= total_size)
- {
- ULONG bytes_left = size = total_size;
- PIP_ADAPTER_ADDRESSES first_aa = aa;
- PIP_ADAPTER_DNS_SERVER_ADDRESS firstDns;
- WCHAR *dnsSuffix;
- for (i = 0; i < table->numIndexes; i++)
- {
- if ((ret = adapterAddressesFromIndex(family, flags, table->indexes[i], aa, &size)))
- {
- HeapFree(GetProcessHeap(), 0, table);
- return ret;
- }
- if (i < table->numIndexes - 1)
- {
- aa->Next = (IP_ADAPTER_ADDRESSES *)((char *)aa + size);
- aa = aa->Next;
- size = bytes_left -= size;
- }
- }
- if (dns_server_size)
- {
- firstDns = (PIP_ADAPTER_DNS_SERVER_ADDRESS)((BYTE *)first_aa + total_size - dns_server_size - dns_suffix_size);
- get_dns_server_addresses( family, firstDns, &dns_server_size );
- for (aa = first_aa; aa; aa = aa->Next)
- {
- if (aa->IfType != IF_TYPE_SOFTWARE_LOOPBACK && aa->OperStatus == IfOperStatusUp)
- aa->FirstDnsServerAddress = firstDns;
- }
- }
- aa = first_aa;
- dnsSuffix = (WCHAR *)((BYTE *)aa + total_size - dns_suffix_size);
- get_dns_suffix(dnsSuffix, &dns_suffix_size);
- for (; aa; aa = aa->Next)
+ str_ptr = (char *)(aa + count);
+ for (i = 0; i < count; i++)
+ {
+ if ((err = adapterAddressesFromIndex(family, flags, table->indexes[i], aa + i, &str_ptr)))
{
- if (aa->IfType != IF_TYPE_SOFTWARE_LOOPBACK && aa->OperStatus == IfOperStatusUp)
- aa->DnsSuffix = dnsSuffix;
- else
- aa->DnsSuffix = dnsSuffix + dns_suffix_size / sizeof(WCHAR) - 1;
+ HeapFree(GetProcessHeap(), 0, table);
+ return err;
}
- ret = ERROR_SUCCESS;
+ if (i < count - 1) aa[i].Next = aa + i + 1;
}
- else
+
+ err = dns_info_alloc( aa, family, flags );
+
+err:
+ HeapFree(GetProcessHeap(), 0, table);
+ if (!err) *info = aa;
+ else adapters_addresses_free( aa );
+ return err;
+}
+
+ULONG WINAPI DECLSPEC_HOTPATCH GetAdaptersAddresses( ULONG family, ULONG flags, void *reserved,
+ IP_ADAPTER_ADDRESSES *aa, ULONG *size )
+{
+ IP_ADAPTER_ADDRESSES *info;
+ DWORD err, needed;
+
+ TRACE( "(%d, %08x, %p, %p, %p)\n", family, flags, reserved, aa, size );
+
+ if (!size) return ERROR_INVALID_PARAMETER;
+
+ err = adapters_addresses_alloc( family, flags, &info );
+ if (err) return err;
+
+ needed = adapters_addresses_size( info );
+ if (!aa || *size < needed)
{
- ret = ERROR_BUFFER_OVERFLOW;
- *buflen = total_size;
+ *size = needed;
+ err = ERROR_BUFFER_OVERFLOW;
}
+ else
+ adapters_addresses_copy( aa, info );
- TRACE("num adapters %u\n", table->numIndexes);
- HeapFree(GetProcessHeap(), 0, table);
- return ret;
+ adapters_addresses_free( info );
+ return err;
}
/******************************************************************
--
2.23.0
1
0
09 Aug '21
This was already done correctly in the res_getservers() case.
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/dnsapi/libresolv.c | 2 +-
dlls/dnsapi/tests/query.c | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/dlls/dnsapi/libresolv.c b/dlls/dnsapi/libresolv.c
index 7e545cf36fb..864c517333d 100644
--- a/dlls/dnsapi/libresolv.c
+++ b/dlls/dnsapi/libresolv.c
@@ -414,7 +414,7 @@ DNS_STATUS CDECL resolv_get_serverlist( USHORT family, DNS_ADDR_ARRAY *addrs, DW
if (!addrs || *len < needed)
{
*len = needed;
- return !addrs ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
+ return !addrs ? ERROR_SUCCESS : ERROR_MORE_DATA;
}
*len = needed;
memset( addrs, 0, needed );
diff --git a/dlls/dnsapi/tests/query.c b/dlls/dnsapi/tests/query.c
index 5fb47d89782..e691822a46a 100644
--- a/dlls/dnsapi/tests/query.c
+++ b/dlls/dnsapi/tests/query.c
@@ -155,6 +155,10 @@ static void test_DnsQueryConfig( void )
err = DnsQueryConfig( DnsConfigDnsServersIpv4, 0, name, NULL, NULL, &size );
if (err) continue;
ipv4 = malloc( size );
+ size--;
+ err = DnsQueryConfig( DnsConfigDnsServersIpv4, 0, name, NULL, ipv4, &size );
+ ok( err == ERROR_MORE_DATA, "got %d\n", err );
+ size++;
err = DnsQueryConfig( DnsConfigDnsServersIpv4, 0, name, NULL, ipv4, &size );
ok( !err, "got %d\n", err );
--
2.23.0
1
0