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/Makefile.in | 1 -
dlls/gdi32/metadc.c | 322 +++++++++++++++++++++++++++
dlls/gdi32/mfdrv/graphics.c | 430 ------------------------------------
3 files changed, 322 insertions(+), 431 deletions(-)
delete mode 100644 dlls/gdi32/mfdrv/graphics.c
2
1
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/gdi32/Makefile.in | 1 -
dlls/gdi32/metadc.c | 130 +++++++++++++++++++++++++++++++++++
dlls/gdi32/mfdrv/dc.c | 151 -----------------------------------------
3 files changed, 130 insertions(+), 152 deletions(-)
delete mode 100644 dlls/gdi32/mfdrv/dc.c
2
1
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/gdi32/Makefile.in | 2 +-
dlls/gdi32/{mfdrv/init.c => metadc.c} | 344 ++++++++++++--------------
2 files changed, 158 insertions(+), 188 deletions(-)
rename dlls/gdi32/{mfdrv/init.c => metadc.c} (87%)
2
1
[PATCH v2 2/2] user32: Check control type in the STM_SETIMAGE/STM_SETICON handlers before calling the helpers.
by Dmitry Timoshkov 18 Aug '21
by Dmitry Timoshkov 18 Aug '21
18 Aug '21
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/user32/static.c | 7 ++-
dlls/user32/tests/static.c | 121 ++++++++++++++++++++++++++++++++++++-
2 files changed, 122 insertions(+), 6 deletions(-)
diff --git a/dlls/user32/static.c b/dlls/user32/static.c
index 72e49e15e8f..35bdc2490c0 100644
--- a/dlls/user32/static.c
+++ b/dlls/user32/static.c
@@ -103,7 +103,6 @@ static HICON STATIC_SetIcon( HWND hwnd, HICON hicon, DWORD style )
HICON prevIcon;
SIZE size;
- if ((style & SS_TYPEMASK) != SS_ICON) return 0;
if (hicon && !get_icon_size( hicon, &size ))
{
WARN("hicon != 0, but invalid\n");
@@ -138,7 +137,6 @@ static HBITMAP STATIC_SetBitmap( HWND hwnd, HBITMAP hBitmap, DWORD style )
{
HBITMAP hOldBitmap;
- if ((style & SS_TYPEMASK) != SS_BITMAP) return 0;
if (hBitmap && GetObjectType(hBitmap) != OBJ_BITMAP) {
WARN("hBitmap != 0, but it's not a bitmap\n");
return 0;
@@ -174,7 +172,6 @@ static HBITMAP STATIC_SetBitmap( HWND hwnd, HBITMAP hBitmap, DWORD style )
*/
static HENHMETAFILE STATIC_SetEnhMetaFile( HWND hwnd, HENHMETAFILE hEnhMetaFile, DWORD style )
{
- if ((style & SS_TYPEMASK) != SS_ENHMETAFILE) return 0;
if (hEnhMetaFile && GetObjectType(hEnhMetaFile) != OBJ_ENHMETAFILE) {
WARN("hEnhMetaFile != 0, but it's not an enhanced metafile\n");
return 0;
@@ -501,13 +498,16 @@ LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam
case STM_SETIMAGE:
switch(wParam) {
case IMAGE_BITMAP:
+ if (style != SS_BITMAP) return 0;
lResult = (LRESULT)STATIC_SetBitmap( hwnd, (HBITMAP)lParam, full_style );
break;
case IMAGE_ENHMETAFILE:
+ if (style != SS_ENHMETAFILE) return 0;
lResult = (LRESULT)STATIC_SetEnhMetaFile( hwnd, (HENHMETAFILE)lParam, full_style );
break;
case IMAGE_ICON:
case IMAGE_CURSOR:
+ if (style != SS_ICON) return 0;
lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)lParam, full_style );
break;
default:
@@ -518,6 +518,7 @@ LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam
break;
case STM_SETICON:
+ if (style != SS_ICON) return 0;
lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)wParam, full_style );
STATIC_TryPaintFcn( hwnd, full_style );
break;
diff --git a/dlls/user32/tests/static.c b/dlls/user32/tests/static.c
index 0c453d08a67..731e0f5df72 100644
--- a/dlls/user32/tests/static.c
+++ b/dlls/user32/tests/static.c
@@ -20,9 +20,11 @@
#include <stdarg.h>
#include <stdio.h>
-#define STRICT
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#define OEMRESOURCE
+#include "winuser.h"
#include "wine/test.h"
@@ -189,6 +191,118 @@ static void test_set_image(void)
DeleteObject(image);
}
+static void test_STM_SETIMAGE(void)
+{
+ DWORD type;
+ HWND hwnd;
+ HICON icon, old_image;
+ HBITMAP bmp;
+ HENHMETAFILE emf;
+ HDC dc;
+
+ icon = LoadIconW(0, (LPCWSTR)IDI_APPLICATION);
+ bmp = LoadBitmapW(0, (LPCWSTR)OBM_CLOSE);
+ dc = CreateEnhMetaFileW(0, NULL, NULL, NULL);
+ LineTo(dc, 1, 1);
+ emf = CloseEnhMetaFile(dc);
+ DeleteDC(dc);
+
+ for (type = SS_LEFT; type < SS_ETCHEDFRAME; type++)
+ {
+ winetest_push_context("%u", type);
+
+ hwnd = build_static(type);
+ ok(hwnd != 0, "failed to create static type %#x\n", type);
+
+ /* set icon */
+ g_nReceivedColorStatic = 0;
+ old_image = (HICON)SendMessageW(hwnd, STM_SETIMAGE, IMAGE_ICON, (LPARAM)icon);
+ ok(!old_image, "got %p\n", old_image);
+ if (type == SS_ICON)
+ ok(g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ else
+ ok(!g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+
+ g_nReceivedColorStatic = 0;
+ old_image = (HICON)SendMessageW(hwnd, STM_SETIMAGE, IMAGE_ICON, (LPARAM)icon);
+ if (type == SS_ICON)
+ {
+ ok(old_image != 0, "got %p\n", old_image);
+ ok(g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ }
+ else
+ {
+ ok(!old_image, "got %p\n", old_image);
+ ok(!g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ }
+
+ g_nReceivedColorStatic = 0;
+ old_image = (HICON)SendMessageW(hwnd, STM_SETICON, (WPARAM)icon, 0);
+ if (type == SS_ICON)
+ {
+ ok(old_image != 0, "got %p\n", old_image);
+ ok(g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ }
+ else
+ {
+ ok(!old_image, "got %p\n", old_image);
+ ok(!g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ }
+
+ /* set bitmap */
+ g_nReceivedColorStatic = 0;
+ old_image = (HICON)SendMessageW(hwnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)bmp);
+ ok(!old_image, "got %p\n", old_image);
+ if (type == SS_BITMAP)
+ ok(g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ else
+ ok(!g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+
+ g_nReceivedColorStatic = 0;
+ old_image = (HICON)SendMessageW(hwnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)bmp);
+ if (type == SS_BITMAP)
+ {
+ ok(old_image != 0, "got %p\n", old_image);
+ ok(g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ }
+ else
+ {
+ ok(!old_image, "got %p\n", old_image);
+ ok(!g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ }
+
+ /* set EMF */
+ g_nReceivedColorStatic = 0;
+ old_image = (HICON)SendMessageW(hwnd, STM_SETIMAGE, IMAGE_ENHMETAFILE, (LPARAM)emf);
+ ok(!old_image, "got %p\n", old_image);
+ if (type == SS_ENHMETAFILE)
+ ok(g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ else
+ ok(!g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+
+ g_nReceivedColorStatic = 0;
+ old_image = (HICON)SendMessageW(hwnd, STM_SETIMAGE, IMAGE_ENHMETAFILE, (LPARAM)emf);
+ if (type == SS_ENHMETAFILE)
+ {
+ ok(old_image != 0, "got %p\n", old_image);
+ ok(g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ }
+ else
+ {
+ ok(!old_image, "got %p\n", old_image);
+ ok(!g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ }
+
+ DestroyWindow(hwnd);
+
+ winetest_pop_context();
+ }
+
+ DestroyIcon(icon);
+ DeleteObject(bmp);
+ DeleteEnhMetaFile(emf);
+}
+
START_TEST(static)
{
static const char szClassName[] = "testclass";
@@ -222,6 +336,7 @@ START_TEST(static)
test_updates(SS_ETCHEDVERT, TODO_COUNT);
test_set_text();
test_set_image();
+ test_STM_SETIMAGE();
DestroyWindow(hMainWnd);
}
--
2.31.1
1
0
[PATCH v2 1/2] comctl32: Check control type in the STM_SETIMAGE/STM_SETICON handlers before calling the helpers.
by Dmitry Timoshkov 18 Aug '21
by Dmitry Timoshkov 18 Aug '21
18 Aug '21
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/comctl32/static.c | 7 +-
dlls/comctl32/tests/static.c | 121 ++++++++++++++++++++++++++++++++++-
2 files changed, 122 insertions(+), 6 deletions(-)
diff --git a/dlls/comctl32/static.c b/dlls/comctl32/static.c
index 2bd2b22bc20..60af6696425 100644
--- a/dlls/comctl32/static.c
+++ b/dlls/comctl32/static.c
@@ -133,7 +133,6 @@ static HICON STATIC_SetIcon( HWND hwnd, HICON hicon, DWORD style )
SIZE size;
struct static_extra_info *extra;
- if ((style & SS_TYPEMASK) != SS_ICON) return 0;
if (hicon && !get_icon_size( hicon, &size ))
{
WARN("hicon != 0, but invalid\n");
@@ -220,7 +219,6 @@ static HBITMAP STATIC_SetBitmap( HWND hwnd, HBITMAP hBitmap, DWORD style )
HBITMAP hOldBitmap, alpha;
struct static_extra_info *extra;
- if ((style & SS_TYPEMASK) != SS_BITMAP) return 0;
if (hBitmap && GetObjectType(hBitmap) != OBJ_BITMAP)
{
WARN("hBitmap != 0, but it's not a bitmap\n");
@@ -277,7 +275,6 @@ static HENHMETAFILE STATIC_SetEnhMetaFile( HWND hwnd, HENHMETAFILE hEnhMetaFile,
HENHMETAFILE old_hemf;
struct static_extra_info *extra;
- if ((style & SS_TYPEMASK) != SS_ENHMETAFILE) return 0;
if (hEnhMetaFile && GetObjectType(hEnhMetaFile) != OBJ_ENHMETAFILE)
{
WARN("hEnhMetaFile != 0, but it's not an enhanced metafile\n");
@@ -594,13 +591,16 @@ static LRESULT CALLBACK STATIC_WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam,
switch (wParam)
{
case IMAGE_BITMAP:
+ if (style != SS_BITMAP) return 0;
lResult = (LRESULT)STATIC_SetBitmap( hwnd, (HBITMAP)lParam, full_style );
break;
case IMAGE_ENHMETAFILE:
+ if (style != SS_ENHMETAFILE) return 0;
lResult = (LRESULT)STATIC_SetEnhMetaFile( hwnd, (HENHMETAFILE)lParam, full_style );
break;
case IMAGE_ICON:
case IMAGE_CURSOR:
+ if (style != SS_ICON) return 0;
lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)lParam, full_style );
break;
default:
@@ -611,6 +611,7 @@ static LRESULT CALLBACK STATIC_WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam,
break;
case STM_SETICON:
+ if (style != SS_ICON) return 0;
lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)wParam, full_style );
STATIC_TryPaintFcn( hwnd, full_style );
break;
diff --git a/dlls/comctl32/tests/static.c b/dlls/comctl32/tests/static.c
index 4efb7685790..40a337b97b0 100644
--- a/dlls/comctl32/tests/static.c
+++ b/dlls/comctl32/tests/static.c
@@ -20,9 +20,11 @@
#include <stdarg.h>
#include <stdio.h>
-#define STRICT
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#define OEMRESOURCE
+#include "winuser.h"
#include "commctrl.h"
#include "resources.h"
@@ -263,6 +265,118 @@ static void test_set_image(void)
DeleteObject(image);
}
+static void test_STM_SETIMAGE(void)
+{
+ DWORD type;
+ HWND hwnd;
+ HICON icon, old_image;
+ HBITMAP bmp;
+ HENHMETAFILE emf;
+ HDC dc;
+
+ icon = LoadIconW(0, (LPCWSTR)IDI_APPLICATION);
+ bmp = LoadBitmapW(0, (LPCWSTR)OBM_CLOSE);
+ dc = CreateEnhMetaFileW(0, NULL, NULL, NULL);
+ LineTo(dc, 1, 1);
+ emf = CloseEnhMetaFile(dc);
+ DeleteDC(dc);
+
+ for (type = SS_LEFT; type < SS_ETCHEDFRAME; type++)
+ {
+ winetest_push_context("%u", type);
+
+ hwnd = create_static(type);
+ ok(hwnd != 0, "failed to create static type %#x\n", type);
+
+ /* set icon */
+ g_nReceivedColorStatic = 0;
+ old_image = (HICON)SendMessageW(hwnd, STM_SETIMAGE, IMAGE_ICON, (LPARAM)icon);
+ ok(!old_image, "got %p\n", old_image);
+ if (type == SS_ICON)
+ ok(g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ else
+ ok(!g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+
+ g_nReceivedColorStatic = 0;
+ old_image = (HICON)SendMessageW(hwnd, STM_SETIMAGE, IMAGE_ICON, (LPARAM)icon);
+ if (type == SS_ICON)
+ {
+ ok(old_image != 0, "got %p\n", old_image);
+ ok(g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ }
+ else
+ {
+ ok(!old_image, "got %p\n", old_image);
+ ok(!g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ }
+
+ g_nReceivedColorStatic = 0;
+ old_image = (HICON)SendMessageW(hwnd, STM_SETICON, (WPARAM)icon, 0);
+ if (type == SS_ICON)
+ {
+ ok(old_image != 0, "got %p\n", old_image);
+ ok(g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ }
+ else
+ {
+ ok(!old_image, "got %p\n", old_image);
+ ok(!g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ }
+
+ /* set bitmap */
+ g_nReceivedColorStatic = 0;
+ old_image = (HICON)SendMessageW(hwnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)bmp);
+ ok(!old_image, "got %p\n", old_image);
+ if (type == SS_BITMAP)
+ ok(g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ else
+ ok(!g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+
+ g_nReceivedColorStatic = 0;
+ old_image = (HICON)SendMessageW(hwnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)bmp);
+ if (type == SS_BITMAP)
+ {
+ ok(old_image != 0, "got %p\n", old_image);
+ ok(g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ }
+ else
+ {
+ ok(!old_image, "got %p\n", old_image);
+ ok(!g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ }
+
+ /* set EMF */
+ g_nReceivedColorStatic = 0;
+ old_image = (HICON)SendMessageW(hwnd, STM_SETIMAGE, IMAGE_ENHMETAFILE, (LPARAM)emf);
+ ok(!old_image, "got %p\n", old_image);
+ if (type == SS_ENHMETAFILE)
+ ok(g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ else
+ ok(!g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+
+ g_nReceivedColorStatic = 0;
+ old_image = (HICON)SendMessageW(hwnd, STM_SETIMAGE, IMAGE_ENHMETAFILE, (LPARAM)emf);
+ if (type == SS_ENHMETAFILE)
+ {
+ ok(old_image != 0, "got %p\n", old_image);
+ ok(g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ }
+ else
+ {
+ ok(!old_image, "got %p\n", old_image);
+ ok(!g_nReceivedColorStatic, "Unexpected WM_CTLCOLORSTATIC value %d\n", g_nReceivedColorStatic);
+ }
+
+ DestroyWindow(hwnd);
+
+ winetest_pop_context();
+ }
+
+ DestroyIcon(icon);
+ DeleteObject(bmp);
+ DeleteEnhMetaFile(emf);
+}
+
START_TEST(static)
{
static const char classname[] = "testclass";
@@ -302,6 +416,7 @@ START_TEST(static)
test_updates(SS_ETCHEDVERT, TODO_COUNT);
test_set_text();
test_set_image();
+ test_STM_SETIMAGE();
DestroyWindow(hMainWnd);
--
2.31.1
1
0
[PATCH] [DbgHelp]: fix copy_line_W64_from_64 when A and W buffers are identical
by Eric Pouech 18 Aug '21
by Eric Pouech 18 Aug '21
18 Aug '21
As reported by Alistair, when doing Unicode conversion for FileName field
from IMAGEHLP_LINE64 into IMAGEHLP_LINE64W, both structures would refer
to the same buffer allocated by fetch_buffer.
So properly detect and handle this situation.
Signed-off-by: Eric Pouech <eric.pouech(a)gmail.com>
---
dlls/dbghelp/symbol.c | 35 +++++++++++++++++++++++++++--------
1 file changed, 27 insertions(+), 8 deletions(-)
diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c
index b2b4d578910..3b264eb9a52 100644
--- a/dlls/dbghelp/symbol.c
+++ b/dlls/dbghelp/symbol.c
@@ -1588,19 +1588,39 @@ static void copy_line_64_from_32(IMAGEHLP_LINE64* l64, const IMAGEHLP_LINE* l32)
}
/******************************************************************
- * copy_line_W64_from_32 (internal)
+ * copy_line_W64_from_64 (internal)
*
+ * Note: upon return, l64w->FileName is always allocated by fetch_buffer().
+ * So, if input l64->FileName has *also* been allocated by fetch_buffer()
+ * before calling this function, l64->FileName will be overwritten
+ * (as it's the same buffer returned in l64w).
+ * In consequence, don't use the l64 structure *after* calling this function.
*/
-static void copy_line_W64_from_64(struct process* pcs, IMAGEHLP_LINEW64* l64w, const IMAGEHLP_LINE64* l64)
+static BOOL copy_line_W64_from_64(struct process* pcs, IMAGEHLP_LINEW64* l64w, const IMAGEHLP_LINE64* l64)
{
- unsigned len;
+ char* incoming = l64->FileName;
+ unsigned len = MultiByteToWideChar(CP_ACP, 0, l64->FileName, -1, NULL, 0);
+
+ /* detect when l64->FileName has been allocated by fetch_buffer()
+ * and make a copy before calling fetch_buffer() again
+ */
+ if (incoming >= (char*)pcs->buffer && incoming < (char*)pcs->buffer + pcs->buffer_size)
+ {
+ DWORD sz = strlen(incoming) + 1;
+ char* new = HeapAlloc(GetProcessHeap(), 0, sz);
+ if (!new)
+ return FALSE;
+ incoming = memcpy(new, incoming, sz);
+ }
l64w->Key = l64->Key;
l64w->LineNumber = l64->LineNumber;
- len = MultiByteToWideChar(CP_ACP, 0, l64->FileName, -1, NULL, 0);
- if ((l64w->FileName = fetch_buffer(pcs, len * sizeof(WCHAR))))
- MultiByteToWideChar(CP_ACP, 0, l64->FileName, -1, l64w->FileName, len);
l64w->Address = l64->Address;
+ if (!(l64w->FileName = fetch_buffer(pcs, len * sizeof(WCHAR))))
+ return FALSE;
+ MultiByteToWideChar(CP_ACP, 0, incoming, -1, l64w->FileName, len);
+ if (incoming != l64->FileName) HeapFree(GetProcessHeap(), 0, incoming);
+ return TRUE;
}
/******************************************************************
@@ -1671,8 +1691,7 @@ BOOL WINAPI SymGetLineFromAddrW64(HANDLE hProcess, DWORD64 dwAddr,
il64.SizeOfStruct = sizeof(il64);
if (!SymGetLineFromAddr64(hProcess, dwAddr, pdwDisplacement, &il64))
return FALSE;
- copy_line_W64_from_64(process_find_by_handle(hProcess), Line, &il64);
- return TRUE;
+ return copy_line_W64_from_64(process_find_by_handle(hProcess), Line, &il64);
}
/******************************************************************
1
0
18 Aug '21
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/iphlpapi/Makefile.in | 4 +-
dlls/iphlpapi/ifenum.c | 395 ----------------------------------
dlls/iphlpapi/ifenum.h | 66 ------
dlls/iphlpapi/iphlpapi_main.c | 48 ++++-
dlls/iphlpapi/ipstats.c | 370 -------------------------------
dlls/nsi/tests/nsi.c | 1 -
6 files changed, 48 insertions(+), 836 deletions(-)
delete mode 100644 dlls/iphlpapi/ifenum.c
delete mode 100644 dlls/iphlpapi/ifenum.h
delete mode 100644 dlls/iphlpapi/ipstats.c
diff --git a/dlls/iphlpapi/Makefile.in b/dlls/iphlpapi/Makefile.in
index 3797ac793e6..326cf8bf75e 100644
--- a/dlls/iphlpapi/Makefile.in
+++ b/dlls/iphlpapi/Makefile.in
@@ -5,8 +5,6 @@ EXTRALIBS = $(KSTAT_LIBS) $(PROCSTAT_LIBS)
C_SRCS = \
icmp.c \
- ifenum.c \
- iphlpapi_main.c \
- ipstats.c
+ iphlpapi_main.c
RC_SRCS = version.rc
diff --git a/dlls/iphlpapi/ifenum.c b/dlls/iphlpapi/ifenum.c
deleted file mode 100644
index 0264f621b1f..00000000000
--- a/dlls/iphlpapi/ifenum.c
+++ /dev/null
@@ -1,395 +0,0 @@
-/* Copyright (C) 2003,2006,2011 Juan Lang
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#include "config.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include <sys/types.h>
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
-#ifdef HAVE_NET_IF_H
-#include <net/if.h>
-#endif
-
-#ifdef HAVE_NET_IF_ARP_H
-#include <net/if_arp.h>
-#endif
-
-#ifdef HAVE_NET_ROUTE_H
-#include <net/route.h>
-#endif
-
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-
-#ifdef HAVE_SYS_SYSCTL_H
-#include <sys/sysctl.h>
-#endif
-
-#ifdef HAVE_SYS_SOCKIO_H
-#include <sys/sockio.h>
-#endif
-
-#ifdef HAVE_NET_IF_DL_H
-#include <net/if_dl.h>
-#endif
-
-#ifdef HAVE_NET_IF_TYPES_H
-#include <net/if_types.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
-#ifdef HAVE_IFADDRS_H
-#include <ifaddrs.h>
-#endif
-
-#ifdef HAVE_LINUX_RTNETLINK_H
-#include <linux/rtnetlink.h>
-#endif
-
-#include "ifenum.h"
-#include "ws2ipdef.h"
-
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
-#define ifreq_len(ifr) \
- max(sizeof(struct ifreq), sizeof((ifr)->ifr_name)+(ifr)->ifr_addr.sa_len)
-#else
-#define ifreq_len(ifr) sizeof(struct ifreq)
-#endif
-
-#ifndef ETH_ALEN
-#define ETH_ALEN 6
-#endif
-
-#ifndef IF_NAMESIZE
-#define IF_NAMESIZE 16
-#endif
-
-#ifndef INADDR_NONE
-#define INADDR_NONE (~0U)
-#endif
-
-#define INITIAL_INTERFACES_ASSUMED 4
-
-/* Functions */
-
-static BOOL isLoopbackInterface(int fd, const char *name)
-{
- BOOL ret = FALSE;
-
- if (name) {
- struct ifreq ifr;
-
- lstrcpynA(ifr.ifr_name, name, IFNAMSIZ);
- if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0)
- ret = ifr.ifr_flags & IFF_LOOPBACK;
- }
- return !!ret;
-}
-
-/* The comments say MAX_ADAPTER_NAME is required, but really only IF_NAMESIZE
- * bytes are necessary.
- */
-static char *getInterfaceNameByIndex(IF_INDEX index, char *name)
-{
- return if_indextoname(index, name);
-}
-
-DWORD getInterfaceIndexByName(const char *name, IF_INDEX *index)
-{
- DWORD ret;
- unsigned int idx;
-
- if (!name)
- return ERROR_INVALID_PARAMETER;
- if (!index)
- return ERROR_INVALID_PARAMETER;
- idx = if_nametoindex(name);
- if (idx) {
- *index = idx;
- ret = NO_ERROR;
- }
- else
- ret = ERROR_INVALID_DATA;
- return ret;
-}
-
-static BOOL isIfIndexLoopback(ULONG idx)
-{
- BOOL ret = FALSE;
- char name[IFNAMSIZ];
- int fd;
-
- getInterfaceNameByIndex(idx, name);
- fd = socket(PF_INET, SOCK_DGRAM, 0);
- if (fd != -1) {
- ret = isLoopbackInterface(fd, name);
- close(fd);
- }
- return ret;
-}
-
-#ifdef HAVE_IF_NAMEINDEX
-DWORD get_interface_indices( BOOL skip_loopback, InterfaceIndexTable **table )
-{
- DWORD count = 0, i;
- struct if_nameindex *p, *indices = if_nameindex();
- InterfaceIndexTable *ret;
-
- if (table) *table = NULL;
- if (!indices) return 0;
-
- for (p = indices; p->if_name; p++)
- {
- if (skip_loopback && isIfIndexLoopback( p->if_index )) continue;
- count++;
- }
-
- if (table)
- {
- ret = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET(InterfaceIndexTable, indexes[count]) );
- if (!ret)
- {
- count = 0;
- goto end;
- }
- for (p = indices, i = 0; p->if_name && i < count; p++)
- {
- if (skip_loopback && isIfIndexLoopback( p->if_index )) continue;
- ret->indexes[i++] = p->if_index;
- }
- ret->numIndexes = count = i;
- *table = ret;
- }
-
-end:
- if_freenameindex( indices );
- return count;
-}
-
-#elif defined(HAVE_LINUX_RTNETLINK_H)
-static int open_netlink( int *pid )
-{
- int fd = socket( AF_NETLINK, SOCK_RAW, NETLINK_ROUTE );
- struct sockaddr_nl addr;
- socklen_t len;
-
- if (fd < 0) return fd;
-
- memset( &addr, 0, sizeof(addr) );
- addr.nl_family = AF_NETLINK;
-
- if (bind( fd, (struct sockaddr *)&addr, sizeof(addr) ) < 0)
- goto fail;
-
- len = sizeof(addr);
- if (getsockname( fd, (struct sockaddr *)&addr, &len ) < 0)
- goto fail;
-
- *pid = addr.nl_pid;
- return fd;
-fail:
- close( fd );
- return -1;
-}
-
-static int send_netlink_req( int fd, int pid, int type, int *seq_no )
-{
- static LONG seq;
- struct request
- {
- struct nlmsghdr hdr;
- struct rtgenmsg gen;
- } req;
- struct sockaddr_nl addr;
-
- req.hdr.nlmsg_len = sizeof(req);
- req.hdr.nlmsg_type = type;
- req.hdr.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
- req.hdr.nlmsg_pid = pid;
- req.hdr.nlmsg_seq = InterlockedIncrement( &seq );
- req.gen.rtgen_family = AF_UNSPEC;
-
- memset( &addr, 0, sizeof(addr) );
- addr.nl_family = AF_NETLINK;
- if (sendto( fd, &req, sizeof(req), 0, (struct sockaddr *)&addr, sizeof(addr) ) != sizeof(req))
- return -1;
- *seq_no = req.hdr.nlmsg_seq;
- return 0;
-}
-
-struct netlink_reply
-{
- struct netlink_reply *next;
- int size;
- struct nlmsghdr *hdr;
-};
-
-static void free_netlink_reply( struct netlink_reply *data )
-{
- struct netlink_reply *ptr;
- while( data )
- {
- ptr = data->next;
- HeapFree( GetProcessHeap(), 0, data );
- data = ptr;
- }
-}
-
-static int recv_netlink_reply( int fd, int pid, int seq, struct netlink_reply **data )
-{
- int bufsize = getpagesize();
- int left, read;
- BOOL done = FALSE;
- socklen_t sa_len;
- struct sockaddr_nl addr;
- struct netlink_reply *cur, *last = NULL;
- struct nlmsghdr *hdr;
- char *buf;
-
- *data = NULL;
- buf = HeapAlloc( GetProcessHeap(), 0, bufsize );
- if (!buf) return -1;
-
- do
- {
- left = read = recvfrom( fd, buf, bufsize, 0, (struct sockaddr *)&addr, &sa_len );
- if (read < 0) goto fail;
- if (addr.nl_pid != 0) continue; /* not from kernel */
-
- for (hdr = (struct nlmsghdr *)buf; NLMSG_OK(hdr, left); hdr = NLMSG_NEXT(hdr, left))
- {
- if (hdr->nlmsg_pid != pid || hdr->nlmsg_seq != seq) continue;
- if (hdr->nlmsg_type == NLMSG_DONE)
- {
- done = TRUE;
- break;
- }
- }
-
- cur = HeapAlloc( GetProcessHeap(), 0, sizeof(*cur) + read );
- if (!cur) goto fail;
- cur->next = NULL;
- cur->size = read;
- cur->hdr = (struct nlmsghdr *)(cur + 1);
- memcpy( cur->hdr, buf, read );
- if (last) last->next = cur;
- else *data = cur;
- last = cur;
- } while (!done);
-
- HeapFree( GetProcessHeap(), 0, buf );
- return 0;
-
-fail:
- free_netlink_reply( *data );
- HeapFree( GetProcessHeap(), 0, buf );
- return -1;
-}
-
-
-static DWORD get_indices_from_reply( struct netlink_reply *reply, int pid, int seq,
- BOOL skip_loopback, InterfaceIndexTable *table )
-{
- struct nlmsghdr *hdr;
- struct netlink_reply *r;
- int count = 0;
-
- for (r = reply; r; r = r->next)
- {
- int size = r->size;
- for (hdr = r->hdr; NLMSG_OK(hdr, size); hdr = NLMSG_NEXT(hdr, size))
- {
- if (hdr->nlmsg_pid != pid || hdr->nlmsg_seq != seq) continue;
- if (hdr->nlmsg_type == NLMSG_DONE) break;
-
- if (hdr->nlmsg_type == RTM_NEWLINK)
- {
- struct ifinfomsg *info = NLMSG_DATA(hdr);
-
- if (skip_loopback && (info->ifi_flags & IFF_LOOPBACK)) continue;
- if (table) table->indexes[count] = info->ifi_index;
- count++;
- }
- }
- }
- return count;
-}
-
-DWORD get_interface_indices( BOOL skip_loopback, InterfaceIndexTable **table )
-{
- int fd, pid, seq;
- struct netlink_reply *reply = NULL;
- DWORD count = 0;
-
- if (table) *table = NULL;
- fd = open_netlink( &pid );
- if (fd < 0) return 0;
-
- if (send_netlink_req( fd, pid, RTM_GETLINK, &seq ) < 0)
- goto end;
-
- if (recv_netlink_reply( fd, pid, seq, &reply ) < 0)
- goto end;
-
- count = get_indices_from_reply( reply, pid, seq, skip_loopback, NULL );
-
- if (table)
- {
- InterfaceIndexTable *ret = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET(InterfaceIndexTable, indexes[count]) );
- if (!ret)
- {
- count = 0;
- goto end;
- }
-
- ret->numIndexes = count;
- get_indices_from_reply( reply, pid, seq, skip_loopback, ret );
- *table = ret;
- }
-
-end:
- free_netlink_reply( reply );
- close( fd );
- return count;
-}
-
-#else
-DWORD get_interface_indices( BOOL skip_loopback, InterfaceIndexTable **table )
-{
- if (table) *table = NULL;
- return 0;
-}
-#endif
diff --git a/dlls/iphlpapi/ifenum.h b/dlls/iphlpapi/ifenum.h
deleted file mode 100644
index 710b493ad36..00000000000
--- a/dlls/iphlpapi/ifenum.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* ifenum.h
- * Copyright (C) 2003,2006 Juan Lang
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- *
- * This module implements network interface and address enumeration. It's
- * meant to hide some problematic defines like socket(), and make iphlpapi
- * more portable.
- *
- * Like Windows, it uses a numeric index to identify an interface uniquely.
- * As implemented, an interface represents a UNIX network interface, virtual
- * or real, and thus can have 0 or 1 IP addresses associated with it. (This
- * only supports IPv4.)
- * The indexes returned are not guaranteed to be contiguous, so don't call
- * getNumInterfaces() and assume the values [0,getNumInterfaces() - 1] will be
- * valid indexes; use getInterfaceIndexTable() instead.
- *
- * See also the companion file, ipstats.h, for functions related to getting
- * statistics.
- */
-#ifndef WINE_IFENUM_H_
-#define WINE_IFENUM_H_
-
-#include <stdarg.h>
-
-#include "windef.h"
-#include "winbase.h"
-#define USE_WS_PREFIX
-#include "iprtrmib.h"
-#include "winsock2.h"
-
-#define MAX_INTERFACE_PHYSADDR 8
-#define MAX_INTERFACE_DESCRIPTION 256
-
-/* A table of interface indexes, see get_interface_indices(). */
-typedef struct _InterfaceIndexTable {
- DWORD numIndexes;
- IF_INDEX indexes[1];
-} InterfaceIndexTable;
-
-/* Returns the count of all interface indexes and optionally a ptr to an interface table.
- * HeapFree() the returned table. Will optionally ignore loopback devices.
- */
-DWORD get_interface_indices( BOOL skip_loopback, InterfaceIndexTable **table ) DECLSPEC_HIDDEN;
-
-/* ByName/ByIndex versions of various getter functions. */
-
-/* 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;
-
-#endif /* ndef WINE_IFENUM_H_ */
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index 82c63b0dfce..8a8b6b3e7cf 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -42,7 +42,6 @@
#include "ws2ipdef.h"
#include "windns.h"
#include "iphlpapi.h"
-#include "ifenum.h"
#include "ipifcons.h"
#include "fltdefs.h"
#include "ifdef.h"
@@ -3282,6 +3281,53 @@ DWORD WINAPI AllocateAndGetTcpExTableFromStack( void **table, BOOL sort, HANDLE
return allocate_tcp_table( table, sort, heap, flags, family, TCP_TABLE_OWNER_PID_ALL );
}
+/******************************************************************
+ * GetUdpStatistics (IPHLPAPI.@)
+ *
+ * Get the UDP statistics for the local computer.
+ *
+ * PARAMS
+ * stats [Out] buffer for UDP statistics
+ */
+DWORD WINAPI GetUdpStatistics( MIB_UDPSTATS *stats )
+{
+ return GetUdpStatisticsEx( stats, WS_AF_INET );
+}
+
+/******************************************************************
+ * GetUdpStatisticsEx (IPHLPAPI.@)
+ *
+ * Get the IPv4 and IPv6 UDP statistics for the local computer.
+ *
+ * PARAMS
+ * stats [Out] buffer for UDP statistics
+ * family [In] specifies whether IPv4 or IPv6 statistics are returned
+ *
+ * RETURNS
+ * Success: NO_ERROR
+ * Failure: error code from winerror.h
+ */
+DWORD WINAPI GetUdpStatisticsEx( MIB_UDPSTATS *stats, DWORD family )
+{
+ struct nsi_udp_stats_dynamic dyn;
+ USHORT key = (USHORT)family;
+ DWORD err;
+
+ if (!stats || !ip_module_id( family )) return ERROR_INVALID_PARAMETER;
+ memset( stats, 0, sizeof(*stats) );
+
+ err = NsiGetAllParameters( 1, &NPI_MS_UDP_MODULEID, NSI_UDP_STATS_TABLE, &key, sizeof(key), NULL, 0,
+ &dyn, sizeof(dyn), NULL, 0 );
+ if (err) return err;
+
+ stats->dwInDatagrams = dyn.in_dgrams;
+ stats->dwNoPorts = dyn.no_ports;
+ stats->dwInErrors = dyn.in_errs;
+ stats->dwOutDatagrams = dyn.out_dgrams;
+ stats->dwNumAddrs = dyn.num_addrs;
+ return err;
+}
+
/******************************************************************
* GetUdpTable (IPHLPAPI.@)
*
diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c
deleted file mode 100644
index 1a71396e388..00000000000
--- a/dlls/iphlpapi/ipstats.c
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright (C) 2003,2006 Juan Lang
- * Copyright (C) 2007 TransGaming Technologies Inc.
- * Copyright (C) 2009 Alexandre Julliard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#include "config.h"
-#include "wine/port.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#ifdef HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-#ifdef HAVE_ALIAS_H
-#include <alias.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef HAVE_SYS_SOCKETVAR_H
-#include <sys/socketvar.h>
-#endif
-#ifdef HAVE_SYS_TIMEOUT_H
-#include <sys/timeout.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_NETINET_IN_SYSTM_H
-#include <netinet/in_systm.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#ifdef HAVE_NET_IF_H
-#include <net/if.h>
-#endif
-#ifdef HAVE_NET_IF_DL_H
-#include <net/if_dl.h>
-#endif
-#ifdef HAVE_NET_IF_TYPES_H
-#include <net/if_types.h>
-#endif
-#ifdef HAVE_NET_ROUTE_H
-#include <net/route.h>
-#endif
-#ifdef HAVE_NET_IF_ARP_H
-#include <net/if_arp.h>
-#endif
-#ifdef HAVE_NETINET_IF_ETHER_H
-#include <netinet/if_ether.h>
-#endif
-#ifdef HAVE_NETINET_IF_INARP_H
-#include <netinet/if_inarp.h>
-#endif
-#ifdef HAVE_NETINET_IP_H
-#include <netinet/ip.h>
-#endif
-#ifdef HAVE_NETINET_TCP_H
-#include <netinet/tcp.h>
-#endif
-#ifdef HAVE_NETINET_IP_VAR_H
-#include <netinet/ip_var.h>
-#endif
-#ifdef HAVE_NETINET_TCP_FSM_H
-#include <netinet/tcp_fsm.h>
-#endif
-#ifdef HAVE_NETINET_IN_PCB_H
-#include <netinet/in_pcb.h>
-#endif
-#ifdef HAVE_NETINET_TCP_TIMER_H
-#include <netinet/tcp_timer.h>
-#endif
-#ifdef HAVE_NETINET_TCP_VAR_H
-#include <netinet/tcp_var.h>
-#endif
-#ifdef HAVE_NETINET_IP_ICMP_H
-#include <netinet/ip_icmp.h>
-#endif
-#ifdef HAVE_NETINET_ICMP_VAR_H
-#include <netinet/icmp_var.h>
-#endif
-#ifdef HAVE_NETINET_UDP_H
-#include <netinet/udp.h>
-#endif
-#ifdef HAVE_NETINET_UDP_VAR_H
-#include <netinet/udp_var.h>
-#endif
-#ifdef HAVE_SYS_PROTOSW_H
-#include <sys/protosw.h>
-#endif
-#ifdef HAVE_SYS_SYSCTL_H
-#include <sys/sysctl.h>
-#endif
-#ifdef HAVE_KSTAT_H
-#include <kstat.h>
-#endif
-#ifdef HAVE_INET_MIB2_H
-#include <inet/mib2.h>
-#endif
-#ifdef HAVE_STROPTS_H
-#include <stropts.h>
-#endif
-#ifdef HAVE_SYS_TIHDR_H
-#include <sys/tihdr.h>
-#endif
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#ifdef HAVE_SYS_QUEUE_H
-#include <sys/queue.h>
-#endif
-#ifdef HAVE_SYS_USER_H
-/* Make sure the definitions of struct kinfo_proc are the same. */
-#include <sys/user.h>
-#endif
-#ifdef HAVE_LIBPROCSTAT_H
-#include <libprocstat.h>
-#endif
-#ifdef HAVE_LIBPROC_H
-#include <libproc.h>
-#endif
-#ifdef HAVE_IFADDRS_H
-#include <ifaddrs.h>
-#endif
-
-#ifndef ROUNDUP
-#define ROUNDUP(a) \
- ((a) > 0 ? (1 + (((a) - 1) | (sizeof(int) - 1))) : sizeof(int))
-#endif
-#ifndef ADVANCE
-#define ADVANCE(x, n) (x += ROUNDUP(((struct sockaddr *)n)->sa_len))
-#endif
-
-#include "ntstatus.h"
-#define WIN32_NO_STATUS
-#define NONAMELESSUNION
-#define USE_WS_PREFIX
-#include "winsock2.h"
-#include "ws2ipdef.h"
-#include "ifenum.h"
-#include "iphlpapi.h"
-
-#include "wine/debug.h"
-#include "wine/server.h"
-#include "wine/unicode.h"
-
-#ifndef HAVE_NETINET_TCP_FSM_H
-#define TCPS_ESTABLISHED 1
-#define TCPS_SYN_SENT 2
-#define TCPS_SYN_RECEIVED 3
-#define TCPS_FIN_WAIT_1 4
-#define TCPS_FIN_WAIT_2 5
-#define TCPS_TIME_WAIT 6
-#define TCPS_CLOSED 7
-#define TCPS_CLOSE_WAIT 8
-#define TCPS_LAST_ACK 9
-#define TCPS_LISTEN 10
-#define TCPS_CLOSING 11
-#endif
-
-#ifndef RTF_MULTICAST
-#define RTF_MULTICAST 0 /* Not available on NetBSD/OpenBSD */
-#endif
-
-#ifndef RTF_LLINFO
-#define RTF_LLINFO 0 /* Not available on FreeBSD 8 and above */
-#endif
-
-WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
-
-#ifdef HAVE_LIBKSTAT
-static DWORD kstat_get_ui32( kstat_t *ksp, const char *name )
-{
- unsigned int i;
- kstat_named_t *data = ksp->ks_data;
-
- for (i = 0; i < ksp->ks_ndata; i++)
- if (!strcmp( data[i].name, name )) return data[i].value.ui32;
- return 0;
-}
-#endif
-
-/******************************************************************
- * GetUdpStatistics (IPHLPAPI.@)
- *
- * Get the IPv4 and IPv6 UDP statistics for the local computer.
- *
- * PARAMS
- * stats [Out] buffer for UDP statistics
- * family [In] specifies whether IPv4 or IPv6 statistics are returned
- *
- * RETURNS
- * Success: NO_ERROR
- * Failure: error code from winerror.h
- */
-DWORD WINAPI GetUdpStatisticsEx(PMIB_UDPSTATS stats, DWORD family)
-{
- DWORD ret = ERROR_NOT_SUPPORTED;
-
- if (!stats) return ERROR_INVALID_PARAMETER;
- if (family != WS_AF_INET && family != WS_AF_INET6) return ERROR_INVALID_PARAMETER;
- memset( stats, 0, sizeof(*stats) );
-
- stats->dwNumAddrs = get_interface_indices( FALSE, NULL );
-
- if (family == WS_AF_INET6)
- {
-#ifdef __linux__
- {
- FILE *fp;
-
- if ((fp = fopen("/proc/net/snmp6", "r")))
- {
- struct {
- const char *name;
- DWORD *elem;
- } udpstatlist[] = {
- { "Udp6InDatagrams", &stats->dwInDatagrams },
- { "Udp6NoPorts", &stats->dwNoPorts },
- { "Udp6InErrors", &stats->dwInErrors },
- { "Udp6OutDatagrams", &stats->dwOutDatagrams },
- };
- char buf[512], *ptr, *value;
- DWORD res, i;
-
- while ((ptr = fgets(buf, sizeof(buf), fp)))
- {
- if (!(value = strchr(buf, ' ')))
- continue;
-
- /* terminate the valuename */
- ptr = value - 1;
- *(ptr + 1) = '\0';
-
- /* and strip leading spaces from value */
- value += 1;
- while (*value==' ') value++;
- if ((ptr = strchr(value, '\n')))
- *ptr='\0';
-
- for (i = 0; i < ARRAY_SIZE(udpstatlist); i++)
- if (!_strnicmp(buf, udpstatlist[i].name, -1) && sscanf(value, "%d", &res))
- *udpstatlist[i].elem = res;
- }
- fclose(fp);
- ret = NO_ERROR;
- }
- }
-#else
- FIXME( "unimplemented for IPv6\n" );
-#endif
- return ret;
- }
-
-#ifdef __linux__
- {
- FILE *fp;
-
- if ((fp = fopen("/proc/net/snmp", "r")))
- {
- static const char hdr[] = "Udp:";
- char buf[512], *ptr;
-
- while ((ptr = fgets(buf, sizeof(buf), fp)))
- {
- if (_strnicmp(buf, hdr, sizeof(hdr) - 1)) continue;
- /* last line was a header, get another */
- if (!(ptr = fgets(buf, sizeof(buf), fp))) break;
- if (!_strnicmp(buf, hdr, sizeof(hdr) - 1))
- {
- ptr += sizeof(hdr);
- sscanf( ptr, "%u %u %u %u %u",
- &stats->dwInDatagrams, &stats->dwNoPorts,
- &stats->dwInErrors, &stats->dwOutDatagrams, &stats->dwNumAddrs );
- break;
- }
- }
- fclose(fp);
- ret = NO_ERROR;
- }
- }
-#elif defined(HAVE_LIBKSTAT)
- {
- static char udp[] = "udp";
- kstat_ctl_t *kc;
- kstat_t *ksp;
- MIB_UDPTABLE *udp_table;
-
- if ((kc = kstat_open()) &&
- (ksp = kstat_lookup( kc, udp, 0, udp )) &&
- kstat_read( kc, ksp, NULL ) != -1 &&
- ksp->ks_type == KSTAT_TYPE_NAMED)
- {
- stats->dwInDatagrams = kstat_get_ui32( ksp, "inDatagrams" );
- stats->dwNoPorts = 0; /* FIXME */
- stats->dwInErrors = kstat_get_ui32( ksp, "inErrors" );
- stats->dwOutDatagrams = kstat_get_ui32( ksp, "outDatagrams" );
- if (!AllocateAndGetUdpTableFromStack( &udp_table, FALSE, GetProcessHeap(), 0 ))
- {
- stats->dwNumAddrs = udp_table->dwNumEntries;
- HeapFree( GetProcessHeap(), 0, udp_table );
- }
- ret = NO_ERROR;
- }
- if (kc) kstat_close( kc );
- }
-#elif defined(HAVE_SYS_SYSCTL_H) && defined(UDPCTL_STATS) && defined(HAVE_STRUCT_UDPSTAT_UDPS_IPACKETS)
- {
- int mib[] = {CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_STATS};
- struct udpstat udp_stat;
- MIB_UDPTABLE *udp_table;
- size_t needed = sizeof(udp_stat);
-
- if(sysctl(mib, ARRAY_SIZE(mib), &udp_stat, &needed, NULL, 0) != -1)
- {
- stats->dwInDatagrams = udp_stat.udps_ipackets;
- stats->dwOutDatagrams = udp_stat.udps_opackets;
- stats->dwNoPorts = udp_stat.udps_noport;
- stats->dwInErrors = udp_stat.udps_hdrops + udp_stat.udps_badsum + udp_stat.udps_fullsock + udp_stat.udps_badlen;
- if (!AllocateAndGetUdpTableFromStack( &udp_table, FALSE, GetProcessHeap(), 0 ))
- {
- stats->dwNumAddrs = udp_table->dwNumEntries;
- HeapFree( GetProcessHeap(), 0, udp_table );
- }
- ret = NO_ERROR;
- }
- else ERR ("failed to get udpstat\n");
- }
-#else
- FIXME( "unimplemented for IPv4\n" );
-#endif
- return ret;
-}
-
-/******************************************************************
- * GetUdpStatistics (IPHLPAPI.@)
- *
- * Get the UDP statistics for the local computer.
- *
- * PARAMS
- * stats [Out] buffer for UDP statistics
- *
- * RETURNS
- * Success: NO_ERROR
- * Failure: error code from winerror.h
- */
-DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS stats)
-{
- return GetUdpStatisticsEx(stats, WS_AF_INET);
-}
diff --git a/dlls/nsi/tests/nsi.c b/dlls/nsi/tests/nsi.c
index bd7992f6916..f1f3c4f387f 100644
--- a/dlls/nsi/tests/nsi.c
+++ b/dlls/nsi/tests/nsi.c
@@ -966,7 +966,6 @@ static void test_udp_stats( int family )
table.dwInErrors, dyn.in_errs, dyn2.in_errs );
ok( bounded( table.dwOutDatagrams, dyn.out_dgrams, dyn2.out_dgrams ), "%d vs [%I64d %I64d]\n",
table.dwOutDatagrams, dyn.out_dgrams, dyn2.out_dgrams );
-todo_wine_if(!unstable(0) && table.dwNumAddrs != dyn.num_addrs)
ok( unstable( table.dwNumAddrs == dyn.num_addrs ), "%d %d\n", table.dwNumAddrs, dyn.num_addrs );
winetest_pop_context();
--
2.23.0
1
0
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/nsi/tests/nsi.c | 36 +++++++++++
dlls/nsiproxy.sys/udp.c | 128 ++++++++++++++++++++++++++++++++++++++++
include/wine/nsi.h | 11 ++++
3 files changed, 175 insertions(+)
diff --git a/dlls/nsi/tests/nsi.c b/dlls/nsi/tests/nsi.c
index ce09bbf8a22..bd7992f6916 100644
--- a/dlls/nsi/tests/nsi.c
+++ b/dlls/nsi/tests/nsi.c
@@ -938,6 +938,40 @@ static void test_tcp_tables( int family, int table_type )
winetest_pop_context();
}
+static void test_udp_stats( int family )
+{
+ DWORD err;
+ USHORT key = family;
+ struct nsi_udp_stats_dynamic dyn, dyn2;
+ MIB_UDPSTATS table;
+
+ winetest_push_context( family == AF_INET ? "AF_INET" : "AF_INET6" );
+
+ err = NsiGetAllParameters( 1, &NPI_MS_UDP_MODULEID, NSI_UDP_STATS_TABLE, &key, sizeof(key), NULL, 0,
+ &dyn, sizeof(dyn), NULL, 0 );
+ ok( !err, "got %x\n", err );
+
+ err = GetUdpStatisticsEx( &table, family );
+ ok( !err, "got %d\n", err );
+
+ err = NsiGetAllParameters( 1, &NPI_MS_UDP_MODULEID, NSI_UDP_STATS_TABLE, &key, sizeof(key), NULL, 0,
+ &dyn2, sizeof(dyn2), NULL, 0 );
+ ok( !err, "got %x\n", err );
+
+ ok( bounded( table.dwInDatagrams, dyn.in_dgrams, dyn2.in_dgrams ), "%d vs [%I64d %I64d]\n",
+ table.dwInDatagrams, dyn.in_dgrams, dyn2.in_dgrams );
+ ok( bounded( table.dwNoPorts, dyn.no_ports, dyn2.no_ports ), "%d vs [%d %d]\n",
+ table.dwNoPorts, dyn.no_ports, dyn2.no_ports);
+ ok( bounded( table.dwInErrors, dyn.in_errs, dyn2.in_errs ), "%d vs [%d %d]\n",
+ table.dwInErrors, dyn.in_errs, dyn2.in_errs );
+ ok( bounded( table.dwOutDatagrams, dyn.out_dgrams, dyn2.out_dgrams ), "%d vs [%I64d %I64d]\n",
+ table.dwOutDatagrams, dyn.out_dgrams, dyn2.out_dgrams );
+todo_wine_if(!unstable(0) && table.dwNumAddrs != dyn.num_addrs)
+ ok( unstable( table.dwNumAddrs == dyn.num_addrs ), "%d %d\n", table.dwNumAddrs, dyn.num_addrs );
+
+ winetest_pop_context();
+}
+
static void test_udp_tables( int family )
{
DWORD i, err, count, size;
@@ -1030,6 +1064,8 @@ START_TEST( nsi )
test_tcp_tables( AF_INET6, TCP_TABLE_OWNER_MODULE_CONNECTIONS );
test_tcp_tables( AF_INET6, TCP_TABLE_OWNER_MODULE_LISTENER );
+ test_udp_stats( AF_INET );
+ test_udp_stats( AF_INET6 );
test_udp_tables( AF_INET );
test_udp_tables( AF_INET6 );
}
diff --git a/dlls/nsiproxy.sys/udp.c b/dlls/nsiproxy.sys/udp.c
index 454aefe95aa..49acedcf214 100644
--- a/dlls/nsiproxy.sys/udp.c
+++ b/dlls/nsiproxy.sys/udp.c
@@ -73,6 +73,125 @@
WINE_DEFAULT_DEBUG_CHANNEL(nsi);
+static DWORD udp_num_addrs( USHORT family )
+{
+ DWORD endpoint_count = 0;
+
+ nsi_enumerate_all( 1, 0, &NPI_MS_UDP_MODULEID, NSI_UDP_ENDPOINT_TABLE,
+ NULL, 0, NULL, 0, NULL, 0, NULL, 0, &endpoint_count );
+ /* FIXME: actually retrieve the keys and only count endpoints which match family */
+ return endpoint_count;
+}
+
+static NTSTATUS udp_stats_get_all_parameters( const void *key, DWORD key_size, void *rw_data, DWORD rw_size,
+ void *dynamic_data, DWORD dynamic_size, void *static_data, DWORD static_size )
+{
+ struct nsi_udp_stats_dynamic dyn;
+ const USHORT *family = key;
+
+ TRACE( "%p %d %p %d %p %d %p %d\n", key, key_size, rw_data, rw_size, dynamic_data, dynamic_size,
+ static_data, static_size );
+
+ if (*family != WS_AF_INET && *family != WS_AF_INET6) return STATUS_NOT_SUPPORTED;
+
+ memset( &dyn, 0, sizeof(dyn) );
+
+ dyn.num_addrs = udp_num_addrs( *family );
+
+#ifdef __linux__
+ if (*family == WS_AF_INET)
+ {
+ NTSTATUS status = STATUS_NOT_SUPPORTED;
+ static const char hdr[] = "Udp:";
+ char buf[512], *ptr;
+ FILE *fp;
+
+ if (!(fp = fopen( "/proc/net/snmp", "r" ))) return STATUS_NOT_SUPPORTED;
+
+ while ((ptr = fgets( buf, sizeof(buf), fp )))
+ {
+ if (_strnicmp( buf, hdr, sizeof(hdr) - 1) ) continue;
+ /* last line was a header, get another */
+ if (!(ptr = fgets( buf, sizeof(buf), fp ))) break;
+ if (!_strnicmp(buf, hdr, sizeof(hdr) - 1))
+ {
+ unsigned int in_dgrams, out_dgrams;
+ ptr += sizeof(hdr);
+ sscanf( ptr, "%u %u %u %u %u",
+ &in_dgrams, &dyn.no_ports, &dyn.in_errs, &out_dgrams, &dyn.num_addrs );
+ dyn.in_dgrams = in_dgrams;
+ dyn.out_dgrams = out_dgrams;
+ if (dynamic_data) *(struct nsi_udp_stats_dynamic *)dynamic_data = dyn;
+ status = STATUS_SUCCESS;
+ break;
+ }
+ }
+ fclose( fp );
+ return status;
+ }
+ else
+ {
+ unsigned int in_dgrams = 0, out_dgrams = 0;
+ struct
+ {
+ const char *name;
+ DWORD *elem;
+ } udp_stat_list[] =
+ {
+ { "Udp6InDatagrams", &in_dgrams },
+ { "Udp6NoPorts", &dyn.no_ports },
+ { "Udp6InErrors", &dyn.in_errs },
+ { "Udp6OutDatagrams", &out_dgrams },
+ };
+ char buf[512], *ptr, *value;
+ DWORD res, i;
+ FILE *fp;
+
+ if (!(fp = fopen( "/proc/net/snmp6", "r" ))) return STATUS_NOT_SUPPORTED;
+
+ while ((ptr = fgets( buf, sizeof(buf), fp )))
+ {
+ if (!(value = strchr( buf, ' ' ))) continue;
+
+ /* terminate the valuename */
+ ptr = value - 1;
+ *(ptr + 1) = '\0';
+
+ /* and strip leading spaces from value */
+ value += 1;
+ while (*value==' ') value++;
+ if ((ptr = strchr( value, '\n' ))) *ptr='\0';
+
+ for (i = 0; i < ARRAY_SIZE(udp_stat_list); i++)
+ if (!_strnicmp( buf, udp_stat_list[i].name, -1 ) && sscanf( value, "%d", &res ))
+ *udp_stat_list[i].elem = res;
+ }
+ dyn.in_dgrams = in_dgrams;
+ dyn.out_dgrams = out_dgrams;
+ if (dynamic_data) *(struct nsi_udp_stats_dynamic *)dynamic_data = dyn;
+ fclose( fp );
+ return STATUS_SUCCESS;
+ }
+#elif defined(HAVE_SYS_SYSCTL_H) && defined(UDPCTL_STATS) && defined(HAVE_STRUCT_UDPSTAT_UDPS_IPACKETS)
+ {
+ int mib[] = { CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_STATS };
+ struct udpstat udp_stat;
+ size_t needed = sizeof(udp_stat);
+
+ if (sysctl( mib, ARRAY_SIZE(mib), &udp_stat, &needed, NULL, 0 ) == -1) return STATUS_NOT_SUPPORTED;
+
+ dyn.in_dgrams = udp_stat.udps_ipackets;
+ dyn.out_dgrams = udp_stat.udps_opackets;
+ dyn.no_ports = udp_stat.udps_noport;
+ dyn.in_errs = udp_stat.udps_hdrops + udp_stat.udps_badsum + udp_stat.udps_fullsock + udp_stat.udps_badlen;
+ if (dynamic_data) *(struct nsi_udp_stats_dynamic *)dynamic_data = dyn;
+ return STATUS_SUCCESS;
+ }
+#endif
+ FIXME( "Not implemented\n" );
+ return STATUS_NOT_SUPPORTED;
+}
+
static NTSTATUS udp_endpoint_enumerate_all( void *key_data, DWORD key_size, void *rw_data, DWORD rw_size,
void *dynamic_data, DWORD dynamic_size,
void *static_data, DWORD static_size, DWORD_PTR *count )
@@ -271,6 +390,15 @@ static NTSTATUS udp_endpoint_enumerate_all( void *key_data, DWORD key_size, void
static struct module_table udp_tables[] =
{
+ {
+ NSI_UDP_STATS_TABLE,
+ {
+ sizeof(USHORT), 0,
+ sizeof(struct nsi_udp_stats_dynamic), 0
+ },
+ NULL,
+ udp_stats_get_all_parameters,
+ },
{
NSI_UDP_ENDPOINT_TABLE,
{
diff --git a/include/wine/nsi.h b/include/wine/nsi.h
index 8bf3bc1d5d0..7b8cb29e9d5 100644
--- a/include/wine/nsi.h
+++ b/include/wine/nsi.h
@@ -347,8 +347,19 @@ struct nsi_tcp_conn_static
};
/* Undocumented NSI UDP tables */
+#define NSI_UDP_STATS_TABLE 0
#define NSI_UDP_ENDPOINT_TABLE 1
+struct nsi_udp_stats_dynamic
+{
+ ULONGLONG in_dgrams;
+ DWORD no_ports;
+ DWORD in_errs;
+ ULONGLONG out_dgrams;
+ DWORD num_addrs;
+ DWORD unk[5];
+};
+
struct nsi_udp_endpoint_key
{
SOCKADDR_INET local;
--
2.23.0
1
0
[PATCH 3/5] iphlpapi: Implement AllocateAndGetUdpTableFromStack() on top of nsi.
by Huw Davies 18 Aug '21
by Huw Davies 18 Aug '21
18 Aug '21
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/iphlpapi/iphlpapi_main.c | 21 ++
dlls/iphlpapi/ipstats.c | 524 ----------------------------------
2 files changed, 21 insertions(+), 524 deletions(-)
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index bcda2b81b6e..82c63b0dfce 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -3491,6 +3491,27 @@ DWORD WINAPI GetExtendedUdpTable( void *table, DWORD *size, BOOL sort, ULONG fam
return err;
}
+DWORD WINAPI AllocateAndGetUdpTableFromStack( MIB_UDPTABLE **table, BOOL sort, HANDLE heap, DWORD flags )
+{
+ DWORD err, size = 0x100, attempt;
+
+ TRACE("table %p, sort %d, heap %p, flags 0x%08x\n", table, sort, heap, flags );
+
+ if (!table) return ERROR_INVALID_PARAMETER;
+
+ for (attempt = 0; attempt < 5; attempt++)
+ {
+ *table = HeapAlloc( heap, flags, size );
+ if (!*table) return ERROR_NOT_ENOUGH_MEMORY;
+ err = GetExtendedUdpTable( *table, &size, sort, WS_AF_INET, UDP_TABLE_BASIC, 0 );
+ if (!err) break;
+ HeapFree( heap, flags, *table );
+ *table = NULL;
+ if (err != ERROR_INSUFFICIENT_BUFFER) break;
+ }
+ return err;
+}
+
static void unicast_row_fill( MIB_UNICASTIPADDRESS_ROW *row, USHORT fam, void *key, struct nsi_ip_unicast_rw *rw,
struct nsi_ip_unicast_dynamic *dyn, struct nsi_ip_unicast_static *stat )
{
diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c
index 65bf65fec7b..1a71396e388 100644
--- a/dlls/iphlpapi/ipstats.c
+++ b/dlls/iphlpapi/ipstats.c
@@ -200,81 +200,6 @@ static DWORD kstat_get_ui32( kstat_t *ksp, const char *name )
}
#endif
-#if defined(HAVE_SYS_TIHDR_H) && defined(T_OPTMGMT_ACK)
-static int open_streams_mib( const char *proto )
-{
- int fd;
- struct strbuf buf;
- struct request
- {
- struct T_optmgmt_req req_header;
- struct opthdr opt_header;
- } request;
-
- if ((fd = open( "/dev/arp", O_RDWR )) == -1)
- {
- WARN( "could not open /dev/arp: %s\n", strerror(errno) );
- return -1;
- }
- if (proto) ioctl( fd, I_PUSH, proto );
-
- request.req_header.PRIM_type = T_SVR4_OPTMGMT_REQ;
- request.req_header.OPT_length = sizeof(request.opt_header);
- request.req_header.OPT_offset = FIELD_OFFSET( struct request, opt_header );
- request.req_header.MGMT_flags = T_CURRENT;
- request.opt_header.level = MIB2_IP;
- request.opt_header.name = 0;
- request.opt_header.len = 0;
-
- buf.len = sizeof(request);
- buf.buf = (caddr_t)&request;
- if (putmsg( fd, &buf, NULL, 0 ) == -1)
- {
- WARN( "putmsg: %s\n", strerror(errno) );
- close( fd );
- fd = -1;
- }
- return fd;
-}
-
-static void *read_mib_entry( int fd, int level, int name, int *len )
-{
- struct strbuf buf;
- void *data;
- int ret, flags = 0;
-
- struct reply
- {
- struct T_optmgmt_ack ack_header;
- struct opthdr opt_header;
- } reply;
-
- for (;;)
- {
- buf.maxlen = sizeof(reply);
- buf.buf = (caddr_t)&reply;
- if ((ret = getmsg( fd, &buf, NULL, &flags )) < 0) return NULL;
- if (!(ret & MOREDATA)) return NULL;
- if (reply.ack_header.PRIM_type != T_OPTMGMT_ACK) return NULL;
- if (buf.len < sizeof(reply.ack_header)) return NULL;
- if (reply.ack_header.OPT_length < sizeof(reply.opt_header)) return NULL;
-
- if (!(data = HeapAlloc( GetProcessHeap(), 0, reply.opt_header.len ))) return NULL;
- buf.maxlen = reply.opt_header.len;
- buf.buf = (caddr_t)data;
- flags = 0;
- if (getmsg( fd, NULL, &buf, &flags ) >= 0 &&
- reply.opt_header.level == level &&
- reply.opt_header.name == name)
- {
- *len = buf.len;
- return data;
- }
- HeapFree( GetProcessHeap(), 0, data );
- }
-}
-#endif /* HAVE_SYS_TIHDR_H && T_OPTMGMT_ACK */
-
/******************************************************************
* GetUdpStatistics (IPHLPAPI.@)
*
@@ -443,452 +368,3 @@ DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS stats)
{
return GetUdpStatisticsEx(stats, WS_AF_INET);
}
-
-static void *append_table_row( HANDLE heap, DWORD flags, void *table, DWORD *table_size, DWORD *table_capacity,
- const void *row, DWORD row_size )
-{
- DWORD *num_entries = table; /* this must be the first field */
- if (*num_entries == *table_capacity)
- {
- void *new_table;
- *table_size += *table_capacity * row_size;
- if (!(new_table = HeapReAlloc( heap, flags, table, *table_size )))
- {
- HeapFree( heap, 0, table );
- return NULL;
- }
- num_entries = table = new_table;
- *table_capacity *= 2;
- }
- memcpy( (char *)table + *table_size - (*table_capacity - *num_entries) * row_size, row, row_size );
- (*num_entries)++;
- return table;
-}
-
-struct pid_map
-{
- unsigned int pid;
- unsigned int unix_pid;
-};
-
-static struct pid_map *get_pid_map( unsigned int *num_entries )
-{
- struct pid_map *map;
- unsigned int i = 0, buffer_len = 4096, process_count, pos = 0;
- NTSTATUS ret;
- char *buffer = NULL, *new_buffer;
-
- if (!(buffer = HeapAlloc( GetProcessHeap(), 0, buffer_len ))) return NULL;
-
- for (;;)
- {
- SERVER_START_REQ( list_processes )
- {
- wine_server_set_reply( req, buffer, buffer_len );
- ret = wine_server_call( req );
- buffer_len = reply->info_size;
- process_count = reply->process_count;
- }
- SERVER_END_REQ;
-
- if (ret != STATUS_INFO_LENGTH_MISMATCH) break;
-
- if (!(new_buffer = HeapReAlloc( GetProcessHeap(), 0, buffer, buffer_len )))
- {
- HeapFree( GetProcessHeap(), 0, buffer );
- return NULL;
- }
- buffer = new_buffer;
- }
-
- if (!(map = HeapAlloc( GetProcessHeap(), 0, process_count * sizeof(*map) )))
- {
- HeapFree( GetProcessHeap(), 0, buffer );
- return NULL;
- }
-
- for (i = 0; i < process_count; ++i)
- {
- const struct process_info *process;
-
- pos = (pos + 7) & ~7;
- process = (const struct process_info *)(buffer + pos);
-
- map[i].pid = process->pid;
- map[i].unix_pid = process->unix_pid;
-
- pos += sizeof(struct process_info) + process->name_len;
- pos = (pos + 7) & ~7;
- pos += process->thread_count * sizeof(struct thread_info);
- }
-
- HeapFree( GetProcessHeap(), 0, buffer );
- *num_entries = process_count;
- return map;
-}
-
-static unsigned int find_owning_pid( struct pid_map *map, unsigned int num_entries, UINT_PTR inode )
-{
-#ifdef __linux__
- unsigned int i, len_socket;
- char socket[32];
-
- sprintf( socket, "socket:[%lu]", inode );
- len_socket = strlen( socket );
- for (i = 0; i < num_entries; i++)
- {
- char dir[32];
- struct dirent *dirent;
- DIR *dirfd;
-
- sprintf( dir, "/proc/%u/fd", map[i].unix_pid );
- if ((dirfd = opendir( dir )))
- {
- while ((dirent = readdir( dirfd )))
- {
- char link[sizeof(dirent->d_name) + 32], name[32];
- int len;
-
- sprintf( link, "/proc/%u/fd/%s", map[i].unix_pid, dirent->d_name );
- if ((len = readlink( link, name, sizeof(name) - 1 )) > 0) name[len] = 0;
- if (len == len_socket && !strcmp( socket, name ))
- {
- closedir( dirfd );
- return map[i].pid;
- }
- }
- closedir( dirfd );
- }
- }
- return 0;
-#elif defined(HAVE_LIBPROCSTAT)
- struct procstat *pstat;
- struct kinfo_proc *proc;
- struct filestat_list *fds;
- struct filestat *fd;
- struct sockstat sock;
- unsigned int i, proc_count;
-
- pstat = procstat_open_sysctl();
- if (!pstat) return 0;
-
- for (i = 0; i < num_entries; i++)
- {
- proc = procstat_getprocs( pstat, KERN_PROC_PID, map[i].unix_pid, &proc_count );
- if (!proc || proc_count < 1) continue;
-
- fds = procstat_getfiles( pstat, proc, 0 );
- if (!fds)
- {
- procstat_freeprocs( pstat, proc );
- continue;
- }
-
- STAILQ_FOREACH( fd, fds, next )
- {
- char errbuf[_POSIX2_LINE_MAX];
-
- if (fd->fs_type != PS_FST_TYPE_SOCKET) continue;
-
- procstat_get_socket_info( pstat, fd, &sock, errbuf );
-
- if (sock.so_pcb == inode)
- {
- procstat_freefiles( pstat, fds );
- procstat_freeprocs( pstat, proc );
- procstat_close( pstat );
- return map[i].pid;
- }
- }
-
- procstat_freefiles( pstat, fds );
- procstat_freeprocs( pstat, proc );
- }
-
- procstat_close( pstat );
- return 0;
-#elif defined(HAVE_PROC_PIDINFO)
- struct proc_fdinfo *fds;
- struct socket_fdinfo sock;
- unsigned int i, j, n;
-
- for (i = 0; i < num_entries; i++)
- {
- int fd_len = proc_pidinfo( map[i].unix_pid, PROC_PIDLISTFDS, 0, NULL, 0 );
- if (fd_len <= 0) continue;
-
- fds = HeapAlloc( GetProcessHeap(), 0, fd_len );
- if (!fds) continue;
-
- proc_pidinfo( map[i].unix_pid, PROC_PIDLISTFDS, 0, fds, fd_len );
- n = fd_len / sizeof(struct proc_fdinfo);
- for (j = 0; j < n; j++)
- {
- if (fds[j].proc_fdtype != PROX_FDTYPE_SOCKET) continue;
-
- proc_pidfdinfo( map[i].unix_pid, fds[j].proc_fd, PROC_PIDFDSOCKETINFO, &sock, sizeof(sock) );
- if (sock.psi.soi_pcb == inode)
- {
- HeapFree( GetProcessHeap(), 0, fds );
- return map[i].pid;
- }
- }
-
- HeapFree( GetProcessHeap(), 0, fds );
- }
- return 0;
-#else
- FIXME( "not implemented\n" );
- return 0;
-#endif
-}
-
-static DWORD get_udp_table_sizes( UDP_TABLE_CLASS class, DWORD row_count, DWORD *row_size )
-{
- DWORD table_size;
-
- switch (class)
- {
- case UDP_TABLE_BASIC:
- {
- table_size = FIELD_OFFSET(MIB_UDPTABLE, table[row_count]);
- if (row_size) *row_size = sizeof(MIB_UDPROW);
- break;
- }
- case UDP_TABLE_OWNER_PID:
- {
- table_size = FIELD_OFFSET(MIB_UDPTABLE_OWNER_PID, table[row_count]);
- if (row_size) *row_size = sizeof(MIB_UDPROW_OWNER_PID);
- break;
- }
- case UDP_TABLE_OWNER_MODULE:
- {
- table_size = FIELD_OFFSET(MIB_UDPTABLE_OWNER_MODULE, table[row_count]);
- if (row_size) *row_size = sizeof(MIB_UDPROW_OWNER_MODULE);
- break;
- }
- default:
- ERR("unhandled class %u\n", class);
- return 0;
- }
- return table_size;
-}
-
-static int compare_udp_rows(const void *a, const void *b)
-{
- const MIB_UDPROW *rowA = a;
- const MIB_UDPROW *rowB = b;
- int ret;
-
- if ((ret = rowA->dwLocalAddr - rowB->dwLocalAddr) != 0) return ret;
- return rowA->dwLocalPort - rowB->dwLocalPort;
-}
-
-DWORD build_udp_table( UDP_TABLE_CLASS class, void **tablep, BOOL order, HANDLE heap, DWORD flags,
- DWORD *size )
-{
- MIB_UDPTABLE *table;
- MIB_UDPROW_OWNER_MODULE row;
- DWORD ret = NO_ERROR, count = 16, table_size, row_size;
-
- if (!(table_size = get_udp_table_sizes( class, count, &row_size )))
- return ERROR_INVALID_PARAMETER;
-
- if (!(table = HeapAlloc( heap, flags, table_size )))
- return ERROR_OUTOFMEMORY;
-
- table->dwNumEntries = 0;
- memset( &row, 0, sizeof(row) );
-
-#ifdef __linux__
- {
- FILE *fp;
-
- if ((fp = fopen( "/proc/net/udp", "r" )))
- {
- char buf[512], *ptr;
- struct pid_map *map = NULL;
- unsigned int num_entries = 0;
- int inode;
-
- if (class >= UDP_TABLE_OWNER_PID) map = get_pid_map( &num_entries );
-
- /* skip header line */
- ptr = fgets( buf, sizeof(buf), fp );
- while ((ptr = fgets( buf, sizeof(buf), fp )))
- {
- if (sscanf( ptr, "%*u: %x:%x %*s %*s %*s %*s %*s %*s %*s %d",
- &row.dwLocalAddr, &row.dwLocalPort, &inode ) != 3)
- continue;
- row.dwLocalPort = htons( row.dwLocalPort );
-
- if (class >= UDP_TABLE_OWNER_PID)
- row.dwOwningPid = find_owning_pid( map, num_entries, inode );
- if (class >= UDP_TABLE_OWNER_MODULE)
- {
- row.liCreateTimestamp.QuadPart = 0; /* FIXME */
- row.dwFlags = 0;
- memset( &row.OwningModuleInfo, 0, sizeof(row.OwningModuleInfo) );
- }
- if (!(table = append_table_row( heap, flags, table, &table_size, &count, &row, row_size )))
- break;
- }
- HeapFree( GetProcessHeap(), 0, map );
- fclose( fp );
- }
- else ret = ERROR_NOT_SUPPORTED;
- }
-#elif defined(HAVE_SYS_TIHDR_H) && defined(T_OPTMGMT_ACK)
- {
- void *data;
- int fd, len;
- mib2_udpEntry_t *entry;
-
- if ((fd = open_streams_mib( "udp" )) != -1)
- {
- if ((data = read_mib_entry( fd, MIB2_UDP, MIB2_UDP_ENTRY, &len )))
- {
- for (entry = data; (char *)(entry + 1) <= (char *)data + len; entry++)
- {
- row.dwLocalAddr = entry->udpLocalAddress;
- row.dwLocalPort = htons( entry->udpLocalPort );
- if (!(table = append_table_row( heap, flags, table, &table_size, &count, &row, row_size )))
- break;
- }
- HeapFree( GetProcessHeap(), 0, data );
- }
- close( fd );
- }
- else ret = ERROR_NOT_SUPPORTED;
- }
-#elif defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_STRUCT_XINPGEN)
- {
- size_t Len = 0;
- char *Buf = NULL;
- struct xinpgen *pXIG, *pOrigXIG;
- struct pid_map *pMap = NULL;
- unsigned NumEntries;
-
- if (sysctlbyname ("net.inet.udp.pcblist", NULL, &Len, NULL, 0) < 0)
- {
- ERR ("Failure to read net.inet.udp.pcblist via sysctlbyname!\n");
- ret = ERROR_NOT_SUPPORTED;
- goto done;
- }
-
- Buf = HeapAlloc (GetProcessHeap (), 0, Len);
- if (!Buf)
- {
- ret = ERROR_OUTOFMEMORY;
- goto done;
- }
-
- if (sysctlbyname ("net.inet.udp.pcblist", Buf, &Len, NULL, 0) < 0)
- {
- ERR ("Failure to read net.inet.udp.pcblist via sysctlbyname!\n");
- ret = ERROR_NOT_SUPPORTED;
- goto done;
- }
-
- if (class >= UDP_TABLE_OWNER_PID)
- pMap = get_pid_map( &NumEntries );
-
- /* Might be nothing here; first entry is just a header it seems */
- if (Len <= sizeof (struct xinpgen)) goto done;
-
- pOrigXIG = (struct xinpgen *)Buf;
- pXIG = pOrigXIG;
-
- for (pXIG = (struct xinpgen *)((char *)pXIG + pXIG->xig_len);
- pXIG->xig_len > sizeof (struct xinpgen);
- pXIG = (struct xinpgen *)((char *)pXIG + pXIG->xig_len))
- {
-#if __FreeBSD_version >= 1200026
- struct xinpcb *pINData = (struct xinpcb *)pXIG;
- struct xsocket *pSockData = &pINData->xi_socket;
-#else
- struct inpcb *pINData = &((struct xinpcb *)pXIG)->xi_inp;
- struct xsocket *pSockData = &((struct xinpcb *)pXIG)->xi_socket;
-#endif
-
- /* Ignore sockets for other protocols */
- if (pSockData->xso_protocol != IPPROTO_UDP)
- continue;
-
- /* Ignore PCBs that were freed while generating the data */
- if (pINData->inp_gencnt > pOrigXIG->xig_gen)
- continue;
-
- /* we're only interested in IPv4 addresses */
- if (!(pINData->inp_vflag & INP_IPV4) ||
- (pINData->inp_vflag & INP_IPV6))
- continue;
-
- /* If all 0's, skip it */
- if (!pINData->inp_laddr.s_addr &&
- !pINData->inp_lport)
- continue;
-
- /* Fill in structure details */
- row.dwLocalAddr = pINData->inp_laddr.s_addr;
- row.dwLocalPort = pINData->inp_lport;
- if (class >= UDP_TABLE_OWNER_PID)
- row.dwOwningPid = find_owning_pid( pMap, NumEntries, (UINT_PTR)pSockData->so_pcb );
- if (class >= UDP_TABLE_OWNER_MODULE)
- {
- row.liCreateTimestamp.QuadPart = 0; /* FIXME */
- row.dwFlags = 0;
- row.SpecificPortBind = !(pINData->inp_flags & INP_ANONPORT);
- memset( &row.OwningModuleInfo, 0, sizeof(row.OwningModuleInfo) );
- }
- if (!(table = append_table_row( heap, flags, table, &table_size, &count, &row, row_size )))
- break;
- }
-
- done:
- HeapFree( GetProcessHeap(), 0, pMap );
- HeapFree (GetProcessHeap (), 0, Buf);
- }
-#else
- FIXME( "not implemented\n" );
- ret = ERROR_NOT_SUPPORTED;
-#endif
-
- if (!table) return ERROR_OUTOFMEMORY;
- if (!ret)
- {
- if (order && table->dwNumEntries)
- qsort( table->table, table->dwNumEntries, row_size, compare_udp_rows );
- *tablep = table;
- }
- else HeapFree( heap, flags, table );
- if (size) *size = get_udp_table_sizes( class, count, NULL );
- TRACE( "returning ret %u table %p\n", ret, table );
- return ret;
-}
-
-/******************************************************************
- * AllocateAndGetUdpTableFromStack (IPHLPAPI.@)
- *
- * Get the UDP listener table.
- * Like GetUdpTable(), but allocate the returned table from heap.
- *
- * PARAMS
- * ppUdpTable [Out] pointer into which the MIB_UDPTABLE is
- * allocated and returned.
- * bOrder [In] whether to sort the table
- * heap [In] heap from which the table is allocated
- * flags [In] flags to HeapAlloc
- *
- * RETURNS
- * ERROR_INVALID_PARAMETER if ppUdpTable is NULL, whatever GetUdpTable()
- * returns otherwise.
- */
-DWORD WINAPI AllocateAndGetUdpTableFromStack(PMIB_UDPTABLE *ppUdpTable, BOOL bOrder,
- HANDLE heap, DWORD flags)
-{
- TRACE("table %p, bOrder %d, heap %p, flags 0x%08x\n", ppUdpTable, bOrder, heap, flags);
-
- if (!ppUdpTable) return ERROR_INVALID_PARAMETER;
- return build_udp_table( UDP_TABLE_BASIC, (void **)ppUdpTable, bOrder, heap, flags, NULL );
-}
--
2.23.0
1
0
18 Aug '21
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/iphlpapi/iphlpapi_main.c | 225 +++++++++++++++++-----
dlls/iphlpapi/ipstats.c | 350 ----------------------------------
dlls/iphlpapi/ipstats.h | 33 ----
3 files changed, 175 insertions(+), 433 deletions(-)
delete mode 100644 dlls/iphlpapi/ipstats.h
diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index e78689d8f11..bcda2b81b6e 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -43,7 +43,6 @@
#include "windns.h"
#include "iphlpapi.h"
#include "ifenum.h"
-#include "ipstats.h"
#include "ipifcons.h"
#include "fltdefs.h"
#include "ifdef.h"
@@ -3289,81 +3288,207 @@ DWORD WINAPI AllocateAndGetTcpExTableFromStack( void **table, BOOL sort, HANDLE
* Get a table of active UDP connections.
*
* PARAMS
- * pUdpTable [Out] buffer for UDP connections table
- * pdwSize [In/Out] length of output buffer
- * bOrder [In] whether to order the table
- *
- * RETURNS
- * Success: NO_ERROR
- * Failure: error code from winerror.h
+ * table [Out] buffer for UDP connections table
+ * size [In/Out] length of output buffer
+ * sort [In] whether to order the table
*
- * NOTES
- * If pdwSize is less than required, the function will return
- * ERROR_INSUFFICIENT_BUFFER, and *pdwSize will be set to the
- * required byte size.
- * If bOrder is true, the returned table will be sorted, first by
- * local address, then by local port number.
*/
-DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder)
+DWORD WINAPI GetUdpTable( MIB_UDPTABLE *table, DWORD *size, BOOL sort )
{
- return GetExtendedUdpTable(pUdpTable, pdwSize, bOrder, WS_AF_INET, UDP_TABLE_BASIC, 0);
+ return GetExtendedUdpTable( table, size, sort, WS_AF_INET, UDP_TABLE_BASIC, 0 );
}
/******************************************************************
* GetUdp6Table (IPHLPAPI.@)
*/
-DWORD WINAPI GetUdp6Table(PMIB_UDP6TABLE pUdpTable, PDWORD pdwSize, BOOL bOrder)
+DWORD WINAPI GetUdp6Table( MIB_UDP6TABLE *table, DWORD *size, BOOL sort )
{
- return GetExtendedUdpTable(pUdpTable, pdwSize, bOrder, WS_AF_INET6, UDP_TABLE_BASIC, 0);
+ return GetExtendedUdpTable( table, size, sort, WS_AF_INET6, UDP_TABLE_BASIC, 0 );
}
-/******************************************************************
- * GetExtendedUdpTable (IPHLPAPI.@)
- */
-DWORD WINAPI GetExtendedUdpTable(PVOID pUdpTable, PDWORD pdwSize, BOOL bOrder,
- ULONG ulAf, UDP_TABLE_CLASS TableClass, ULONG Reserved)
+static DWORD udp_table_size( ULONG family, ULONG table_class, DWORD row_count, DWORD *row_size )
{
- DWORD ret, size;
- void *table;
+ switch (table_class)
+ {
+ case UDP_TABLE_BASIC:
+ *row_size = (family == WS_AF_INET) ? sizeof(MIB_UDPROW) : sizeof(MIB_UDP6ROW);
+ return (family == WS_AF_INET) ? FIELD_OFFSET(MIB_UDPTABLE, table[row_count]) :
+ FIELD_OFFSET(MIB_UDP6TABLE, table[row_count]);
- TRACE("pUdpTable %p, pdwSize %p, bOrder %d, ulAf %u, TableClass %u, Reserved %u\n",
- pUdpTable, pdwSize, bOrder, ulAf, TableClass, Reserved);
+ case UDP_TABLE_OWNER_PID:
+ *row_size = (family == WS_AF_INET) ? sizeof(MIB_UDPROW_OWNER_PID) : sizeof(MIB_UDP6ROW_OWNER_PID);
+ return (family == WS_AF_INET) ? FIELD_OFFSET(MIB_UDPTABLE_OWNER_PID, table[row_count]) :
+ FIELD_OFFSET(MIB_UDP6TABLE_OWNER_PID, table[row_count]);
- if (!pdwSize) return ERROR_INVALID_PARAMETER;
+ case UDP_TABLE_OWNER_MODULE:
+ *row_size = (family == WS_AF_INET) ? sizeof(MIB_UDPROW_OWNER_MODULE) : sizeof(MIB_UDP6ROW_OWNER_MODULE);
+ return (family == WS_AF_INET) ? FIELD_OFFSET(MIB_UDPTABLE_OWNER_MODULE, table[row_count]) :
+ FIELD_OFFSET(MIB_UDP6TABLE_OWNER_MODULE, table[row_count]);
- if (TableClass == UDP_TABLE_OWNER_MODULE)
- FIXME("UDP_TABLE_OWNER_MODULE not fully supported\n");
+ default:
+ ERR( "unhandled class %u\n", table_class );
+ return 0;
+ }
+}
- switch (ulAf)
+static void udp_row_fill( void *table, DWORD num, ULONG family, ULONG table_class,
+ struct nsi_udp_endpoint_key *key,
+ struct nsi_udp_endpoint_static *stat )
+{
+ if (family == WS_AF_INET)
{
- case WS_AF_INET:
- ret = build_udp_table(TableClass, &table, bOrder, GetProcessHeap(), 0, &size);
- break;
-
- case WS_AF_INET6:
- ret = build_udp6_table(TableClass, &table, bOrder, GetProcessHeap(), 0, &size);
- break;
-
+ switch (table_class)
+ {
+ case UDP_TABLE_BASIC:
+ {
+ MIB_UDPROW *row = ((MIB_UDPTABLE *)table)->table + num;
+ row->dwLocalAddr = key->local.Ipv4.sin_addr.WS_s_addr;
+ row->dwLocalPort = key->local.Ipv4.sin_port;
+ return;
+ }
+ case UDP_TABLE_OWNER_PID:
+ {
+ MIB_UDPROW_OWNER_PID *row = ((MIB_UDPTABLE_OWNER_PID *)table)->table + num;
+ row->dwLocalAddr = key->local.Ipv4.sin_addr.WS_s_addr;
+ row->dwLocalPort = key->local.Ipv4.sin_port;
+ row->dwOwningPid = stat->pid;
+ return;
+ }
+ case UDP_TABLE_OWNER_MODULE:
+ {
+ MIB_UDPROW_OWNER_MODULE *row = ((MIB_UDPTABLE_OWNER_MODULE *)table)->table + num;
+ row->dwLocalAddr = key->local.Ipv4.sin_addr.WS_s_addr;
+ row->dwLocalPort = key->local.Ipv4.sin_port;
+ row->dwOwningPid = stat->pid;
+ row->liCreateTimestamp.QuadPart = stat->create_time;
+ row->dwFlags = stat->flags;
+ row->OwningModuleInfo[0] = stat->mod_info;
+ memset( row->OwningModuleInfo + 1, 0, sizeof(row->OwningModuleInfo) - sizeof(row->OwningModuleInfo[0]) );
+ return;
+ }
default:
- FIXME("ulAf = %u not supported\n", ulAf);
- ret = ERROR_NOT_SUPPORTED;
+ ERR( "Unknown class %d\n", table_class );
+ return;
+ }
}
+ else
+ {
+ switch (table_class)
+ {
+ case UDP_TABLE_BASIC:
+ {
+ MIB_UDP6ROW *row = ((MIB_UDP6TABLE *)table)->table + num;
+ memcpy( &row->dwLocalAddr, &key->local.Ipv6.sin6_addr, sizeof(row->dwLocalAddr) );
+ row->dwLocalScopeId = key->local.Ipv6.sin6_scope_id;
+ row->dwLocalPort = key->local.Ipv6.sin6_port;
+ return;
+ }
+ case UDP_TABLE_OWNER_PID:
+ {
+ MIB_UDP6ROW_OWNER_PID *row = ((MIB_UDP6TABLE_OWNER_PID *)table)->table + num;
+ memcpy( &row->ucLocalAddr, &key->local.Ipv6.sin6_addr, sizeof(row->ucLocalAddr) );
+ row->dwLocalScopeId = key->local.Ipv6.sin6_scope_id;
+ row->dwLocalPort = key->local.Ipv6.sin6_port;
+ row->dwOwningPid = stat->pid;
+ return;
+ }
+ case UDP_TABLE_OWNER_MODULE:
+ {
+ MIB_UDP6ROW_OWNER_MODULE *row = ((MIB_UDP6TABLE_OWNER_MODULE *)table)->table + num;
+ memcpy( &row->ucLocalAddr, &key->local.Ipv6.sin6_addr, sizeof(row->ucLocalAddr) );
+ row->dwLocalScopeId = key->local.Ipv6.sin6_scope_id;
+ row->dwLocalPort = key->local.Ipv6.sin6_port;
+ row->dwOwningPid = stat->pid;
+ row->liCreateTimestamp.QuadPart = stat->create_time;
+ row->dwFlags = stat->flags;
+ row->OwningModuleInfo[0] = stat->mod_info;
+ memset( row->OwningModuleInfo + 1, 0, sizeof(row->OwningModuleInfo) - sizeof(row->OwningModuleInfo[0]) );
+ return;
+ }
+ default:
+ ERR( "Unknown class %d\n", table_class );
+ return;
+ }
+ }
+ ERR( "Unknown family %d\n", family );
+ return;
+}
- if (ret)
- return ret;
+static int udp_row_cmp( const void *a, const void *b )
+{
+ const MIB_UDPROW *rowA = a;
+ const MIB_UDPROW *rowB = b;
+ int ret;
+
+ if ((ret = RtlUlongByteSwap( rowA->dwLocalAddr ) - RtlUlongByteSwap( rowB->dwLocalAddr )) != 0) return ret;
+ return RtlUshortByteSwap( rowA->dwLocalPort ) - RtlUshortByteSwap( rowB->dwLocalPort );
+}
+
+static int udp6_row_cmp( const void *a, const void *b )
+{
+ const MIB_UDP6ROW *rowA = a;
+ const MIB_UDP6ROW *rowB = b;
+ int ret;
+
+ if ((ret = memcmp( &rowA->dwLocalAddr, &rowB->dwLocalAddr, sizeof(rowA->dwLocalAddr) )) != 0) return ret;
+ if ((ret = rowA->dwLocalScopeId - rowB->dwLocalScopeId) != 0) return ret;
+ return RtlUshortByteSwap( rowA->dwLocalPort ) - RtlUshortByteSwap( rowB->dwLocalPort );
+}
+
+/******************************************************************
+ * GetExtendedUdpTable (IPHLPAPI.@)
+ */
+DWORD WINAPI GetExtendedUdpTable( void *table, DWORD *size, BOOL sort, ULONG family,
+ UDP_TABLE_CLASS table_class, ULONG reserved )
+{
+ DWORD err, count, needed, i, num = 0, row_size = 0;
+ struct nsi_udp_endpoint_key *key;
+ struct nsi_udp_endpoint_static *stat;
+
+ TRACE( "table %p, size %p, sort %d, family %u, table_class %u, reserved %u\n",
+ table, size, sort, family, table_class, reserved );
+
+ if (!size || !ip_module_id( family )) return ERROR_INVALID_PARAMETER;
+
+ err = NsiAllocateAndGetTable( 1, &NPI_MS_UDP_MODULEID, NSI_UDP_ENDPOINT_TABLE, (void **)&key, sizeof(*key),
+ NULL, 0, NULL, 0, (void **)&stat, sizeof(*stat), &count, 0 );
+ if (err) return err;
+
+ for (i = 0; i < count; i++)
+ if (key[i].local.si_family == family)
+ num++;
- if (!pUdpTable || *pdwSize < size)
+ needed = udp_table_size( family, table_class, num, &row_size );
+ if (!table || *size < needed)
{
- *pdwSize = size;
- ret = ERROR_INSUFFICIENT_BUFFER;
+ *size = needed;
+ err = ERROR_INSUFFICIENT_BUFFER;
}
else
{
- *pdwSize = size;
- memcpy(pUdpTable, table, size);
+ *size = needed;
+ *(DWORD *)table = num;
+ num = 0;
+ for (i = 0; i < count; i++)
+ {
+ if (key[i].local.si_family != family) continue;
+ udp_row_fill( table, num++, family, table_class, key + i, stat + i );
+ }
+ }
+
+ if (!err && sort)
+ {
+ int (*fn)(const void *, const void *);
+ DWORD offset = udp_table_size( family, table_class, 0, &row_size );
+
+ if (family == WS_AF_INET) fn = udp_row_cmp;
+ else fn = udp6_row_cmp;
+
+ qsort( (BYTE *)table + offset, num, row_size, fn );
}
- HeapFree(GetProcessHeap(), 0, table);
- return ret;
+
+ NsiFreeTable( key, NULL, NULL, stat );
+ return err;
}
static void unicast_row_fill( MIB_UNICASTIPADDRESS_ROW *row, USHORT fam, void *key, struct nsi_ip_unicast_rw *rw,
diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c
index 326db56f5bc..65bf65fec7b 100644
--- a/dlls/iphlpapi/ipstats.c
+++ b/dlls/iphlpapi/ipstats.c
@@ -158,7 +158,6 @@
#include "winsock2.h"
#include "ws2ipdef.h"
#include "ifenum.h"
-#include "ipstats.h"
#include "iphlpapi.h"
#include "wine/debug.h"
@@ -868,355 +867,6 @@ DWORD build_udp_table( UDP_TABLE_CLASS class, void **tablep, BOOL order, HANDLE
return ret;
}
-static DWORD get_udp6_table_sizes( UDP_TABLE_CLASS class, DWORD row_count, DWORD *row_size )
-{
- DWORD table_size;
-
- switch (class)
- {
- case UDP_TABLE_BASIC:
- {
- table_size = FIELD_OFFSET(MIB_UDP6TABLE, table[row_count]);
- if (row_size) *row_size = sizeof(MIB_UDP6ROW);
- break;
- }
- case UDP_TABLE_OWNER_PID:
- {
- table_size = FIELD_OFFSET(MIB_UDP6TABLE_OWNER_PID, table[row_count]);
- if (row_size) *row_size = sizeof(MIB_UDP6ROW_OWNER_PID);
- break;
- }
- case UDP_TABLE_OWNER_MODULE:
- {
- table_size = FIELD_OFFSET(MIB_UDP6TABLE_OWNER_MODULE, table[row_count]);
- if (row_size) *row_size = sizeof(MIB_UDP6ROW_OWNER_MODULE);
- break;
- }
- default:
- ERR("unhandled class %u\n", class);
- return 0;
- }
- return table_size;
-}
-
-static int compare_udp6_rows(const void *a, const void *b)
-{
- const MIB_UDP6ROW *rowA = a;
- const MIB_UDP6ROW *rowB = b;
- int ret;
-
- if ((ret = memcmp(&rowA->dwLocalAddr, &rowB->dwLocalAddr, sizeof(rowA->dwLocalAddr))) != 0) return ret;
- if ((ret = rowA->dwLocalScopeId - rowB->dwLocalScopeId) != 0) return ret;
- return rowA->dwLocalPort - rowB->dwLocalPort;
-}
-
-#if defined(__linux__) || (defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_STRUCT_XINPGEN))
-struct ipv6_addr_scope
-{
- IN6_ADDR addr;
- DWORD scope;
-};
-
-static struct ipv6_addr_scope *get_ipv6_addr_scope_table(unsigned int *size)
-{
- struct ipv6_addr_scope *table = NULL;
- unsigned int table_size = 0;
-#ifdef __linux__
- char buf[512], *ptr;
- FILE *fp;
-#elif defined(HAVE_GETIFADDRS)
- struct ifaddrs *addrs, *cur;
-#endif
-
- if (!(table = HeapAlloc( GetProcessHeap(), 0, sizeof(table[0]) )))
- return NULL;
-
-#ifdef __linux__
- if (!(fp = fopen( "/proc/net/if_inet6", "r" )))
- goto failed;
-
- while ((ptr = fgets( buf, sizeof(buf), fp )))
- {
- WORD a[8];
- DWORD scope;
- struct ipv6_addr_scope *new_table;
- struct ipv6_addr_scope *entry;
- unsigned int i;
-
- if (sscanf( ptr, "%4hx%4hx%4hx%4hx%4hx%4hx%4hx%4hx %*s %*s %x",
- &a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6], &a[7], &scope ) != 9)
- continue;
-
- table_size++;
- if (!(new_table = HeapReAlloc( GetProcessHeap(), 0, table, table_size * sizeof(table[0]) )))
- {
- fclose(fp);
- goto failed;
- }
-
- table = new_table;
- entry = &table[table_size - 1];
-
- i = 0;
- while (i < 8)
- {
- entry->addr.u.Word[i] = htons(a[i]);
- i++;
- }
-
- entry->scope = htons(scope);
- }
-
- fclose(fp);
-#elif defined(HAVE_GETIFADDRS)
- if (getifaddrs(&addrs) == -1)
- goto failed;
-
- for (cur = addrs; cur; cur = cur->ifa_next)
- {
- struct sockaddr_in6 *sin6;
- struct ipv6_addr_scope *new_table;
- struct ipv6_addr_scope *entry;
-
- if (cur->ifa_addr->sa_family != AF_INET6)
- continue;
-
- sin6 = (struct sockaddr_in6 *)cur->ifa_addr;
-
- table_size++;
- if (!(new_table = HeapReAlloc( GetProcessHeap(), 0, table, table_size * sizeof(table[0]) )))
- {
- freeifaddrs(addrs);
- goto failed;
- }
-
- table = new_table;
- entry = &table[table_size - 1];
-
- memcpy(&entry->addr, &sin6->sin6_addr, sizeof(entry->addr));
- entry->scope = sin6->sin6_scope_id;
- }
-
- freeifaddrs(addrs);
-#else
- FIXME( "not implemented\n" );
- goto failed;
-#endif
-
- *size = table_size;
- return table;
-
-failed:
- HeapFree( GetProcessHeap(), 0, table );
- return NULL;
-}
-
-static DWORD find_ipv6_addr_scope(const IN6_ADDR *addr, const struct ipv6_addr_scope *table, unsigned int size)
-{
- const BYTE multicast_scope_mask = 0x0F;
- const BYTE multicast_scope_shift = 0;
- unsigned int i = 0;
-
- if (WS_IN6_IS_ADDR_UNSPECIFIED(addr))
- return 0;
-
- if (WS_IN6_IS_ADDR_MULTICAST(addr))
- return htons((addr->u.Byte[1] & multicast_scope_mask) >> multicast_scope_shift);
-
- if (!table)
- return -1;
-
- while (i < size)
- {
- if (memcmp(&table[i].addr, addr, sizeof(table[i].addr)) == 0)
- return table[i].scope;
- i++;
- }
-
- return -1;
-}
-#endif
-
-DWORD build_udp6_table( UDP_TABLE_CLASS class, void **tablep, BOOL order, HANDLE heap, DWORD flags,
- DWORD *size )
-{
- MIB_UDP6TABLE *table;
- MIB_UDP6ROW_OWNER_MODULE row;
- DWORD ret = NO_ERROR, count = 16, table_size, row_size;
-
- if (!(table_size = get_udp6_table_sizes( class, count, &row_size )))
- return ERROR_INVALID_PARAMETER;
-
- if (!(table = HeapAlloc( heap, flags, table_size )))
- return ERROR_OUTOFMEMORY;
-
- table->dwNumEntries = 0;
- memset( &row, 0, sizeof(row) );
-
-#ifdef __linux__
- {
- FILE *fp;
-
- if ((fp = fopen( "/proc/net/udp6", "r" )))
- {
- char buf[512], *ptr;
- struct pid_map *map = NULL;
- unsigned int num_entries = 0;
- struct ipv6_addr_scope *addr_scopes;
- unsigned int addr_scopes_size = 0;
- int inode;
-
- addr_scopes = get_ipv6_addr_scope_table(&addr_scopes_size);
-
- if (class >= UDP_TABLE_OWNER_PID) map = get_pid_map( &num_entries );
-
- /* skip header line */
- ptr = fgets( buf, sizeof(buf), fp );
- while ((ptr = fgets( buf, sizeof(buf), fp )))
- {
- DWORD *local_addr = (DWORD *)&row.ucLocalAddr;
-
- if (sscanf( ptr, "%*u: %8x%8x%8x%8x:%x %*s %*s %*s %*s %*s %*s %*s %d",
- &local_addr[0], &local_addr[1], &local_addr[2], &local_addr[3],
- &row.dwLocalPort, &inode ) != 6)
- continue;
- row.dwLocalScopeId = find_ipv6_addr_scope((const IN6_ADDR *)&row.ucLocalAddr, addr_scopes, addr_scopes_size);
- row.dwLocalPort = htons( row.dwLocalPort );
-
- if (class >= UDP_TABLE_OWNER_PID)
- row.dwOwningPid = find_owning_pid( map, num_entries, inode );
- if (class >= UDP_TABLE_OWNER_MODULE)
- {
- row.liCreateTimestamp.QuadPart = 0; /* FIXME */
- row.dwFlags = 0;
- memset( &row.OwningModuleInfo, 0, sizeof(row.OwningModuleInfo) );
- }
- if (!(table = append_table_row( heap, flags, table, &table_size, &count, &row, row_size )))
- break;
- }
- HeapFree( GetProcessHeap(), 0, map );
- HeapFree( GetProcessHeap(), 0, addr_scopes );
- fclose( fp );
- }
- else ret = ERROR_NOT_SUPPORTED;
- }
-#elif defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_STRUCT_XINPGEN)
- {
- static const char zero[sizeof(IN6_ADDR)] = {0};
-
- size_t len = 0;
- char *buf = NULL;
- struct xinpgen *xig, *orig_xig;
- struct pid_map *map = NULL;
- unsigned num_entries;
- struct ipv6_addr_scope *addr_scopes = NULL;
- unsigned int addr_scopes_size = 0;
-
- if (sysctlbyname( "net.inet.udp.pcblist", NULL, &len, NULL, 0 ) < 0)
- {
- ERR( "Failure to read net.inet.udp.pcblist via sysctlbyname!\n" );
- ret = ERROR_NOT_SUPPORTED;
- goto done;
- }
-
- buf = HeapAlloc( GetProcessHeap(), 0, len );
- if (!buf)
- {
- ret = ERROR_OUTOFMEMORY;
- goto done;
- }
-
- if (sysctlbyname( "net.inet.udp.pcblist", buf, &len, NULL, 0 ) < 0)
- {
- ERR ("Failure to read net.inet.udp.pcblist via sysctlbyname!\n");
- ret = ERROR_NOT_SUPPORTED;
- goto done;
- }
-
- addr_scopes = get_ipv6_addr_scope_table( &addr_scopes_size );
- if (!addr_scopes)
- {
- ret = ERROR_OUTOFMEMORY;
- goto done;
- }
-
- if (class >= UDP_TABLE_OWNER_PID) map = get_pid_map( &num_entries );
-
- /* Might be nothing here; first entry is just a header it seems */
- if (len <= sizeof (struct xinpgen)) goto done;
-
- orig_xig = (struct xinpgen *)buf;
- xig = orig_xig;
-
- for (xig = (struct xinpgen *)((char *)xig + xig->xig_len);
- xig->xig_len > sizeof (struct xinpgen);
- xig = (struct xinpgen *)((char *)xig + xig->xig_len))
- {
-#if __FreeBSD_version >= 1200026
- struct xinpcb *in = (struct xinpcb *)xig;
- struct xsocket *sock = &in->xi_socket;
-#else
- struct inpcb *in = &((struct xinpcb *)xig)->xi_inp;
- struct xsocket *sock = &((struct xinpcb *)xig)->xi_socket;
-#endif
-
- /* Ignore sockets for other protocols */
- if (sock->xso_protocol != IPPROTO_UDP)
- continue;
-
- /* Ignore PCBs that were freed while generating the data */
- if (in->inp_gencnt > orig_xig->xig_gen)
- continue;
-
- /* we're only interested in IPv6 addresses */
- if (!(in->inp_vflag & INP_IPV6) ||
- (in->inp_vflag & INP_IPV4))
- continue;
-
- /* If all 0's, skip it */
- if (!memcmp( &in->in6p_laddr.s6_addr, zero, sizeof(zero) ) && !in->inp_lport)
- continue;
-
- /* Fill in structure details */
- memcpy(row.ucLocalAddr, &in->in6p_laddr.s6_addr, sizeof(row.ucLocalAddr));
- row.dwLocalPort = in->inp_lport;
- row.dwLocalScopeId = find_ipv6_addr_scope((const IN6_ADDR *)&row.ucLocalAddr, addr_scopes, addr_scopes_size);
- if (class >= UDP_TABLE_OWNER_PID)
- row.dwOwningPid = find_owning_pid( map, num_entries, (UINT_PTR)sock->so_pcb );
- if (class >= UDP_TABLE_OWNER_MODULE)
- {
- row.liCreateTimestamp.QuadPart = 0; /* FIXME */
- row.dwFlags = 0;
- row.SpecificPortBind = !(in->inp_flags & INP_ANONPORT);
- memset( &row.OwningModuleInfo, 0, sizeof(row.OwningModuleInfo) );
- }
- if (!(table = append_table_row( heap, flags, table, &table_size, &count, &row, row_size )))
- break;
- }
-
- done:
- HeapFree( GetProcessHeap(), 0, map );
- HeapFree( GetProcessHeap(), 0, buf );
- HeapFree( GetProcessHeap(), 0, addr_scopes );
- }
-#else
- FIXME( "not implemented\n" );
- ret = ERROR_NOT_SUPPORTED;
-#endif
-
- if (!table) return ERROR_OUTOFMEMORY;
- if (!ret)
- {
- if (order && table->dwNumEntries)
- qsort( table->table, table->dwNumEntries, row_size, compare_udp6_rows );
- *tablep = table;
- }
- else HeapFree( heap, flags, table );
- if (size) *size = get_udp6_table_sizes( class, count, NULL );
- TRACE( "returning ret %u table %p\n", ret, table );
- return ret;
-}
-
/******************************************************************
* AllocateAndGetUdpTableFromStack (IPHLPAPI.@)
*
diff --git a/dlls/iphlpapi/ipstats.h b/dlls/iphlpapi/ipstats.h
deleted file mode 100644
index 60398609207..00000000000
--- a/dlls/iphlpapi/ipstats.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* ipstats.h
- * Copyright (C) 2003,2006 Juan Lang
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- *
- * This module implements functions that get network-related statistics.
- * It's meant to hide some platform-specificisms.
- */
-#ifndef WINE_IPSTATS_H_
-#define WINE_IPSTATS_H_
-
-#include <stdarg.h>
-
-#include "windef.h"
-#include "winbase.h"
-#include "iprtrmib.h"
-
-DWORD build_udp_table(UDP_TABLE_CLASS, void **, BOOL, HANDLE, DWORD, DWORD *) DECLSPEC_HIDDEN;
-DWORD build_udp6_table(UDP_TABLE_CLASS, void **, BOOL, HANDLE, DWORD, DWORD *) DECLSPEC_HIDDEN;
-
-#endif /* ndef WINE_IPSTATS_H_ */
--
2.23.0
1
0