sync shell32_winetest with wine 1.1.20
authorChristoph von Wittich <christoph_vw@reactos.org>
Wed, 29 Apr 2009 15:11:22 +0000 (15:11 +0000)
committerChristoph von Wittich <christoph_vw@reactos.org>
Wed, 29 Apr 2009 15:11:22 +0000 (15:11 +0000)
svn path=/trunk/; revision=40733

14 files changed:
rostests/winetests/shell32/appbar.c [new file with mode: 0644]
rostests/winetests/shell32/autocomplete.c [new file with mode: 0644]
rostests/winetests/shell32/generated.c
rostests/winetests/shell32/rsrc.rc [new file with mode: 0644]
rostests/winetests/shell32/shell32.rbuild
rostests/winetests/shell32/shelllink.c
rostests/winetests/shell32/shellpath.c
rostests/winetests/shell32/shfldr_special.c [new file with mode: 0644]
rostests/winetests/shell32/shlexec.c
rostests/winetests/shell32/shlfileop.c
rostests/winetests/shell32/shlfolder.c
rostests/winetests/shell32/string.c
rostests/winetests/shell32/systray.c
rostests/winetests/shell32/testlist.c

diff --git a/rostests/winetests/shell32/appbar.c b/rostests/winetests/shell32/appbar.c
new file mode 100644 (file)
index 0000000..51bea2b
--- /dev/null
@@ -0,0 +1,420 @@
+/* Unit tests for appbars
+ *
+ * Copyright 2008 Vincent Povirk for CodeWeavers
+ *
+ * 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 <assert.h>
+#include <stdarg.h>
+
+#include <windows.h>
+
+#include "wine/test.h"
+
+#define MSG_APPBAR WM_APP
+
+static const CHAR testwindow_class[] = "testwindow";
+
+static HMONITOR (WINAPI *pMonitorFromWindow)(HWND, DWORD);
+
+typedef BOOL (*boolean_function)(void);
+
+struct testwindow_info
+{
+    HWND hwnd;
+    BOOL registered;
+    RECT desired_rect;
+    UINT edge;
+    RECT allocated_rect;
+};
+
+static struct testwindow_info windows[3];
+
+static int expected_bottom;
+
+static void testwindow_setpos(HWND hwnd)
+{
+    struct testwindow_info* info = (struct testwindow_info*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+    APPBARDATA abd;
+    BOOL ret;
+
+    ok(info != NULL, "got unexpected ABN_POSCHANGED notification\n");
+
+    if (!info || !info->registered)
+    {
+        return;
+    }
+
+    abd.cbSize = sizeof(abd);
+    abd.hWnd = hwnd;
+    abd.uEdge = info->edge;
+    abd.rc = info->desired_rect;
+    ret = SHAppBarMessage(ABM_QUERYPOS, &abd);
+    ok(ret == TRUE, "SHAppBarMessage returned %i\n", ret);
+    switch (info->edge)
+    {
+        case ABE_BOTTOM:
+            ok(info->desired_rect.top == abd.rc.top, "ABM_QUERYPOS changed top of rect from %i to %i\n", info->desired_rect.top, abd.rc.top);
+            abd.rc.top = abd.rc.bottom - (info->desired_rect.bottom - info->desired_rect.top);
+            break;
+        case ABE_LEFT:
+            ok(info->desired_rect.right == abd.rc.right, "ABM_QUERYPOS changed right of rect from %i to %i\n", info->desired_rect.top, abd.rc.top);
+            abd.rc.right = abd.rc.left + (info->desired_rect.right - info->desired_rect.left);
+            break;
+        case ABE_RIGHT:
+            ok(info->desired_rect.left == abd.rc.left, "ABM_QUERYPOS changed left of rect from %i to %i\n", info->desired_rect.top, abd.rc.top);
+            abd.rc.left = abd.rc.right - (info->desired_rect.right - info->desired_rect.left);
+            break;
+        case ABE_TOP:
+            ok(info->desired_rect.bottom == abd.rc.bottom, "ABM_QUERYPOS changed bottom of rect from %i to %i\n", info->desired_rect.top, abd.rc.top);
+            abd.rc.bottom = abd.rc.top + (info->desired_rect.bottom - info->desired_rect.top);
+            break;
+    }
+
+    ret = SHAppBarMessage(ABM_SETPOS, &abd);
+    ok(ret == TRUE, "SHAppBarMessage returned %i\n", ret);
+
+    info->allocated_rect = abd.rc;
+    MoveWindow(hwnd, abd.rc.left, abd.rc.top, abd.rc.right-abd.rc.left, abd.rc.bottom-abd.rc.top, TRUE);
+}
+
+static LRESULT CALLBACK testwindow_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+    switch(msg)
+    {
+        case MSG_APPBAR:
+        {
+            switch(wparam)
+            {
+                case ABN_POSCHANGED:
+                    testwindow_setpos(hwnd);
+                    break;
+            }
+            return 0;
+        }
+    }
+
+    return DefWindowProc(hwnd, msg, wparam, lparam);
+}
+
+/* process pending messages until a condition is true or 3 seconds pass */
+static void do_events_until(boolean_function test)
+{
+    MSG msg;
+    UINT_PTR timerid;
+    BOOL timedout=FALSE;
+
+    timerid = SetTimer(0, 0, 3000, NULL);
+
+    while (1)
+    {
+        while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
+        {
+            if (msg.hwnd == 0 && msg.message == WM_TIMER && msg.wParam == timerid)
+                timedout = TRUE;
+            TranslateMessage(&msg);
+            DispatchMessageA(&msg);
+        }
+        if (timedout || test())
+            break;
+        WaitMessage();
+    }
+
+    KillTimer(0, timerid);
+}
+
+/* process any pending messages */
+static void do_events(void)
+{
+    MSG msg;
+
+    while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
+    {
+        TranslateMessage(&msg);
+        DispatchMessageA(&msg);
+    }
+}
+
+static BOOL no_appbars_intersect(void)
+{
+    int i, j;
+    RECT rc;
+
+    for (i=0; i<2; i++)
+    {
+        for (j=i+1; j<3; j++)
+        {
+            if (windows[i].registered && windows[j].registered &&
+                IntersectRect(&rc, &windows[i].allocated_rect, &windows[j].allocated_rect))
+                return FALSE;
+        }
+    }
+    return TRUE;
+}
+
+static BOOL got_expected_bottom(void)
+{
+    return (no_appbars_intersect() && windows[1].allocated_rect.bottom == expected_bottom);
+}
+
+static void register_testwindow_class(void)
+{
+    WNDCLASSEXA cls;
+
+    ZeroMemory(&cls, sizeof(cls));
+    cls.cbSize = sizeof(cls);
+    cls.style = 0;
+    cls.lpfnWndProc = testwindow_wndproc;
+    cls.hInstance = NULL;
+    cls.hCursor = LoadCursor(0, IDC_ARROW);
+    cls.hbrBackground = (HBRUSH) COLOR_WINDOW;
+    cls.lpszClassName = testwindow_class;
+
+    RegisterClassExA(&cls);
+}
+
+#define test_window_rects(a, b) \
+    ok(!IntersectRect(&rc, &windows[a].allocated_rect, &windows[b].allocated_rect), \
+        "rectangles intersect (%i,%i,%i,%i)/(%i,%i,%i,%i)\n", \
+        windows[a].allocated_rect.left, windows[a].allocated_rect.top, windows[a].allocated_rect.right, windows[a].allocated_rect.bottom, \
+        windows[b].allocated_rect.left, windows[b].allocated_rect.top, windows[b].allocated_rect.right, windows[b].allocated_rect.bottom)
+
+static void test_setpos(void)
+{
+    APPBARDATA abd;
+    RECT rc;
+    int screen_width, screen_height;
+    BOOL ret;
+
+    screen_width = GetSystemMetrics(SM_CXSCREEN);
+    screen_height = GetSystemMetrics(SM_CYSCREEN);
+
+    /* create and register windows[0] */
+    windows[0].hwnd = CreateWindowExA(WS_EX_TOOLWINDOW|WS_EX_TOPMOST,
+        testwindow_class, testwindow_class, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0,
+        NULL, NULL, NULL, NULL);
+    ok(windows[0].hwnd != NULL, "couldn't create window\n");
+    do_events();
+    abd.cbSize = sizeof(abd);
+    abd.hWnd = windows[0].hwnd;
+    abd.uCallbackMessage = MSG_APPBAR;
+    ret = SHAppBarMessage(ABM_NEW, &abd);
+    ok(ret == TRUE, "SHAppBarMessage returned %i\n", ret);
+
+    /* ABM_NEW should return FALSE if the window is already registered */
+    ret = SHAppBarMessage(ABM_NEW, &abd);
+    ok(ret == FALSE, "SHAppBarMessage returned %i\n", ret);
+    do_events();
+
+    /* dock windows[0] to the bottom of the screen */
+    windows[0].registered = TRUE;
+    windows[0].edge = ABE_BOTTOM;
+    windows[0].desired_rect.left = 0;
+    windows[0].desired_rect.right = screen_width;
+    windows[0].desired_rect.top = screen_height - 15;
+    windows[0].desired_rect.bottom = screen_height;
+    SetWindowLongPtr(windows[0].hwnd, GWLP_USERDATA, (LONG_PTR)&windows[0]);
+    testwindow_setpos(windows[0].hwnd);
+    do_events();
+
+    /* create and register windows[1] */
+    windows[1].hwnd = CreateWindowExA(WS_EX_TOOLWINDOW|WS_EX_TOPMOST,
+        testwindow_class, testwindow_class, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0,
+        NULL, NULL, NULL, NULL);
+    ok(windows[1].hwnd != NULL, "couldn't create window\n");
+    abd.hWnd = windows[1].hwnd;
+    ret = SHAppBarMessage(ABM_NEW, &abd);
+    ok(ret == TRUE, "SHAppBarMessage returned %i\n", ret);
+
+    /* dock windows[1] to the bottom of the screen */
+    windows[1].registered = TRUE;
+    windows[1].edge = ABE_BOTTOM;
+    windows[1].desired_rect.left = 0;
+    windows[1].desired_rect.right = screen_width;
+    windows[1].desired_rect.top = screen_height - 10;
+    windows[1].desired_rect.bottom = screen_height;
+    SetWindowLongPtr(windows[1].hwnd, GWLP_USERDATA, (LONG_PTR)&windows[1]);
+    testwindow_setpos(windows[1].hwnd);
+
+    /* the windows are adjusted to they don't overlap */
+    do_events_until(no_appbars_intersect);
+    test_window_rects(0, 1);
+
+    /* make windows[0] larger, forcing windows[1] to move out of its way */
+    windows[0].desired_rect.top = screen_height - 20;
+    testwindow_setpos(windows[0].hwnd);
+    do_events_until(no_appbars_intersect);
+    test_window_rects(0, 1);
+
+    /* create and register windows[2] */
+    windows[2].hwnd = CreateWindowExA(WS_EX_TOOLWINDOW|WS_EX_TOPMOST,
+        testwindow_class, testwindow_class, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0,
+        NULL, NULL, NULL, NULL);
+    ok(windows[2].hwnd != NULL, "couldn't create window\n");
+    do_events();
+
+    abd.hWnd = windows[2].hwnd;
+    ret = SHAppBarMessage(ABM_NEW, &abd);
+    ok(ret == TRUE, "SHAppBarMessage returned %i\n", ret);
+
+    /* dock windows[2] to the bottom of the screen */
+    windows[2].registered = TRUE;
+    windows[2].edge = ABE_BOTTOM;
+    windows[2].desired_rect.left = 0;
+    windows[2].desired_rect.right = screen_width;
+    windows[2].desired_rect.top = screen_height - 10;
+    windows[2].desired_rect.bottom = screen_height;
+    SetWindowLongPtr(windows[2].hwnd, GWLP_USERDATA, (LONG_PTR)&windows[2]);
+    testwindow_setpos(windows[2].hwnd);
+
+    do_events_until(no_appbars_intersect);
+    test_window_rects(0, 1);
+    test_window_rects(0, 2);
+    test_window_rects(1, 2);
+
+    /* move windows[2] to the right side of the screen */
+    windows[2].edge = ABE_RIGHT;
+    windows[2].desired_rect.left = screen_width - 15;
+    windows[2].desired_rect.right = screen_width;
+    windows[2].desired_rect.top = 0;
+    windows[2].desired_rect.bottom = screen_height;
+    testwindow_setpos(windows[2].hwnd);
+
+    do_events_until(no_appbars_intersect);
+    test_window_rects(0, 1);
+    test_window_rects(0, 2);
+    test_window_rects(1, 2);
+
+    /* move windows[1] to the top of the screen */
+    windows[1].edge = ABE_TOP;
+    windows[1].desired_rect.left = 0;
+    windows[1].desired_rect.right = screen_width;
+    windows[1].desired_rect.top = 0;
+    windows[1].desired_rect.bottom = 15;
+    testwindow_setpos(windows[1].hwnd);
+
+    do_events_until(no_appbars_intersect);
+    test_window_rects(0, 1);
+    test_window_rects(0, 2);
+    test_window_rects(1, 2);
+
+    /* move windows[1] back to the bottom of the screen */
+    windows[1].edge = ABE_BOTTOM;
+    windows[1].desired_rect.left = 0;
+    windows[1].desired_rect.right = screen_width;
+    windows[1].desired_rect.top = screen_height - 10;
+    windows[1].desired_rect.bottom = screen_height;
+    testwindow_setpos(windows[1].hwnd);
+
+    do_events_until(no_appbars_intersect);
+    test_window_rects(0, 1);
+    test_window_rects(0, 2);
+    test_window_rects(1, 2);
+
+    /* removing windows[0] will cause windows[1] to move down into its space */
+    expected_bottom = max(windows[0].allocated_rect.bottom, windows[1].allocated_rect.bottom);
+
+    abd.hWnd = windows[0].hwnd;
+    ret = SHAppBarMessage(ABM_REMOVE, &abd);
+    ok(ret == TRUE, "SHAppBarMessage returned %i\n", ret);
+    windows[0].registered = FALSE;
+    DestroyWindow(windows[0].hwnd);
+
+    do_events_until(got_expected_bottom);
+
+    ok(windows[1].allocated_rect.bottom == expected_bottom, "windows[1]'s bottom is %i, expected %i\n", windows[1].allocated_rect.bottom, expected_bottom);
+
+    test_window_rects(1, 2);
+
+    /* remove the other windows */
+    abd.hWnd = windows[1].hwnd;
+    ret = SHAppBarMessage(ABM_REMOVE, &abd);
+    ok(ret == TRUE, "SHAppBarMessage returned %i\n", ret);
+    windows[1].registered = FALSE;
+    DestroyWindow(windows[1].hwnd);
+
+    abd.hWnd = windows[2].hwnd;
+    ret = SHAppBarMessage(ABM_REMOVE, &abd);
+    ok(ret == TRUE, "SHAppBarMessage returned %i\n", ret);
+    windows[2].registered = FALSE;
+    DestroyWindow(windows[2].hwnd);
+}
+
+static void test_appbarget(void)
+{
+    APPBARDATA abd;
+    HWND hwnd, foregnd, unset_hwnd;
+    UINT_PTR ret;
+
+    memset(&abd, 0xcc, sizeof(abd));
+    memset(&unset_hwnd, 0xcc, sizeof(unset_hwnd));
+    abd.cbSize = sizeof(abd);
+    abd.uEdge = ABE_BOTTOM;
+
+    hwnd = (HWND)SHAppBarMessage(ABM_GETAUTOHIDEBAR, &abd);
+    ok(hwnd == NULL || IsWindow(hwnd), "ret %p which is not a window\n", hwnd);
+    ok(abd.hWnd == unset_hwnd, "hWnd overwritten %p\n",abd.hWnd);
+
+    if (!pMonitorFromWindow)
+    {
+        win_skip("MonitorFromWindow is not available\n");
+    }
+    else
+    {
+        /* Presumably one can pass a hwnd with ABM_GETAUTOHIDEBAR to specify a monitor.
+           Pass the foreground window and check */
+        foregnd = GetForegroundWindow();
+        if(foregnd)
+        {
+            abd.hWnd = foregnd;
+            hwnd = (HWND)SHAppBarMessage(ABM_GETAUTOHIDEBAR, &abd);
+            ok(hwnd == NULL || IsWindow(hwnd), "ret %p which is not a window\n", hwnd);
+            ok(abd.hWnd == foregnd, "hWnd overwritten\n");
+            if(hwnd)
+            {
+                HMONITOR appbar_mon, foregnd_mon;
+                appbar_mon = pMonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
+                foregnd_mon = pMonitorFromWindow(foregnd, MONITOR_DEFAULTTONEAREST);
+                ok(appbar_mon == foregnd_mon, "Windows on different monitors\n");
+            }
+        }
+    }
+
+    memset(&abd, 0xcc, sizeof(abd));
+    abd.cbSize = sizeof(abd);
+    ret = SHAppBarMessage(ABM_GETTASKBARPOS, &abd);
+    if(ret)
+    {
+        ok(abd.hWnd == (HWND)0xcccccccc, "hWnd overwritten\n");
+        ok(abd.uEdge <= ABE_BOTTOM, "uEdge not returned\n");
+        ok(abd.rc.left != 0xcccccccc, "rc not updated\n");
+    }
+
+    return;
+}
+
+START_TEST(appbar)
+{
+    HMODULE huser32;
+
+    huser32 = GetModuleHandleA("user32.dll");
+    pMonitorFromWindow = (void*)GetProcAddress(huser32, "MonitorFromWindow");
+
+    register_testwindow_class();
+
+    test_setpos();
+    test_appbarget();
+}
diff --git a/rostests/winetests/shell32/autocomplete.c b/rostests/winetests/shell32/autocomplete.c
new file mode 100644 (file)
index 0000000..20315c7
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Tests for autocomplete
+ *
+ * Copyright 2008 Jan de Mooij
+ *
+ * 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
+ */
+
+#define COBJMACROS
+
+#include <wine/test.h>
+#include <stdarg.h>
+
+#include "windows.h"
+#include "shobjidl.h"
+#include "shlguid.h"
+#include "initguid.h"
+#include "shldisp.h"
+
+static HWND hMainWnd, hEdit;
+static HINSTANCE hinst;
+static int killfocus_count;
+
+static BOOL test_init(void) {
+    HRESULT r;
+    IAutoComplete* ac;
+    IUnknown *acSource;
+
+    /* AutoComplete instance */
+    r = CoCreateInstance(&CLSID_AutoComplete, NULL, CLSCTX_INPROC_SERVER,
+                         &IID_IAutoComplete, (LPVOID*)&ac);
+    if (r == REGDB_E_CLASSNOTREG)
+    {
+        win_skip("CLSID_AutoComplete is not registered\n");
+        return FALSE;
+    }
+    ok(SUCCEEDED(r), "no IID_IAutoComplete (0x%08x)\n", r);
+
+    /* AutoComplete source */
+    r = CoCreateInstance(&CLSID_ACLMulti, NULL, CLSCTX_INPROC_SERVER,
+                        &IID_IACList, (LPVOID*)&acSource);
+    if (r == REGDB_E_CLASSNOTREG)
+    {
+        win_skip("CLSID_ACLMulti is not registered\n");
+        return FALSE;
+    }
+    ok(SUCCEEDED(r), "no IID_IACList (0x%08x)\n", r);
+
+    /* bind to edit control */
+    r = IAutoComplete_Init(ac, hEdit, acSource, NULL, NULL);
+    ok(SUCCEEDED(r), "Init failed (0x%08x)\n", r);
+
+    return TRUE;
+}
+static void test_killfocus(void) {
+    /* Test if WM_KILLFOCUS messages are handled properly by checking if
+     * the parent receives an EN_KILLFOCUS message. */
+    SetFocus(hEdit);
+    killfocus_count = 0;
+    SetFocus(0);
+    ok(killfocus_count == 1, "Expected one EN_KILLFOCUS message, got: %d\n", killfocus_count);
+}
+static LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
+    switch(msg) {
+    case WM_CREATE:
+        /* create edit control */
+        hEdit = CreateWindowEx(0, "EDIT", "Some text", 0, 10, 10, 300, 300,
+                    hWnd, NULL, hinst, NULL);
+        ok(hEdit != NULL, "Can't create edit control\n");
+        break;
+    case WM_COMMAND:
+        if(HIWORD(wParam) == EN_KILLFOCUS)
+            killfocus_count++;
+        break;
+    }
+    return DefWindowProcA(hWnd, msg, wParam, lParam);
+}
+static void createMainWnd(void) {
+    WNDCLASSA wc;
+    wc.style = CS_HREDRAW | CS_VREDRAW;
+    wc.cbClsExtra = 0;
+    wc.cbWndExtra = 0;
+    wc.hInstance = GetModuleHandleA(NULL);
+    wc.hIcon = NULL;
+    wc.hCursor = LoadCursorA(NULL, IDC_IBEAM);
+    wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
+    wc.lpszMenuName = NULL;
+    wc.lpszClassName = "MyTestWnd";
+    wc.lpfnWndProc = MyWndProc;
+    RegisterClassA(&wc);
+
+    hMainWnd = CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW,
+      CW_USEDEFAULT, CW_USEDEFAULT, 130, 105, NULL, NULL, GetModuleHandleA(NULL), 0);
+}
+START_TEST(autocomplete) {
+    HRESULT r;
+    MSG msg;
+
+    r = CoInitialize(NULL);
+    ok(SUCCEEDED(r), "CoInitialize failed (0x%08x). Tests aborted.\n", r);
+    if (FAILED(r))
+        return;
+
+    createMainWnd();
+
+    if(!ok(hMainWnd != NULL, "Failed to create parent window. Tests aborted.\n"))
+        return;
+
+    if (!test_init())
+        goto cleanup;
+    test_killfocus();
+
+    PostQuitMessage(0);
+    while(GetMessageA(&msg,0,0,0)) {
+        TranslateMessage(&msg);
+        DispatchMessageA(&msg);
+    }
+
+cleanup:
+    DestroyWindow(hEdit);
+    DestroyWindow(hMainWnd);
+
+    CoUninitialize();
+}
index 7e8d281..76eec39 100755 (executable)
@@ -1,4 +1,4 @@
-/* File generated automatically from tools/winapi/test.dat; do not edit! */
+/* File generated automatically from tools/winapi/tests.dat; do not edit! */
 /* This file can be copied, modified and distributed without restriction. */
 
 /*
  * Windows API extension
  */
 
-#if defined(_MSC_VER) && (_MSC_VER >= 1300) && defined(__cplusplus)
-# define FIELD_ALIGNMENT(type, field) __alignof(((type*)0)->field)
-#elif defined(__GNUC__)
-# define FIELD_ALIGNMENT(type, field) __alignof__(((type*)0)->field)
-#else
-/* FIXME: Not sure if is possible to do without compiler extension */
-#endif
-
 #if defined(_MSC_VER) && (_MSC_VER >= 1300) && defined(__cplusplus)
 # define _TYPE_ALIGNMENT(type) __alignof(type)
 #elif defined(__GNUC__)
 # define _TYPE_ALIGNMENT(type) __alignof__(type)
 #else
 /*
- * FIXME: Not sure if is possible to do without compiler extension
- *        (if type is not just a name that is, if so the normal)
+ * FIXME: May not be possible without a compiler extension
+ *        (if type is not just a name that is, otherwise the normal
  *         TYPE_ALIGNMENT can be used)
  */
 #endif
  * Test helper macros
  */
 
-#ifdef FIELD_ALIGNMENT
-# define TEST_FIELD_ALIGNMENT(type, field, align) \
-   ok(FIELD_ALIGNMENT(type, field) == align, \
-       "FIELD_ALIGNMENT(" #type ", " #field ") == %d (expected " #align ")\n", \
-           (int)FIELD_ALIGNMENT(type, field))
-#else
-# define TEST_FIELD_ALIGNMENT(type, field, align) do { } while (0)
-#endif
+#ifdef _WIN64
 
-#define TEST_FIELD_OFFSET(type, field, offset) \
-    ok(FIELD_OFFSET(type, field) == offset, \
-        "FIELD_OFFSET(" #type ", " #field ") == %ld (expected " #offset ")\n", \
-             (long int)FIELD_OFFSET(type, field))
+# define TEST_TYPE_SIZE(type, size)
+# define TEST_TYPE_ALIGN(type, align)
+# define TEST_TARGET_ALIGN(type, align)
+# define TEST_FIELD_ALIGN(type, field, align)
+# define TEST_FIELD_OFFSET(type, field, offset)
 
-#ifdef _TYPE_ALIGNMENT
-#define TEST__TYPE_ALIGNMENT(type, align) \
-    ok(_TYPE_ALIGNMENT(type) == align, "TYPE_ALIGNMENT(" #type ") == %d (expected " #align ")\n", (int)_TYPE_ALIGNMENT(type))
 #else
-# define TEST__TYPE_ALIGNMENT(type, align) do { } while (0)
-#endif
-
-#ifdef TYPE_ALIGNMENT
-#define TEST_TYPE_ALIGNMENT(type, align) \
-    ok(TYPE_ALIGNMENT(type) == align, "TYPE_ALIGNMENT(" #type ") == %d (expected " #align ")\n", (int)TYPE_ALIGNMENT(type))
-#else
-# define TEST_TYPE_ALIGNMENT(type, align) do { } while (0)
-#endif
 
-#define TEST_TYPE_SIZE(type, size) \
-    ok(sizeof(type) == size, "sizeof(" #type ") == %d (expected " #size ")\n", ((int) sizeof(type)))
+# define TEST_TYPE_SIZE(type, size)             C_ASSERT(sizeof(type) == size);
 
-/***********************************************************************
- * Test macros
- */
+# ifdef TYPE_ALIGNMENT
+#  define TEST_TYPE_ALIGN(type, align)          C_ASSERT(TYPE_ALIGNMENT(type) == align);
+# else
+#  define TEST_TYPE_ALIGN(type, align)
+# endif
 
-#define TEST_FIELD(type, field_type, field_name, field_offset, field_size, field_align) \
-  TEST_TYPE_SIZE(field_type, field_size); \
-  TEST_FIELD_ALIGNMENT(type, field_name, field_align); \
-  TEST_FIELD_OFFSET(type, field_name, field_offset); \
+# ifdef _TYPE_ALIGNMENT
+#  define TEST_TARGET_ALIGN(type, align)        C_ASSERT(_TYPE_ALIGNMENT(*(type)0) == align);
+#  define TEST_FIELD_ALIGN(type, field, align)  C_ASSERT(_TYPE_ALIGNMENT(((type*)0)->field) == align);
+# else
+#  define TEST_TARGET_ALIGN(type, align)
+#  define TEST_FIELD_ALIGN(type, field, align)
+# endif
 
-#define TEST_TYPE(type, size, align) \
-  TEST_TYPE_ALIGNMENT(type, align); \
-  TEST_TYPE_SIZE(type, size)
+# define TEST_FIELD_OFFSET(type, field, offset) C_ASSERT(FIELD_OFFSET(type, field) == offset);
 
-#define TEST_TYPE_POINTER(type, size, align) \
-    TEST__TYPE_ALIGNMENT(*(type)0, align); \
-    TEST_TYPE_SIZE(*(type)0, size)
+#endif
 
-#define TEST_TYPE_SIGNED(type) \
-    ok((type) -1 < 0, "(" #type ") -1 < 0\n");
+#define TEST_TARGET_SIZE(type, size)            TEST_TYPE_SIZE(*(type)0, size)
+#define TEST_FIELD_SIZE(type, field, size)      TEST_TYPE_SIZE((((type*)0)->field), size)
+#define TEST_TYPE_SIGNED(type)                  C_ASSERT((type) -1 < 0);
+#define TEST_TYPE_UNSIGNED(type)                C_ASSERT((type) -1 > 0);
 
-#define TEST_TYPE_UNSIGNED(type) \
-     ok((type) -1 > 0, "(" #type ") -1 > 0\n");
 
 static void test_pack_BLOB(void)
 {
     /* BLOB (pack 4) */
-    TEST_TYPE(BLOB, 8, 4);
-    TEST_FIELD(BLOB, ULONG, cbSize, 0, 4, 4);
-    TEST_FIELD(BLOB, BYTE *, pBlobData, 4, 4, 4);
+    TEST_TYPE_SIZE   (BLOB, 8)
+    TEST_TYPE_ALIGN  (BLOB, 4)
+    TEST_FIELD_SIZE  (BLOB, cbSize, 4)
+    TEST_FIELD_ALIGN (BLOB, cbSize, 4)
+    TEST_FIELD_OFFSET(BLOB, cbSize, 0)
+    TEST_FIELD_SIZE  (BLOB, pBlobData, 4)
+    TEST_FIELD_ALIGN (BLOB, pBlobData, 4)
+    TEST_FIELD_OFFSET(BLOB, pBlobData, 4)
 }
 
 static void test_pack_BSTR(void)
 {
     /* BSTR */
-    TEST_TYPE(BSTR, 4, 4);
-    TEST_TYPE_POINTER(BSTR, 2, 2);
+    TEST_TYPE_SIZE   (BSTR, 4)
+    TEST_TYPE_ALIGN  (BSTR, 4)
+    TEST_TARGET_SIZE (BSTR, 2)
+    TEST_TARGET_ALIGN(BSTR, 2)
 }
 
 static void test_pack_BSTRBLOB(void)
 {
     /* BSTRBLOB (pack 4) */
-    TEST_TYPE(BSTRBLOB, 8, 4);
-    TEST_FIELD(BSTRBLOB, ULONG, cbSize, 0, 4, 4);
-    TEST_FIELD(BSTRBLOB, BYTE *, pData, 4, 4, 4);
+    TEST_TYPE_SIZE   (BSTRBLOB, 8)
+    TEST_TYPE_ALIGN  (BSTRBLOB, 4)
+    TEST_FIELD_SIZE  (BSTRBLOB, cbSize, 4)
+    TEST_FIELD_ALIGN (BSTRBLOB, cbSize, 4)
+    TEST_FIELD_OFFSET(BSTRBLOB, cbSize, 0)
+    TEST_FIELD_SIZE  (BSTRBLOB, pData, 4)
+    TEST_FIELD_ALIGN (BSTRBLOB, pData, 4)
+    TEST_FIELD_OFFSET(BSTRBLOB, pData, 4)
 }
 
 static void test_pack_BYTE_BLOB(void)
 {
     /* BYTE_BLOB (pack 4) */
-    TEST_TYPE(BYTE_BLOB, 8, 4);
-    TEST_FIELD(BYTE_BLOB, unsigned long, clSize, 0, 4, 4);
-    TEST_FIELD(BYTE_BLOB, byte[1], abData, 4, 1, 1);
+    TEST_TYPE_SIZE   (BYTE_BLOB, 8)
+    TEST_TYPE_ALIGN  (BYTE_BLOB, 4)
+    TEST_FIELD_SIZE  (BYTE_BLOB, clSize, 4)
+    TEST_FIELD_ALIGN (BYTE_BLOB, clSize, 4)
+    TEST_FIELD_OFFSET(BYTE_BLOB, clSize, 0)
+    TEST_FIELD_SIZE  (BYTE_BLOB, abData, 1)
+    TEST_FIELD_ALIGN (BYTE_BLOB, abData, 1)
+    TEST_FIELD_OFFSET(BYTE_BLOB, abData, 4)
 }
 
 static void test_pack_BYTE_SIZEDARR(void)
 {
     /* BYTE_SIZEDARR (pack 4) */
-    TEST_TYPE(BYTE_SIZEDARR, 8, 4);
-    TEST_FIELD(BYTE_SIZEDARR, unsigned long, clSize, 0, 4, 4);
-    TEST_FIELD(BYTE_SIZEDARR, byte *, pData, 4, 4, 4);
+    TEST_TYPE_SIZE   (BYTE_SIZEDARR, 8)
+    TEST_TYPE_ALIGN  (BYTE_SIZEDARR, 4)
+    TEST_FIELD_SIZE  (BYTE_SIZEDARR, clSize, 4)
+    TEST_FIELD_ALIGN (BYTE_SIZEDARR, clSize, 4)
+    TEST_FIELD_OFFSET(BYTE_SIZEDARR, clSize, 0)
+    TEST_FIELD_SIZE  (BYTE_SIZEDARR, pData, 4)
+    TEST_FIELD_ALIGN (BYTE_SIZEDARR, pData, 4)
+    TEST_FIELD_OFFSET(BYTE_SIZEDARR, pData, 4)
 }
 
 static void test_pack_CLIPDATA(void)
 {
     /* CLIPDATA (pack 4) */
-    TEST_TYPE(CLIPDATA, 12, 4);
-    TEST_FIELD(CLIPDATA, ULONG, cbSize, 0, 4, 4);
-    TEST_FIELD(CLIPDATA, long, ulClipFmt, 4, 4, 4);
-    TEST_FIELD(CLIPDATA, BYTE *, pClipData, 8, 4, 4);
+    TEST_TYPE_SIZE   (CLIPDATA, 12)
+    TEST_TYPE_ALIGN  (CLIPDATA, 4)
+    TEST_FIELD_SIZE  (CLIPDATA, cbSize, 4)
+    TEST_FIELD_ALIGN (CLIPDATA, cbSize, 4)
+    TEST_FIELD_OFFSET(CLIPDATA, cbSize, 0)
+    TEST_FIELD_SIZE  (CLIPDATA, ulClipFmt, 4)
+    TEST_FIELD_ALIGN (CLIPDATA, ulClipFmt, 4)
+    TEST_FIELD_OFFSET(CLIPDATA, ulClipFmt, 4)
+    TEST_FIELD_SIZE  (CLIPDATA, pClipData, 4)
+    TEST_FIELD_ALIGN (CLIPDATA, pClipData, 4)
+    TEST_FIELD_OFFSET(CLIPDATA, pClipData, 8)
 }
 
 static void test_pack_CLIPFORMAT(void)
 {
     /* CLIPFORMAT */
-    TEST_TYPE(CLIPFORMAT, 2, 2);
-    TEST_TYPE_UNSIGNED(CLIPFORMAT);
+    TEST_TYPE_SIZE   (CLIPFORMAT, 2)
+    TEST_TYPE_ALIGN  (CLIPFORMAT, 2)
+    TEST_TYPE_UNSIGNED(CLIPFORMAT)
 }
 
 static void test_pack_COAUTHIDENTITY(void)
 {
     /* COAUTHIDENTITY (pack 4) */
-    TEST_TYPE(COAUTHIDENTITY, 28, 4);
-    TEST_FIELD(COAUTHIDENTITY, USHORT *, User, 0, 4, 4);
-    TEST_FIELD(COAUTHIDENTITY, ULONG, UserLength, 4, 4, 4);
-    TEST_FIELD(COAUTHIDENTITY, USHORT *, Domain, 8, 4, 4);
-    TEST_FIELD(COAUTHIDENTITY, ULONG, DomainLength, 12, 4, 4);
-    TEST_FIELD(COAUTHIDENTITY, USHORT *, Password, 16, 4, 4);
-    TEST_FIELD(COAUTHIDENTITY, ULONG, PasswordLength, 20, 4, 4);
-    TEST_FIELD(COAUTHIDENTITY, ULONG, Flags, 24, 4, 4);
+    TEST_TYPE_SIZE   (COAUTHIDENTITY, 28)
+    TEST_TYPE_ALIGN  (COAUTHIDENTITY, 4)
+    TEST_FIELD_SIZE  (COAUTHIDENTITY, User, 4)
+    TEST_FIELD_ALIGN (COAUTHIDENTITY, User, 4)
+    TEST_FIELD_OFFSET(COAUTHIDENTITY, User, 0)
+    TEST_FIELD_SIZE  (COAUTHIDENTITY, UserLength, 4)
+    TEST_FIELD_ALIGN (COAUTHIDENTITY, UserLength, 4)
+    TEST_FIELD_OFFSET(COAUTHIDENTITY, UserLength, 4)
+    TEST_FIELD_SIZE  (COAUTHIDENTITY, Domain, 4)
+    TEST_FIELD_ALIGN (COAUTHIDENTITY, Domain, 4)
+    TEST_FIELD_OFFSET(COAUTHIDENTITY, Domain, 8)
+    TEST_FIELD_SIZE  (COAUTHIDENTITY, DomainLength, 4)
+    TEST_FIELD_ALIGN (COAUTHIDENTITY, DomainLength, 4)
+    TEST_FIELD_OFFSET(COAUTHIDENTITY, DomainLength, 12)
+    TEST_FIELD_SIZE  (COAUTHIDENTITY, Password, 4)
+    TEST_FIELD_ALIGN (COAUTHIDENTITY, Password, 4)
+    TEST_FIELD_OFFSET(COAUTHIDENTITY, Password, 16)
+    TEST_FIELD_SIZE  (COAUTHIDENTITY, PasswordLength, 4)
+    TEST_FIELD_ALIGN (COAUTHIDENTITY, PasswordLength, 4)
+    TEST_FIELD_OFFSET(COAUTHIDENTITY, PasswordLength, 20)
+    TEST_FIELD_SIZE  (COAUTHIDENTITY, Flags, 4)
+    TEST_FIELD_ALIGN (COAUTHIDENTITY, Flags, 4)
+    TEST_FIELD_OFFSET(COAUTHIDENTITY, Flags, 24)
 }
 
 static void test_pack_COAUTHINFO(void)
 {
     /* COAUTHINFO (pack 4) */
-    TEST_TYPE(COAUTHINFO, 28, 4);
-    TEST_FIELD(COAUTHINFO, DWORD, dwAuthnSvc, 0, 4, 4);
-    TEST_FIELD(COAUTHINFO, DWORD, dwAuthzSvc, 4, 4, 4);
-    TEST_FIELD(COAUTHINFO, LPWSTR, pwszServerPrincName, 8, 4, 4);
-    TEST_FIELD(COAUTHINFO, DWORD, dwAuthnLevel, 12, 4, 4);
-    TEST_FIELD(COAUTHINFO, DWORD, dwImpersonationLevel, 16, 4, 4);
-    TEST_FIELD(COAUTHINFO, COAUTHIDENTITY *, pAuthIdentityData, 20, 4, 4);
-    TEST_FIELD(COAUTHINFO, DWORD, dwCapabilities, 24, 4, 4);
+    TEST_TYPE_SIZE   (COAUTHINFO, 28)
+    TEST_TYPE_ALIGN  (COAUTHINFO, 4)
+    TEST_FIELD_SIZE  (COAUTHINFO, dwAuthnSvc, 4)
+    TEST_FIELD_ALIGN (COAUTHINFO, dwAuthnSvc, 4)
+    TEST_FIELD_OFFSET(COAUTHINFO, dwAuthnSvc, 0)
+    TEST_FIELD_SIZE  (COAUTHINFO, dwAuthzSvc, 4)
+    TEST_FIELD_ALIGN (COAUTHINFO, dwAuthzSvc, 4)
+    TEST_FIELD_OFFSET(COAUTHINFO, dwAuthzSvc, 4)
+    TEST_FIELD_SIZE  (COAUTHINFO, pwszServerPrincName, 4)
+    TEST_FIELD_ALIGN (COAUTHINFO, pwszServerPrincName, 4)
+    TEST_FIELD_OFFSET(COAUTHINFO, pwszServerPrincName, 8)
+    TEST_FIELD_SIZE  (COAUTHINFO, dwAuthnLevel, 4)
+    TEST_FIELD_ALIGN (COAUTHINFO, dwAuthnLevel, 4)
+    TEST_FIELD_OFFSET(COAUTHINFO, dwAuthnLevel, 12)
+    TEST_FIELD_SIZE  (COAUTHINFO, dwImpersonationLevel, 4)
+    TEST_FIELD_ALIGN (COAUTHINFO, dwImpersonationLevel, 4)
+    TEST_FIELD_OFFSET(COAUTHINFO, dwImpersonationLevel, 16)
+    TEST_FIELD_SIZE  (COAUTHINFO, pAuthIdentityData, 4)
+    TEST_FIELD_ALIGN (COAUTHINFO, pAuthIdentityData, 4)
+    TEST_FIELD_OFFSET(COAUTHINFO, pAuthIdentityData, 20)
+    TEST_FIELD_SIZE  (COAUTHINFO, dwCapabilities, 4)
+    TEST_FIELD_ALIGN (COAUTHINFO, dwCapabilities, 4)
+    TEST_FIELD_OFFSET(COAUTHINFO, dwCapabilities, 24)
 }
 
 static void test_pack_DATE(void)
 {
     /* DATE */
-    TEST_TYPE(DATE, 8, 8);
+    TEST_TYPE_SIZE   (DATE, 8)
+    TEST_TYPE_ALIGN  (DATE, 8)
 }
 
 static void test_pack_DOUBLE(void)
 {
     /* DOUBLE */
-    TEST_TYPE(DOUBLE, 8, 8);
+    TEST_TYPE_SIZE   (DOUBLE, 8)
+    TEST_TYPE_ALIGN  (DOUBLE, 8)
 }
 
 static void test_pack_DWORD_SIZEDARR(void)
 {
     /* DWORD_SIZEDARR (pack 4) */
-    TEST_TYPE(DWORD_SIZEDARR, 8, 4);
-    TEST_FIELD(DWORD_SIZEDARR, unsigned long, clSize, 0, 4, 4);
-    TEST_FIELD(DWORD_SIZEDARR, unsigned long *, pData, 4, 4, 4);
+    TEST_TYPE_SIZE   (DWORD_SIZEDARR, 8)
+    TEST_TYPE_ALIGN  (DWORD_SIZEDARR, 4)
+    TEST_FIELD_SIZE  (DWORD_SIZEDARR, clSize, 4)
+    TEST_FIELD_ALIGN (DWORD_SIZEDARR, clSize, 4)
+    TEST_FIELD_OFFSET(DWORD_SIZEDARR, clSize, 0)
+    TEST_FIELD_SIZE  (DWORD_SIZEDARR, pData, 4)
+    TEST_FIELD_ALIGN (DWORD_SIZEDARR, pData, 4)
+    TEST_FIELD_OFFSET(DWORD_SIZEDARR, pData, 4)
 }
 
 static void test_pack_FLAGGED_BYTE_BLOB(void)
 {
     /* FLAGGED_BYTE_BLOB (pack 4) */
-    TEST_TYPE(FLAGGED_BYTE_BLOB, 12, 4);
-    TEST_FIELD(FLAGGED_BYTE_BLOB, unsigned long, fFlags, 0, 4, 4);
-    TEST_FIELD(FLAGGED_BYTE_BLOB, unsigned long, clSize, 4, 4, 4);
-    TEST_FIELD(FLAGGED_BYTE_BLOB, byte[1], abData, 8, 1, 1);
+    TEST_TYPE_SIZE   (FLAGGED_BYTE_BLOB, 12)
+    TEST_TYPE_ALIGN  (FLAGGED_BYTE_BLOB, 4)
+    TEST_FIELD_SIZE  (FLAGGED_BYTE_BLOB, fFlags, 4)
+    TEST_FIELD_ALIGN (FLAGGED_BYTE_BLOB, fFlags, 4)
+    TEST_FIELD_OFFSET(FLAGGED_BYTE_BLOB, fFlags, 0)
+    TEST_FIELD_SIZE  (FLAGGED_BYTE_BLOB, clSize, 4)
+    TEST_FIELD_ALIGN (FLAGGED_BYTE_BLOB, clSize, 4)
+    TEST_FIELD_OFFSET(FLAGGED_BYTE_BLOB, clSize, 4)
+    TEST_FIELD_SIZE  (FLAGGED_BYTE_BLOB, abData, 1)
+    TEST_FIELD_ALIGN (FLAGGED_BYTE_BLOB, abData, 1)
+    TEST_FIELD_OFFSET(FLAGGED_BYTE_BLOB, abData, 8)
 }
 
 static void test_pack_FLAGGED_WORD_BLOB(void)
 {
     /* FLAGGED_WORD_BLOB (pack 4) */
-    TEST_TYPE(FLAGGED_WORD_BLOB, 12, 4);
-    TEST_FIELD(FLAGGED_WORD_BLOB, unsigned long, fFlags, 0, 4, 4);
-    TEST_FIELD(FLAGGED_WORD_BLOB, unsigned long, clSize, 4, 4, 4);
-    TEST_FIELD(FLAGGED_WORD_BLOB, unsigned short[1], asData, 8, 2, 2);
+    TEST_TYPE_SIZE   (FLAGGED_WORD_BLOB, 12)
+    TEST_TYPE_ALIGN  (FLAGGED_WORD_BLOB, 4)
+    TEST_FIELD_SIZE  (FLAGGED_WORD_BLOB, fFlags, 4)
+    TEST_FIELD_ALIGN (FLAGGED_WORD_BLOB, fFlags, 4)
+    TEST_FIELD_OFFSET(FLAGGED_WORD_BLOB, fFlags, 0)
+    TEST_FIELD_SIZE  (FLAGGED_WORD_BLOB, clSize, 4)
+    TEST_FIELD_ALIGN (FLAGGED_WORD_BLOB, clSize, 4)
+    TEST_FIELD_OFFSET(FLAGGED_WORD_BLOB, clSize, 4)
+    TEST_FIELD_SIZE  (FLAGGED_WORD_BLOB, asData, 2)
+    TEST_FIELD_ALIGN (FLAGGED_WORD_BLOB, asData, 2)
+    TEST_FIELD_OFFSET(FLAGGED_WORD_BLOB, asData, 8)
 }
 
 static void test_pack_HMETAFILEPICT(void)
 {
     /* HMETAFILEPICT */
-    TEST_TYPE(HMETAFILEPICT, 4, 4);
+    TEST_TYPE_SIZE   (HMETAFILEPICT, 4)
+    TEST_TYPE_ALIGN  (HMETAFILEPICT, 4)
 }
 
 static void test_pack_HYPER_SIZEDARR(void)
 {
     /* HYPER_SIZEDARR (pack 4) */
-    TEST_TYPE(HYPER_SIZEDARR, 8, 4);
-    TEST_FIELD(HYPER_SIZEDARR, unsigned long, clSize, 0, 4, 4);
-    TEST_FIELD(HYPER_SIZEDARR, hyper *, pData, 4, 4, 4);
+    TEST_TYPE_SIZE   (HYPER_SIZEDARR, 8)
+    TEST_TYPE_ALIGN  (HYPER_SIZEDARR, 4)
+    TEST_FIELD_SIZE  (HYPER_SIZEDARR, clSize, 4)
+    TEST_FIELD_ALIGN (HYPER_SIZEDARR, clSize, 4)
+    TEST_FIELD_OFFSET(HYPER_SIZEDARR, clSize, 0)
+    TEST_FIELD_SIZE  (HYPER_SIZEDARR, pData, 4)
+    TEST_FIELD_ALIGN (HYPER_SIZEDARR, pData, 4)
+    TEST_FIELD_OFFSET(HYPER_SIZEDARR, pData, 4)
 }
 
 static void test_pack_LPBLOB(void)
 {
     /* LPBLOB */
-    TEST_TYPE(LPBLOB, 4, 4);
+    TEST_TYPE_SIZE   (LPBLOB, 4)
+    TEST_TYPE_ALIGN  (LPBLOB, 4)
 }
 
 static void test_pack_LPBSTR(void)
 {
     /* LPBSTR */
-    TEST_TYPE(LPBSTR, 4, 4);
-    TEST_TYPE_POINTER(LPBSTR, 4, 4);
+    TEST_TYPE_SIZE   (LPBSTR, 4)
+    TEST_TYPE_ALIGN  (LPBSTR, 4)
+    TEST_TARGET_SIZE (LPBSTR, 4)
+    TEST_TARGET_ALIGN(LPBSTR, 4)
 }
 
 static void test_pack_LPBSTRBLOB(void)
 {
     /* LPBSTRBLOB */
-    TEST_TYPE(LPBSTRBLOB, 4, 4);
+    TEST_TYPE_SIZE   (LPBSTRBLOB, 4)
+    TEST_TYPE_ALIGN  (LPBSTRBLOB, 4)
 }
 
 static void test_pack_LPCOLESTR(void)
 {
     /* LPCOLESTR */
-    TEST_TYPE(LPCOLESTR, 4, 4);
-    TEST_TYPE_POINTER(LPCOLESTR, 2, 2);
+    TEST_TYPE_SIZE   (LPCOLESTR, 4)
+    TEST_TYPE_ALIGN  (LPCOLESTR, 4)
+    TEST_TARGET_SIZE (LPCOLESTR, 2)
+    TEST_TARGET_ALIGN(LPCOLESTR, 2)
 }
 
 static void test_pack_LPCY(void)
 {
     /* LPCY */
-    TEST_TYPE(LPCY, 4, 4);
+    TEST_TYPE_SIZE   (LPCY, 4)
+    TEST_TYPE_ALIGN  (LPCY, 4)
 }
 
 static void test_pack_LPDECIMAL(void)
 {
     /* LPDECIMAL */
-    TEST_TYPE(LPDECIMAL, 4, 4);
+    TEST_TYPE_SIZE   (LPDECIMAL, 4)
+    TEST_TYPE_ALIGN  (LPDECIMAL, 4)
 }
 
 static void test_pack_LPOLESTR(void)
 {
     /* LPOLESTR */
-    TEST_TYPE(LPOLESTR, 4, 4);
-    TEST_TYPE_POINTER(LPOLESTR, 2, 2);
+    TEST_TYPE_SIZE   (LPOLESTR, 4)
+    TEST_TYPE_ALIGN  (LPOLESTR, 4)
+    TEST_TARGET_SIZE (LPOLESTR, 2)
+    TEST_TARGET_ALIGN(LPOLESTR, 2)
 }
 
 static void test_pack_OLECHAR(void)
 {
     /* OLECHAR */
-    TEST_TYPE(OLECHAR, 2, 2);
+    TEST_TYPE_SIZE   (OLECHAR, 2)
+    TEST_TYPE_ALIGN  (OLECHAR, 2)
 }
 
 static void test_pack_PROPID(void)
 {
     /* PROPID */
-    TEST_TYPE(PROPID, 4, 4);
+    TEST_TYPE_SIZE   (PROPID, 4)
+    TEST_TYPE_ALIGN  (PROPID, 4)
 }
 
 static void test_pack_RemHBITMAP(void)
 {
     /* RemHBITMAP (pack 4) */
-    TEST_TYPE(RemHBITMAP, 8, 4);
-    TEST_FIELD(RemHBITMAP, unsigned long, cbData, 0, 4, 4);
-    TEST_FIELD(RemHBITMAP, byte[1], data, 4, 1, 1);
+    TEST_TYPE_SIZE   (RemHBITMAP, 8)
+    TEST_TYPE_ALIGN  (RemHBITMAP, 4)
+    TEST_FIELD_SIZE  (RemHBITMAP, cbData, 4)
+    TEST_FIELD_ALIGN (RemHBITMAP, cbData, 4)
+    TEST_FIELD_OFFSET(RemHBITMAP, cbData, 0)
+    TEST_FIELD_SIZE  (RemHBITMAP, data, 1)
+    TEST_FIELD_ALIGN (RemHBITMAP, data, 1)
+    TEST_FIELD_OFFSET(RemHBITMAP, data, 4)
 }
 
 static void test_pack_RemHENHMETAFILE(void)
 {
     /* RemHENHMETAFILE (pack 4) */
-    TEST_TYPE(RemHENHMETAFILE, 8, 4);
-    TEST_FIELD(RemHENHMETAFILE, unsigned long, cbData, 0, 4, 4);
-    TEST_FIELD(RemHENHMETAFILE, byte[1], data, 4, 1, 1);
+    TEST_TYPE_SIZE   (RemHENHMETAFILE, 8)
+    TEST_TYPE_ALIGN  (RemHENHMETAFILE, 4)
+    TEST_FIELD_SIZE  (RemHENHMETAFILE, cbData, 4)
+    TEST_FIELD_ALIGN (RemHENHMETAFILE, cbData, 4)
+    TEST_FIELD_OFFSET(RemHENHMETAFILE, cbData, 0)
+    TEST_FIELD_SIZE  (RemHENHMETAFILE, data, 1)
+    TEST_FIELD_ALIGN (RemHENHMETAFILE, data, 1)
+    TEST_FIELD_OFFSET(RemHENHMETAFILE, data, 4)
 }
 
 static void test_pack_RemHGLOBAL(void)
 {
     /* RemHGLOBAL (pack 4) */
-    TEST_TYPE(RemHGLOBAL, 12, 4);
-    TEST_FIELD(RemHGLOBAL, long, fNullHGlobal, 0, 4, 4);
-    TEST_FIELD(RemHGLOBAL, unsigned long, cbData, 4, 4, 4);
-    TEST_FIELD(RemHGLOBAL, byte[1], data, 8, 1, 1);
+    TEST_TYPE_SIZE   (RemHGLOBAL, 12)
+    TEST_TYPE_ALIGN  (RemHGLOBAL, 4)
+    TEST_FIELD_SIZE  (RemHGLOBAL, fNullHGlobal, 4)
+    TEST_FIELD_ALIGN (RemHGLOBAL, fNullHGlobal, 4)
+    TEST_FIELD_OFFSET(RemHGLOBAL, fNullHGlobal, 0)
+    TEST_FIELD_SIZE  (RemHGLOBAL, cbData, 4)
+    TEST_FIELD_ALIGN (RemHGLOBAL, cbData, 4)
+    TEST_FIELD_OFFSET(RemHGLOBAL, cbData, 4)
+    TEST_FIELD_SIZE  (RemHGLOBAL, data, 1)
+    TEST_FIELD_ALIGN (RemHGLOBAL, data, 1)
+    TEST_FIELD_OFFSET(RemHGLOBAL, data, 8)
 }
 
 static void test_pack_RemHMETAFILEPICT(void)
 {
     /* RemHMETAFILEPICT (pack 4) */
-    TEST_TYPE(RemHMETAFILEPICT, 20, 4);
-    TEST_FIELD(RemHMETAFILEPICT, long, mm, 0, 4, 4);
-    TEST_FIELD(RemHMETAFILEPICT, long, xExt, 4, 4, 4);
-    TEST_FIELD(RemHMETAFILEPICT, long, yExt, 8, 4, 4);
-    TEST_FIELD(RemHMETAFILEPICT, unsigned long, cbData, 12, 4, 4);
-    TEST_FIELD(RemHMETAFILEPICT, byte[1], data, 16, 1, 1);
+    TEST_TYPE_SIZE   (RemHMETAFILEPICT, 20)
+    TEST_TYPE_ALIGN  (RemHMETAFILEPICT, 4)
+    TEST_FIELD_SIZE  (RemHMETAFILEPICT, mm, 4)
+    TEST_FIELD_ALIGN (RemHMETAFILEPICT, mm, 4)
+    TEST_FIELD_OFFSET(RemHMETAFILEPICT, mm, 0)
+    TEST_FIELD_SIZE  (RemHMETAFILEPICT, xExt, 4)
+    TEST_FIELD_ALIGN (RemHMETAFILEPICT, xExt, 4)
+    TEST_FIELD_OFFSET(RemHMETAFILEPICT, xExt, 4)
+    TEST_FIELD_SIZE  (RemHMETAFILEPICT, yExt, 4)
+    TEST_FIELD_ALIGN (RemHMETAFILEPICT, yExt, 4)
+    TEST_FIELD_OFFSET(RemHMETAFILEPICT, yExt, 8)
+    TEST_FIELD_SIZE  (RemHMETAFILEPICT, cbData, 4)
+    TEST_FIELD_ALIGN (RemHMETAFILEPICT, cbData, 4)
+    TEST_FIELD_OFFSET(RemHMETAFILEPICT, cbData, 12)
+    TEST_FIELD_SIZE  (RemHMETAFILEPICT, data, 1)
+    TEST_FIELD_ALIGN (RemHMETAFILEPICT, data, 1)
+    TEST_FIELD_OFFSET(RemHMETAFILEPICT, data, 16)
 }
 
 static void test_pack_RemHPALETTE(void)
 {
     /* RemHPALETTE (pack 4) */
-    TEST_TYPE(RemHPALETTE, 8, 4);
-    TEST_FIELD(RemHPALETTE, unsigned long, cbData, 0, 4, 4);
-    TEST_FIELD(RemHPALETTE, byte[1], data, 4, 1, 1);
+    TEST_TYPE_SIZE   (RemHPALETTE, 8)
+    TEST_TYPE_ALIGN  (RemHPALETTE, 4)
+    TEST_FIELD_SIZE  (RemHPALETTE, cbData, 4)
+    TEST_FIELD_ALIGN (RemHPALETTE, cbData, 4)
+    TEST_FIELD_OFFSET(RemHPALETTE, cbData, 0)
+    TEST_FIELD_SIZE  (RemHPALETTE, data, 1)
+    TEST_FIELD_ALIGN (RemHPALETTE, data, 1)
+    TEST_FIELD_OFFSET(RemHPALETTE, data, 4)
 }
 
 static void test_pack_SCODE(void)
 {
     /* SCODE */
-    TEST_TYPE(SCODE, 4, 4);
+    TEST_TYPE_SIZE   (SCODE, 4)
+    TEST_TYPE_ALIGN  (SCODE, 4)
 }
 
 static void test_pack_UP_BYTE_BLOB(void)
 {
     /* UP_BYTE_BLOB */
-    TEST_TYPE(UP_BYTE_BLOB, 4, 4);
-    TEST_TYPE_POINTER(UP_BYTE_BLOB, 8, 4);
+    TEST_TYPE_SIZE   (UP_BYTE_BLOB, 4)
+    TEST_TYPE_ALIGN  (UP_BYTE_BLOB, 4)
+    TEST_TARGET_SIZE (UP_BYTE_BLOB, 8)
+    TEST_TARGET_ALIGN(UP_BYTE_BLOB, 4)
 }
 
 static void test_pack_UP_FLAGGED_BYTE_BLOB(void)
 {
     /* UP_FLAGGED_BYTE_BLOB */
-    TEST_TYPE(UP_FLAGGED_BYTE_BLOB, 4, 4);
-    TEST_TYPE_POINTER(UP_FLAGGED_BYTE_BLOB, 12, 4);
+    TEST_TYPE_SIZE   (UP_FLAGGED_BYTE_BLOB, 4)
+    TEST_TYPE_ALIGN  (UP_FLAGGED_BYTE_BLOB, 4)
+    TEST_TARGET_SIZE (UP_FLAGGED_BYTE_BLOB, 12)
+    TEST_TARGET_ALIGN(UP_FLAGGED_BYTE_BLOB, 4)
 }
 
 static void test_pack_UP_FLAGGED_WORD_BLOB(void)
 {
     /* UP_FLAGGED_WORD_BLOB */
-    TEST_TYPE(UP_FLAGGED_WORD_BLOB, 4, 4);
-    TEST_TYPE_POINTER(UP_FLAGGED_WORD_BLOB, 12, 4);
+    TEST_TYPE_SIZE   (UP_FLAGGED_WORD_BLOB, 4)
+    TEST_TYPE_ALIGN  (UP_FLAGGED_WORD_BLOB, 4)
+    TEST_TARGET_SIZE (UP_FLAGGED_WORD_BLOB, 12)
+    TEST_TARGET_ALIGN(UP_FLAGGED_WORD_BLOB, 4)
 }
 
 static void test_pack_VARIANT_BOOL(void)
 {
     /* VARIANT_BOOL */
-    TEST_TYPE(VARIANT_BOOL, 2, 2);
-    TEST_TYPE_SIGNED(VARIANT_BOOL);
+    TEST_TYPE_SIZE   (VARIANT_BOOL, 2)
+    TEST_TYPE_ALIGN  (VARIANT_BOOL, 2)
+    TEST_TYPE_SIGNED(VARIANT_BOOL)
 }
 
 static void test_pack_VARTYPE(void)
 {
     /* VARTYPE */
-    TEST_TYPE(VARTYPE, 2, 2);
-    TEST_TYPE_UNSIGNED(VARTYPE);
+    TEST_TYPE_SIZE   (VARTYPE, 2)
+    TEST_TYPE_ALIGN  (VARTYPE, 2)
+    TEST_TYPE_UNSIGNED(VARTYPE)
 }
 
 static void test_pack_WORD_SIZEDARR(void)
 {
     /* WORD_SIZEDARR (pack 4) */
-    TEST_TYPE(WORD_SIZEDARR, 8, 4);
-    TEST_FIELD(WORD_SIZEDARR, unsigned long, clSize, 0, 4, 4);
-    TEST_FIELD(WORD_SIZEDARR, unsigned short *, pData, 4, 4, 4);
+    TEST_TYPE_SIZE   (WORD_SIZEDARR, 8)
+    TEST_TYPE_ALIGN  (WORD_SIZEDARR, 4)
+    TEST_FIELD_SIZE  (WORD_SIZEDARR, clSize, 4)
+    TEST_FIELD_ALIGN (WORD_SIZEDARR, clSize, 4)
+    TEST_FIELD_OFFSET(WORD_SIZEDARR, clSize, 0)
+    TEST_FIELD_SIZE  (WORD_SIZEDARR, pData, 4)
+    TEST_FIELD_ALIGN (WORD_SIZEDARR, pData, 4)
+    TEST_FIELD_OFFSET(WORD_SIZEDARR, pData, 4)
 }
 
 static void test_pack_remoteMETAFILEPICT(void)
 {
     /* remoteMETAFILEPICT (pack 4) */
-    TEST_TYPE(remoteMETAFILEPICT, 16, 4);
-    TEST_FIELD(remoteMETAFILEPICT, long, mm, 0, 4, 4);
-    TEST_FIELD(remoteMETAFILEPICT, long, xExt, 4, 4, 4);
-    TEST_FIELD(remoteMETAFILEPICT, long, yExt, 8, 4, 4);
-    TEST_FIELD(remoteMETAFILEPICT, userHMETAFILE *, hMF, 12, 4, 4);
+    TEST_TYPE_SIZE   (remoteMETAFILEPICT, 16)
+    TEST_TYPE_ALIGN  (remoteMETAFILEPICT, 4)
+    TEST_FIELD_SIZE  (remoteMETAFILEPICT, mm, 4)
+    TEST_FIELD_ALIGN (remoteMETAFILEPICT, mm, 4)
+    TEST_FIELD_OFFSET(remoteMETAFILEPICT, mm, 0)
+    TEST_FIELD_SIZE  (remoteMETAFILEPICT, xExt, 4)
+    TEST_FIELD_ALIGN (remoteMETAFILEPICT, xExt, 4)
+    TEST_FIELD_OFFSET(remoteMETAFILEPICT, xExt, 4)
+    TEST_FIELD_SIZE  (remoteMETAFILEPICT, yExt, 4)
+    TEST_FIELD_ALIGN (remoteMETAFILEPICT, yExt, 4)
+    TEST_FIELD_OFFSET(remoteMETAFILEPICT, yExt, 8)
+    TEST_FIELD_SIZE  (remoteMETAFILEPICT, hMF, 4)
+    TEST_FIELD_ALIGN (remoteMETAFILEPICT, hMF, 4)
+    TEST_FIELD_OFFSET(remoteMETAFILEPICT, hMF, 12)
 }
 
 static void test_pack_userBITMAP(void)
 {
     /* userBITMAP (pack 4) */
-    TEST_TYPE(userBITMAP, 28, 4);
-    TEST_FIELD(userBITMAP, LONG, bmType, 0, 4, 4);
-    TEST_FIELD(userBITMAP, LONG, bmWidth, 4, 4, 4);
-    TEST_FIELD(userBITMAP, LONG, bmHeight, 8, 4, 4);
-    TEST_FIELD(userBITMAP, LONG, bmWidthBytes, 12, 4, 4);
-    TEST_FIELD(userBITMAP, WORD, bmPlanes, 16, 2, 2);
-    TEST_FIELD(userBITMAP, WORD, bmBitsPixel, 18, 2, 2);
-    TEST_FIELD(userBITMAP, ULONG, cbSize, 20, 4, 4);
-    TEST_FIELD(userBITMAP, byte[1], pBuffer, 24, 1, 1);
+    TEST_TYPE_SIZE   (userBITMAP, 28)
+    TEST_TYPE_ALIGN  (userBITMAP, 4)
+    TEST_FIELD_SIZE  (userBITMAP, bmType, 4)
+    TEST_FIELD_ALIGN (userBITMAP, bmType, 4)
+    TEST_FIELD_OFFSET(userBITMAP, bmType, 0)
+    TEST_FIELD_SIZE  (userBITMAP, bmWidth, 4)
+    TEST_FIELD_ALIGN (userBITMAP, bmWidth, 4)
+    TEST_FIELD_OFFSET(userBITMAP, bmWidth, 4)
+    TEST_FIELD_SIZE  (userBITMAP, bmHeight, 4)
+    TEST_FIELD_ALIGN (userBITMAP, bmHeight, 4)
+    TEST_FIELD_OFFSET(userBITMAP, bmHeight, 8)
+    TEST_FIELD_SIZE  (userBITMAP, bmWidthBytes, 4)
+    TEST_FIELD_ALIGN (userBITMAP, bmWidthBytes, 4)
+    TEST_FIELD_OFFSET(userBITMAP, bmWidthBytes, 12)
+    TEST_FIELD_SIZE  (userBITMAP, bmPlanes, 2)
+    TEST_FIELD_ALIGN (userBITMAP, bmPlanes, 2)
+    TEST_FIELD_OFFSET(userBITMAP, bmPlanes, 16)
+    TEST_FIELD_SIZE  (userBITMAP, bmBitsPixel, 2)
+    TEST_FIELD_ALIGN (userBITMAP, bmBitsPixel, 2)
+    TEST_FIELD_OFFSET(userBITMAP, bmBitsPixel, 18)
+    TEST_FIELD_SIZE  (userBITMAP, cbSize, 4)
+    TEST_FIELD_ALIGN (userBITMAP, cbSize, 4)
+    TEST_FIELD_OFFSET(userBITMAP, cbSize, 20)
+    TEST_FIELD_SIZE  (userBITMAP, pBuffer, 1)
+    TEST_FIELD_ALIGN (userBITMAP, pBuffer, 1)
+    TEST_FIELD_OFFSET(userBITMAP, pBuffer, 24)
 }
 
 static void test_pack_userCLIPFORMAT(void)
 {
     /* userCLIPFORMAT (pack 4) */
-    TEST_FIELD(userCLIPFORMAT, long, fContext, 0, 4, 4);
+    TEST_FIELD_SIZE  (userCLIPFORMAT, fContext, 4)
+    TEST_FIELD_ALIGN (userCLIPFORMAT, fContext, 4)
+    TEST_FIELD_OFFSET(userCLIPFORMAT, fContext, 0)
 }
 
 static void test_pack_userHBITMAP(void)
 {
     /* userHBITMAP (pack 4) */
-    TEST_FIELD(userHBITMAP, long, fContext, 0, 4, 4);
+    TEST_FIELD_SIZE  (userHBITMAP, fContext, 4)
+    TEST_FIELD_ALIGN (userHBITMAP, fContext, 4)
+    TEST_FIELD_OFFSET(userHBITMAP, fContext, 0)
 }
 
 static void test_pack_userHENHMETAFILE(void)
 {
     /* userHENHMETAFILE (pack 4) */
-    TEST_FIELD(userHENHMETAFILE, long, fContext, 0, 4, 4);
+    TEST_FIELD_SIZE  (userHENHMETAFILE, fContext, 4)
+    TEST_FIELD_ALIGN (userHENHMETAFILE, fContext, 4)
+    TEST_FIELD_OFFSET(userHENHMETAFILE, fContext, 0)
 }
 
 static void test_pack_userHGLOBAL(void)
 {
     /* userHGLOBAL (pack 4) */
-    TEST_FIELD(userHGLOBAL, long, fContext, 0, 4, 4);
+    TEST_FIELD_SIZE  (userHGLOBAL, fContext, 4)
+    TEST_FIELD_ALIGN (userHGLOBAL, fContext, 4)
+    TEST_FIELD_OFFSET(userHGLOBAL, fContext, 0)
 }
 
 static void test_pack_userHMETAFILE(void)
 {
     /* userHMETAFILE (pack 4) */
-    TEST_FIELD(userHMETAFILE, long, fContext, 0, 4, 4);
+    TEST_FIELD_SIZE  (userHMETAFILE, fContext, 4)
+    TEST_FIELD_ALIGN (userHMETAFILE, fContext, 4)
+    TEST_FIELD_OFFSET(userHMETAFILE, fContext, 0)
 }
 
 static void test_pack_userHMETAFILEPICT(void)
 {
     /* userHMETAFILEPICT (pack 4) */
-    TEST_FIELD(userHMETAFILEPICT, long, fContext, 0, 4, 4);
+    TEST_FIELD_SIZE  (userHMETAFILEPICT, fContext, 4)
+    TEST_FIELD_ALIGN (userHMETAFILEPICT, fContext, 4)
+    TEST_FIELD_OFFSET(userHMETAFILEPICT, fContext, 0)
 }
 
 static void test_pack_userHPALETTE(void)
 {
     /* userHPALETTE (pack 4) */
-    TEST_FIELD(userHPALETTE, long, fContext, 0, 4, 4);
+    TEST_FIELD_SIZE  (userHPALETTE, fContext, 4)
+    TEST_FIELD_ALIGN (userHPALETTE, fContext, 4)
+    TEST_FIELD_OFFSET(userHPALETTE, fContext, 0)
 }
 
 static void test_pack_wireBSTR(void)
 {
     /* wireBSTR */
-    TEST_TYPE(wireBSTR, 4, 4);
-    TEST_TYPE_POINTER(wireBSTR, 12, 4);
+    TEST_TYPE_SIZE   (wireBSTR, 4)
+    TEST_TYPE_ALIGN  (wireBSTR, 4)
+    TEST_TARGET_SIZE (wireBSTR, 12)
+    TEST_TARGET_ALIGN(wireBSTR, 4)
 }
 
 static void test_pack_wireCLIPFORMAT(void)
 {
     /* wireCLIPFORMAT */
-    TEST_TYPE(wireCLIPFORMAT, 4, 4);
+    TEST_TYPE_SIZE   (wireCLIPFORMAT, 4)
+    TEST_TYPE_ALIGN  (wireCLIPFORMAT, 4)
 }
 
 static void test_pack_wireHBITMAP(void)
 {
     /* wireHBITMAP */
-    TEST_TYPE(wireHBITMAP, 4, 4);
+    TEST_TYPE_SIZE   (wireHBITMAP, 4)
+    TEST_TYPE_ALIGN  (wireHBITMAP, 4)
 }
 
 static void test_pack_wireHENHMETAFILE(void)
 {
     /* wireHENHMETAFILE */
-    TEST_TYPE(wireHENHMETAFILE, 4, 4);
+    TEST_TYPE_SIZE   (wireHENHMETAFILE, 4)
+    TEST_TYPE_ALIGN  (wireHENHMETAFILE, 4)
 }
 
 static void test_pack_wireHGLOBAL(void)
 {
     /* wireHGLOBAL */
-    TEST_TYPE(wireHGLOBAL, 4, 4);
+    TEST_TYPE_SIZE   (wireHGLOBAL, 4)
+    TEST_TYPE_ALIGN  (wireHGLOBAL, 4)
 }
 
 static void test_pack_wireHMETAFILE(void)
 {
     /* wireHMETAFILE */
-    TEST_TYPE(wireHMETAFILE, 4, 4);
+    TEST_TYPE_SIZE   (wireHMETAFILE, 4)
+    TEST_TYPE_ALIGN  (wireHMETAFILE, 4)
 }
 
 static void test_pack_wireHMETAFILEPICT(void)
 {
     /* wireHMETAFILEPICT */
-    TEST_TYPE(wireHMETAFILEPICT, 4, 4);
+    TEST_TYPE_SIZE   (wireHMETAFILEPICT, 4)
+    TEST_TYPE_ALIGN  (wireHMETAFILEPICT, 4)
 }
 
 static void test_pack_wireHPALETTE(void)
 {
     /* wireHPALETTE */
-    TEST_TYPE(wireHPALETTE, 4, 4);
+    TEST_TYPE_SIZE   (wireHPALETTE, 4)
+    TEST_TYPE_ALIGN  (wireHPALETTE, 4)
 }
 
 static void test_pack_CLSID(void)
 {
     /* CLSID */
-    TEST_TYPE(CLSID, 16, 4);
+    TEST_TYPE_SIZE   (CLSID, 16)
+    TEST_TYPE_ALIGN  (CLSID, 4)
 }
 
 static void test_pack_FMTID(void)
 {
     /* FMTID */
-    TEST_TYPE(FMTID, 16, 4);
-}
-
-static void test_pack_GUID(void)
-{
-    /* GUID (pack 4) */
-    TEST_TYPE(GUID, 16, 4);
-    TEST_FIELD(GUID, unsigned long, Data1, 0, 4, 4);
-    TEST_FIELD(GUID, unsigned short, Data2, 4, 2, 2);
-    TEST_FIELD(GUID, unsigned short, Data3, 6, 2, 2);
-    TEST_FIELD(GUID, unsigned char[ 8 ], Data4, 8, 8, 1);
+    TEST_TYPE_SIZE   (FMTID, 16)
+    TEST_TYPE_ALIGN  (FMTID, 4)
 }
 
 static void test_pack_IID(void)
 {
     /* IID */
-    TEST_TYPE(IID, 16, 4);
-}
-
-static void test_pack_LPGUID(void)
-{
-    /* LPGUID */
-    TEST_TYPE(LPGUID, 4, 4);
-    TEST_TYPE_POINTER(LPGUID, 16, 4);
+    TEST_TYPE_SIZE   (IID, 16)
+    TEST_TYPE_ALIGN  (IID, 4)
 }
 
 static void test_pack_APPBARDATA(void)
 {
     /* APPBARDATA (pack 1) */
-    TEST_TYPE(APPBARDATA, 36, 1);
-    TEST_FIELD(APPBARDATA, DWORD, cbSize, 0, 4, 1);
-    TEST_FIELD(APPBARDATA, HWND, hWnd, 4, 4, 1);
-    TEST_FIELD(APPBARDATA, UINT, uCallbackMessage, 8, 4, 1);
-    TEST_FIELD(APPBARDATA, UINT, uEdge, 12, 4, 1);
-    TEST_FIELD(APPBARDATA, RECT, rc, 16, 16, 1);
-    TEST_FIELD(APPBARDATA, LPARAM, lParam, 32, 4, 1);
+    TEST_TYPE_SIZE   (APPBARDATA, 36)
+    TEST_TYPE_ALIGN  (APPBARDATA, 1)
+    TEST_FIELD_SIZE  (APPBARDATA, cbSize, 4)
+    TEST_FIELD_ALIGN (APPBARDATA, cbSize, 1)
+    TEST_FIELD_OFFSET(APPBARDATA, cbSize, 0)
+    TEST_FIELD_SIZE  (APPBARDATA, hWnd, 4)
+    TEST_FIELD_ALIGN (APPBARDATA, hWnd, 1)
+    TEST_FIELD_OFFSET(APPBARDATA, hWnd, 4)
+    TEST_FIELD_SIZE  (APPBARDATA, uCallbackMessage, 4)
+    TEST_FIELD_ALIGN (APPBARDATA, uCallbackMessage, 1)
+    TEST_FIELD_OFFSET(APPBARDATA, uCallbackMessage, 8)
+    TEST_FIELD_SIZE  (APPBARDATA, uEdge, 4)
+    TEST_FIELD_ALIGN (APPBARDATA, uEdge, 1)
+    TEST_FIELD_OFFSET(APPBARDATA, uEdge, 12)
+    TEST_FIELD_SIZE  (APPBARDATA, rc, 16)
+    TEST_FIELD_ALIGN (APPBARDATA, rc, 1)
+    TEST_FIELD_OFFSET(APPBARDATA, rc, 16)
+    TEST_FIELD_SIZE  (APPBARDATA, lParam, 4)
+    TEST_FIELD_ALIGN (APPBARDATA, lParam, 1)
+    TEST_FIELD_OFFSET(APPBARDATA, lParam, 32)
 }
 
 static void test_pack_DRAGINFOA(void)
 {
     /* DRAGINFOA (pack 1) */
-    TEST_TYPE(DRAGINFOA, 24, 1);
-    TEST_FIELD(DRAGINFOA, UINT, uSize, 0, 4, 1);
-    TEST_FIELD(DRAGINFOA, POINT, pt, 4, 8, 1);
-    TEST_FIELD(DRAGINFOA, BOOL, fNC, 12, 4, 1);
-    TEST_FIELD(DRAGINFOA, LPSTR, lpFileList, 16, 4, 1);
-    TEST_FIELD(DRAGINFOA, DWORD, grfKeyState, 20, 4, 1);
+    TEST_TYPE_SIZE   (DRAGINFOA, 24)
+    TEST_TYPE_ALIGN  (DRAGINFOA, 1)
+    TEST_FIELD_SIZE  (DRAGINFOA, uSize, 4)
+    TEST_FIELD_ALIGN (DRAGINFOA, uSize, 1)
+    TEST_FIELD_OFFSET(DRAGINFOA, uSize, 0)
+    TEST_FIELD_SIZE  (DRAGINFOA, pt, 8)
+    TEST_FIELD_ALIGN (DRAGINFOA, pt, 1)
+    TEST_FIELD_OFFSET(DRAGINFOA, pt, 4)
+    TEST_FIELD_SIZE  (DRAGINFOA, fNC, 4)
+    TEST_FIELD_ALIGN (DRAGINFOA, fNC, 1)
+    TEST_FIELD_OFFSET(DRAGINFOA, fNC, 12)
+    TEST_FIELD_SIZE  (DRAGINFOA, lpFileList, 4)
+    TEST_FIELD_ALIGN (DRAGINFOA, lpFileList, 1)
+    TEST_FIELD_OFFSET(DRAGINFOA, lpFileList, 16)
+    TEST_FIELD_SIZE  (DRAGINFOA, grfKeyState, 4)
+    TEST_FIELD_ALIGN (DRAGINFOA, grfKeyState, 1)
+    TEST_FIELD_OFFSET(DRAGINFOA, grfKeyState, 20)
 }
 
 static void test_pack_DRAGINFOW(void)
 {
     /* DRAGINFOW (pack 1) */
-    TEST_TYPE(DRAGINFOW, 24, 1);
-    TEST_FIELD(DRAGINFOW, UINT, uSize, 0, 4, 1);
-    TEST_FIELD(DRAGINFOW, POINT, pt, 4, 8, 1);
-    TEST_FIELD(DRAGINFOW, BOOL, fNC, 12, 4, 1);
-    TEST_FIELD(DRAGINFOW, LPWSTR, lpFileList, 16, 4, 1);
-    TEST_FIELD(DRAGINFOW, DWORD, grfKeyState, 20, 4, 1);
+    TEST_TYPE_SIZE   (DRAGINFOW, 24)
+    TEST_TYPE_ALIGN  (DRAGINFOW, 1)
+    TEST_FIELD_SIZE  (DRAGINFOW, uSize, 4)
+    TEST_FIELD_ALIGN (DRAGINFOW, uSize, 1)
+    TEST_FIELD_OFFSET(DRAGINFOW, uSize, 0)
+    TEST_FIELD_SIZE  (DRAGINFOW, pt, 8)
+    TEST_FIELD_ALIGN (DRAGINFOW, pt, 1)
+    TEST_FIELD_OFFSET(DRAGINFOW, pt, 4)
+    TEST_FIELD_SIZE  (DRAGINFOW, fNC, 4)
+    TEST_FIELD_ALIGN (DRAGINFOW, fNC, 1)
+    TEST_FIELD_OFFSET(DRAGINFOW, fNC, 12)
+    TEST_FIELD_SIZE  (DRAGINFOW, lpFileList, 4)
+    TEST_FIELD_ALIGN (DRAGINFOW, lpFileList, 1)
+    TEST_FIELD_OFFSET(DRAGINFOW, lpFileList, 16)
+    TEST_FIELD_SIZE  (DRAGINFOW, grfKeyState, 4)
+    TEST_FIELD_ALIGN (DRAGINFOW, grfKeyState, 1)
+    TEST_FIELD_OFFSET(DRAGINFOW, grfKeyState, 20)
 }
 
 static void test_pack_FILEOP_FLAGS(void)
 {
     /* FILEOP_FLAGS */
-    TEST_TYPE(FILEOP_FLAGS, 2, 2);
-    TEST_TYPE_UNSIGNED(FILEOP_FLAGS);
+    TEST_TYPE_SIZE   (FILEOP_FLAGS, 2)
+    TEST_TYPE_ALIGN  (FILEOP_FLAGS, 2)
+    TEST_TYPE_UNSIGNED(FILEOP_FLAGS)
 }
 
 static void test_pack_LPDRAGINFOA(void)
 {
     /* LPDRAGINFOA */
-    TEST_TYPE(LPDRAGINFOA, 4, 4);
-    TEST_TYPE_POINTER(LPDRAGINFOA, 24, 1);
+    TEST_TYPE_SIZE   (LPDRAGINFOA, 4)
+    TEST_TYPE_ALIGN  (LPDRAGINFOA, 4)
+    TEST_TARGET_SIZE (LPDRAGINFOA, 24)
+    TEST_TARGET_ALIGN(LPDRAGINFOA, 1)
 }
 
 static void test_pack_LPDRAGINFOW(void)
 {
     /* LPDRAGINFOW */
-    TEST_TYPE(LPDRAGINFOW, 4, 4);
-    TEST_TYPE_POINTER(LPDRAGINFOW, 24, 1);
+    TEST_TYPE_SIZE   (LPDRAGINFOW, 4)
+    TEST_TYPE_ALIGN  (LPDRAGINFOW, 4)
+    TEST_TARGET_SIZE (LPDRAGINFOW, 24)
+    TEST_TARGET_ALIGN(LPDRAGINFOW, 1)
 }
 
 static void test_pack_LPSHELLEXECUTEINFOA(void)
 {
     /* LPSHELLEXECUTEINFOA */
-    TEST_TYPE(LPSHELLEXECUTEINFOA, 4, 4);
+    TEST_TYPE_SIZE   (LPSHELLEXECUTEINFOA, 4)
+    TEST_TYPE_ALIGN  (LPSHELLEXECUTEINFOA, 4)
 }
 
 static void test_pack_LPSHELLEXECUTEINFOW(void)
 {
     /* LPSHELLEXECUTEINFOW */
-    TEST_TYPE(LPSHELLEXECUTEINFOW, 4, 4);
+    TEST_TYPE_SIZE   (LPSHELLEXECUTEINFOW, 4)
+    TEST_TYPE_ALIGN  (LPSHELLEXECUTEINFOW, 4)
 }
 
 static void test_pack_LPSHFILEOPSTRUCTA(void)
 {
     /* LPSHFILEOPSTRUCTA */
-    TEST_TYPE(LPSHFILEOPSTRUCTA, 4, 4);
-    TEST_TYPE_POINTER(LPSHFILEOPSTRUCTA, 30, 1);
+    TEST_TYPE_SIZE   (LPSHFILEOPSTRUCTA, 4)
+    TEST_TYPE_ALIGN  (LPSHFILEOPSTRUCTA, 4)
+    TEST_TARGET_SIZE (LPSHFILEOPSTRUCTA, 30)
+    TEST_TARGET_ALIGN(LPSHFILEOPSTRUCTA, 1)
 }
 
 static void test_pack_LPSHFILEOPSTRUCTW(void)
 {
     /* LPSHFILEOPSTRUCTW */
-    TEST_TYPE(LPSHFILEOPSTRUCTW, 4, 4);
-    TEST_TYPE_POINTER(LPSHFILEOPSTRUCTW, 30, 1);
+    TEST_TYPE_SIZE   (LPSHFILEOPSTRUCTW, 4)
+    TEST_TYPE_ALIGN  (LPSHFILEOPSTRUCTW, 4)
+    TEST_TARGET_SIZE (LPSHFILEOPSTRUCTW, 30)
+    TEST_TARGET_ALIGN(LPSHFILEOPSTRUCTW, 1)
 }
 
 static void test_pack_LPSHNAMEMAPPINGA(void)
 {
     /* LPSHNAMEMAPPINGA */
-    TEST_TYPE(LPSHNAMEMAPPINGA, 4, 4);
-    TEST_TYPE_POINTER(LPSHNAMEMAPPINGA, 16, 1);
+    TEST_TYPE_SIZE   (LPSHNAMEMAPPINGA, 4)
+    TEST_TYPE_ALIGN  (LPSHNAMEMAPPINGA, 4)
+    TEST_TARGET_SIZE (LPSHNAMEMAPPINGA, 16)
+    TEST_TARGET_ALIGN(LPSHNAMEMAPPINGA, 1)
 }
 
 static void test_pack_LPSHNAMEMAPPINGW(void)
 {
     /* LPSHNAMEMAPPINGW */
-    TEST_TYPE(LPSHNAMEMAPPINGW, 4, 4);
-    TEST_TYPE_POINTER(LPSHNAMEMAPPINGW, 16, 1);
+    TEST_TYPE_SIZE   (LPSHNAMEMAPPINGW, 4)
+    TEST_TYPE_ALIGN  (LPSHNAMEMAPPINGW, 4)
+    TEST_TARGET_SIZE (LPSHNAMEMAPPINGW, 16)
+    TEST_TARGET_ALIGN(LPSHNAMEMAPPINGW, 1)
 }
 
 static void test_pack_NOTIFYICONDATAA(void)
 {
     /* NOTIFYICONDATAA (pack 1) */
-    TEST_FIELD(NOTIFYICONDATAA, DWORD, cbSize, 0, 4, 1);
-    TEST_FIELD(NOTIFYICONDATAA, HWND, hWnd, 4, 4, 1);
-    TEST_FIELD(NOTIFYICONDATAA, UINT, uID, 8, 4, 1);
-    TEST_FIELD(NOTIFYICONDATAA, UINT, uFlags, 12, 4, 1);
-    TEST_FIELD(NOTIFYICONDATAA, UINT, uCallbackMessage, 16, 4, 1);
-    TEST_FIELD(NOTIFYICONDATAA, HICON, hIcon, 20, 4, 1);
-    TEST_FIELD(NOTIFYICONDATAA, CHAR[128], szTip, 24, 128, 1);
-    TEST_FIELD(NOTIFYICONDATAA, DWORD, dwState, 152, 4, 1);
-    TEST_FIELD(NOTIFYICONDATAA, DWORD, dwStateMask, 156, 4, 1);
-    TEST_FIELD(NOTIFYICONDATAA, CHAR[256], szInfo, 160, 256, 1);
+    TEST_FIELD_SIZE  (NOTIFYICONDATAA, cbSize, 4)
+    TEST_FIELD_ALIGN (NOTIFYICONDATAA, cbSize, 1)
+    TEST_FIELD_OFFSET(NOTIFYICONDATAA, cbSize, 0)
+    TEST_FIELD_SIZE  (NOTIFYICONDATAA, hWnd, 4)
+    TEST_FIELD_ALIGN (NOTIFYICONDATAA, hWnd, 1)
+    TEST_FIELD_OFFSET(NOTIFYICONDATAA, hWnd, 4)
+    TEST_FIELD_SIZE  (NOTIFYICONDATAA, uID, 4)
+    TEST_FIELD_ALIGN (NOTIFYICONDATAA, uID, 1)
+    TEST_FIELD_OFFSET(NOTIFYICONDATAA, uID, 8)
+    TEST_FIELD_SIZE  (NOTIFYICONDATAA, uFlags, 4)
+    TEST_FIELD_ALIGN (NOTIFYICONDATAA, uFlags, 1)
+    TEST_FIELD_OFFSET(NOTIFYICONDATAA, uFlags, 12)
+    TEST_FIELD_SIZE  (NOTIFYICONDATAA, uCallbackMessage, 4)
+    TEST_FIELD_ALIGN (NOTIFYICONDATAA, uCallbackMessage, 1)
+    TEST_FIELD_OFFSET(NOTIFYICONDATAA, uCallbackMessage, 16)
+    TEST_FIELD_SIZE  (NOTIFYICONDATAA, hIcon, 4)
+    TEST_FIELD_ALIGN (NOTIFYICONDATAA, hIcon, 1)
+    TEST_FIELD_OFFSET(NOTIFYICONDATAA, hIcon, 20)
+    TEST_FIELD_SIZE  (NOTIFYICONDATAA, szTip, 128)
+    TEST_FIELD_ALIGN (NOTIFYICONDATAA, szTip, 1)
+    TEST_FIELD_OFFSET(NOTIFYICONDATAA, szTip, 24)
+    TEST_FIELD_SIZE  (NOTIFYICONDATAA, dwState, 4)
+    TEST_FIELD_ALIGN (NOTIFYICONDATAA, dwState, 1)
+    TEST_FIELD_OFFSET(NOTIFYICONDATAA, dwState, 152)
+    TEST_FIELD_SIZE  (NOTIFYICONDATAA, dwStateMask, 4)
+    TEST_FIELD_ALIGN (NOTIFYICONDATAA, dwStateMask, 1)
+    TEST_FIELD_OFFSET(NOTIFYICONDATAA, dwStateMask, 156)
+    TEST_FIELD_SIZE  (NOTIFYICONDATAA, szInfo, 256)
+    TEST_FIELD_ALIGN (NOTIFYICONDATAA, szInfo, 1)
+    TEST_FIELD_OFFSET(NOTIFYICONDATAA, szInfo, 160)
 }
 
 static void test_pack_NOTIFYICONDATAW(void)
 {
     /* NOTIFYICONDATAW (pack 1) */
-    TEST_FIELD(NOTIFYICONDATAW, DWORD, cbSize, 0, 4, 1);
-    TEST_FIELD(NOTIFYICONDATAW, HWND, hWnd, 4, 4, 1);
-    TEST_FIELD(NOTIFYICONDATAW, UINT, uID, 8, 4, 1);
-    TEST_FIELD(NOTIFYICONDATAW, UINT, uFlags, 12, 4, 1);
-    TEST_FIELD(NOTIFYICONDATAW, UINT, uCallbackMessage, 16, 4, 1);
-    TEST_FIELD(NOTIFYICONDATAW, HICON, hIcon, 20, 4, 1);
-    TEST_FIELD(NOTIFYICONDATAW, WCHAR[128], szTip, 24, 256, 1);
-    TEST_FIELD(NOTIFYICONDATAW, DWORD, dwState, 280, 4, 1);
-    TEST_FIELD(NOTIFYICONDATAW, DWORD, dwStateMask, 284, 4, 1);
-    TEST_FIELD(NOTIFYICONDATAW, WCHAR[256], szInfo, 288, 512, 1);
+    TEST_FIELD_SIZE  (NOTIFYICONDATAW, cbSize, 4)
+    TEST_FIELD_ALIGN (NOTIFYICONDATAW, cbSize, 1)
+    TEST_FIELD_OFFSET(NOTIFYICONDATAW, cbSize, 0)
+    TEST_FIELD_SIZE  (NOTIFYICONDATAW, hWnd, 4)
+    TEST_FIELD_ALIGN (NOTIFYICONDATAW, hWnd, 1)
+    TEST_FIELD_OFFSET(NOTIFYICONDATAW, hWnd, 4)
+    TEST_FIELD_SIZE  (NOTIFYICONDATAW, uID, 4)
+    TEST_FIELD_ALIGN (NOTIFYICONDATAW, uID, 1)
+    TEST_FIELD_OFFSET(NOTIFYICONDATAW, uID, 8)
+    TEST_FIELD_SIZE  (NOTIFYICONDATAW, uFlags, 4)
+    TEST_FIELD_ALIGN (NOTIFYICONDATAW, uFlags, 1)
+    TEST_FIELD_OFFSET(NOTIFYICONDATAW, uFlags, 12)
+    TEST_FIELD_SIZE  (NOTIFYICONDATAW, uCallbackMessage, 4)
+    TEST_FIELD_ALIGN (NOTIFYICONDATAW, uCallbackMessage, 1)
+    TEST_FIELD_OFFSET(NOTIFYICONDATAW, uCallbackMessage, 16)
+    TEST_FIELD_SIZE  (NOTIFYICONDATAW, hIcon, 4)
+    TEST_FIELD_ALIGN (NOTIFYICONDATAW, hIcon, 1)
+    TEST_FIELD_OFFSET(NOTIFYICONDATAW, hIcon, 20)
+    TEST_FIELD_SIZE  (NOTIFYICONDATAW, szTip, 256)
+    TEST_FIELD_ALIGN (NOTIFYICONDATAW, szTip, 1)
+    TEST_FIELD_OFFSET(NOTIFYICONDATAW, szTip, 24)
+    TEST_FIELD_SIZE  (NOTIFYICONDATAW, dwState, 4)
+    TEST_FIELD_ALIGN (NOTIFYICONDATAW, dwState, 1)
+    TEST_FIELD_OFFSET(NOTIFYICONDATAW, dwState, 280)
+    TEST_FIELD_SIZE  (NOTIFYICONDATAW, dwStateMask, 4)
+    TEST_FIELD_ALIGN (NOTIFYICONDATAW, dwStateMask, 1)
+    TEST_FIELD_OFFSET(NOTIFYICONDATAW, dwStateMask, 284)
+    TEST_FIELD_SIZE  (NOTIFYICONDATAW, szInfo, 512)
+    TEST_FIELD_ALIGN (NOTIFYICONDATAW, szInfo, 1)
+    TEST_FIELD_OFFSET(NOTIFYICONDATAW, szInfo, 288)
 }
 
 static void test_pack_PAPPBARDATA(void)
 {
     /* PAPPBARDATA */
-    TEST_TYPE(PAPPBARDATA, 4, 4);
-    TEST_TYPE_POINTER(PAPPBARDATA, 36, 1);
+    TEST_TYPE_SIZE   (PAPPBARDATA, 4)
+    TEST_TYPE_ALIGN  (PAPPBARDATA, 4)
+    TEST_TARGET_SIZE (PAPPBARDATA, 36)
+    TEST_TARGET_ALIGN(PAPPBARDATA, 1)
 }
 
 static void test_pack_PNOTIFYICONDATAA(void)
 {
     /* PNOTIFYICONDATAA */
-    TEST_TYPE(PNOTIFYICONDATAA, 4, 4);
+    TEST_TYPE_SIZE   (PNOTIFYICONDATAA, 4)
+    TEST_TYPE_ALIGN  (PNOTIFYICONDATAA, 4)
 }
 
 static void test_pack_PNOTIFYICONDATAW(void)
 {
     /* PNOTIFYICONDATAW */
-    TEST_TYPE(PNOTIFYICONDATAW, 4, 4);
+    TEST_TYPE_SIZE   (PNOTIFYICONDATAW, 4)
+    TEST_TYPE_ALIGN  (PNOTIFYICONDATAW, 4)
 }
 
 static void test_pack_PRINTEROP_FLAGS(void)
 {
     /* PRINTEROP_FLAGS */
-    TEST_TYPE(PRINTEROP_FLAGS, 2, 2);
-    TEST_TYPE_UNSIGNED(PRINTEROP_FLAGS);
+    TEST_TYPE_SIZE   (PRINTEROP_FLAGS, 2)
+    TEST_TYPE_ALIGN  (PRINTEROP_FLAGS, 2)
+    TEST_TYPE_UNSIGNED(PRINTEROP_FLAGS)
 }
 
 static void test_pack_SHELLEXECUTEINFOA(void)
 {
     /* SHELLEXECUTEINFOA (pack 1) */
-    TEST_FIELD(SHELLEXECUTEINFOA, DWORD, cbSize, 0, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOA, ULONG, fMask, 4, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOA, HWND, hwnd, 8, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOA, LPCSTR, lpVerb, 12, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOA, LPCSTR, lpFile, 16, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOA, LPCSTR, lpParameters, 20, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOA, LPCSTR, lpDirectory, 24, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOA, INT, nShow, 28, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOA, HINSTANCE, hInstApp, 32, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOA, LPVOID, lpIDList, 36, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOA, LPCSTR, lpClass, 40, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOA, HKEY, hkeyClass, 44, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOA, DWORD, dwHotKey, 48, 4, 1);
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOA, cbSize, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOA, cbSize, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOA, cbSize, 0)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOA, fMask, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOA, fMask, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOA, fMask, 4)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOA, hwnd, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOA, hwnd, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOA, hwnd, 8)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOA, lpVerb, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOA, lpVerb, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOA, lpVerb, 12)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOA, lpFile, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOA, lpFile, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOA, lpFile, 16)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOA, lpParameters, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOA, lpParameters, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOA, lpParameters, 20)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOA, lpDirectory, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOA, lpDirectory, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOA, lpDirectory, 24)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOA, nShow, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOA, nShow, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOA, nShow, 28)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOA, hInstApp, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOA, hInstApp, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOA, hInstApp, 32)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOA, lpIDList, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOA, lpIDList, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOA, lpIDList, 36)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOA, lpClass, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOA, lpClass, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOA, lpClass, 40)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOA, hkeyClass, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOA, hkeyClass, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOA, hkeyClass, 44)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOA, dwHotKey, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOA, dwHotKey, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOA, dwHotKey, 48)
 }
 
 static void test_pack_SHELLEXECUTEINFOW(void)
 {
     /* SHELLEXECUTEINFOW (pack 1) */
-    TEST_FIELD(SHELLEXECUTEINFOW, DWORD, cbSize, 0, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOW, ULONG, fMask, 4, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOW, HWND, hwnd, 8, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOW, LPCWSTR, lpVerb, 12, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOW, LPCWSTR, lpFile, 16, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOW, LPCWSTR, lpParameters, 20, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOW, LPCWSTR, lpDirectory, 24, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOW, INT, nShow, 28, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOW, HINSTANCE, hInstApp, 32, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOW, LPVOID, lpIDList, 36, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOW, LPCWSTR, lpClass, 40, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOW, HKEY, hkeyClass, 44, 4, 1);
-    TEST_FIELD(SHELLEXECUTEINFOW, DWORD, dwHotKey, 48, 4, 1);
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOW, cbSize, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOW, cbSize, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOW, cbSize, 0)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOW, fMask, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOW, fMask, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOW, fMask, 4)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOW, hwnd, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOW, hwnd, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOW, hwnd, 8)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOW, lpVerb, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOW, lpVerb, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOW, lpVerb, 12)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOW, lpFile, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOW, lpFile, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOW, lpFile, 16)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOW, lpParameters, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOW, lpParameters, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOW, lpParameters, 20)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOW, lpDirectory, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOW, lpDirectory, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOW, lpDirectory, 24)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOW, nShow, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOW, nShow, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOW, nShow, 28)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOW, hInstApp, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOW, hInstApp, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOW, hInstApp, 32)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOW, lpIDList, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOW, lpIDList, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOW, lpIDList, 36)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOW, lpClass, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOW, lpClass, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOW, lpClass, 40)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOW, hkeyClass, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOW, hkeyClass, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOW, hkeyClass, 44)
+    TEST_FIELD_SIZE  (SHELLEXECUTEINFOW, dwHotKey, 4)
+    TEST_FIELD_ALIGN (SHELLEXECUTEINFOW, dwHotKey, 1)
+    TEST_FIELD_OFFSET(SHELLEXECUTEINFOW, dwHotKey, 48)
 }
 
 static void test_pack_SHFILEINFOA(void)
 {
     /* SHFILEINFOA (pack 1) */
-    TEST_TYPE(SHFILEINFOA, 352, 1);
-    TEST_FIELD(SHFILEINFOA, HICON, hIcon, 0, 4, 1);
-    TEST_FIELD(SHFILEINFOA, int, iIcon, 4, 4, 1);
-    TEST_FIELD(SHFILEINFOA, DWORD, dwAttributes, 8, 4, 1);
-    TEST_FIELD(SHFILEINFOA, CHAR[MAX_PATH], szDisplayName, 12, 260, 1);
-    TEST_FIELD(SHFILEINFOA, CHAR[80], szTypeName, 272, 80, 1);
+    TEST_TYPE_SIZE   (SHFILEINFOA, 352)
+    TEST_TYPE_ALIGN  (SHFILEINFOA, 1)
+    TEST_FIELD_SIZE  (SHFILEINFOA, hIcon, 4)
+    TEST_FIELD_ALIGN (SHFILEINFOA, hIcon, 1)
+    TEST_FIELD_OFFSET(SHFILEINFOA, hIcon, 0)
+    TEST_FIELD_SIZE  (SHFILEINFOA, iIcon, 4)
+    TEST_FIELD_ALIGN (SHFILEINFOA, iIcon, 1)
+    TEST_FIELD_OFFSET(SHFILEINFOA, iIcon, 4)
+    TEST_FIELD_SIZE  (SHFILEINFOA, dwAttributes, 4)
+    TEST_FIELD_ALIGN (SHFILEINFOA, dwAttributes, 1)
+    TEST_FIELD_OFFSET(SHFILEINFOA, dwAttributes, 8)
+    TEST_FIELD_SIZE  (SHFILEINFOA, szDisplayName, 260)
+    TEST_FIELD_ALIGN (SHFILEINFOA, szDisplayName, 1)
+    TEST_FIELD_OFFSET(SHFILEINFOA, szDisplayName, 12)
+    TEST_FIELD_SIZE  (SHFILEINFOA, szTypeName, 80)
+    TEST_FIELD_ALIGN (SHFILEINFOA, szTypeName, 1)
+    TEST_FIELD_OFFSET(SHFILEINFOA, szTypeName, 272)
 }
 
 static void test_pack_SHFILEINFOW(void)
 {
     /* SHFILEINFOW (pack 1) */
-    TEST_TYPE(SHFILEINFOW, 692, 1);
-    TEST_FIELD(SHFILEINFOW, HICON, hIcon, 0, 4, 1);
-    TEST_FIELD(SHFILEINFOW, int, iIcon, 4, 4, 1);
-    TEST_FIELD(SHFILEINFOW, DWORD, dwAttributes, 8, 4, 1);
-    TEST_FIELD(SHFILEINFOW, WCHAR[MAX_PATH], szDisplayName, 12, 520, 1);
-    TEST_FIELD(SHFILEINFOW, WCHAR[80], szTypeName, 532, 160, 1);
+    TEST_TYPE_SIZE   (SHFILEINFOW, 692)
+    TEST_TYPE_ALIGN  (SHFILEINFOW, 1)
+    TEST_FIELD_SIZE  (SHFILEINFOW, hIcon, 4)
+    TEST_FIELD_ALIGN (SHFILEINFOW, hIcon, 1)
+    TEST_FIELD_OFFSET(SHFILEINFOW, hIcon, 0)
+    TEST_FIELD_SIZE  (SHFILEINFOW, iIcon, 4)
+    TEST_FIELD_ALIGN (SHFILEINFOW, iIcon, 1)
+    TEST_FIELD_OFFSET(SHFILEINFOW, iIcon, 4)
+    TEST_FIELD_SIZE  (SHFILEINFOW, dwAttributes, 4)
+    TEST_FIELD_ALIGN (SHFILEINFOW, dwAttributes, 1)
+    TEST_FIELD_OFFSET(SHFILEINFOW, dwAttributes, 8)
+    TEST_FIELD_SIZE  (SHFILEINFOW, szDisplayName, 520)
+    TEST_FIELD_ALIGN (SHFILEINFOW, szDisplayName, 1)
+    TEST_FIELD_OFFSET(SHFILEINFOW, szDisplayName, 12)
+    TEST_FIELD_SIZE  (SHFILEINFOW, szTypeName, 160)
+    TEST_FIELD_ALIGN (SHFILEINFOW, szTypeName, 1)
+    TEST_FIELD_OFFSET(SHFILEINFOW, szTypeName, 532)
 }
 
 static void test_pack_SHFILEOPSTRUCTA(void)
 {
     /* SHFILEOPSTRUCTA (pack 1) */
-    TEST_TYPE(SHFILEOPSTRUCTA, 30, 1);
-    TEST_FIELD(SHFILEOPSTRUCTA, HWND, hwnd, 0, 4, 1);
-    TEST_FIELD(SHFILEOPSTRUCTA, UINT, wFunc, 4, 4, 1);
-    TEST_FIELD(SHFILEOPSTRUCTA, LPCSTR, pFrom, 8, 4, 1);
-    TEST_FIELD(SHFILEOPSTRUCTA, LPCSTR, pTo, 12, 4, 1);
-    TEST_FIELD(SHFILEOPSTRUCTA, FILEOP_FLAGS, fFlags, 16, 2, 1);
-    TEST_FIELD(SHFILEOPSTRUCTA, BOOL, fAnyOperationsAborted, 18, 4, 1);
-    TEST_FIELD(SHFILEOPSTRUCTA, LPVOID, hNameMappings, 22, 4, 1);
-    TEST_FIELD(SHFILEOPSTRUCTA, LPCSTR, lpszProgressTitle, 26, 4, 1);
+    TEST_TYPE_SIZE   (SHFILEOPSTRUCTA, 30)
+    TEST_TYPE_ALIGN  (SHFILEOPSTRUCTA, 1)
+    TEST_FIELD_SIZE  (SHFILEOPSTRUCTA, hwnd, 4)
+    TEST_FIELD_ALIGN (SHFILEOPSTRUCTA, hwnd, 1)
+    TEST_FIELD_OFFSET(SHFILEOPSTRUCTA, hwnd, 0)
+    TEST_FIELD_SIZE  (SHFILEOPSTRUCTA, wFunc, 4)
+    TEST_FIELD_ALIGN (SHFILEOPSTRUCTA, wFunc, 1)
+    TEST_FIELD_OFFSET(SHFILEOPSTRUCTA, wFunc, 4)
+    TEST_FIELD_SIZE  (SHFILEOPSTRUCTA, pFrom, 4)
+    TEST_FIELD_ALIGN (SHFILEOPSTRUCTA, pFrom, 1)
+    TEST_FIELD_OFFSET(SHFILEOPSTRUCTA, pFrom, 8)
+    TEST_FIELD_SIZE  (SHFILEOPSTRUCTA, pTo, 4)
+    TEST_FIELD_ALIGN (SHFILEOPSTRUCTA, pTo, 1)
+    TEST_FIELD_OFFSET(SHFILEOPSTRUCTA, pTo, 12)
+    TEST_FIELD_SIZE  (SHFILEOPSTRUCTA, fFlags, 2)
+    TEST_FIELD_ALIGN (SHFILEOPSTRUCTA, fFlags, 1)
+    TEST_FIELD_OFFSET(SHFILEOPSTRUCTA, fFlags, 16)
+    TEST_FIELD_SIZE  (SHFILEOPSTRUCTA, fAnyOperationsAborted, 4)
+    TEST_FIELD_ALIGN (SHFILEOPSTRUCTA, fAnyOperationsAborted, 1)
+    TEST_FIELD_OFFSET(SHFILEOPSTRUCTA, fAnyOperationsAborted, 18)
+    TEST_FIELD_SIZE  (SHFILEOPSTRUCTA, hNameMappings, 4)
+    TEST_FIELD_ALIGN (SHFILEOPSTRUCTA, hNameMappings, 1)
+    TEST_FIELD_OFFSET(SHFILEOPSTRUCTA, hNameMappings, 22)
+    TEST_FIELD_SIZE  (SHFILEOPSTRUCTA, lpszProgressTitle, 4)
+    TEST_FIELD_ALIGN (SHFILEOPSTRUCTA, lpszProgressTitle, 1)
+    TEST_FIELD_OFFSET(SHFILEOPSTRUCTA, lpszProgressTitle, 26)
 }
 
 static void test_pack_SHFILEOPSTRUCTW(void)
 {
     /* SHFILEOPSTRUCTW (pack 1) */
-    TEST_TYPE(SHFILEOPSTRUCTW, 30, 1);
-    TEST_FIELD(SHFILEOPSTRUCTW, HWND, hwnd, 0, 4, 1);
-    TEST_FIELD(SHFILEOPSTRUCTW, UINT, wFunc, 4, 4, 1);
-    TEST_FIELD(SHFILEOPSTRUCTW, LPCWSTR, pFrom, 8, 4, 1);
-    TEST_FIELD(SHFILEOPSTRUCTW, LPCWSTR, pTo, 12, 4, 1);
-    TEST_FIELD(SHFILEOPSTRUCTW, FILEOP_FLAGS, fFlags, 16, 2, 1);
-    TEST_FIELD(SHFILEOPSTRUCTW, BOOL, fAnyOperationsAborted, 18, 4, 1);
-    TEST_FIELD(SHFILEOPSTRUCTW, LPVOID, hNameMappings, 22, 4, 1);
-    TEST_FIELD(SHFILEOPSTRUCTW, LPCWSTR, lpszProgressTitle, 26, 4, 1);
+    TEST_TYPE_SIZE   (SHFILEOPSTRUCTW, 30)
+    TEST_TYPE_ALIGN  (SHFILEOPSTRUCTW, 1)
+    TEST_FIELD_SIZE  (SHFILEOPSTRUCTW, hwnd, 4)
+    TEST_FIELD_ALIGN (SHFILEOPSTRUCTW, hwnd, 1)
+    TEST_FIELD_OFFSET(SHFILEOPSTRUCTW, hwnd, 0)
+    TEST_FIELD_SIZE  (SHFILEOPSTRUCTW, wFunc, 4)
+    TEST_FIELD_ALIGN (SHFILEOPSTRUCTW, wFunc, 1)
+    TEST_FIELD_OFFSET(SHFILEOPSTRUCTW, wFunc, 4)
+    TEST_FIELD_SIZE  (SHFILEOPSTRUCTW, pFrom, 4)
+    TEST_FIELD_ALIGN (SHFILEOPSTRUCTW, pFrom, 1)
+    TEST_FIELD_OFFSET(SHFILEOPSTRUCTW, pFrom, 8)
+    TEST_FIELD_SIZE  (SHFILEOPSTRUCTW, pTo, 4)
+    TEST_FIELD_ALIGN (SHFILEOPSTRUCTW, pTo, 1)
+    TEST_FIELD_OFFSET(SHFILEOPSTRUCTW, pTo, 12)
+    TEST_FIELD_SIZE  (SHFILEOPSTRUCTW, fFlags, 2)
+    TEST_FIELD_ALIGN (SHFILEOPSTRUCTW, fFlags, 1)
+    TEST_FIELD_OFFSET(SHFILEOPSTRUCTW, fFlags, 16)
+    TEST_FIELD_SIZE  (SHFILEOPSTRUCTW, fAnyOperationsAborted, 4)
+    TEST_FIELD_ALIGN (SHFILEOPSTRUCTW, fAnyOperationsAborted, 1)
+    TEST_FIELD_OFFSET(SHFILEOPSTRUCTW, fAnyOperationsAborted, 18)
+    TEST_FIELD_SIZE  (SHFILEOPSTRUCTW, hNameMappings, 4)
+    TEST_FIELD_ALIGN (SHFILEOPSTRUCTW, hNameMappings, 1)
+    TEST_FIELD_OFFSET(SHFILEOPSTRUCTW, hNameMappings, 22)
+    TEST_FIELD_SIZE  (SHFILEOPSTRUCTW, lpszProgressTitle, 4)
+    TEST_FIELD_ALIGN (SHFILEOPSTRUCTW, lpszProgressTitle, 1)
+    TEST_FIELD_OFFSET(SHFILEOPSTRUCTW, lpszProgressTitle, 26)
 }
 
 static void test_pack_SHNAMEMAPPINGA(void)
 {
     /* SHNAMEMAPPINGA (pack 1) */
-    TEST_TYPE(SHNAMEMAPPINGA, 16, 1);
-    TEST_FIELD(SHNAMEMAPPINGA, LPSTR, pszOldPath, 0, 4, 1);
-    TEST_FIELD(SHNAMEMAPPINGA, LPSTR, pszNewPath, 4, 4, 1);
-    TEST_FIELD(SHNAMEMAPPINGA, int, cchOldPath, 8, 4, 1);
-    TEST_FIELD(SHNAMEMAPPINGA, int, cchNewPath, 12, 4, 1);
+    TEST_TYPE_SIZE   (SHNAMEMAPPINGA, 16)
+    TEST_TYPE_ALIGN  (SHNAMEMAPPINGA, 1)
+    TEST_FIELD_SIZE  (SHNAMEMAPPINGA, pszOldPath, 4)
+    TEST_FIELD_ALIGN (SHNAMEMAPPINGA, pszOldPath, 1)
+    TEST_FIELD_OFFSET(SHNAMEMAPPINGA, pszOldPath, 0)
+    TEST_FIELD_SIZE  (SHNAMEMAPPINGA, pszNewPath, 4)
+    TEST_FIELD_ALIGN (SHNAMEMAPPINGA, pszNewPath, 1)
+    TEST_FIELD_OFFSET(SHNAMEMAPPINGA, pszNewPath, 4)
+    TEST_FIELD_SIZE  (SHNAMEMAPPINGA, cchOldPath, 4)
+    TEST_FIELD_ALIGN (SHNAMEMAPPINGA, cchOldPath, 1)
+    TEST_FIELD_OFFSET(SHNAMEMAPPINGA, cchOldPath, 8)
+    TEST_FIELD_SIZE  (SHNAMEMAPPINGA, cchNewPath, 4)
+    TEST_FIELD_ALIGN (SHNAMEMAPPINGA, cchNewPath, 1)
+    TEST_FIELD_OFFSET(SHNAMEMAPPINGA, cchNewPath, 12)
 }
 
 static void test_pack_SHNAMEMAPPINGW(void)
 {
     /* SHNAMEMAPPINGW (pack 1) */
-    TEST_TYPE(SHNAMEMAPPINGW, 16, 1);
-    TEST_FIELD(SHNAMEMAPPINGW, LPWSTR, pszOldPath, 0, 4, 1);
-    TEST_FIELD(SHNAMEMAPPINGW, LPWSTR, pszNewPath, 4, 4, 1);
-    TEST_FIELD(SHNAMEMAPPINGW, int, cchOldPath, 8, 4, 1);
-    TEST_FIELD(SHNAMEMAPPINGW, int, cchNewPath, 12, 4, 1);
+    TEST_TYPE_SIZE   (SHNAMEMAPPINGW, 16)
+    TEST_TYPE_ALIGN  (SHNAMEMAPPINGW, 1)
+    TEST_FIELD_SIZE  (SHNAMEMAPPINGW, pszOldPath, 4)
+    TEST_FIELD_ALIGN (SHNAMEMAPPINGW, pszOldPath, 1)
+    TEST_FIELD_OFFSET(SHNAMEMAPPINGW, pszOldPath, 0)
+    TEST_FIELD_SIZE  (SHNAMEMAPPINGW, pszNewPath, 4)
+    TEST_FIELD_ALIGN (SHNAMEMAPPINGW, pszNewPath, 1)
+    TEST_FIELD_OFFSET(SHNAMEMAPPINGW, pszNewPath, 4)
+    TEST_FIELD_SIZE  (SHNAMEMAPPINGW, cchOldPath, 4)
+    TEST_FIELD_ALIGN (SHNAMEMAPPINGW, cchOldPath, 1)
+    TEST_FIELD_OFFSET(SHNAMEMAPPINGW, cchOldPath, 8)
+    TEST_FIELD_SIZE  (SHNAMEMAPPINGW, cchNewPath, 4)
+    TEST_FIELD_ALIGN (SHNAMEMAPPINGW, cchNewPath, 1)
+    TEST_FIELD_OFFSET(SHNAMEMAPPINGW, cchNewPath, 12)
 }
 
 static void test_pack_ITEMIDLIST(void)
 {
     /* ITEMIDLIST (pack 1) */
-    TEST_TYPE(ITEMIDLIST, 3, 1);
-    TEST_FIELD(ITEMIDLIST, SHITEMID, mkid, 0, 3, 1);
+    TEST_TYPE_SIZE   (ITEMIDLIST, 3)
+    TEST_TYPE_ALIGN  (ITEMIDLIST, 1)
+    TEST_FIELD_SIZE  (ITEMIDLIST, mkid, 3)
+    TEST_FIELD_ALIGN (ITEMIDLIST, mkid, 1)
+    TEST_FIELD_OFFSET(ITEMIDLIST, mkid, 0)
 }
 
 static void test_pack_LPCITEMIDLIST(void)
 {
     /* LPCITEMIDLIST */
-    TEST_TYPE(LPCITEMIDLIST, 4, 4);
-    TEST_TYPE_POINTER(LPCITEMIDLIST, 3, 1);
+    TEST_TYPE_SIZE   (LPCITEMIDLIST, 4)
+    TEST_TYPE_ALIGN  (LPCITEMIDLIST, 4)
+    TEST_TARGET_SIZE (LPCITEMIDLIST, 3)
+    TEST_TARGET_ALIGN(LPCITEMIDLIST, 1)
 }
 
 static void test_pack_LPCSHITEMID(void)
 {
     /* LPCSHITEMID */
-    TEST_TYPE(LPCSHITEMID, 4, 4);
-    TEST_TYPE_POINTER(LPCSHITEMID, 3, 1);
+    TEST_TYPE_SIZE   (LPCSHITEMID, 4)
+    TEST_TYPE_ALIGN  (LPCSHITEMID, 4)
+    TEST_TARGET_SIZE (LPCSHITEMID, 3)
+    TEST_TARGET_ALIGN(LPCSHITEMID, 1)
 }
 
 static void test_pack_LPITEMIDLIST(void)
 {
     /* LPITEMIDLIST */
-    TEST_TYPE(LPITEMIDLIST, 4, 4);
+    TEST_TYPE_SIZE   (LPITEMIDLIST, 4)
+    TEST_TYPE_ALIGN  (LPITEMIDLIST, 4)
 }
 
 static void test_pack_LPSHELLDETAILS(void)
 {
     /* LPSHELLDETAILS */
-    TEST_TYPE(LPSHELLDETAILS, 4, 4);
+    TEST_TYPE_SIZE   (LPSHELLDETAILS, 4)
+    TEST_TYPE_ALIGN  (LPSHELLDETAILS, 4)
 }
 
 static void test_pack_LPSHITEMID(void)
 {
     /* LPSHITEMID */
-    TEST_TYPE(LPSHITEMID, 4, 4);
+    TEST_TYPE_SIZE   (LPSHITEMID, 4)
+    TEST_TYPE_ALIGN  (LPSHITEMID, 4)
 }
 
 static void test_pack_LPSTRRET(void)
 {
     /* LPSTRRET */
-    TEST_TYPE(LPSTRRET, 4, 4);
+    TEST_TYPE_SIZE   (LPSTRRET, 4)
+    TEST_TYPE_ALIGN  (LPSTRRET, 4)
 }
 
 static void test_pack_SHELLDETAILS(void)
 {
     /* SHELLDETAILS (pack 1) */
-    TEST_FIELD(SHELLDETAILS, int, fmt, 0, 4, 1);
-    TEST_FIELD(SHELLDETAILS, int, cxChar, 4, 4, 1);
+    TEST_FIELD_SIZE  (SHELLDETAILS, fmt, 4)
+    TEST_FIELD_ALIGN (SHELLDETAILS, fmt, 1)
+    TEST_FIELD_OFFSET(SHELLDETAILS, fmt, 0)
+    TEST_FIELD_SIZE  (SHELLDETAILS, cxChar, 4)
+    TEST_FIELD_ALIGN (SHELLDETAILS, cxChar, 1)
+    TEST_FIELD_OFFSET(SHELLDETAILS, cxChar, 4)
 }
 
 static void test_pack_SHITEMID(void)
 {
     /* SHITEMID (pack 1) */
-    TEST_TYPE(SHITEMID, 3, 1);
-    TEST_FIELD(SHITEMID, WORD, cb, 0, 2, 1);
-    TEST_FIELD(SHITEMID, BYTE[1], abID, 2, 1, 1);
+    TEST_TYPE_SIZE   (SHITEMID, 3)
+    TEST_TYPE_ALIGN  (SHITEMID, 1)
+    TEST_FIELD_SIZE  (SHITEMID, cb, 2)
+    TEST_FIELD_ALIGN (SHITEMID, cb, 1)
+    TEST_FIELD_OFFSET(SHITEMID, cb, 0)
+    TEST_FIELD_SIZE  (SHITEMID, abID, 1)
+    TEST_FIELD_ALIGN (SHITEMID, abID, 1)
+    TEST_FIELD_OFFSET(SHITEMID, abID, 2)
 }
 
 static void test_pack_STRRET(void)
 {
     /* STRRET (pack 4) */
-    TEST_FIELD(STRRET, UINT, uType, 0, 4, 4);
+    TEST_FIELD_SIZE  (STRRET, uType, 4)
+    TEST_FIELD_ALIGN (STRRET, uType, 4)
+    TEST_FIELD_OFFSET(STRRET, uType, 0)
 }
 
 static void test_pack_AUTO_SCROLL_DATA(void)
 {
     /* AUTO_SCROLL_DATA (pack 1) */
-    TEST_TYPE(AUTO_SCROLL_DATA, 48, 1);
-    TEST_FIELD(AUTO_SCROLL_DATA, int, iNextSample, 0, 4, 1);
-    TEST_FIELD(AUTO_SCROLL_DATA, DWORD, dwLastScroll, 4, 4, 1);
-    TEST_FIELD(AUTO_SCROLL_DATA, BOOL, bFull, 8, 4, 1);
-    TEST_FIELD(AUTO_SCROLL_DATA, POINT[NUM_POINTS], pts, 12, 24, 1);
-    TEST_FIELD(AUTO_SCROLL_DATA, DWORD[NUM_POINTS], dwTimes, 36, 12, 1);
+    TEST_TYPE_SIZE   (AUTO_SCROLL_DATA, 48)
+    TEST_TYPE_ALIGN  (AUTO_SCROLL_DATA, 1)
+    TEST_FIELD_SIZE  (AUTO_SCROLL_DATA, iNextSample, 4)
+    TEST_FIELD_ALIGN (AUTO_SCROLL_DATA, iNextSample, 1)
+    TEST_FIELD_OFFSET(AUTO_SCROLL_DATA, iNextSample, 0)
+    TEST_FIELD_SIZE  (AUTO_SCROLL_DATA, dwLastScroll, 4)
+    TEST_FIELD_ALIGN (AUTO_SCROLL_DATA, dwLastScroll, 1)
+    TEST_FIELD_OFFSET(AUTO_SCROLL_DATA, dwLastScroll, 4)
+    TEST_FIELD_SIZE  (AUTO_SCROLL_DATA, bFull, 4)
+    TEST_FIELD_ALIGN (AUTO_SCROLL_DATA, bFull, 1)
+    TEST_FIELD_OFFSET(AUTO_SCROLL_DATA, bFull, 8)
+    TEST_FIELD_SIZE  (AUTO_SCROLL_DATA, pts, 24)
+    TEST_FIELD_ALIGN (AUTO_SCROLL_DATA, pts, 1)
+    TEST_FIELD_OFFSET(AUTO_SCROLL_DATA, pts, 12)
+    TEST_FIELD_SIZE  (AUTO_SCROLL_DATA, dwTimes, 12)
+    TEST_FIELD_ALIGN (AUTO_SCROLL_DATA, dwTimes, 1)
+    TEST_FIELD_OFFSET(AUTO_SCROLL_DATA, dwTimes, 36)
 }
 
 static void test_pack_BFFCALLBACK(void)
 {
     /* BFFCALLBACK */
-    TEST_TYPE(BFFCALLBACK, 4, 4);
+    TEST_TYPE_SIZE   (BFFCALLBACK, 4)
+    TEST_TYPE_ALIGN  (BFFCALLBACK, 4)
 }
 
 static void test_pack_BROWSEINFOA(void)
 {
     /* BROWSEINFOA (pack 8) */
-    TEST_TYPE(BROWSEINFOA, 32, 4);
-    TEST_FIELD(BROWSEINFOA, HWND, hwndOwner, 0, 4, 4);
-    TEST_FIELD(BROWSEINFOA, LPCITEMIDLIST, pidlRoot, 4, 4, 4);
-    TEST_FIELD(BROWSEINFOA, LPSTR, pszDisplayName, 8, 4, 4);
-    TEST_FIELD(BROWSEINFOA, LPCSTR, lpszTitle, 12, 4, 4);
-    TEST_FIELD(BROWSEINFOA, UINT, ulFlags, 16, 4, 4);
-    TEST_FIELD(BROWSEINFOA, BFFCALLBACK, lpfn, 20, 4, 4);
-    TEST_FIELD(BROWSEINFOA, LPARAM, lParam, 24, 4, 4);
-    TEST_FIELD(BROWSEINFOA, INT, iImage, 28, 4, 4);
+    TEST_TYPE_SIZE   (BROWSEINFOA, 32)
+    TEST_TYPE_ALIGN  (BROWSEINFOA, 4)
+    TEST_FIELD_SIZE  (BROWSEINFOA, hwndOwner, 4)
+    TEST_FIELD_ALIGN (BROWSEINFOA, hwndOwner, 4)
+    TEST_FIELD_OFFSET(BROWSEINFOA, hwndOwner, 0)
+    TEST_FIELD_SIZE  (BROWSEINFOA, pidlRoot, 4)
+    TEST_FIELD_ALIGN (BROWSEINFOA, pidlRoot, 4)
+    TEST_FIELD_OFFSET(BROWSEINFOA, pidlRoot, 4)
+    TEST_FIELD_SIZE  (BROWSEINFOA, pszDisplayName, 4)
+    TEST_FIELD_ALIGN (BROWSEINFOA, pszDisplayName, 4)
+    TEST_FIELD_OFFSET(BROWSEINFOA, pszDisplayName, 8)
+    TEST_FIELD_SIZE  (BROWSEINFOA, lpszTitle, 4)
+    TEST_FIELD_ALIGN (BROWSEINFOA, lpszTitle, 4)
+    TEST_FIELD_OFFSET(BROWSEINFOA, lpszTitle, 12)
+    TEST_FIELD_SIZE  (BROWSEINFOA, ulFlags, 4)
+    TEST_FIELD_ALIGN (BROWSEINFOA, ulFlags, 4)
+    TEST_FIELD_OFFSET(BROWSEINFOA, ulFlags, 16)
+    TEST_FIELD_SIZE  (BROWSEINFOA, lpfn, 4)
+    TEST_FIELD_ALIGN (BROWSEINFOA, lpfn, 4)
+    TEST_FIELD_OFFSET(BROWSEINFOA, lpfn, 20)
+    TEST_FIELD_SIZE  (BROWSEINFOA, lParam, 4)
+    TEST_FIELD_ALIGN (BROWSEINFOA, lParam, 4)
+    TEST_FIELD_OFFSET(BROWSEINFOA, lParam, 24)
+    TEST_FIELD_SIZE  (BROWSEINFOA, iImage, 4)
+    TEST_FIELD_ALIGN (BROWSEINFOA, iImage, 4)
+    TEST_FIELD_OFFSET(BROWSEINFOA, iImage, 28)
 }
 
 static void test_pack_BROWSEINFOW(void)
 {
     /* BROWSEINFOW (pack 8) */
-    TEST_TYPE(BROWSEINFOW, 32, 4);
-    TEST_FIELD(BROWSEINFOW, HWND, hwndOwner, 0, 4, 4);
-    TEST_FIELD(BROWSEINFOW, LPCITEMIDLIST, pidlRoot, 4, 4, 4);
-    TEST_FIELD(BROWSEINFOW, LPWSTR, pszDisplayName, 8, 4, 4);
-    TEST_FIELD(BROWSEINFOW, LPCWSTR, lpszTitle, 12, 4, 4);
-    TEST_FIELD(BROWSEINFOW, UINT, ulFlags, 16, 4, 4);
-    TEST_FIELD(BROWSEINFOW, BFFCALLBACK, lpfn, 20, 4, 4);
-    TEST_FIELD(BROWSEINFOW, LPARAM, lParam, 24, 4, 4);
-    TEST_FIELD(BROWSEINFOW, INT, iImage, 28, 4, 4);
+    TEST_TYPE_SIZE   (BROWSEINFOW, 32)
+    TEST_TYPE_ALIGN  (BROWSEINFOW, 4)
+    TEST_FIELD_SIZE  (BROWSEINFOW, hwndOwner, 4)
+    TEST_FIELD_ALIGN (BROWSEINFOW, hwndOwner, 4)
+    TEST_FIELD_OFFSET(BROWSEINFOW, hwndOwner, 0)
+    TEST_FIELD_SIZE  (BROWSEINFOW, pidlRoot, 4)
+    TEST_FIELD_ALIGN (BROWSEINFOW, pidlRoot, 4)
+    TEST_FIELD_OFFSET(BROWSEINFOW, pidlRoot, 4)
+    TEST_FIELD_SIZE  (BROWSEINFOW, pszDisplayName, 4)
+    TEST_FIELD_ALIGN (BROWSEINFOW, pszDisplayName, 4)
+    TEST_FIELD_OFFSET(BROWSEINFOW, pszDisplayName, 8)
+    TEST_FIELD_SIZE  (BROWSEINFOW, lpszTitle, 4)
+    TEST_FIELD_ALIGN (BROWSEINFOW, lpszTitle, 4)
+    TEST_FIELD_OFFSET(BROWSEINFOW, lpszTitle, 12)
+    TEST_FIELD_SIZE  (BROWSEINFOW, ulFlags, 4)
+    TEST_FIELD_ALIGN (BROWSEINFOW, ulFlags, 4)
+    TEST_FIELD_OFFSET(BROWSEINFOW, ulFlags, 16)
+    TEST_FIELD_SIZE  (BROWSEINFOW, lpfn, 4)
+    TEST_FIELD_ALIGN (BROWSEINFOW, lpfn, 4)
+    TEST_FIELD_OFFSET(BROWSEINFOW, lpfn, 20)
+    TEST_FIELD_SIZE  (BROWSEINFOW, lParam, 4)
+    TEST_FIELD_ALIGN (BROWSEINFOW, lParam, 4)
+    TEST_FIELD_OFFSET(BROWSEINFOW, lParam, 24)
+    TEST_FIELD_SIZE  (BROWSEINFOW, iImage, 4)
+    TEST_FIELD_ALIGN (BROWSEINFOW, iImage, 4)
+    TEST_FIELD_OFFSET(BROWSEINFOW, iImage, 28)
 }
 
 static void test_pack_CABINETSTATE(void)
 {
     /* CABINETSTATE (pack 1) */
-    TEST_TYPE(CABINETSTATE, 12, 1);
-    TEST_FIELD(CABINETSTATE, WORD, cLength, 0, 2, 1);
-    TEST_FIELD(CABINETSTATE, WORD, nVersion, 2, 2, 1);
-    TEST_FIELD(CABINETSTATE, UINT, fMenuEnumFilter, 8, 4, 1);
+    TEST_TYPE_SIZE   (CABINETSTATE, 12)
+    TEST_TYPE_ALIGN  (CABINETSTATE, 1)
+    TEST_FIELD_SIZE  (CABINETSTATE, cLength, 2)
+    TEST_FIELD_ALIGN (CABINETSTATE, cLength, 1)
+    TEST_FIELD_OFFSET(CABINETSTATE, cLength, 0)
+    TEST_FIELD_SIZE  (CABINETSTATE, nVersion, 2)
+    TEST_FIELD_ALIGN (CABINETSTATE, nVersion, 1)
+    TEST_FIELD_OFFSET(CABINETSTATE, nVersion, 2)
+    TEST_FIELD_SIZE  (CABINETSTATE, fMenuEnumFilter, 4)
+    TEST_FIELD_ALIGN (CABINETSTATE, fMenuEnumFilter, 1)
+    TEST_FIELD_OFFSET(CABINETSTATE, fMenuEnumFilter, 8)
 }
 
 static void test_pack_CIDA(void)
 {
     /* CIDA (pack 1) */
-    TEST_TYPE(CIDA, 8, 1);
-    TEST_FIELD(CIDA, UINT, cidl, 0, 4, 1);
-    TEST_FIELD(CIDA, UINT[1], aoffset, 4, 4, 1);
+    TEST_TYPE_SIZE   (CIDA, 8)
+    TEST_TYPE_ALIGN  (CIDA, 1)
+    TEST_FIELD_SIZE  (CIDA, cidl, 4)
+    TEST_FIELD_ALIGN (CIDA, cidl, 1)
+    TEST_FIELD_OFFSET(CIDA, cidl, 0)
+    TEST_FIELD_SIZE  (CIDA, aoffset, 4)
+    TEST_FIELD_ALIGN (CIDA, aoffset, 1)
+    TEST_FIELD_OFFSET(CIDA, aoffset, 4)
 }
 
 static void test_pack_CSFV(void)
 {
     /* CSFV (pack 1) */
-    TEST_FIELD(CSFV, UINT, cbSize, 0, 4, 1);
-    TEST_FIELD(CSFV, IShellFolder*, pshf, 4, 4, 1);
-    TEST_FIELD(CSFV, IShellView*, psvOuter, 8, 4, 1);
-    TEST_FIELD(CSFV, LPCITEMIDLIST, pidl, 12, 4, 1);
-    TEST_FIELD(CSFV, LONG, lEvents, 16, 4, 1);
-    TEST_FIELD(CSFV, LPFNVIEWCALLBACK, pfnCallback, 20, 4, 1);
+    TEST_FIELD_SIZE  (CSFV, cbSize, 4)
+    TEST_FIELD_ALIGN (CSFV, cbSize, 1)
+    TEST_FIELD_OFFSET(CSFV, cbSize, 0)
+    TEST_FIELD_SIZE  (CSFV, pshf, 4)
+    TEST_FIELD_ALIGN (CSFV, pshf, 1)
+    TEST_FIELD_OFFSET(CSFV, pshf, 4)
+    TEST_FIELD_SIZE  (CSFV, psvOuter, 4)
+    TEST_FIELD_ALIGN (CSFV, psvOuter, 1)
+    TEST_FIELD_OFFSET(CSFV, psvOuter, 8)
+    TEST_FIELD_SIZE  (CSFV, pidl, 4)
+    TEST_FIELD_ALIGN (CSFV, pidl, 1)
+    TEST_FIELD_OFFSET(CSFV, pidl, 12)
+    TEST_FIELD_SIZE  (CSFV, lEvents, 4)
+    TEST_FIELD_ALIGN (CSFV, lEvents, 1)
+    TEST_FIELD_OFFSET(CSFV, lEvents, 16)
+    TEST_FIELD_SIZE  (CSFV, pfnCallback, 4)
+    TEST_FIELD_ALIGN (CSFV, pfnCallback, 1)
+    TEST_FIELD_OFFSET(CSFV, pfnCallback, 20)
 }
 
 static void test_pack_DROPFILES(void)
 {
     /* DROPFILES (pack 1) */
-    TEST_TYPE(DROPFILES, 20, 1);
-    TEST_FIELD(DROPFILES, DWORD, pFiles, 0, 4, 1);
-    TEST_FIELD(DROPFILES, POINT, pt, 4, 8, 1);
-    TEST_FIELD(DROPFILES, BOOL, fNC, 12, 4, 1);
-    TEST_FIELD(DROPFILES, BOOL, fWide, 16, 4, 1);
+    TEST_TYPE_SIZE   (DROPFILES, 20)
+    TEST_TYPE_ALIGN  (DROPFILES, 1)
+    TEST_FIELD_SIZE  (DROPFILES, pFiles, 4)
+    TEST_FIELD_ALIGN (DROPFILES, pFiles, 1)
+    TEST_FIELD_OFFSET(DROPFILES, pFiles, 0)
+    TEST_FIELD_SIZE  (DROPFILES, pt, 8)
+    TEST_FIELD_ALIGN (DROPFILES, pt, 1)
+    TEST_FIELD_OFFSET(DROPFILES, pt, 4)
+    TEST_FIELD_SIZE  (DROPFILES, fNC, 4)
+    TEST_FIELD_ALIGN (DROPFILES, fNC, 1)
+    TEST_FIELD_OFFSET(DROPFILES, fNC, 12)
+    TEST_FIELD_SIZE  (DROPFILES, fWide, 4)
+    TEST_FIELD_ALIGN (DROPFILES, fWide, 1)
+    TEST_FIELD_OFFSET(DROPFILES, fWide, 16)
 }
 
 static void test_pack_FILEDESCRIPTORA(void)
 {
     /* FILEDESCRIPTORA (pack 1) */
-    TEST_TYPE(FILEDESCRIPTORA, 332, 1);
-    TEST_FIELD(FILEDESCRIPTORA, DWORD, dwFlags, 0, 4, 1);
-    TEST_FIELD(FILEDESCRIPTORA, CLSID, clsid, 4, 16, 1);
-    TEST_FIELD(FILEDESCRIPTORA, SIZEL, sizel, 20, 8, 1);
-    TEST_FIELD(FILEDESCRIPTORA, POINTL, pointl, 28, 8, 1);
-    TEST_FIELD(FILEDESCRIPTORA, DWORD, dwFileAttributes, 36, 4, 1);
-    TEST_FIELD(FILEDESCRIPTORA, FILETIME, ftCreationTime, 40, 8, 1);
-    TEST_FIELD(FILEDESCRIPTORA, FILETIME, ftLastAccessTime, 48, 8, 1);
-    TEST_FIELD(FILEDESCRIPTORA, FILETIME, ftLastWriteTime, 56, 8, 1);
-    TEST_FIELD(FILEDESCRIPTORA, DWORD, nFileSizeHigh, 64, 4, 1);
-    TEST_FIELD(FILEDESCRIPTORA, DWORD, nFileSizeLow, 68, 4, 1);
-    TEST_FIELD(FILEDESCRIPTORA, CHAR[MAX_PATH], cFileName, 72, 260, 1);
+    TEST_TYPE_SIZE   (FILEDESCRIPTORA, 332)
+    TEST_TYPE_ALIGN  (FILEDESCRIPTORA, 1)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORA, dwFlags, 4)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORA, dwFlags, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORA, dwFlags, 0)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORA, clsid, 16)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORA, clsid, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORA, clsid, 4)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORA, sizel, 8)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORA, sizel, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORA, sizel, 20)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORA, pointl, 8)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORA, pointl, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORA, pointl, 28)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORA, dwFileAttributes, 4)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORA, dwFileAttributes, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORA, dwFileAttributes, 36)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORA, ftCreationTime, 8)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORA, ftCreationTime, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORA, ftCreationTime, 40)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORA, ftLastAccessTime, 8)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORA, ftLastAccessTime, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORA, ftLastAccessTime, 48)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORA, ftLastWriteTime, 8)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORA, ftLastWriteTime, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORA, ftLastWriteTime, 56)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORA, nFileSizeHigh, 4)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORA, nFileSizeHigh, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORA, nFileSizeHigh, 64)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORA, nFileSizeLow, 4)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORA, nFileSizeLow, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORA, nFileSizeLow, 68)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORA, cFileName, 260)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORA, cFileName, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORA, cFileName, 72)
 }
 
 static void test_pack_FILEDESCRIPTORW(void)
 {
     /* FILEDESCRIPTORW (pack 1) */
-    TEST_TYPE(FILEDESCRIPTORW, 592, 1);
-    TEST_FIELD(FILEDESCRIPTORW, DWORD, dwFlags, 0, 4, 1);
-    TEST_FIELD(FILEDESCRIPTORW, CLSID, clsid, 4, 16, 1);
-    TEST_FIELD(FILEDESCRIPTORW, SIZEL, sizel, 20, 8, 1);
-    TEST_FIELD(FILEDESCRIPTORW, POINTL, pointl, 28, 8, 1);
-    TEST_FIELD(FILEDESCRIPTORW, DWORD, dwFileAttributes, 36, 4, 1);
-    TEST_FIELD(FILEDESCRIPTORW, FILETIME, ftCreationTime, 40, 8, 1);
-    TEST_FIELD(FILEDESCRIPTORW, FILETIME, ftLastAccessTime, 48, 8, 1);
-    TEST_FIELD(FILEDESCRIPTORW, FILETIME, ftLastWriteTime, 56, 8, 1);
-    TEST_FIELD(FILEDESCRIPTORW, DWORD, nFileSizeHigh, 64, 4, 1);
-    TEST_FIELD(FILEDESCRIPTORW, DWORD, nFileSizeLow, 68, 4, 1);
-    TEST_FIELD(FILEDESCRIPTORW, WCHAR[MAX_PATH], cFileName, 72, 520, 1);
+    TEST_TYPE_SIZE   (FILEDESCRIPTORW, 592)
+    TEST_TYPE_ALIGN  (FILEDESCRIPTORW, 1)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORW, dwFlags, 4)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORW, dwFlags, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORW, dwFlags, 0)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORW, clsid, 16)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORW, clsid, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORW, clsid, 4)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORW, sizel, 8)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORW, sizel, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORW, sizel, 20)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORW, pointl, 8)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORW, pointl, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORW, pointl, 28)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORW, dwFileAttributes, 4)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORW, dwFileAttributes, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORW, dwFileAttributes, 36)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORW, ftCreationTime, 8)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORW, ftCreationTime, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORW, ftCreationTime, 40)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORW, ftLastAccessTime, 8)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORW, ftLastAccessTime, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORW, ftLastAccessTime, 48)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORW, ftLastWriteTime, 8)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORW, ftLastWriteTime, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORW, ftLastWriteTime, 56)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORW, nFileSizeHigh, 4)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORW, nFileSizeHigh, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORW, nFileSizeHigh, 64)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORW, nFileSizeLow, 4)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORW, nFileSizeLow, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORW, nFileSizeLow, 68)
+    TEST_FIELD_SIZE  (FILEDESCRIPTORW, cFileName, 520)
+    TEST_FIELD_ALIGN (FILEDESCRIPTORW, cFileName, 1)
+    TEST_FIELD_OFFSET(FILEDESCRIPTORW, cFileName, 72)
 }
 
 static void test_pack_FILEGROUPDESCRIPTORA(void)
 {
     /* FILEGROUPDESCRIPTORA (pack 1) */
-    TEST_TYPE(FILEGROUPDESCRIPTORA, 336, 1);
-    TEST_FIELD(FILEGROUPDESCRIPTORA, UINT, cItems, 0, 4, 1);
-    TEST_FIELD(FILEGROUPDESCRIPTORA, FILEDESCRIPTORA[1], fgd, 4, 332, 1);
+    TEST_TYPE_SIZE   (FILEGROUPDESCRIPTORA, 336)
+    TEST_TYPE_ALIGN  (FILEGROUPDESCRIPTORA, 1)
+    TEST_FIELD_SIZE  (FILEGROUPDESCRIPTORA, cItems, 4)
+    TEST_FIELD_ALIGN (FILEGROUPDESCRIPTORA, cItems, 1)
+    TEST_FIELD_OFFSET(FILEGROUPDESCRIPTORA, cItems, 0)
+    TEST_FIELD_SIZE  (FILEGROUPDESCRIPTORA, fgd, 332)
+    TEST_FIELD_ALIGN (FILEGROUPDESCRIPTORA, fgd, 1)
+    TEST_FIELD_OFFSET(FILEGROUPDESCRIPTORA, fgd, 4)
 }
 
 static void test_pack_FILEGROUPDESCRIPTORW(void)
 {
     /* FILEGROUPDESCRIPTORW (pack 1) */
-    TEST_TYPE(FILEGROUPDESCRIPTORW, 596, 1);
-    TEST_FIELD(FILEGROUPDESCRIPTORW, UINT, cItems, 0, 4, 1);
-    TEST_FIELD(FILEGROUPDESCRIPTORW, FILEDESCRIPTORW[1], fgd, 4, 592, 1);
+    TEST_TYPE_SIZE   (FILEGROUPDESCRIPTORW, 596)
+    TEST_TYPE_ALIGN  (FILEGROUPDESCRIPTORW, 1)
+    TEST_FIELD_SIZE  (FILEGROUPDESCRIPTORW, cItems, 4)
+    TEST_FIELD_ALIGN (FILEGROUPDESCRIPTORW, cItems, 1)
+    TEST_FIELD_OFFSET(FILEGROUPDESCRIPTORW, cItems, 0)
+    TEST_FIELD_SIZE  (FILEGROUPDESCRIPTORW, fgd, 592)
+    TEST_FIELD_ALIGN (FILEGROUPDESCRIPTORW, fgd, 1)
+    TEST_FIELD_OFFSET(FILEGROUPDESCRIPTORW, fgd, 4)
 }
 
 static void test_pack_LPBROWSEINFOA(void)
 {
     /* LPBROWSEINFOA */
-    TEST_TYPE(LPBROWSEINFOA, 4, 4);
-    TEST_TYPE_POINTER(LPBROWSEINFOA, 32, 4);
+    TEST_TYPE_SIZE   (LPBROWSEINFOA, 4)
+    TEST_TYPE_ALIGN  (LPBROWSEINFOA, 4)
+    TEST_TARGET_SIZE (LPBROWSEINFOA, 32)
+    TEST_TARGET_ALIGN(LPBROWSEINFOA, 4)
 }
 
 static void test_pack_LPBROWSEINFOW(void)
 {
     /* LPBROWSEINFOW */
-    TEST_TYPE(LPBROWSEINFOW, 4, 4);
-    TEST_TYPE_POINTER(LPBROWSEINFOW, 32, 4);
+    TEST_TYPE_SIZE   (LPBROWSEINFOW, 4)
+    TEST_TYPE_ALIGN  (LPBROWSEINFOW, 4)
+    TEST_TARGET_SIZE (LPBROWSEINFOW, 32)
+    TEST_TARGET_ALIGN(LPBROWSEINFOW, 4)
 }
 
 static void test_pack_LPCABINETSTATE(void)
 {
     /* LPCABINETSTATE */
-    TEST_TYPE(LPCABINETSTATE, 4, 4);
-    TEST_TYPE_POINTER(LPCABINETSTATE, 12, 1);
+    TEST_TYPE_SIZE   (LPCABINETSTATE, 4)
+    TEST_TYPE_ALIGN  (LPCABINETSTATE, 4)
+    TEST_TARGET_SIZE (LPCABINETSTATE, 12)
+    TEST_TARGET_ALIGN(LPCABINETSTATE, 1)
 }
 
 static void test_pack_LPCSFV(void)
 {
     /* LPCSFV */
-    TEST_TYPE(LPCSFV, 4, 4);
+    TEST_TYPE_SIZE   (LPCSFV, 4)
+    TEST_TYPE_ALIGN  (LPCSFV, 4)
 }
 
 static void test_pack_LPDROPFILES(void)
 {
     /* LPDROPFILES */
-    TEST_TYPE(LPDROPFILES, 4, 4);
-    TEST_TYPE_POINTER(LPDROPFILES, 20, 1);
+    TEST_TYPE_SIZE   (LPDROPFILES, 4)
+    TEST_TYPE_ALIGN  (LPDROPFILES, 4)
+    TEST_TARGET_SIZE (LPDROPFILES, 20)
+    TEST_TARGET_ALIGN(LPDROPFILES, 1)
 }
 
 static void test_pack_LPFILEDESCRIPTORA(void)
 {
     /* LPFILEDESCRIPTORA */
-    TEST_TYPE(LPFILEDESCRIPTORA, 4, 4);
-    TEST_TYPE_POINTER(LPFILEDESCRIPTORA, 332, 1);
+    TEST_TYPE_SIZE   (LPFILEDESCRIPTORA, 4)
+    TEST_TYPE_ALIGN  (LPFILEDESCRIPTORA, 4)
+    TEST_TARGET_SIZE (LPFILEDESCRIPTORA, 332)
+    TEST_TARGET_ALIGN(LPFILEDESCRIPTORA, 1)
 }
 
 static void test_pack_LPFILEDESCRIPTORW(void)
 {
     /* LPFILEDESCRIPTORW */
-    TEST_TYPE(LPFILEDESCRIPTORW, 4, 4);
-    TEST_TYPE_POINTER(LPFILEDESCRIPTORW, 592, 1);
+    TEST_TYPE_SIZE   (LPFILEDESCRIPTORW, 4)
+    TEST_TYPE_ALIGN  (LPFILEDESCRIPTORW, 4)
+    TEST_TARGET_SIZE (LPFILEDESCRIPTORW, 592)
+    TEST_TARGET_ALIGN(LPFILEDESCRIPTORW, 1)
 }
 
 static void test_pack_LPFILEGROUPDESCRIPTORA(void)
 {
     /* LPFILEGROUPDESCRIPTORA */
-    TEST_TYPE(LPFILEGROUPDESCRIPTORA, 4, 4);
-    TEST_TYPE_POINTER(LPFILEGROUPDESCRIPTORA, 336, 1);
+    TEST_TYPE_SIZE   (LPFILEGROUPDESCRIPTORA, 4)
+    TEST_TYPE_ALIGN  (LPFILEGROUPDESCRIPTORA, 4)
+    TEST_TARGET_SIZE (LPFILEGROUPDESCRIPTORA, 336)
+    TEST_TARGET_ALIGN(LPFILEGROUPDESCRIPTORA, 1)
 }
 
 static void test_pack_LPFILEGROUPDESCRIPTORW(void)
 {
     /* LPFILEGROUPDESCRIPTORW */
-    TEST_TYPE(LPFILEGROUPDESCRIPTORW, 4, 4);
-    TEST_TYPE_POINTER(LPFILEGROUPDESCRIPTORW, 596, 1);
+    TEST_TYPE_SIZE   (LPFILEGROUPDESCRIPTORW, 4)
+    TEST_TYPE_ALIGN  (LPFILEGROUPDESCRIPTORW, 4)
+    TEST_TARGET_SIZE (LPFILEGROUPDESCRIPTORW, 596)
+    TEST_TARGET_ALIGN(LPFILEGROUPDESCRIPTORW, 1)
 }
 
 static void test_pack_LPFNVIEWCALLBACK(void)
 {
     /* LPFNVIEWCALLBACK */
-    TEST_TYPE(LPFNVIEWCALLBACK, 4, 4);
+    TEST_TYPE_SIZE   (LPFNVIEWCALLBACK, 4)
+    TEST_TYPE_ALIGN  (LPFNVIEWCALLBACK, 4)
 }
 
 static void test_pack_LPIDA(void)
 {
     /* LPIDA */
-    TEST_TYPE(LPIDA, 4, 4);
-    TEST_TYPE_POINTER(LPIDA, 8, 1);
+    TEST_TYPE_SIZE   (LPIDA, 4)
+    TEST_TYPE_ALIGN  (LPIDA, 4)
+    TEST_TARGET_SIZE (LPIDA, 8)
+    TEST_TARGET_ALIGN(LPIDA, 1)
 }
 
 static void test_pack_LPQCMINFO(void)
 {
     /* LPQCMINFO */
-    TEST_TYPE(LPQCMINFO, 4, 4);
-    TEST_TYPE_POINTER(LPQCMINFO, 20, 4);
+    TEST_TYPE_SIZE   (LPQCMINFO, 4)
+    TEST_TYPE_ALIGN  (LPQCMINFO, 4)
+    TEST_TARGET_SIZE (LPQCMINFO, 20)
+    TEST_TARGET_ALIGN(LPQCMINFO, 4)
 }
 
 static void test_pack_LPSHChangeDWORDAsIDList(void)
 {
     /* LPSHChangeDWORDAsIDList */
-    TEST_TYPE(LPSHChangeDWORDAsIDList, 4, 4);
-    TEST_TYPE_POINTER(LPSHChangeDWORDAsIDList, 12, 1);
+    TEST_TYPE_SIZE   (LPSHChangeDWORDAsIDList, 4)
+    TEST_TYPE_ALIGN  (LPSHChangeDWORDAsIDList, 4)
+    TEST_TARGET_SIZE (LPSHChangeDWORDAsIDList, 12)
+    TEST_TARGET_ALIGN(LPSHChangeDWORDAsIDList, 1)
 }
 
 static void test_pack_LPSHChangeProductKeyAsIDList(void)
 {
     /* LPSHChangeProductKeyAsIDList */
-    TEST_TYPE(LPSHChangeProductKeyAsIDList, 4, 4);
-    TEST_TYPE_POINTER(LPSHChangeProductKeyAsIDList, 82, 1);
+    TEST_TYPE_SIZE   (LPSHChangeProductKeyAsIDList, 4)
+    TEST_TYPE_ALIGN  (LPSHChangeProductKeyAsIDList, 4)
+    TEST_TARGET_SIZE (LPSHChangeProductKeyAsIDList, 82)
+    TEST_TARGET_ALIGN(LPSHChangeProductKeyAsIDList, 1)
 }
 
 static void test_pack_LPSHDESCRIPTIONID(void)
 {
     /* LPSHDESCRIPTIONID */
-    TEST_TYPE(LPSHDESCRIPTIONID, 4, 4);
-    TEST_TYPE_POINTER(LPSHDESCRIPTIONID, 20, 4);
+    TEST_TYPE_SIZE   (LPSHDESCRIPTIONID, 4)
+    TEST_TYPE_ALIGN  (LPSHDESCRIPTIONID, 4)
+    TEST_TARGET_SIZE (LPSHDESCRIPTIONID, 20)
+    TEST_TARGET_ALIGN(LPSHDESCRIPTIONID, 4)
 }
 
 static void test_pack_LPSHELLFLAGSTATE(void)
 {
     /* LPSHELLFLAGSTATE */
-    TEST_TYPE(LPSHELLFLAGSTATE, 4, 4);
-    TEST_TYPE_POINTER(LPSHELLFLAGSTATE, 4, 1);
+    TEST_TYPE_SIZE   (LPSHELLFLAGSTATE, 4)
+    TEST_TYPE_ALIGN  (LPSHELLFLAGSTATE, 4)
+    TEST_TARGET_SIZE (LPSHELLFLAGSTATE, 4)
+    TEST_TARGET_ALIGN(LPSHELLFLAGSTATE, 1)
 }
 
 static void test_pack_LPSHELLSTATE(void)
 {
     /* LPSHELLSTATE */
-    TEST_TYPE(LPSHELLSTATE, 4, 4);
-    TEST_TYPE_POINTER(LPSHELLSTATE, 32, 1);
+    TEST_TYPE_SIZE   (LPSHELLSTATE, 4)
+    TEST_TYPE_ALIGN  (LPSHELLSTATE, 4)
+    TEST_TARGET_SIZE (LPSHELLSTATE, 32)
+    TEST_TARGET_ALIGN(LPSHELLSTATE, 1)
 }
 
 static void test_pack_LPTBINFO(void)
 {
     /* LPTBINFO */
-    TEST_TYPE(LPTBINFO, 4, 4);
-    TEST_TYPE_POINTER(LPTBINFO, 8, 4);
+    TEST_TYPE_SIZE   (LPTBINFO, 4)
+    TEST_TYPE_ALIGN  (LPTBINFO, 4)
+    TEST_TARGET_SIZE (LPTBINFO, 8)
+    TEST_TARGET_ALIGN(LPTBINFO, 4)
 }
 
 static void test_pack_PBROWSEINFOA(void)
 {
     /* PBROWSEINFOA */
-    TEST_TYPE(PBROWSEINFOA, 4, 4);
-    TEST_TYPE_POINTER(PBROWSEINFOA, 32, 4);
+    TEST_TYPE_SIZE   (PBROWSEINFOA, 4)
+    TEST_TYPE_ALIGN  (PBROWSEINFOA, 4)
+    TEST_TARGET_SIZE (PBROWSEINFOA, 32)
+    TEST_TARGET_ALIGN(PBROWSEINFOA, 4)
 }
 
 static void test_pack_PBROWSEINFOW(void)
 {
     /* PBROWSEINFOW */
-    TEST_TYPE(PBROWSEINFOW, 4, 4);
-    TEST_TYPE_POINTER(PBROWSEINFOW, 32, 4);
+    TEST_TYPE_SIZE   (PBROWSEINFOW, 4)
+    TEST_TYPE_ALIGN  (PBROWSEINFOW, 4)
+    TEST_TARGET_SIZE (PBROWSEINFOW, 32)
+    TEST_TARGET_ALIGN(PBROWSEINFOW, 4)
 }
 
 static void test_pack_QCMINFO(void)
 {
     /* QCMINFO (pack 8) */
-    TEST_TYPE(QCMINFO, 20, 4);
-    TEST_FIELD(QCMINFO, HMENU, hmenu, 0, 4, 4);
-    TEST_FIELD(QCMINFO, UINT, indexMenu, 4, 4, 4);
-    TEST_FIELD(QCMINFO, UINT, idCmdFirst, 8, 4, 4);
-    TEST_FIELD(QCMINFO, UINT, idCmdLast, 12, 4, 4);
-    TEST_FIELD(QCMINFO, QCMINFO_IDMAP const*, pIdMap, 16, 4, 4);
+    TEST_TYPE_SIZE   (QCMINFO, 20)
+    TEST_TYPE_ALIGN  (QCMINFO, 4)
+    TEST_FIELD_SIZE  (QCMINFO, hmenu, 4)
+    TEST_FIELD_ALIGN (QCMINFO, hmenu, 4)
+    TEST_FIELD_OFFSET(QCMINFO, hmenu, 0)
+    TEST_FIELD_SIZE  (QCMINFO, indexMenu, 4)
+    TEST_FIELD_ALIGN (QCMINFO, indexMenu, 4)
+    TEST_FIELD_OFFSET(QCMINFO, indexMenu, 4)
+    TEST_FIELD_SIZE  (QCMINFO, idCmdFirst, 4)
+    TEST_FIELD_ALIGN (QCMINFO, idCmdFirst, 4)
+    TEST_FIELD_OFFSET(QCMINFO, idCmdFirst, 8)
+    TEST_FIELD_SIZE  (QCMINFO, idCmdLast, 4)
+    TEST_FIELD_ALIGN (QCMINFO, idCmdLast, 4)
+    TEST_FIELD_OFFSET(QCMINFO, idCmdLast, 12)
+    TEST_FIELD_SIZE  (QCMINFO, pIdMap, 4)
+    TEST_FIELD_ALIGN (QCMINFO, pIdMap, 4)
+    TEST_FIELD_OFFSET(QCMINFO, pIdMap, 16)
 }
 
 static void test_pack_QCMINFO_IDMAP(void)
 {
     /* QCMINFO_IDMAP (pack 8) */
-    TEST_TYPE(QCMINFO_IDMAP, 12, 4);
-    TEST_FIELD(QCMINFO_IDMAP, UINT, nMaxIds, 0, 4, 4);
-    TEST_FIELD(QCMINFO_IDMAP, QCMINFO_IDMAP_PLACEMENT[1], pIdList, 4, 8, 4);
+    TEST_TYPE_SIZE   (QCMINFO_IDMAP, 12)
+    TEST_TYPE_ALIGN  (QCMINFO_IDMAP, 4)
+    TEST_FIELD_SIZE  (QCMINFO_IDMAP, nMaxIds, 4)
+    TEST_FIELD_ALIGN (QCMINFO_IDMAP, nMaxIds, 4)
+    TEST_FIELD_OFFSET(QCMINFO_IDMAP, nMaxIds, 0)
+    TEST_FIELD_SIZE  (QCMINFO_IDMAP, pIdList, 8)
+    TEST_FIELD_ALIGN (QCMINFO_IDMAP, pIdList, 4)
+    TEST_FIELD_OFFSET(QCMINFO_IDMAP, pIdList, 4)
 }
 
 static void test_pack_QCMINFO_IDMAP_PLACEMENT(void)
 {
     /* QCMINFO_IDMAP_PLACEMENT (pack 8) */
-    TEST_TYPE(QCMINFO_IDMAP_PLACEMENT, 8, 4);
-    TEST_FIELD(QCMINFO_IDMAP_PLACEMENT, UINT, id, 0, 4, 4);
-    TEST_FIELD(QCMINFO_IDMAP_PLACEMENT, UINT, fFlags, 4, 4, 4);
+    TEST_TYPE_SIZE   (QCMINFO_IDMAP_PLACEMENT, 8)
+    TEST_TYPE_ALIGN  (QCMINFO_IDMAP_PLACEMENT, 4)
+    TEST_FIELD_SIZE  (QCMINFO_IDMAP_PLACEMENT, id, 4)
+    TEST_FIELD_ALIGN (QCMINFO_IDMAP_PLACEMENT, id, 4)
+    TEST_FIELD_OFFSET(QCMINFO_IDMAP_PLACEMENT, id, 0)
+    TEST_FIELD_SIZE  (QCMINFO_IDMAP_PLACEMENT, fFlags, 4)
+    TEST_FIELD_ALIGN (QCMINFO_IDMAP_PLACEMENT, fFlags, 4)
+    TEST_FIELD_OFFSET(QCMINFO_IDMAP_PLACEMENT, fFlags, 4)
 }
 
 static void test_pack_SHChangeDWORDAsIDList(void)
 {
     /* SHChangeDWORDAsIDList (pack 1) */
-    TEST_TYPE(SHChangeDWORDAsIDList, 12, 1);
-    TEST_FIELD(SHChangeDWORDAsIDList, USHORT, cb, 0, 2, 1);
-    TEST_FIELD(SHChangeDWORDAsIDList, DWORD, dwItem1, 2, 4, 1);
-    TEST_FIELD(SHChangeDWORDAsIDList, DWORD, dwItem2, 6, 4, 1);
-    TEST_FIELD(SHChangeDWORDAsIDList, USHORT, cbZero, 10, 2, 1);
+    TEST_TYPE_SIZE   (SHChangeDWORDAsIDList, 12)
+    TEST_TYPE_ALIGN  (SHChangeDWORDAsIDList, 1)
+    TEST_FIELD_SIZE  (SHChangeDWORDAsIDList, cb, 2)
+    TEST_FIELD_ALIGN (SHChangeDWORDAsIDList, cb, 1)
+    TEST_FIELD_OFFSET(SHChangeDWORDAsIDList, cb, 0)
+    TEST_FIELD_SIZE  (SHChangeDWORDAsIDList, dwItem1, 4)
+    TEST_FIELD_ALIGN (SHChangeDWORDAsIDList, dwItem1, 1)
+    TEST_FIELD_OFFSET(SHChangeDWORDAsIDList, dwItem1, 2)
+    TEST_FIELD_SIZE  (SHChangeDWORDAsIDList, dwItem2, 4)
+    TEST_FIELD_ALIGN (SHChangeDWORDAsIDList, dwItem2, 1)
+    TEST_FIELD_OFFSET(SHChangeDWORDAsIDList, dwItem2, 6)
+    TEST_FIELD_SIZE  (SHChangeDWORDAsIDList, cbZero, 2)
+    TEST_FIELD_ALIGN (SHChangeDWORDAsIDList, cbZero, 1)
+    TEST_FIELD_OFFSET(SHChangeDWORDAsIDList, cbZero, 10)
 }
 
 static void test_pack_SHChangeNotifyEntry(void)
 {
     /* SHChangeNotifyEntry (pack 1) */
-    TEST_TYPE(SHChangeNotifyEntry, 8, 1);
-    TEST_FIELD(SHChangeNotifyEntry, LPCITEMIDLIST, pidl, 0, 4, 1);
-    TEST_FIELD(SHChangeNotifyEntry, BOOL, fRecursive, 4, 4, 1);
+    TEST_TYPE_SIZE   (SHChangeNotifyEntry, 8)
+    TEST_TYPE_ALIGN  (SHChangeNotifyEntry, 1)
+    TEST_FIELD_SIZE  (SHChangeNotifyEntry, pidl, 4)
+    TEST_FIELD_ALIGN (SHChangeNotifyEntry, pidl, 1)
+    TEST_FIELD_OFFSET(SHChangeNotifyEntry, pidl, 0)
+    TEST_FIELD_SIZE  (SHChangeNotifyEntry, fRecursive, 4)
+    TEST_FIELD_ALIGN (SHChangeNotifyEntry, fRecursive, 1)
+    TEST_FIELD_OFFSET(SHChangeNotifyEntry, fRecursive, 4)
 }
 
 static void test_pack_SHChangeProductKeyAsIDList(void)
 {
     /* SHChangeProductKeyAsIDList (pack 1) */
-    TEST_TYPE(SHChangeProductKeyAsIDList, 82, 1);
-    TEST_FIELD(SHChangeProductKeyAsIDList, USHORT, cb, 0, 2, 1);
-    TEST_FIELD(SHChangeProductKeyAsIDList, WCHAR[39], wszProductKey, 2, 78, 1);
-    TEST_FIELD(SHChangeProductKeyAsIDList, USHORT, cbZero, 80, 2, 1);
+    TEST_TYPE_SIZE   (SHChangeProductKeyAsIDList, 82)
+    TEST_TYPE_ALIGN  (SHChangeProductKeyAsIDList, 1)
+    TEST_FIELD_SIZE  (SHChangeProductKeyAsIDList, cb, 2)
+    TEST_FIELD_ALIGN (SHChangeProductKeyAsIDList, cb, 1)
+    TEST_FIELD_OFFSET(SHChangeProductKeyAsIDList, cb, 0)
+    TEST_FIELD_SIZE  (SHChangeProductKeyAsIDList, wszProductKey, 78)
+    TEST_FIELD_ALIGN (SHChangeProductKeyAsIDList, wszProductKey, 1)
+    TEST_FIELD_OFFSET(SHChangeProductKeyAsIDList, wszProductKey, 2)
+    TEST_FIELD_SIZE  (SHChangeProductKeyAsIDList, cbZero, 2)
+    TEST_FIELD_ALIGN (SHChangeProductKeyAsIDList, cbZero, 1)
+    TEST_FIELD_OFFSET(SHChangeProductKeyAsIDList, cbZero, 80)
 }
 
 static void test_pack_SHDESCRIPTIONID(void)
 {
     /* SHDESCRIPTIONID (pack 8) */
-    TEST_TYPE(SHDESCRIPTIONID, 20, 4);
-    TEST_FIELD(SHDESCRIPTIONID, DWORD, dwDescriptionId, 0, 4, 4);
-    TEST_FIELD(SHDESCRIPTIONID, CLSID, clsid, 4, 16, 4);
+    TEST_TYPE_SIZE   (SHDESCRIPTIONID, 20)
+    TEST_TYPE_ALIGN  (SHDESCRIPTIONID, 4)
+    TEST_FIELD_SIZE  (SHDESCRIPTIONID, dwDescriptionId, 4)
+    TEST_FIELD_ALIGN (SHDESCRIPTIONID, dwDescriptionId, 4)
+    TEST_FIELD_OFFSET(SHDESCRIPTIONID, dwDescriptionId, 0)
+    TEST_FIELD_SIZE  (SHDESCRIPTIONID, clsid, 16)
+    TEST_FIELD_ALIGN (SHDESCRIPTIONID, clsid, 4)
+    TEST_FIELD_OFFSET(SHDESCRIPTIONID, clsid, 4)
 }
 
 static void test_pack_SHELLFLAGSTATE(void)
 {
     /* SHELLFLAGSTATE (pack 1) */
-    TEST_TYPE(SHELLFLAGSTATE, 4, 1);
+    TEST_TYPE_SIZE   (SHELLFLAGSTATE, 4)
+    TEST_TYPE_ALIGN  (SHELLFLAGSTATE, 1)
 }
 
 static void test_pack_SHELLSTATE(void)
 {
     /* SHELLSTATE (pack 1) */
-    TEST_TYPE(SHELLSTATE, 32, 1);
-    TEST_FIELD(SHELLSTATE, DWORD, dwWin95Unused, 4, 4, 1);
-    TEST_FIELD(SHELLSTATE, UINT, uWin95Unused, 8, 4, 1);
-    TEST_FIELD(SHELLSTATE, LONG, lParamSort, 12, 4, 1);
-    TEST_FIELD(SHELLSTATE, int, iSortDirection, 16, 4, 1);
-    TEST_FIELD(SHELLSTATE, UINT, version, 20, 4, 1);
-    TEST_FIELD(SHELLSTATE, UINT, uNotUsed, 24, 4, 1);
-}
-
-static void test_pack_SHELLVIEWID(void)
-{
-    /* SHELLVIEWID */
-    TEST_TYPE(SHELLVIEWID, 16, 4);
+    TEST_TYPE_SIZE   (SHELLSTATE, 32)
+    TEST_TYPE_ALIGN  (SHELLSTATE, 1)
+    TEST_FIELD_SIZE  (SHELLSTATE, dwWin95Unused, 4)
+    TEST_FIELD_ALIGN (SHELLSTATE, dwWin95Unused, 1)
+    TEST_FIELD_OFFSET(SHELLSTATE, dwWin95Unused, 4)
+    TEST_FIELD_SIZE  (SHELLSTATE, uWin95Unused, 4)
+    TEST_FIELD_ALIGN (SHELLSTATE, uWin95Unused, 1)
+    TEST_FIELD_OFFSET(SHELLSTATE, uWin95Unused, 8)
+    TEST_FIELD_SIZE  (SHELLSTATE, lParamSort, 4)
+    TEST_FIELD_ALIGN (SHELLSTATE, lParamSort, 1)
+    TEST_FIELD_OFFSET(SHELLSTATE, lParamSort, 12)
+    TEST_FIELD_SIZE  (SHELLSTATE, iSortDirection, 4)
+    TEST_FIELD_ALIGN (SHELLSTATE, iSortDirection, 1)
+    TEST_FIELD_OFFSET(SHELLSTATE, iSortDirection, 16)
+    TEST_FIELD_SIZE  (SHELLSTATE, version, 4)
+    TEST_FIELD_ALIGN (SHELLSTATE, version, 1)
+    TEST_FIELD_OFFSET(SHELLSTATE, version, 20)
+    TEST_FIELD_SIZE  (SHELLSTATE, uNotUsed, 4)
+    TEST_FIELD_ALIGN (SHELLSTATE, uNotUsed, 1)
+    TEST_FIELD_OFFSET(SHELLSTATE, uNotUsed, 24)
 }
 
 static void test_pack_TBINFO(void)
 {
     /* TBINFO (pack 8) */
-    TEST_TYPE(TBINFO, 8, 4);
-    TEST_FIELD(TBINFO, UINT, cbuttons, 0, 4, 4);
-    TEST_FIELD(TBINFO, UINT, uFlags, 4, 4, 4);
+    TEST_TYPE_SIZE   (TBINFO, 8)
+    TEST_TYPE_ALIGN  (TBINFO, 4)
+    TEST_FIELD_SIZE  (TBINFO, cbuttons, 4)
+    TEST_FIELD_ALIGN (TBINFO, cbuttons, 4)
+    TEST_FIELD_OFFSET(TBINFO, cbuttons, 0)
+    TEST_FIELD_SIZE  (TBINFO, uFlags, 4)
+    TEST_FIELD_ALIGN (TBINFO, uFlags, 4)
+    TEST_FIELD_OFFSET(TBINFO, uFlags, 4)
 }
 
 static void test_pack(void)
@@ -1275,7 +1906,6 @@ static void test_pack(void)
     test_pack_FLAGGED_BYTE_BLOB();
     test_pack_FLAGGED_WORD_BLOB();
     test_pack_FMTID();
-    test_pack_GUID();
     test_pack_HMETAFILEPICT();
     test_pack_HYPER_SIZEDARR();
     test_pack_IID();
@@ -1300,7 +1930,6 @@ static void test_pack(void)
     test_pack_LPFILEGROUPDESCRIPTORA();
     test_pack_LPFILEGROUPDESCRIPTORW();
     test_pack_LPFNVIEWCALLBACK();
-    test_pack_LPGUID();
     test_pack_LPIDA();
     test_pack_LPITEMIDLIST();
     test_pack_LPOLESTR();
@@ -1348,7 +1977,6 @@ static void test_pack(void)
     test_pack_SHELLEXECUTEINFOW();
     test_pack_SHELLFLAGSTATE();
     test_pack_SHELLSTATE();
-    test_pack_SHELLVIEWID();
     test_pack_SHFILEINFOA();
     test_pack_SHFILEINFOW();
     test_pack_SHFILEOPSTRUCTA();
@@ -1385,5 +2013,9 @@ static void test_pack(void)
 
 START_TEST(generated)
 {
+#ifdef _WIN64
+    ok(0, "The type size / alignment tests don't support Win64 yet\n");
+#else
     test_pack();
+#endif
 }
diff --git a/rostests/winetests/shell32/rsrc.rc b/rostests/winetests/shell32/rsrc.rc
new file mode 100644 (file)
index 0000000..00c949b
--- /dev/null
@@ -0,0 +1,28 @@
+/* String resource for shlfolder test.
+ *
+ * Copyright 2008 Vincent Povirk for CodeWeavers
+ *
+ * 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 "windef.h"
+#include "winuser.h"
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+
+STRINGTABLE
+{
+  1 "Folder Name Resource"
+}
index 6d29d79..308777b 100644 (file)
@@ -15,6 +15,8 @@
        <library>kernel32</library>
        <library>uuid</library>
        <library>ntdll</library>
+       <file>appbar.c</file>
+       <file>autocomplete.c</file>
        <file>generated.c</file>
        <file>shelllink.c</file>
        <file>shellpath.c</file>
@@ -25,5 +27,7 @@
        <file>systray.c</file>
        <file>testlist.c</file>
        <file>shfldr_netplaces.c</file>
+       <file>shfldr_special.c</file>
+       <file>rsrc.rc</file>
 </module>
 </group>
index a331b10..9e792fd 100755 (executable)
@@ -24,7 +24,8 @@
 
 #define COBJMACROS
 
-#include <windows.h>
+#include "initguid.h"
+#include "windows.h"
 #include "shlguid.h"
 #include "shobjidl.h"
 #include "shlobj.h"
@@ -32,6 +33,9 @@
 
 #include "shell32_test.h"
 
+#ifndef SLDF_HAS_LOGO3ID
+#  define SLDF_HAS_LOGO3ID 0x00000800 /* not available in the Vista SDK */
+#endif
 
 typedef void (WINAPI *fnILFree)(LPITEMIDLIST);
 typedef BOOL (WINAPI *fnILIsEqual)(LPCITEMIDLIST, LPCITEMIDLIST);
@@ -48,7 +52,6 @@ static const GUID _IID_IShellLinkDataList = {
     { 0xb9, 0x2f, 0x00, 0xa0, 0xc9, 0x03, 0x12, 0xe1 }
 };
 
-static const WCHAR lnkfile[]= { 'C',':','\\','t','e','s','t','.','l','n','k',0 };
 static const WCHAR notafile[]= { 'C',':','\\','n','o','n','e','x','i','s','t','e','n','t','\\','f','i','l','e',0 };
 
 
@@ -67,7 +70,7 @@ static LPITEMIDLIST path_to_pidl(const char* path)
         HMODULE hdll=GetModuleHandleA("shell32.dll");
         pSHSimpleIDListFromPathAW=(void*)GetProcAddress(hdll, (char*)162);
         if (!pSHSimpleIDListFromPathAW)
-            trace("SHSimpleIDListFromPathAW not found in shell32.dll\n");
+            win_skip("SHSimpleIDListFromPathAW not found in shell32.dll\n");
     }
 
     pidl=NULL;
@@ -86,9 +89,7 @@ static LPITEMIDLIST path_to_pidl(const char* path)
         MultiByteToWideChar(CP_ACP, 0, path, -1, pathW, len);
 
         r=pSHILCreateFromPath(pathW, &pidl, NULL);
-        todo_wine {
         ok(SUCCEEDED(r), "SHILCreateFromPath failed (0x%08x)\n", r);
-        }
         HeapFree(GetProcessHeap(), 0, pathW);
     }
     return pidl;
@@ -113,7 +114,7 @@ static void test_get_set(void)
     r = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
                          &IID_IShellLinkA, (LPVOID*)&sl);
     ok(SUCCEEDED(r), "no IID_IShellLinkA (0x%08x)\n", r);
-    if (!SUCCEEDED(r))
+    if (FAILED(r))
         return;
 
     /* Test Getting / Setting the description */
@@ -170,9 +171,9 @@ static void test_get_set(void)
     ok(SUCCEEDED(r), "GetPath failed (0x%08x)\n", r);
     ok(lstrcmpi(buffer,str)==0, "GetPath returned '%s'\n", buffer);
 
-    /* Get some real path to play with */
-    r=GetModuleFileName(NULL, mypath, sizeof(mypath));
-    ok(r>=0 && r<sizeof(mypath), "GetModuleFileName failed (%d)\n", r);
+    /* Get some real path to play with */
+    GetWindowsDirectoryA( mypath, sizeof(mypath)-12 );
+    strcat(mypath, "\\regedit.exe");
 
     /* Test the interaction of SetPath and SetIDList */
     tmp_pidl=NULL;
@@ -180,19 +181,19 @@ static void test_get_set(void)
     ok(SUCCEEDED(r), "GetIDList failed (0x%08x)\n", r);
     if (SUCCEEDED(r))
     {
+        BOOL ret;
+
         strcpy(buffer,"garbage");
-        r=SHGetPathFromIDListA(tmp_pidl, buffer);
+        ret = SHGetPathFromIDListA(tmp_pidl, buffer);
         todo_wine {
-        ok(r, "SHGetPathFromIDListA failed\n");
+        ok(ret, "SHGetPathFromIDListA failed\n");
         }
-        if (r)
+        if (ret)
             ok(lstrcmpi(buffer,str)==0, "GetIDList returned '%s'\n", buffer);
     }
 
     pidl=path_to_pidl(mypath);
-    todo_wine {
     ok(pidl!=NULL, "path_to_pidl returned a NULL pidl\n");
-    }
 
     if (pidl)
     {
@@ -211,31 +212,35 @@ static void test_get_set(void)
         strcpy(buffer,"garbage");
         r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH);
         ok(SUCCEEDED(r), "GetPath failed (0x%08x)\n", r);
+        todo_wine
         ok(lstrcmpi(buffer, mypath)==0, "GetPath returned '%s'\n", buffer);
+
     }
 
-    /* test path with quotes (Win98 IShellLinkA_SetPath returns S_FALSE, WinXP returns S_OK) */
+    /* test path with quotes (IShellLinkA_SetPath returns S_FALSE on W2K and below and S_OK on XP and above */
     r = IShellLinkA_SetPath(sl, "\"c:\\nonexistent\\file\"");
     ok(r==S_FALSE || r == S_OK, "SetPath failed (0x%08x)\n", r);
 
     r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH);
     ok(r==S_OK, "GetPath failed (0x%08x)\n", r);
-    ok(!lstrcmp(buffer, "C:\\nonexistent\\file"), "case doesn't match\n");
+    ok(!lstrcmp(buffer, "C:\\nonexistent\\file") ||
+       broken(!lstrcmp(buffer, "C:\\\"c:\\nonexistent\\file\"")), /* NT4 */
+       "case doesn't match\n");
 
     r = IShellLinkA_SetPath(sl, "\"c:\\foo");
-    ok(r==S_FALSE || r == S_OK, "SetPath failed (0x%08x)\n", r);
+    ok(r==S_FALSE || r == S_OK || r == E_INVALIDARG /* Vista */, "SetPath failed (0x%08x)\n", r);
 
     r = IShellLinkA_SetPath(sl, "\"\"c:\\foo");
-    ok(r==S_FALSE || r == S_OK, "SetPath failed (0x%08x)\n", r);
+    ok(r==S_FALSE || r == S_OK || r == E_INVALIDARG /* Vista */, "SetPath failed (0x%08x)\n", r);
 
     r = IShellLinkA_SetPath(sl, "c:\\foo\"");
-    ok(r==S_FALSE || r == S_OK, "SetPath failed (0x%08x)\n", r);
+    ok(r==S_FALSE || r == S_OK || r == E_INVALIDARG /* Vista */, "SetPath failed (0x%08x)\n", r);
 
     r = IShellLinkA_SetPath(sl, "\"\"c:\\foo\"");
-    ok(r==S_FALSE || r == S_OK, "SetPath failed (0x%08x)\n", r);
+    ok(r==S_FALSE || r == S_OK || r == E_INVALIDARG /* Vista */, "SetPath failed (0x%08x)\n", r);
 
     r = IShellLinkA_SetPath(sl, "\"\"c:\\foo\"\"");
-    ok(r==S_FALSE || r == S_OK, "SetPath failed (0x%08x)\n", r);
+    ok(r==S_FALSE || r == S_OK || r == E_INVALIDARG /* Vista */, "SetPath failed (0x%08x)\n", r);
 
     /* Test Getting / Setting the arguments */
     strcpy(buffer,"garbage");
@@ -326,7 +331,7 @@ void create_lnk_(int line, const WCHAR* path, lnk_desc_t* desc, int save_fails)
     r = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
                          &IID_IShellLinkA, (LPVOID*)&sl);
     lok(SUCCEEDED(r), "no IID_IShellLinkA (0x%08x)\n", r);
-    if (!SUCCEEDED(r))
+    if (FAILED(r))
         return;
 
     if (desc->description)
@@ -401,12 +406,12 @@ static void check_lnk_(int line, const WCHAR* path, lnk_desc_t* desc, int todo)
     r = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
                          &IID_IShellLinkA, (LPVOID*)&sl);
     lok(SUCCEEDED(r), "no IID_IShellLinkA (0x%08x)\n", r);
-    if (!SUCCEEDED(r))
+    if (FAILED(r))
         return;
 
     r = IShellLinkA_QueryInterface(sl, &IID_IPersistFile, (LPVOID*)&pf);
     lok(SUCCEEDED(r), "no IID_IPersistFile (0x%08x)\n", r);
-    if (!SUCCEEDED(r))
+    if (FAILED(r))
     {
         IShellLinkA_Release(sl);
         return;
@@ -415,7 +420,7 @@ static void check_lnk_(int line, const WCHAR* path, lnk_desc_t* desc, int todo)
     r = IPersistFile_Load(pf, path, STGM_READ);
     lok(SUCCEEDED(r), "load failed (0x%08x)\n", r);
     IPersistFile_Release(pf);
-    if (!SUCCEEDED(r))
+    if (FAILED(r))
     {
         IShellLinkA_Release(sl);
         return;
@@ -493,6 +498,10 @@ static void check_lnk_(int line, const WCHAR* path, lnk_desc_t* desc, int todo)
 
 static void test_load_save(void)
 {
+    WCHAR lnkfile[MAX_PATH];
+    char lnkfileA[MAX_PATH];
+    static const char lnkfileA_name[] = "\\test.lnk";
+
     lnk_desc_t desc;
     char mypath[MAX_PATH];
     char mydir[MAX_PATH];
@@ -501,6 +510,17 @@ static void test_load_save(void)
     HANDLE hf;
     DWORD r;
 
+    if (!pGetLongPathNameA)
+    {
+        win_skip("GetLongPathNameA is not available\n");
+        return;
+    }
+
+    /* Don't used a fixed path for the test.lnk file */
+    GetTempPathA(MAX_PATH, lnkfileA);
+    lstrcatA(lnkfileA, lnkfileA_name);
+    MultiByteToWideChar(CP_ACP, 0, lnkfileA, -1, lnkfile, MAX_PATH);
+
     /* Save an empty .lnk file */
     memset(&desc, 0, sizeof(desc));
     create_lnk(lnkfile, &desc, 0);
@@ -533,10 +553,13 @@ static void test_load_save(void)
     if (p)
         *p='\0';
 
+    /* IShellLink returns path in long form */
+    if (!pGetLongPathNameA(mypath, realpath, MAX_PATH)) strcpy( realpath, mypath );
+
     /* Overwrite the existing lnk file and point it to existing files */
     desc.description="test 2";
     desc.workdir=mydir;
-    desc.path=mypath;
+    desc.path=realpath;
     desc.pidl=NULL;
     desc.arguments="/option1 /option2 \"Some string\"";
     desc.showcmd=SW_SHOWNORMAL;
@@ -565,11 +588,6 @@ static void test_load_save(void)
     /* Create a temporary non-executable file */
     r=GetTempPath(sizeof(mypath), mypath);
     ok(r<sizeof(mypath), "GetTempPath failed (%d), err %d\n", r, GetLastError());
-    if (!pGetLongPathNameA)
-    {
-        skip("GetLongPathNameA is not available\n");
-        goto cleanup;
-    }
     r=pGetLongPathNameA(mypath, mydir, sizeof(mydir));
     ok(r<sizeof(mydir), "GetLongPathName failed (%d), err %d\n", r, GetLastError());
     p=strrchr(mydir, '\\');
@@ -602,10 +620,9 @@ static void test_load_save(void)
      * represented as a path.
      */
 
-cleanup:
     /* DeleteFileW is not implemented on Win9x */
-    r=DeleteFileA("c:\\test.lnk");
-    ok(r, "failed to delete link (%d)\n", GetLastError());
+    r=DeleteFileA(lnkfileA);
+    ok(r, "failed to delete link '%s' (%d)\n", lnkfileA, GetLastError());
 }
 
 static void test_datalink(void)
@@ -633,19 +650,24 @@ static void test_datalink(void)
 
     r = CoCreateInstance( &CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
                             &IID_IShellLinkW, (LPVOID*)&sl );
-    ok( r == S_OK || r == E_NOINTERFACE, "CoCreateInstance failed (0x%08x)\n", r);
+    ok( r == S_OK ||
+        broken(r == E_NOINTERFACE), /* Win9x */
+        "CoCreateInstance failed (0x%08x)\n", r);
     if (!sl)
     {
-        skip("no shelllink\n");
+        win_skip("no shelllink\n");
         return;
     }
 
     r = IShellLinkW_QueryInterface( sl, &_IID_IShellLinkDataList, (LPVOID*) &dl );
-    ok(r == S_OK, "IShellLinkW_QueryInterface failed (0x%08x)\n", r);
+    ok( r == S_OK ||
+        broken(r == E_NOINTERFACE), /* NT4 */
+        "IShellLinkW_QueryInterface failed (0x%08x)\n", r);
 
     if (!dl)
     {
-        skip("no datalink interface\n");
+        win_skip("no datalink interface\n");
+        IShellLinkW_Release( sl );
         return;
     }
 
@@ -700,7 +722,7 @@ START_TEST(shelllink)
 
     r = CoInitialize(NULL);
     ok(SUCCEEDED(r), "CoInitialize failed (0x%08x)\n", r);
-    if (!SUCCEEDED(r))
+    if (FAILED(r))
         return;
 
     test_get_set();
index a6bbcae..4cacb08 100644 (file)
@@ -19,9 +19,6 @@
  * This is a test program for the SHGet{Special}Folder{Path|Location} functions
  * of shell32, that get either a filesystem path or a LPITEMIDLIST (shell
  * namespace) path for a given folder (CSIDL value).
- *
- * FIXME:
- * - Need to verify on more systems.
  */
 
 #define COBJMACROS
@@ -33,6 +30,7 @@
 #include "shlguid.h"
 #include "shlobj.h"
 #include "shlwapi.h"
+#include "initguid.h"
 #include "wine/test.h"
 
 /* CSIDL_MYDOCUMENTS is now the same as CSIDL_PERSONAL, but what we want
@@ -60,6 +58,9 @@
 #ifndef PT_FOLDER
 #define PT_FOLDER     0x31 /* has path */
 #endif
+#ifndef PT_FOLDERW
+#define PT_FOLDERW    0x35 /* has path */
+#endif
 #ifndef PT_WORKGRP
 #define PT_WORKGRP    0x41 /* no path */
 #endif
@@ -74,8 +75,9 @@
 static GUID CLSID_CommonDocuments = { 0x0000000c, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x1a } };
 
 struct shellExpectedValues {
-    int  folder;
-    BYTE pidlType;
+    int folder;
+    int numTypes;
+    const BYTE *types;
 };
 
 static HRESULT (WINAPI *pDllGetVersion)(DLLVERSIONINFO *);
@@ -89,71 +91,86 @@ static int (WINAPI *pSHFileOperationA)(LPSHFILEOPSTRUCTA);
 static HRESULT (WINAPI *pSHGetMalloc)(LPMALLOC *);
 static DLLVERSIONINFO shellVersion = { 0 };
 static LPMALLOC pMalloc;
+static const BYTE guidType[] = { PT_GUID };
+static const BYTE controlPanelType[] = { PT_SHELLEXT, PT_GUID };
+static const BYTE folderType[] = { PT_FOLDER, PT_FOLDERW };
+static const BYTE favoritesType[] = { PT_FOLDER, PT_FOLDERW, 0, PT_IESPECIAL2 /* Win98 */ };
+static const BYTE folderOrSpecialType[] = { PT_FOLDER, PT_IESPECIAL2 };
+static const BYTE personalType[] = { PT_FOLDER, PT_GUID, PT_DRIVE, 0xff /* Win9x */,
+ PT_IESPECIAL2 /* Win98 */, 0 /* Vista */ };
+/* FIXME: don't know the type of 0x71 returned by Vista/2008 for printers */
+static const BYTE printersType[] = { PT_YAGUID, PT_SHELLEXT, 0x71 };
+static const BYTE ieSpecialType[] = { PT_IESPECIAL2 };
+static const BYTE shellExtType[] = { PT_SHELLEXT };
+static const BYTE workgroupType[] = { PT_WORKGRP };
+#define DECLARE_TYPE(x, y) { x, sizeof(y) / sizeof(y[0]), y }
 static const struct shellExpectedValues requiredShellValues[] = {
{ CSIDL_BITBUCKET, PT_GUID },
{ CSIDL_CONTROLS, PT_SHELLEXT },
{ CSIDL_COOKIES, PT_FOLDER },
{ CSIDL_DESKTOPDIRECTORY, PT_FOLDER },
{ CSIDL_DRIVES, PT_GUID },
{ CSIDL_FAVORITES, PT_FOLDER },
{ CSIDL_FONTS, PT_FOLDER },
DECLARE_TYPE(CSIDL_BITBUCKET, guidType),
DECLARE_TYPE(CSIDL_CONTROLS, controlPanelType),
DECLARE_TYPE(CSIDL_COOKIES, folderType),
DECLARE_TYPE(CSIDL_DESKTOPDIRECTORY, folderType),
DECLARE_TYPE(CSIDL_DRIVES, guidType),
DECLARE_TYPE(CSIDL_FAVORITES, favoritesType),
DECLARE_TYPE(CSIDL_FONTS, folderOrSpecialType),
 /* FIXME: the following fails in Wine, returns type PT_FOLDER
{ CSIDL_HISTORY, PT_IESPECIAL2 },
DECLARE_TYPE(CSIDL_HISTORY, ieSpecialType),
  */
- { CSIDL_INTERNET, PT_GUID },
- { CSIDL_NETHOOD, PT_FOLDER },
- { CSIDL_NETWORK, PT_GUID },
- { CSIDL_PRINTERS, PT_YAGUID },
- { CSIDL_PRINTHOOD, PT_FOLDER },
- { CSIDL_PROGRAMS, PT_FOLDER },
- { CSIDL_RECENT, PT_FOLDER },
- { CSIDL_SENDTO, PT_FOLDER },
- { CSIDL_STARTMENU, PT_FOLDER },
- { CSIDL_STARTUP, PT_FOLDER },
- { CSIDL_TEMPLATES, PT_FOLDER },
+ DECLARE_TYPE(CSIDL_INTERNET, guidType),
+ DECLARE_TYPE(CSIDL_NETHOOD, folderType),
+ DECLARE_TYPE(CSIDL_NETWORK, guidType),
+ DECLARE_TYPE(CSIDL_PERSONAL, personalType),
+ DECLARE_TYPE(CSIDL_PRINTERS, printersType),
+ DECLARE_TYPE(CSIDL_PRINTHOOD, folderType),
+ DECLARE_TYPE(CSIDL_PROGRAMS, folderType),
+ DECLARE_TYPE(CSIDL_RECENT, folderOrSpecialType),
+ DECLARE_TYPE(CSIDL_SENDTO, folderType),
+ DECLARE_TYPE(CSIDL_STARTMENU, folderType),
+ DECLARE_TYPE(CSIDL_STARTUP, folderType),
+ DECLARE_TYPE(CSIDL_TEMPLATES, folderType),
 };
 static const struct shellExpectedValues optionalShellValues[] = {
 /* FIXME: the following only semi-succeed; they return NULL PIDLs on XP.. hmm.
{ CSIDL_ALTSTARTUP, PT_FOLDER },
{ CSIDL_COMMON_ALTSTARTUP, PT_FOLDER },
{ CSIDL_COMMON_OEM_LINKS, PT_FOLDER },
DECLARE_TYPE(CSIDL_ALTSTARTUP, folderType),
DECLARE_TYPE(CSIDL_COMMON_ALTSTARTUP, folderType),
DECLARE_TYPE(CSIDL_COMMON_OEM_LINKS, folderType),
  */
 /* Windows NT-only: */
{ CSIDL_COMMON_DESKTOPDIRECTORY, PT_FOLDER },
{ CSIDL_COMMON_DOCUMENTS, PT_SHELLEXT },
{ CSIDL_COMMON_FAVORITES, PT_FOLDER },
{ CSIDL_COMMON_PROGRAMS, PT_FOLDER },
{ CSIDL_COMMON_STARTMENU, PT_FOLDER },
{ CSIDL_COMMON_STARTUP, PT_FOLDER },
{ CSIDL_COMMON_TEMPLATES, PT_FOLDER },
DECLARE_TYPE(CSIDL_COMMON_DESKTOPDIRECTORY, folderType),
DECLARE_TYPE(CSIDL_COMMON_DOCUMENTS, shellExtType),
DECLARE_TYPE(CSIDL_COMMON_FAVORITES, folderType),
DECLARE_TYPE(CSIDL_COMMON_PROGRAMS, folderType),
DECLARE_TYPE(CSIDL_COMMON_STARTMENU, folderType),
DECLARE_TYPE(CSIDL_COMMON_STARTUP, folderType),
DECLARE_TYPE(CSIDL_COMMON_TEMPLATES, folderType),
 /* first appearing in shell32 version 4.71: */
{ CSIDL_APPDATA, PT_FOLDER },
DECLARE_TYPE(CSIDL_APPDATA, folderType),
 /* first appearing in shell32 version 4.72: */
{ CSIDL_INTERNET_CACHE, PT_IESPECIAL2 },
DECLARE_TYPE(CSIDL_INTERNET_CACHE, ieSpecialType),
 /* first appearing in shell32 version 5.0: */
{ CSIDL_ADMINTOOLS, PT_FOLDER },
{ CSIDL_COMMON_APPDATA, PT_FOLDER },
{ CSIDL_LOCAL_APPDATA, PT_FOLDER },
{ OLD_CSIDL_MYDOCUMENTS, PT_FOLDER },
{ CSIDL_MYMUSIC, PT_FOLDER },
{ CSIDL_MYPICTURES, PT_FOLDER },
{ CSIDL_MYVIDEO, PT_FOLDER },
{ CSIDL_PROFILE, PT_FOLDER },
{ CSIDL_PROGRAM_FILES, PT_FOLDER },
{ CSIDL_PROGRAM_FILESX86, PT_FOLDER },
{ CSIDL_PROGRAM_FILES_COMMON, PT_FOLDER },
{ CSIDL_PROGRAM_FILES_COMMONX86, PT_FOLDER },
{ CSIDL_SYSTEM, PT_FOLDER },
{ CSIDL_WINDOWS, PT_FOLDER },
DECLARE_TYPE(CSIDL_ADMINTOOLS, folderType),
DECLARE_TYPE(CSIDL_COMMON_APPDATA, folderType),
DECLARE_TYPE(CSIDL_LOCAL_APPDATA, folderType),
DECLARE_TYPE(OLD_CSIDL_MYDOCUMENTS, folderType),
DECLARE_TYPE(CSIDL_MYMUSIC, folderType),
DECLARE_TYPE(CSIDL_MYPICTURES, folderType),
DECLARE_TYPE(CSIDL_MYVIDEO, folderType),
DECLARE_TYPE(CSIDL_PROFILE, folderType),
DECLARE_TYPE(CSIDL_PROGRAM_FILES, folderType),
DECLARE_TYPE(CSIDL_PROGRAM_FILESX86, folderType),
DECLARE_TYPE(CSIDL_PROGRAM_FILES_COMMON, folderType),
DECLARE_TYPE(CSIDL_PROGRAM_FILES_COMMONX86, folderType),
DECLARE_TYPE(CSIDL_SYSTEM, folderType),
DECLARE_TYPE(CSIDL_WINDOWS, folderType),
 /* first appearing in shell32 6.0: */
{ CSIDL_CDBURN_AREA, PT_FOLDER },
{ CSIDL_COMMON_MUSIC, PT_FOLDER },
{ CSIDL_COMMON_PICTURES, PT_FOLDER },
{ CSIDL_COMMON_VIDEO, PT_FOLDER },
{ CSIDL_COMPUTERSNEARME, PT_WORKGRP },
{ CSIDL_RESOURCES, PT_FOLDER },
{ CSIDL_RESOURCES_LOCALIZED, PT_FOLDER },
DECLARE_TYPE(CSIDL_CDBURN_AREA, folderType),
DECLARE_TYPE(CSIDL_COMMON_MUSIC, folderType),
DECLARE_TYPE(CSIDL_COMMON_PICTURES, folderType),
DECLARE_TYPE(CSIDL_COMMON_VIDEO, folderType),
DECLARE_TYPE(CSIDL_COMPUTERSNEARME, workgroupType),
DECLARE_TYPE(CSIDL_RESOURCES, folderType),
DECLARE_TYPE(CSIDL_RESOURCES_LOCALIZED, folderType),
 };
+#undef DECLARE_TYPE
 
 static void loadShell32(void)
 {
@@ -188,9 +205,8 @@ static void loadShell32(void)
     {
         shellVersion.cbSize = sizeof(shellVersion);
         pDllGetVersion(&shellVersion);
-        if (winetest_interactive)
-            printf("shell32 version is %d.%d\n",
-             shellVersion.dwMajorVersion, shellVersion.dwMinorVersion);
+        trace("shell32 version is %d.%d\n",
+              shellVersion.dwMajorVersion, shellVersion.dwMinorVersion);
     }
 #undef GET_PROC
 }
@@ -272,10 +288,8 @@ static const char *getFolderName(int folder)
     }
 }
 
-static const char *printGUID(const GUID *guid)
+static const char *printGUID(const GUID *guid, char * guidSTR)
 {
-    static char guidSTR[39];
-
     if (!guid) return NULL;
 
     sprintf(guidSTR, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
@@ -302,15 +316,8 @@ static void testSHGetFolderLocationInvalidArgs(void)
     /* check a bogus user token: */
     pidl = NULL;
     hr = pSHGetFolderLocation(NULL, CSIDL_FAVORITES, (HANDLE)2, 0, &pidl);
-    ok(hr == E_FAIL,
-     "SHGetFolderLocation(NULL, CSIDL_FAVORITES, 2, 0, &pidl) returned 0x%08x, expected E_FAIL\n", hr);
-    if (SUCCEEDED(hr))
-        IMalloc_Free(pMalloc, pidl);
-    /* check reserved is not zero: */
-    pidl = NULL;
-    hr = pSHGetFolderLocation(NULL, CSIDL_DESKTOP, NULL, 1, &pidl);
-    ok(hr == E_INVALIDARG,
-     "SHGetFolderLocation(NULL, CSIDL_DESKTOP, NULL, 1, &pidl) returned 0x%08x, expected E_INVALIDARG\n", hr);
+    ok(hr == E_FAIL || hr == E_HANDLE,
+     "SHGetFolderLocation(NULL, CSIDL_FAVORITES, 2, 0, &pidl) returned 0x%08x, expected E_FAIL or E_HANDLE\n", hr);
     if (SUCCEEDED(hr))
         IMalloc_Free(pMalloc, pidl);
     /* a NULL pidl pointer crashes, so don't test it */
@@ -340,7 +347,9 @@ static void testSHGetFolderPathInvalidArgs(void)
     /* expect 2's a bogus handle, especially since we didn't open it */
     hr = pSHGetFolderPathA(NULL, CSIDL_DESKTOP, (HANDLE)2,
      SHGFP_TYPE_DEFAULT, path);
-    ok(hr == E_FAIL,
+    ok(hr == E_FAIL ||
+       hr == E_HANDLE ||   /* Windows Vista and 2008 */
+       broken(hr == S_OK), /* Windows 2000 and Me */
      "SHGetFolderPathA(NULL, CSIDL_DESKTOP, 2, SHGFP_TYPE_DEFAULT, path) returned 0x%08x, expected E_FAIL\n", hr);
     hr = pSHGetFolderPathA(NULL, 0xeeee, NULL, SHGFP_TYPE_DEFAULT, path);
     ok(hr == E_INVALIDARG,
@@ -379,7 +388,7 @@ static void testApiParameters(void)
 }
 
 /* Returns the folder's PIDL type, or 0xff if one can't be found. */
-static BYTE testSHGetFolderLocation(BOOL optional, int folder)
+static BYTE testSHGetFolderLocation(int folder)
 {
     LPITEMIDLIST pidl;
     HRESULT hr;
@@ -390,12 +399,8 @@ static BYTE testSHGetFolderLocation(BOOL optional, int folder)
 
     pidl = NULL;
     hr = pSHGetFolderLocation(NULL, folder, NULL, 0, &pidl);
-    ok(SUCCEEDED(hr) || optional,
-     "SHGetFolderLocation(NULL, %s, NULL, 0, &pidl) failed: 0x%08x\n", getFolderName(folder), hr);
     if (SUCCEEDED(hr))
     {
-        ok(pidl != NULL,
-         "SHGetFolderLocation(NULL, %s, NULL, 0, &pidl) succeeded, but returned pidl is NULL\n", getFolderName(folder));
         if (pidl)
         {
             LPITEMIDLIST pidlLast = pILFindLastID(pidl);
@@ -411,7 +416,7 @@ static BYTE testSHGetFolderLocation(BOOL optional, int folder)
 }
 
 /* Returns the folder's PIDL type, or 0xff if one can't be found. */
-static BYTE testSHGetSpecialFolderLocation(BOOL optional, int folder)
+static BYTE testSHGetSpecialFolderLocation(int folder)
 {
     LPITEMIDLIST pidl;
     HRESULT hr;
@@ -422,12 +427,8 @@ static BYTE testSHGetSpecialFolderLocation(BOOL optional, int folder)
 
     pidl = NULL;
     hr = pSHGetSpecialFolderLocation(NULL, folder, &pidl);
-    ok(SUCCEEDED(hr) || optional,
-     "SHGetSpecialFolderLocation(NULL, %s, &pidl) failed: 0x%08x\n", getFolderName(folder), hr);
     if (SUCCEEDED(hr))
     {
-        ok(pidl != NULL,
-         "SHGetSpecialFolderLocation(NULL, %s, &pidl) succeeded, but returned pidl is NULL\n", getFolderName(folder));
         if (pidl)
         {
             LPITEMIDLIST pidlLast = pILFindLastID(pidl);
@@ -477,17 +478,27 @@ static void testShellValues(const struct shellExpectedValues testEntries[],
     for (i = 0; i < numEntries; i++)
     {
         BYTE type;
+        int j;
+        BOOL foundTypeMatch = FALSE;
 
-        type = testSHGetFolderLocation(optional, testEntries[i].folder);
-        ok(type == testEntries[i].pidlType || optional,
-         "%s has type %d (0x%02x), expected %d (0x%02x)\n",
-         getFolderName(testEntries[i].folder), type, type,
-         testEntries[i].pidlType, testEntries[i].pidlType);
-        type = testSHGetSpecialFolderLocation(optional, testEntries[i].folder);
-        ok(type == testEntries[i].pidlType || optional,
-         "%s has type %d (0x%02x), expected %d (0x%02x)\n",
-         getFolderName(testEntries[i].folder), type, type,
-         testEntries[i].pidlType, testEntries[i].pidlType);
+        if (pSHGetFolderLocation)
+        {
+            type = testSHGetFolderLocation(testEntries[i].folder);
+            for (j = 0; !foundTypeMatch && j < testEntries[i].numTypes; j++)
+                if (testEntries[i].types[j] == type)
+                    foundTypeMatch = TRUE;
+            ok(foundTypeMatch || optional || broken(type == 0xff) /* Win9x */,
+             "%s has unexpected type %d (0x%02x)\n",
+             getFolderName(testEntries[i].folder), type, type);
+        }
+        type = testSHGetSpecialFolderLocation(testEntries[i].folder);
+        for (j = 0, foundTypeMatch = FALSE; !foundTypeMatch &&
+         j < testEntries[i].numTypes; j++)
+            if (testEntries[i].types[j] == type)
+                foundTypeMatch = TRUE;
+        ok(foundTypeMatch || optional || broken(type == 0xff) /* Win9x */,
+         "%s has unexpected type %d (0x%02x)\n",
+         getFolderName(testEntries[i].folder), type, type);
         switch (type)
         {
             case PT_FOLDER:
@@ -530,7 +541,7 @@ static void matchSpecialFolderPathToEnv(int folder, const char *envVar)
  * fail if it isn't--that check should already have been done.
  * Fails if the returned PIDL is a GUID whose value does not match guid.
  */
-static void matchGUID(int folder, const GUID *guid)
+static void matchGUID(int folder, const GUID *guid, const GUID *guid_alt)
 {
     LPITEMIDLIST pidl;
     HRESULT hr;
@@ -548,10 +559,18 @@ static void matchGUID(int folder, const GUID *guid)
          pidlLast->mkid.abID[0] == PT_GUID))
         {
             GUID *shellGuid = (GUID *)(pidlLast->mkid.abID + 2);
-
-            ok(IsEqualIID(shellGuid, guid),
-             "%s: got GUID %s, expected %s\n", getFolderName(folder),
-             printGUID(shellGuid), printGUID(guid));
+            char shellGuidStr[39], guidStr[39], guid_altStr[39];
+
+            if (!guid_alt)
+             ok(IsEqualIID(shellGuid, guid),
+              "%s: got GUID %s, expected %s\n", getFolderName(folder),
+              printGUID(shellGuid, shellGuidStr), printGUID(guid, guidStr));
+            else
+             ok(IsEqualIID(shellGuid, guid) ||
+              IsEqualIID(shellGuid, guid_alt),
+              "%s: got GUID %s, expected %s or %s\n", getFolderName(folder),
+              printGUID(shellGuid, shellGuidStr), printGUID(guid, guidStr),
+              printGUID(guid_alt, guid_altStr));
         }
         IMalloc_Free(pMalloc, pidl);
     }
@@ -561,56 +580,31 @@ static void testDesktop(void)
 {
     testSHGetFolderPath(FALSE, CSIDL_DESKTOP);
     testSHGetSpecialFolderPath(FALSE, CSIDL_DESKTOP);
-    /* Test the desktop; even though SHITEMID should always contain abID of at
-     * least one type, when cb is 0 its value is undefined.  So don't check
-     * what the returned type is, just make sure it exists.
-     */
-    testSHGetFolderLocation(FALSE, CSIDL_DESKTOP);
-    testSHGetSpecialFolderLocation(FALSE, CSIDL_DESKTOP);
-}
-
-static void testPersonal(void)
-{
-    BYTE type;
-
-    /* The pidl may be a real folder, or a virtual directory, or a drive if the
-     * home directory is set to the root directory of a drive.
-     */
-    type = testSHGetFolderLocation(FALSE, CSIDL_PERSONAL);
-    ok(type == PT_FOLDER || type == PT_GUID || type == PT_DRIVE,
-     "CSIDL_PERSONAL returned invalid type 0x%02x, "
-     "expected PT_FOLDER or PT_GUID\n", type);
-    if (type == PT_FOLDER)
-        testSHGetFolderPath(FALSE, CSIDL_PERSONAL);
-    type = testSHGetSpecialFolderLocation(FALSE, CSIDL_PERSONAL);
-    ok(type == PT_FOLDER || type == PT_GUID || type == PT_DRIVE,
-     "CSIDL_PERSONAL returned invalid type 0x%02x, "
-     "expected PT_FOLDER or PT_GUID\n", type);
-    if (type == PT_FOLDER)
-        testSHGetSpecialFolderPath(FALSE, CSIDL_PERSONAL);
 }
 
 /* Checks the PIDL type of all the known values. */
 static void testPidlTypes(void)
 {
     testDesktop();
-    testPersonal();
     testShellValues(requiredShellValues, ARRAY_SIZE(requiredShellValues),
      FALSE);
     testShellValues(optionalShellValues, ARRAY_SIZE(optionalShellValues),
      TRUE);
 }
 
+/* FIXME: Should be in shobjidl.idl */
+DEFINE_GUID(CLSID_NetworkExplorerFolder, 0xF02C1A0D, 0xBE21, 0x4350, 0x88, 0xB0, 0x73, 0x67, 0xFC, 0x96, 0xEF, 0x3C);
+
 /* Verifies various shell virtual folders have the correct well-known GUIDs. */
 static void testGUIDs(void)
 {
-    matchGUID(CSIDL_BITBUCKET, &CLSID_RecycleBin);
-    matchGUID(CSIDL_CONTROLS, &CLSID_ControlPanel);
-    matchGUID(CSIDL_DRIVES, &CLSID_MyComputer);
-    matchGUID(CSIDL_INTERNET, &CLSID_Internet);
-    matchGUID(CSIDL_NETWORK, &CLSID_NetworkPlaces);
-    matchGUID(CSIDL_PERSONAL, &CLSID_MyDocuments);
-    matchGUID(CSIDL_COMMON_DOCUMENTS, &CLSID_CommonDocuments);
+    matchGUID(CSIDL_BITBUCKET, &CLSID_RecycleBin, NULL);
+    matchGUID(CSIDL_CONTROLS, &CLSID_ControlPanel, NULL);
+    matchGUID(CSIDL_DRIVES, &CLSID_MyComputer, NULL);
+    matchGUID(CSIDL_INTERNET, &CLSID_Internet, NULL);
+    matchGUID(CSIDL_NETWORK, &CLSID_NetworkPlaces, &CLSID_NetworkExplorerFolder); /* Vista and higher */
+    matchGUID(CSIDL_PERSONAL, &CLSID_MyDocuments, NULL);
+    matchGUID(CSIDL_COMMON_DOCUMENTS, &CLSID_CommonDocuments, NULL);
 }
 
 /* Verifies various shell paths match the environment variables to which they
@@ -671,8 +665,8 @@ static void testWinDir(void)
     }
 }
 
-/* Verifies the shell path for CSIDL_SYSTEM and CSIDL_SYSTEMX86 matches the
- * return from GetSystemDirectory.  If SHGetSpecialFolderPath fails, no harm,
+/* Verifies the shell path for CSIDL_SYSTEM matches the return from
+ * GetSystemDirectory.  If SHGetSpecialFolderPath fails, no harm,
  * no foul--not every shell32 version supports CSIDL_SYSTEM.
  */
 static void testSystemDir(void)
@@ -690,16 +684,10 @@ static void testSystemDir(void)
          "GetSystemDirectory returns %s SHGetSpecialFolderPath returns %s\n",
          systemDir, systemShellPath);
     }
-    /* check CSIDL_SYSTEMX86; note that this isn't always present, so don't
-     * worry if it fails
+    /* CSIDL_SYSTEMX86 isn't checked in the same way, since it's different
+     * on Win64 (and non-x86 Windows systems, if there are any still in
+     * existence) than on Win32.
      */
-    if (pSHGetSpecialFolderPathA(NULL, systemShellPath, CSIDL_SYSTEMX86, FALSE))
-    {
-        myPathRemoveBackslashA(systemShellPath);
-        ok(!lstrcmpiA(systemDir, systemShellPath),
-         "GetSystemDirectory returns %s SHGetSpecialFolderPath returns %s\n",
-         systemDir, systemShellPath);
-    }
 }
 
 /* Globals used by subprocesses */
@@ -723,7 +711,7 @@ static void testNonExistentPath1(void)
 {
     HRESULT hr;
     LPITEMIDLIST pidl;
-    char path[MAX_PATH];
+    char *p, path[MAX_PATH];
 
     /* test some failure cases first: */
     hr = pSHGetFolderPathA(NULL, CSIDL_FAVORITES, NULL,
@@ -733,16 +721,16 @@ static void testNonExistentPath1(void)
     pidl = NULL;
     hr = pSHGetFolderLocation(NULL, CSIDL_FAVORITES, NULL, 0,
      &pidl);
-    ok(hr == E_FAIL,
-     "SHGetFolderLocation returned 0x%08x, expected E_FAIL\n", hr);
+    ok(hr == E_FAIL || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
+     "SHGetFolderLocation returned 0x%08x\n", hr);
     if (SUCCEEDED(hr) && pidl)
         IMalloc_Free(pMalloc, pidl);
     ok(!pSHGetSpecialFolderPathA(NULL, path, CSIDL_FAVORITES, FALSE),
      "SHGetSpecialFolderPath succeeded, expected failure\n");
     pidl = NULL;
     hr = pSHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &pidl);
-    ok(hr == E_FAIL, "SHGetFolderLocation returned 0x%08x, expected E_FAIL\n",
-     hr);
+    ok(hr == E_FAIL || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
+       "SHGetFolderLocation returned 0x%08x\n", hr);
     if (SUCCEEDED(hr) && pidl)
         IMalloc_Free(pMalloc, pidl);
     /* now test success: */
@@ -752,8 +740,7 @@ static void testNonExistentPath1(void)
     {
         BOOL ret;
 
-        if (winetest_interactive)
-            printf("CSIDL_FAVORITES was changed to %s\n", path);
+        trace("CSIDL_FAVORITES was changed to %s\n", path);
         ret = CreateDirectoryA(path, NULL);
         ok(!ret,
          "CreateDirectoryA succeeded but should have failed "
@@ -763,6 +750,13 @@ static void testNonExistentPath1(void)
              "CreateDirectoryA failed with %d, "
              "expected ERROR_ALREADY_EXISTS\n",
              GetLastError());
+        p = path + strlen(path);
+        strcpy(p, "\\desktop.ini");
+        DeleteFileA(path);
+        *p = 0;
+        SetFileAttributesA( path, FILE_ATTRIBUTE_NORMAL );
+        ret = RemoveDirectoryA(path);
+        ok( ret, "failed to remove %s error %u\n", path, GetLastError() );
     }
     ok(SUCCEEDED(hr),
      "SHGetFolderPath(NULL, CSIDL_FAVORITES | CSIDL_FLAG_CREATE, "
@@ -831,15 +825,13 @@ static void testNonExistentPath(void)
             memcpy(modifiedPath, originalPath, len);
             modifiedPath[len++] = '2';
             modifiedPath[len++] = '\0';
-            if (winetest_interactive)
-                printf("Changing CSIDL_FAVORITES to %s\n", modifiedPath);
+            trace("Changing CSIDL_FAVORITES to %s\n", modifiedPath);
             if (!RegSetValueExA(key, "Favorites", 0, type,
              (LPBYTE)modifiedPath, len))
             {
                 char buffer[MAX_PATH+20];
                 STARTUPINFOA startup;
                 PROCESS_INFORMATION info;
-                HRESULT hr;
 
                 sprintf(buffer, "%s tests/shellpath.c 1", selfname);
                 memset(&startup, 0, sizeof(startup));
@@ -850,14 +842,8 @@ static void testNonExistentPath(void)
                  &startup, &info);
                 winetest_wait_child_process( info.hProcess );
 
-                /* Query the path to be able to delete it below */
-                hr = pSHGetFolderPathA(NULL, CSIDL_FAVORITES, NULL,
-                 SHGFP_TYPE_CURRENT, modifiedPath);
-                ok(SUCCEEDED(hr), "SHGetFolderPathA failed: 0x%08x\n", hr);
-
                 /* restore original values: */
-                if (winetest_interactive)
-                    printf("Restoring CSIDL_FAVORITES to %s\n", originalPath);
+                trace("Restoring CSIDL_FAVORITES to %s\n", originalPath);
                 RegSetValueExA(key, "Favorites", 0, type, (LPBYTE) originalPath,
                  strlen(originalPath) + 1);
                 RegFlushKey(key);
@@ -871,21 +857,13 @@ static void testNonExistentPath(void)
                  &startup, &info);
                 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0,
                  "child process termination\n");
-
-                strcpy(buffer, modifiedPath);
-                strcat(buffer, "\\desktop.ini");
-                DeleteFileA(buffer);
-                RemoveDirectoryA(modifiedPath);
             }
         }
-        else if (winetest_interactive)
-            printf("RegQueryValueExA(key, Favorites, ...) failed\n");
+        else skip("RegQueryValueExA(key, Favorites, ...) failed\n");
         if (key)
             RegCloseKey(key);
     }
-    else if (winetest_interactive)
-        printf("RegOpenKeyExA(HKEY_CURRENT_USER, %s, ...) failed\n",
-         userShellFolders);
+    else skip("RegOpenKeyExA(HKEY_CURRENT_USER, %s, ...) failed\n", userShellFolders);
 }
 
 START_TEST(shellpath)
@@ -898,6 +876,10 @@ START_TEST(shellpath)
         doChild(myARGV[2]);
     else
     {
+        /* Report missing functions once */
+        if (!pSHGetFolderLocation)
+            win_skip("SHGetFolderLocation is not available\n");
+
         /* first test various combinations of parameters: */
         testApiParameters();
 
diff --git a/rostests/winetests/shell32/shfldr_special.c b/rostests/winetests/shell32/shfldr_special.c
new file mode 100644 (file)
index 0000000..8c14e51
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Tests for special shell folders
+ *
+ * Copyright 2008 Robert Shearman for CodeWeavers
+ * Copyright 2008 Owen Rudge
+ *
+ * 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 <stdarg.h>
+#include <stdio.h>
+
+#define COBJMACROS
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include "shellapi.h"
+#include "shlobj.h"
+
+#include "wine/test.h"
+
+/* Tests for My Network Places */
+static void test_parse_for_entire_network(void)
+{
+    static WCHAR my_network_places_path[] = {
+        ':',':','{','2','0','8','D','2','C','6','0','-','3','A','E','A','-',
+                    '1','0','6','9','-','A','2','D','7','-','0','8','0','0','2','B','3','0','3','0','9','D','}', 0 };
+    static WCHAR entire_network_path[] = {
+        ':',':','{','2','0','8','D','2','C','6','0','-','3','A','E','A','-',
+                    '1','0','6','9','-','A','2','D','7','-','0','8','0','0','2','B','3','0','3','0','9','D',
+                '}','\\','E','n','t','i','r','e','N','e','t','w','o','r','k',0 };
+    IShellFolder *psfDesktop;
+    HRESULT hr;
+    DWORD eaten = 0xdeadbeef;
+    LPITEMIDLIST pidl;
+    DWORD attr = ~0;
+    DWORD expected_attr;
+    DWORD alter_attr;
+
+    hr = SHGetDesktopFolder(&psfDesktop);
+    ok(hr == S_OK, "SHGetDesktopFolder failed with error 0x%x\n", hr);
+
+    hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, my_network_places_path, &eaten, &pidl, &attr);
+    ok(hr == S_OK, "IShellFolder_ParseDisplayName failed with error 0x%x\n", hr);
+    todo_wine
+    ok(eaten == 0xdeadbeef, "eaten should not have been set to %u\n", eaten);
+    expected_attr = SFGAO_HASSUBFOLDER|SFGAO_FOLDER|SFGAO_FILESYSANCESTOR|SFGAO_DROPTARGET|SFGAO_HASPROPSHEET|SFGAO_CANRENAME|SFGAO_CANLINK;
+    todo_wine
+    ok((attr == expected_attr) || /* Win9x, NT4 */
+       (attr == (expected_attr | SFGAO_STREAM)) || /* W2K */
+       (attr == (expected_attr | SFGAO_CANDELETE)) || /* XP, W2K3 */
+       (attr == (expected_attr | SFGAO_CANDELETE | SFGAO_NONENUMERATED)), /* Vista */
+       "Unexpected attributes : %08x\n", attr);
+
+    ILFree(pidl);
+
+    /* Start clean again */
+    eaten = 0xdeadbeef;
+    attr = ~0;
+
+    hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, entire_network_path, &eaten, &pidl, &attr);
+    if (hr == HRESULT_FROM_WIN32(ERROR_BAD_NET_NAME) || hr == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER))
+    {
+        win_skip("'EntireNetwork' is not available on Win9x, NT4 and Vista\n");
+        return;
+    }
+    ok(hr == S_OK, "IShellFolder_ParseDisplayName failed with error 0x%x\n", hr);
+    todo_wine
+    ok(eaten == 0xdeadbeef, "eaten should not have been set to %u\n", eaten);
+    expected_attr = SFGAO_HASSUBFOLDER|SFGAO_FOLDER|SFGAO_FILESYSANCESTOR|SFGAO_STORAGEANCESTOR|SFGAO_HASPROPSHEET|SFGAO_CANLINK;
+    alter_attr = (expected_attr & (~SFGAO_STORAGEANCESTOR)) | SFGAO_STREAM;
+    todo_wine
+    ok(attr == expected_attr ||
+       attr == alter_attr, /* win2k */
+       "attr should be 0x%x or 0x%x, not 0x%x\n", expected_attr, alter_attr, attr);
+
+    ILFree(pidl);
+}
+
+/* Tests for Control Panel */
+static void test_parse_for_control_panel(void)
+{
+    /* path of My Computer\Control Panel */
+    static WCHAR control_panel_path[] = {
+        ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-','A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}','\\',
+        ':',':','{','2','1','E','C','2','0','2','0','-','3','A','E','A','-','1','0','6','9','-','A','2','D','D','-','0','8','0','0','2','B','3','0','3','0','9','D','}', 0 };
+    IShellFolder *psfDesktop;
+    HRESULT hr;
+    DWORD eaten = 0xdeadbeef;
+    LPITEMIDLIST pidl;
+    DWORD attr = ~0;
+
+    hr = SHGetDesktopFolder(&psfDesktop);
+    ok(hr == S_OK, "SHGetDesktopFolder failed with error 0x%x\n", hr);
+
+    hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, control_panel_path, &eaten, &pidl, &attr);
+    ok(hr == S_OK, "IShellFolder_ParseDisplayName failed with error 0x%x\n", hr);
+    todo_wine ok(eaten == 0xdeadbeef, "eaten should not have been set to %u\n", eaten);
+    todo_wine
+    ok((attr == (SFGAO_CANLINK | SFGAO_FOLDER)) || /* Win9x, NT4 */
+       (attr == (SFGAO_CANLINK | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_STREAM)) || /* W2K */
+       (attr == (SFGAO_CANLINK | SFGAO_FOLDER | SFGAO_HASSUBFOLDER)) || /* W2K, XP, W2K3 */
+       (attr == (SFGAO_CANLINK | SFGAO_NONENUMERATED)) || /* Vista */
+       (attr == SFGAO_CANLINK), /* Vista, W2K8 */
+       "Unexpected attributes : %08x\n", attr);
+
+    ILFree(pidl);
+}
+
+
+START_TEST(shfldr_special)
+{
+    test_parse_for_entire_network();
+    test_parse_for_control_panel();
+}
index 4b1bf1b..863cea1 100755 (executable)
  *   we could check
  */
 
-#include <stdio.h>
-#include <assert.h>
-
 /* Needed to get SEE_MASK_NOZONECHECKS with the PSDK */
 #define NTDDI_WINXPSP1 0x05010100
 #define NTDDI_VERSION NTDDI_WINXPSP1
+#define _WIN32_WINNT 0x0501
+
+#include <stdio.h>
+#include <assert.h>
 
 #include "wtypes.h"
 #include "winbase.h"
@@ -89,7 +90,7 @@ static void strcat_param(char* str, const char* param)
 static char shell_call[2048]="";
 static int shell_execute(LPCSTR operation, LPCSTR file, LPCSTR parameters, LPCSTR directory)
 {
-    int rc;
+    INT_PTR rc;
 
     strcpy(shell_call, "ShellExecute(");
     strcat_param(shell_call, operation);
@@ -110,8 +111,7 @@ static int shell_execute(LPCSTR operation, LPCSTR file, LPCSTR parameters, LPCST
      * association it displays the 'Open With' dialog and I could not find
      * a flag to prevent this.
      */
-    rc=(int)ShellExecute(NULL, operation, file, parameters, directory,
-                         SW_SHOWNORMAL);
+    rc=(INT_PTR)ShellExecute(NULL, operation, file, parameters, directory, SW_SHOWNORMAL);
 
     if (rc > 32)
     {
@@ -134,7 +134,7 @@ static int shell_execute_ex(DWORD mask, LPCSTR operation, LPCSTR file,
 {
     SHELLEXECUTEINFO sei;
     BOOL success;
-    int rc;
+    INT_PTR rc;
 
     strcpy(shell_call, "ShellExecuteEx(");
     strcat_param(shell_call, operation);
@@ -167,9 +167,9 @@ static int shell_execute_ex(DWORD mask, LPCSTR operation, LPCSTR file,
     DeleteFile(child_file);
     SetLastError(0xcafebabe);
     success=ShellExecuteEx(&sei);
-    rc=(int)sei.hInstApp;
+    rc=(INT_PTR)sei.hInstApp;
     ok((success && rc > 32) || (!success && rc <= 32),
-       "%s rc=%d and hInstApp=%d is not allowed\n", shell_call, success, rc);
+       "%s rc=%d and hInstApp=%ld is not allowed\n", shell_call, success, rc);
 
     if (rc > 32)
     {
@@ -200,7 +200,7 @@ static int shell_execute_ex(DWORD mask, LPCSTR operation, LPCSTR file,
  *
  ***/
 
-static void create_test_association(const char* extension)
+static BOOL create_test_association(const char* extension)
 {
     HKEY hkey, hkey_shell;
     char class[MAX_PATH];
@@ -209,19 +209,25 @@ static void create_test_association(const char* extension)
     sprintf(class, "shlexec%s", extension);
     rc=RegCreateKeyEx(HKEY_CLASSES_ROOT, extension, 0, NULL, 0, KEY_SET_VALUE,
                       NULL, &hkey, NULL);
-    assert(rc==ERROR_SUCCESS);
+    if (rc != ERROR_SUCCESS)
+        return FALSE;
+
     rc=RegSetValueEx(hkey, NULL, 0, REG_SZ, (LPBYTE) class, strlen(class)+1);
-    assert(rc==ERROR_SUCCESS);
+    ok(rc==ERROR_SUCCESS, "RegSetValueEx '%s' failed, expected ERROR_SUCCESS, got %d\n", class, rc);
     CloseHandle(hkey);
 
     rc=RegCreateKeyEx(HKEY_CLASSES_ROOT, class, 0, NULL, 0,
                       KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS, NULL, &hkey, NULL);
-    assert(rc==ERROR_SUCCESS);
+    ok(rc==ERROR_SUCCESS, "RegCreateKeyEx '%s' failed, expected ERROR_SUCCESS, got %d\n", class, rc);
+
     rc=RegCreateKeyEx(hkey, "shell", 0, NULL, 0,
                       KEY_CREATE_SUB_KEY, NULL, &hkey_shell, NULL);
-    assert(rc==ERROR_SUCCESS);
+    ok(rc==ERROR_SUCCESS, "RegCreateKeyEx 'shell' failed, expected ERROR_SUCCESS, got %d\n", rc);
+
     CloseHandle(hkey);
     CloseHandle(hkey_shell);
+
+    return TRUE;
 }
 
 /* Based on RegDeleteTreeW from dlls/advapi32/registry.c */
@@ -620,8 +626,8 @@ typedef struct
 static filename_tests_t filename_tests[]=
 {
     /* Test bad / nonexistent filenames */
-    {NULL,           "%s\\nonexistent.shlexec", 0x11, SE_ERR_FNF},
-    {NULL,           "%s\\nonexistent.noassoc", 0x11, SE_ERR_FNF},
+    {NULL,           "%s\\nonexistent.shlexec", 0x0, SE_ERR_FNF},
+    {NULL,           "%s\\nonexistent.noassoc", 0x0, SE_ERR_FNF},
 
     /* Standard tests */
     {NULL,           "%s\\test file.shlexec",   0x0, 33},
@@ -637,7 +643,7 @@ static filename_tests_t filename_tests[]=
     {NULL,           "%s\\test file.shlexec.noassoc", 0x0, SE_ERR_NOASSOC},
 
     /* Test alternate verbs */
-    {"LowerL",       "%s\\nonexistent.shlexec", 0x11, SE_ERR_FNF},
+    {"LowerL",       "%s\\nonexistent.shlexec", 0x0, SE_ERR_FNF},
     {"LowerL",       "%s\\test file.noassoc",   0x0,  SE_ERR_NOASSOC},
 
     {"QuotedLowerL", "%s\\test file.shlexec",   0x0, 33},
@@ -828,45 +834,56 @@ static void test_find_executable(void)
     char filename[MAX_PATH];
     char command[MAX_PATH];
     const filename_tests_t* test;
-    int rc;
+    INT_PTR rc;
 
-    create_test_association(".sfe");
+    if (!create_test_association(".sfe"))
+    {
+        skip("Unable to create association for '.sfe'\n");
+        return;
+    }
     create_test_verb(".sfe", "Open", 1, "%1");
 
     /* Don't test FindExecutable(..., NULL), it always crashes */
 
     strcpy(command, "your word");
-    rc=(int)FindExecutableA(NULL, NULL, command);
-    ok(rc == SE_ERR_FNF || rc > 32 /* nt4 */, "FindExecutable(NULL) returned %d\n", rc);
+    if (0) /* Can crash on Vista! */
+    {
+    rc=(INT_PTR)FindExecutableA(NULL, NULL, command);
+    ok(rc == SE_ERR_FNF || rc > 32 /* nt4 */, "FindExecutable(NULL) returned %ld\n", rc);
     ok(strcmp(command, "your word") != 0, "FindExecutable(NULL) returned command=[%s]\n", command);
+    }
 
     strcpy(command, "your word");
-    rc=(int)FindExecutableA(tmpdir, NULL, command);
-    ok(rc == SE_ERR_NOASSOC /* >= win2000 */ || rc > 32 /* win98, nt4 */, "FindExecutable(NULL) returned %d\n", rc);
+    rc=(INT_PTR)FindExecutableA(tmpdir, NULL, command);
+    ok(rc == SE_ERR_NOASSOC /* >= win2000 */ || rc > 32 /* win98, nt4 */, "FindExecutable(NULL) returned %ld\n", rc);
     ok(strcmp(command, "your word") != 0, "FindExecutable(NULL) returned command=[%s]\n", command);
 
     sprintf(filename, "%s\\test file.sfe", tmpdir);
-    rc=(int)FindExecutableA(filename, NULL, command);
-    ok(rc > 32, "FindExecutable(%s) returned %d\n", filename, rc);
+    rc=(INT_PTR)FindExecutableA(filename, NULL, command);
+    ok(rc > 32, "FindExecutable(%s) returned %ld\n", filename, rc);
     /* Depending on the platform, command could be '%1' or 'test file.sfe' */
 
-    rc=(int)FindExecutableA("test file.sfe", tmpdir, command);
-    ok(rc > 32, "FindExecutable(%s) returned %d\n", filename, rc);
+    rc=(INT_PTR)FindExecutableA("test file.sfe", tmpdir, command);
+    ok(rc > 32, "FindExecutable(%s) returned %ld\n", filename, rc);
 
-    rc=(int)FindExecutableA("test file.sfe", NULL, command);
-    todo_wine ok(rc == SE_ERR_FNF, "FindExecutable(%s) returned %d\n", filename, rc);
+    rc=(INT_PTR)FindExecutableA("test file.sfe", NULL, command);
+    ok(rc == SE_ERR_FNF, "FindExecutable(%s) returned %ld\n", filename, rc);
 
     delete_test_association(".sfe");
 
-    create_test_association(".shl");
+    if (!create_test_association(".shl"))
+    {
+        skip("Unable to create association for '.shl'\n");
+        return;
+    }
     create_test_verb(".shl", "Open", 0, "Open");
 
     sprintf(filename, "%s\\test file.shl", tmpdir);
-    rc=(int)FindExecutableA(filename, NULL, command);
-    ok(rc == SE_ERR_FNF /* NT4 */ || rc > 32, "FindExecutable(%s) returned %d\n", filename, rc);
+    rc=(INT_PTR)FindExecutableA(filename, NULL, command);
+    ok(rc == SE_ERR_FNF /* NT4 */ || rc > 32, "FindExecutable(%s) returned %ld\n", filename, rc);
 
     sprintf(filename, "%s\\test file.shlfoo", tmpdir);
-    rc=(int)FindExecutableA(filename, NULL, command);
+    rc=(INT_PTR)FindExecutableA(filename, NULL, command);
 
     delete_test_association(".shl");
 
@@ -901,16 +918,16 @@ static void test_find_executable(void)
         }
         /* Win98 does not '\0'-terminate command! */
         memset(command, '\0', sizeof(command));
-        rc=(int)FindExecutableA(filename, NULL, command);
+        rc=(INT_PTR)FindExecutableA(filename, NULL, command);
         if (rc > 32)
             rc=33;
         if ((test->todo & 0x10)==0)
         {
-            ok(rc==test->rc, "FindExecutable(%s) failed: rc=%d\n", filename, rc);
+            ok(rc==test->rc, "FindExecutable(%s) failed: rc=%ld\n", filename, rc);
         }
         else todo_wine
         {
-            ok(rc==test->rc, "FindExecutable(%s) failed: rc=%d\n", filename, rc);
+            ok(rc==test->rc, "FindExecutable(%s) failed: rc=%ld\n", filename, rc);
         }
         if (rc > 32)
         {
@@ -1195,7 +1212,7 @@ typedef struct
 
 static DWORD CALLBACK ddeThread(LPVOID arg)
 {
-    dde_thread_info_t *info = (dde_thread_info_t *)arg;
+    dde_thread_info_t *info = arg;
     assert(info && info->filename);
     PostThreadMessage(info->threadIdParent,
                       WM_QUIT,
@@ -1233,7 +1250,11 @@ static void test_dde(void)
     test = dde_tests;
     while (test->command)
     {
-        create_test_association(".sde");
+        if (!create_test_association(".sde"))
+        {
+            skip("Unable to create association for '.sfe'\n");
+            return;
+        }
         create_test_verb_dde(".sde", "Open", 0, test->command, test->ddeexec,
                              test->application, test->topic, test->ifexec);
         hszApplication = DdeCreateStringHandleA(ddeInst, test->application ?
@@ -1245,7 +1266,7 @@ static void test_dde(void)
         denyNextConnection = TRUE;
         ddeExec[0] = 0;
 
-        assert(CreateThread(NULL, 0, ddeThread, (LPVOID)&info, 0, &threadId));
+        assert(CreateThread(NULL, 0, ddeThread, &info, 0, &threadId));
         while (GetMessage(&msg, NULL, 0, 0)) DispatchMessage(&msg);
         rc = msg.wParam > 32 ? 33 : msg.wParam;
         if ((test->todo & 0x1)==0)
@@ -1383,7 +1404,11 @@ static void test_dde_default_app(void)
     test = dde_default_app_tests;
     while (test->command)
     {
-        create_test_association(".sde");
+        if (!create_test_association(".sde"))
+        {
+            skip("Unable to create association for '.sde'\n");
+            return;
+        }
         sprintf(params, test->command, tmpdir);
         create_test_verb_dde(".sde", "Open", 1, params, "[test]", NULL,
                              "shlexec", NULL);
@@ -1394,7 +1419,7 @@ static void test_dde_default_app(void)
          * so don't wait for it */
         SetEvent(hEvent);
 
-        assert(CreateThread(NULL, 0, ddeThread, (LPVOID)&info, 0, &threadId));
+        assert(CreateThread(NULL, 0, ddeThread, &info, 0, &threadId));
         while (GetMessage(&msg, NULL, 0, 0)) DispatchMessage(&msg);
         rc = msg.wParam > 32 ? 33 : msg.wParam;
 
@@ -1479,7 +1504,7 @@ static void init_test(void)
 
     r = CoInitialize(NULL);
     ok(SUCCEEDED(r), "CoInitialize failed (0x%08x)\n", r);
-    if (!SUCCEEDED(r))
+    if (FAILED(r))
         exit(1);
 
     rc=GetModuleFileName(NULL, argv0, sizeof(argv0));
@@ -1543,7 +1568,11 @@ static void init_test(void)
     create_lnk(lnkfile, &desc, 0);
 
     /* Create a basic association suitable for most tests */
-    create_test_association(".shlexec");
+    if (!create_test_association(".shlexec"))
+    {
+        skip("Unable to create association for '.shlexec'\n");
+        return;
+    }
     create_test_verb(".shlexec", "Open", 0, "Open \"%1\"");
     create_test_verb(".shlexec", "NoQuotes", 0, "NoQuotes %1");
     create_test_verb(".shlexec", "LowerL", 0, "LowerL %l");
@@ -1575,6 +1604,79 @@ static void cleanup_test(void)
     CoUninitialize();
 }
 
+static void test_commandline(void)
+{
+    static const WCHAR one[] = {'o','n','e',0};
+    static const WCHAR two[] = {'t','w','o',0};
+    static const WCHAR three[] = {'t','h','r','e','e',0};
+    static const WCHAR four[] = {'f','o','u','r',0};
+
+    static const WCHAR fmt1[] = {'%','s',' ','%','s',' ','%','s',' ','%','s',0};
+    static const WCHAR fmt2[] = {' ','%','s',' ','%','s',' ','%','s',' ','%','s',0};
+    static const WCHAR fmt3[] = {'%','s','=','%','s',' ','%','s','=','\"','%','s','\"',0};
+    static const WCHAR fmt4[] = {'\"','%','s','\"',' ','\"','%','s',' ','%','s','\"',' ','%','s',0};
+    static const WCHAR fmt5[] = {'\\','\"','%','s','\"',' ','%','s','=','\"','%','s','\\','\"',' ','\"','%','s','\\','\"',0};
+    static const WCHAR fmt6[] = {0};
+
+    static const WCHAR chkfmt1[] = {'%','s','=','%','s',0};
+    static const WCHAR chkfmt2[] = {'%','s',' ','%','s',0};
+    static const WCHAR chkfmt3[] = {'\\','\"','%','s','\"',0};
+    static const WCHAR chkfmt4[] = {'%','s','=','%','s','\"',' ','%','s','\"',0};
+    WCHAR cmdline[255];
+    LPWSTR *args = (LPWSTR*)0xdeadcafe;
+    INT numargs = -1;
+
+    wsprintfW(cmdline,fmt1,one,two,three,four);
+    args=CommandLineToArgvW(cmdline,&numargs);
+    if (args == NULL && numargs == -1)
+    {
+        win_skip("CommandLineToArgvW not implemented, skipping\n");
+        return;
+    }
+    ok(numargs == 4, "expected 4 args, got %i\n",numargs);
+    ok(lstrcmpW(args[0],one)==0,"arg0 is not as expected\n");
+    ok(lstrcmpW(args[1],two)==0,"arg1 is not as expected\n");
+    ok(lstrcmpW(args[2],three)==0,"arg2 is not as expected\n");
+    ok(lstrcmpW(args[3],four)==0,"arg3 is not as expected\n");
+
+    wsprintfW(cmdline,fmt2,one,two,three,four);
+    args=CommandLineToArgvW(cmdline,&numargs);
+    ok(numargs == 5, "expected 5 args, got %i\n",numargs);
+    ok(args[0][0]==0,"arg0 is not as expected\n");
+    ok(lstrcmpW(args[1],one)==0,"arg1 is not as expected\n");
+    ok(lstrcmpW(args[2],two)==0,"arg2 is not as expected\n");
+    ok(lstrcmpW(args[3],three)==0,"arg3 is not as expected\n");
+    ok(lstrcmpW(args[4],four)==0,"arg4 is not as expected\n");
+
+    wsprintfW(cmdline,fmt3,one,two,three,four);
+    args=CommandLineToArgvW(cmdline,&numargs);
+    ok(numargs == 2, "expected 2 args, got %i\n",numargs);
+    wsprintfW(cmdline,chkfmt1,one,two);
+    ok(lstrcmpW(args[0],cmdline)==0,"arg0 is not as expected\n");
+    wsprintfW(cmdline,chkfmt1,three,four);
+    ok(lstrcmpW(args[1],cmdline)==0,"arg1 is not as expected\n");
+
+    wsprintfW(cmdline,fmt4,one,two,three,four);
+    args=CommandLineToArgvW(cmdline,&numargs);
+    ok(numargs == 3, "expected 3 args, got %i\n",numargs);
+    ok(lstrcmpW(args[0],one)==0,"arg0 is not as expected\n");
+    wsprintfW(cmdline,chkfmt2,two,three);
+    ok(lstrcmpW(args[1],cmdline)==0,"arg1 is not as expected\n");
+    ok(lstrcmpW(args[2],four)==0,"arg2 is not as expected\n");
+
+    wsprintfW(cmdline,fmt5,one,two,three,four);
+    args=CommandLineToArgvW(cmdline,&numargs);
+    ok(numargs == 2, "expected 2 args, got %i\n",numargs);
+    wsprintfW(cmdline,chkfmt3,one);
+    todo_wine ok(lstrcmpW(args[0],cmdline)==0,"arg0 is not as expected\n");
+    wsprintfW(cmdline,chkfmt4,two,three,four);
+    todo_wine ok(lstrcmpW(args[1],cmdline)==0,"arg1 is not as expected\n");
+
+    wsprintfW(cmdline,fmt6);
+    args=CommandLineToArgvW(cmdline,&numargs);
+    ok(numargs == 1, "expected 1 args, got %i\n",numargs);
+}
+
 START_TEST(shlexec)
 {
 
@@ -1594,6 +1696,7 @@ START_TEST(shlexec)
     test_exes_long();
     test_dde();
     test_dde_default_app();
+    test_commandline();
 
     cleanup_test();
 }
index df4bd41..540fd0d 100644 (file)
 #define FOF_NORECURSION 0x1000
 #endif
 
+/* Error codes could be pre-Win32 */
+#define DE_SAMEFILE      0x71
+#define DE_MANYSRC1DEST  0x72
+#define DE_DIFFDIR       0x73
+#define DE_OPCANCELLED   0x75
+#define DE_DESTSUBTREE   0x76
+#define DE_INVALIDFILES  0x7C
+#define DE_DESTSAMETREE  0x7D
+#define DE_FLDDESTISFILE 0x7E
+#define DE_FILEDESTISFLD 0x80
+#define expect_retval(ret, ret_prewin32)\
+    ok(retval == ret ||\
+       broken(retval == ret_prewin32),\
+       "Expected %d, got %d\n", ret, retval)
+
 static CHAR CURR_DIR[MAX_PATH];
 static const WCHAR UNICODE_PATH[] = {'c',':','\\',0x00c4,'\0','\0'};
     /* "c:\Ä", or "c:\A" with diaeresis */
@@ -41,6 +56,7 @@ static HMODULE hshell32;
 static int (WINAPI *pSHCreateDirectoryExA)(HWND, LPCSTR, LPSECURITY_ATTRIBUTES);
 static int (WINAPI *pSHCreateDirectoryExW)(HWND, LPCWSTR, LPSECURITY_ATTRIBUTES);
 static int (WINAPI *pSHFileOperationW)(LPSHFILEOPSTRUCTW);
+static DWORD_PTR (WINAPI *pSHGetFileInfoW)(LPCWSTR, DWORD , SHFILEINFOW*, UINT, UINT);
 static int (WINAPI *pSHPathPrepareForWriteA)(HWND, IUnknown*, LPCSTR, DWORD);
 static int (WINAPI *pSHPathPrepareForWriteW)(HWND, IUnknown*, LPCWSTR, DWORD);
 
@@ -50,6 +66,7 @@ static void InitFunctionPointers(void)
     pSHCreateDirectoryExA = (void*)GetProcAddress(hshell32, "SHCreateDirectoryExA");
     pSHCreateDirectoryExW = (void*)GetProcAddress(hshell32, "SHCreateDirectoryExW");
     pSHFileOperationW = (void*)GetProcAddress(hshell32, "SHFileOperationW");
+    pSHGetFileInfoW = (void*)GetProcAddress(hshell32, "SHGetFileInfoW");
     pSHPathPrepareForWriteA = (void*)GetProcAddress(hshell32, "SHPathPrepareForWriteA");
     pSHPathPrepareForWriteW = (void*)GetProcAddress(hshell32, "SHPathPrepareForWriteW");
 }
@@ -81,6 +98,17 @@ static BOOL file_exists(const CHAR *name)
     return GetFileAttributesA(name) != INVALID_FILE_ATTRIBUTES;
 }
 
+static BOOL dir_exists(const CHAR *name)
+{
+    DWORD attr;
+    BOOL dir;
+
+    attr = GetFileAttributesA(name);
+    dir = ((attr & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
+
+    return ((attr != INVALID_FILE_ATTRIBUTES) && dir);
+}
+
 static BOOL file_existsW(LPCWSTR name)
 {
   return GetFileAttributesW(name) != INVALID_FILE_ATTRIBUTES;
@@ -154,19 +182,58 @@ static void clean_after_shfo_tests(void)
 static void test_get_file_info(void)
 {
     DWORD rc, rc2;
-    SHFILEINFO shfi, shfi2;
+    SHFILEINFOA shfi, shfi2;
+    SHFILEINFOW shfiw;
     char notepad[MAX_PATH];
 
+    /* Test whether fields of SHFILEINFOA are always cleared */
+    memset(&shfi, 0xcf, sizeof(shfi));
+    rc=SHGetFileInfoA("", 0, &shfi, sizeof(shfi), 0);
+    ok(rc, "SHGetFileInfoA('' | 0) should not fail\n");
+    todo_wine ok(shfi.hIcon == 0, "SHGetFileInfoA('' | 0) did not clear hIcon\n");
+    todo_wine ok(shfi.szDisplayName[0] == 0, "SHGetFileInfoA('' | 0) did not clear szDisplayName[0]\n");
+    todo_wine ok(shfi.szTypeName[0] == 0, "SHGetFileInfoA('' | 0) did not clear szTypeName[0]\n");
+    ok(shfi.iIcon == 0xcfcfcfcf ||
+       broken(shfi.iIcon != 0xcfcfcfcf), /* NT4 doesn't clear but sets this field */
+       "SHGetFileInfoA('' | 0) should not clear iIcon\n");
+    ok(shfi.dwAttributes == 0xcfcfcfcf ||
+       broken(shfi.dwAttributes != 0xcfcfcfcf), /* NT4 doesn't clear but sets this field */
+       "SHGetFileInfoA('' | 0) should not clear dwAttributes\n");
+
+    if (pSHGetFileInfoW)
+    {
+        HANDLE unset_icon;
+        /* Test whether fields of SHFILEINFOW are always cleared */
+        memset(&shfiw, 0xcf, sizeof(shfiw));
+        memset(&unset_icon, 0xcf, sizeof(unset_icon));
+        rc=pSHGetFileInfoW(NULL, 0, &shfiw, sizeof(shfiw), 0);
+        todo_wine ok(!rc, "SHGetFileInfoW(NULL | 0) should fail\n");
+        ok(shfiw.hIcon == unset_icon, "SHGetFileInfoW(NULL | 0) should not clear hIcon\n");
+        todo_wine ok(shfiw.szDisplayName[0] == 0xcfcf, "SHGetFileInfoW(NULL | 0) should not clear szDisplayName[0]\n");
+        todo_wine ok(shfiw.szTypeName[0] == 0xcfcf, "SHGetFileInfoW(NULL | 0) should not clear szTypeName[0]\n");
+        todo_wine ok(shfiw.iIcon == 0xcfcfcfcf, "SHGetFileInfoW(NULL | 0) should not clear iIcon\n");
+        ok(shfiw.dwAttributes == 0xcfcfcfcf, "SHGetFileInfoW(NULL | 0) should not clear dwAttributes\n");
+    }
+    else
+        win_skip("SHGetFileInfoW is not available\n");
+
+
     /* Test some flag combinations that MSDN claims are not allowed,
      * but which work anyway
      */
-    shfi.dwAttributes=0xdeadbeef;
+    memset(&shfi, 0xcf, sizeof(shfi));
     rc=SHGetFileInfoA("c:\\nonexistent", FILE_ATTRIBUTE_DIRECTORY,
                       &shfi, sizeof(shfi),
                       SHGFI_ATTRIBUTES | SHGFI_USEFILEATTRIBUTES);
-    todo_wine ok(rc, "SHGetFileInfoA(c:\\nonexistent | SHGFI_ATTRIBUTES) failed\n");
+    ok(rc, "SHGetFileInfoA(c:\\nonexistent | SHGFI_ATTRIBUTES) failed\n");
     if (rc)
-        ok(shfi.dwAttributes != 0xdeadbeef, "dwFileAttributes is not set\n");
+        ok(shfi.dwAttributes != 0xcfcfcfcf, "dwFileAttributes is not set\n");
+    todo_wine ok(shfi.hIcon == 0, "SHGetFileInfoA(c:\\nonexistent | SHGFI_ATTRIBUTES) did not clear hIcon\n");
+    todo_wine ok(shfi.szDisplayName[0] == 0, "SHGetFileInfoA(c:\\nonexistent | SHGFI_ATTRIBUTES) did not clear szDisplayName[0]\n");
+    todo_wine ok(shfi.szTypeName[0] == 0, "SHGetFileInfoA(c:\\nonexistent | SHGFI_ATTRIBUTES) did not clear szTypeName[0]\n");
+    ok(shfi.iIcon == 0xcfcfcfcf ||
+       broken(shfi.iIcon != 0xcfcfcfcf), /* NT4 doesn't clear but sets this field */
+       "SHGetFileInfoA(c:\\nonexistent | SHGFI_ATTRIBUTES) should not clear iIcon\n");
 
     rc=SHGetFileInfoA("c:\\nonexistent", FILE_ATTRIBUTE_DIRECTORY,
                       &shfi, sizeof(shfi),
@@ -230,6 +297,186 @@ static void test_get_file_info(void)
     }
 }
 
+static void test_get_file_info_iconlist(void)
+{
+    /* Test retrieving a handle to the system image list, and
+     * what that returns for hIcon
+     */
+    HRESULT hr;
+    HIMAGELIST hSysImageList;
+    LPITEMIDLIST pidList;
+    SHFILEINFOA shInfoa;
+    SHFILEINFOW shInfow;
+
+    hr = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidList);
+    if (FAILED(hr)) {
+         skip("can't get desktop pidl\n");
+         return;
+    }
+
+    memset(&shInfoa, 0xcf, sizeof(shInfoa));
+    hSysImageList = (HIMAGELIST) SHGetFileInfoA((const char *)pidList, 0,
+            &shInfoa, sizeof(shInfoa),
+           SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_PIDL);
+    ok(hSysImageList != INVALID_HANDLE_VALUE, "Can't get handle for CSIDL_DESKTOP imagelist\n");
+    todo_wine ok(shInfoa.hIcon == 0, "SHGetFileInfoA(CSIDL_DESKTOP, SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_PIDL) did not clear hIcon\n");
+    todo_wine ok(shInfoa.szTypeName[0] == 0, "SHGetFileInfoA(CSIDL_DESKTOP, SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_PIDL) did not clear szTypeName[0]\n");
+    ok(shInfoa.iIcon != 0xcfcfcfcf, "SHGetFileInfoA(CSIDL_DESKTOP, SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_PIDL) should set iIcon\n");
+    ok(shInfoa.dwAttributes == 0xcfcfcfcf ||
+       shInfoa.dwAttributes ==  0 || /* Vista */
+       broken(shInfoa.dwAttributes != 0xcfcfcfcf), /* NT4 doesn't clear but sets this field */
+       "SHGetFileInfoA(CSIDL_DESKTOP, SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_PIDL), unexpected dwAttributes\n");
+    CloseHandle(hSysImageList);
+
+    if (!pSHGetFileInfoW)
+    {
+        win_skip("SHGetFileInfoW is not available\n");
+        ILFree(pidList);
+        return;
+    }
+
+    memset(&shInfow, 0xcf, sizeof(shInfow));
+    hSysImageList = (HIMAGELIST) pSHGetFileInfoW((const WCHAR *)pidList, 0,
+            &shInfow, sizeof(shInfow),
+           SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_PIDL);
+    if (!hSysImageList)
+    {
+        win_skip("SHGetFileInfoW is not implemented\n");
+        return;
+    }
+    ok(hSysImageList != INVALID_HANDLE_VALUE, "Can't get handle for CSIDL_DESKTOP imagelist\n");
+    todo_wine ok(shInfow.hIcon == 0, "SHGetFileInfoW(CSIDL_DESKTOP, SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_PIDL) did not clear hIcon\n");
+    ok(shInfow.szTypeName[0] == 0, "SHGetFileInfoW(CSIDL_DESKTOP, SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_PIDL) did not clear szTypeName[0]\n");
+    ok(shInfow.iIcon != 0xcfcfcfcf, "SHGetFileInfoW(CSIDL_DESKTOP, SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_PIDL) should set iIcon\n");
+    ok(shInfow.dwAttributes == 0xcfcfcfcf ||
+       shInfoa.dwAttributes ==  0, /* Vista */
+       "SHGetFileInfoW(CSIDL_DESKTOP, SHGFI_SYSICONINDEX|SHGFI_SMALLICON|SHGFI_PIDL) unexpected dwAttributes\n");
+    CloseHandle(hSysImageList);
+
+    /* Various suposidly invalid flag testing */
+    memset(&shInfow, 0xcf, sizeof(shInfow));
+    hr =  pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+           SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON);
+    ok(hr != 0, "SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON Failed\n");
+    ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
+    ok(shInfow.dwAttributes==0xcfcfcfcf ||
+       shInfoa.dwAttributes==0, /* Vista */
+       "unexpected dwAttributes\n");
+
+    memset(&shInfow, 0xcf, sizeof(shInfow));
+    hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+           SHGFI_ICON|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON);
+    ok(hr != 0, " SHGFI_ICON|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON Failed\n");
+    ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
+    ok(shInfow.hIcon!=(HICON)0xcfcfcfcf && shInfow.hIcon!=0,"hIcon invalid\n");
+    if (shInfow.hIcon!=(HICON)0xcfcfcfcf) DestroyIcon(shInfow.hIcon);
+    todo_wine ok(shInfow.dwAttributes==0,"dwAttributes not set\n");
+
+    memset(&shInfow, 0xcf, sizeof(shInfow));
+    hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+           SHGFI_ICON|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_LARGEICON);
+    ok(hr != 0, "SHGFI_ICON|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_LARGEICON Failed\n");
+    ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
+    ok(shInfow.hIcon!=(HICON)0xcfcfcfcf && shInfow.hIcon!=0,"hIcon invalid\n");
+    if (shInfow.hIcon != (HICON)0xcfcfcfcf) DestroyIcon(shInfow.hIcon);
+    todo_wine ok(shInfow.dwAttributes==0,"dwAttributes not set\n");
+
+    memset(&shInfow, 0xcf, sizeof(shInfow));
+    hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+           SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_LARGEICON);
+    ok(hr != 0, "SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_LARGEICON Failed\n");
+    ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
+    ok(shInfow.dwAttributes==0xcfcfcfcf ||
+       shInfoa.dwAttributes==0, /* Vista */
+       "unexpected dwAttributes\n");
+
+    memset(&shInfow, 0xcf, sizeof(shInfow));
+    hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+           SHGFI_OPENICON|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON);
+    ok(hr != 0, "SHGFI_OPENICON|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON Failed\n");
+    todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
+    ok(shInfow.dwAttributes==0xcfcfcfcf,"dwAttributes modified\n");
+
+    memset(&shInfow, 0xcf, sizeof(shInfow));
+    hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+           SHGFI_SHELLICONSIZE|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON);
+    ok(hr != 0, "SHGFI_SHELLICONSIZE|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON Failed\n");
+    todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
+    ok(shInfow.dwAttributes==0xcfcfcfcf,"dwAttributes modified\n");
+
+    memset(&shInfow, 0xcf, sizeof(shInfow));
+    hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+           SHGFI_SHELLICONSIZE|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON);
+    ok(hr != 0, "SHGFI_SHELLICONSIZE|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON Failed\n");
+    todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
+    ok(shInfow.dwAttributes==0xcfcfcfcf,"dwAttributes modified\n");
+
+    memset(&shInfow, 0xcf, sizeof(shInfow));
+    hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+           SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON|
+        SHGFI_ATTRIBUTES);
+    ok(hr != 0, "SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON|SHGFI_ATTRIBUTES Failed\n");
+    ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
+    ok(shInfow.dwAttributes!=0xcfcfcfcf,"dwAttributes not set\n");
+
+    memset(&shInfow, 0xcf, sizeof(shInfow));
+    hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+           SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON|
+        SHGFI_EXETYPE);
+    todo_wine ok(hr != 0, "SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON|SHGFI_EXETYPE Failed\n");
+    ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
+    ok(shInfow.dwAttributes==0xcfcfcfcf ||
+       shInfoa.dwAttributes==0, /* Vista */
+       "unexpected dwAttributes\n");
+
+    memset(&shInfow, 0xcf, sizeof(shInfow));
+    hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+        SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON|SHGFI_EXETYPE);
+    todo_wine ok(hr != 0, "SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON|SHGFI_EXETYPE Failed\n");
+    todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
+    ok(shInfow.dwAttributes==0xcfcfcfcf,"dwAttributes modified\n");
+
+    memset(&shInfow, 0xcf, sizeof(shInfow));
+    hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+        SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON|SHGFI_ATTRIBUTES);
+    ok(hr != 0, "SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_SMALLICON|SHGFI_ATTRIBUTES Failed\n");
+    todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
+    ok(shInfow.dwAttributes!=0xcfcfcfcf,"dwAttributes not set\n");
+
+    memset(&shInfow, 0xcf, sizeof(shInfow));
+    hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+           SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|
+        SHGFI_ATTRIBUTES);
+    ok(hr != 0, "SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_ATTRIBUTES Failed\n");
+    ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
+    ok(shInfow.dwAttributes!=0xcfcfcfcf,"dwAttributes not set\n");
+
+    memset(&shInfow, 0xcf, sizeof(shInfow));
+    hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+        SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_EXETYPE);
+    todo_wine ok(hr != 0, "SHGFI_SYSICONINDEX|SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_EXETYPE Failed\n");
+    ok(shInfow.iIcon!=0xcfcfcfcf, "Icon Index Missing\n");
+    ok(shInfow.dwAttributes==0xcfcfcfcf ||
+       shInfoa.dwAttributes==0, /* Vista */
+       "unexpected dwAttributes\n");
+
+    memset(&shInfow, 0xcf, sizeof(shInfow));
+    hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+        SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_EXETYPE);
+    todo_wine ok(hr != 0, "SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_EXETYPE Failed\n");
+    todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
+    ok(shInfow.dwAttributes==0xcfcfcfcf,"dwAttributes modified\n");
+
+    memset(&shInfow, 0xcf, sizeof(shInfow));
+    hr = pSHGetFileInfoW((const WCHAR *)pidList, 0, &shInfow, sizeof(shInfow),
+        SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_ATTRIBUTES);
+    ok(hr != 0, "SHGFI_USEFILEATTRIBUTES|SHGFI_PIDL|SHGFI_ATTRIBUTES Failed\n");
+    todo_wine ok(shInfow.iIcon==0xcfcfcfcf, "Icon Index Modified\n");
+    ok(shInfow.dwAttributes!=0xcfcfcfcf,"dwAttributes not set\n");
+
+    ILFree(pidList);
+}
+
 
 /*
  puts into the specified buffer file names with current directory.
@@ -266,23 +513,25 @@ static void test_delete(void)
     shfo.hwnd = NULL;
     shfo.wFunc = FO_DELETE;
     shfo.pFrom = buf;
-    shfo.pTo = "\0";
+    shfo.pTo = NULL;
     shfo.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_SILENT;
     shfo.hNameMappings = NULL;
     shfo.lpszProgressTitle = NULL;
 
     ok(!SHFileOperationA(&shfo), "Deletion was not successful\n");
-    ok(file_exists("test4.txt"), "Directory should not have been removed\n");
+    ok(dir_exists("test4.txt"), "Directory should not have been removed\n");
     ok(!file_exists("test1.txt"), "File should have been removed\n");
+    ok(!file_exists("test2.txt"), "File should have been removed\n");
+    ok(!file_exists("test3.txt"), "File should have been removed\n");
 
     ret = SHFileOperationA(&shfo);
-    ok(!ret, "Directory exists, but is not removed, ret=%d\n", ret);
-    ok(file_exists("test4.txt"), "Directory should not have been removed\n");
+    ok(ret == ERROR_SUCCESS, "Directory exists, but is not removed, ret=%d\n", ret);
+    ok(dir_exists("test4.txt"), "Directory should not have been removed\n");
 
     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
 
     ok(!SHFileOperationA(&shfo), "Directory is not removed\n");
-    ok(!file_exists("test4.txt"), "Directory should have been removed\n");
+    ok(!dir_exists("test4.txt"), "Directory should have been removed\n");
 
     ret = SHFileOperationA(&shfo);
     ok(!ret, "The requested file does not exist, ret=%d\n", ret);
@@ -292,13 +541,13 @@ static void test_delete(void)
     buf[strlen(buf) + 1] = '\0';
     ok(MoveFileA("test1.txt", "test4.txt\\test1.txt"), "Filling the subdirectory failed\n");
     ok(!SHFileOperationA(&shfo), "Directory is not removed\n");
-    ok(!file_exists("test4.txt"), "Directory is not removed\n");
+    ok(!dir_exists("test4.txt"), "Directory is not removed\n");
 
     init_shfo_tests();
     shfo.pFrom = "test1.txt\0test4.txt\0";
     ok(!SHFileOperationA(&shfo), "Directory and a file are not removed\n");
     ok(!file_exists("test1.txt"), "The file should have been removed\n");
-    ok(!file_exists("test4.txt"), "Directory should have been removed\n");
+    ok(!dir_exists("test4.txt"), "Directory should have been removed\n");
     ok(file_exists("test2.txt"), "This file should not have been removed\n");
 
     /* FOF_FILESONLY does not delete a dir matching a wildcard */
@@ -308,51 +557,79 @@ static void test_delete(void)
     ok(!SHFileOperation(&shfo), "Failed to delete files\n");
     ok(!file_exists("test1.txt"), "test1.txt should have been removed\n");
     ok(!file_exists("test_5.txt"), "test_5.txt should have been removed\n");
-    ok(file_exists("test4.txt"), "test4.txt should not have been removed\n");
+    ok(dir_exists("test4.txt"), "test4.txt should not have been removed\n");
 
     /* FOF_FILESONLY only deletes a dir if explicitly specified */
     init_shfo_tests();
     shfo.pFrom = "test_?.txt\0test4.txt\0";
     ok(!SHFileOperation(&shfo), "Failed to delete files and directory\n");
-    ok(!file_exists("test4.txt"), "test4.txt should have been removed\n");
+    ok(!dir_exists("test4.txt") ||
+       broken(dir_exists("test4.txt")), /* NT4 */
+      "test4.txt should have been removed\n");
     ok(!file_exists("test_5.txt"), "test_5.txt should have been removed\n");
     ok(file_exists("test1.txt"), "test1.txt should not have been removed\n");
 
     /* try to delete an invalid filename */
-    init_shfo_tests();
-    shfo.pFrom = "\0";
-    shfo.fFlags &= ~FOF_FILESONLY;
-    shfo.fAnyOperationsAborted = FALSE;
-    ret = SHFileOperation(&shfo);
-    ok(ret == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", ret);
-    ok(!shfo.fAnyOperationsAborted, "Expected no aborted operations\n");
-    ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
+    if (0) {
+        /* this crashes on win9x */
+        init_shfo_tests();
+        shfo.pFrom = "\0";
+        shfo.fFlags &= ~FOF_FILESONLY;
+        shfo.fAnyOperationsAborted = FALSE;
+        ret = SHFileOperation(&shfo);
+        ok(ret == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", ret);
+        ok(!shfo.fAnyOperationsAborted, "Expected no aborted operations\n");
+        ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
+    }
 
     /* try an invalid function */
     init_shfo_tests();
     shfo.pFrom = "test1.txt\0";
     shfo.wFunc = 0;
     ret = SHFileOperation(&shfo);
-    ok(ret == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", ret);
+    ok(ret == ERROR_INVALID_PARAMETER ||
+       broken(ret == ERROR_SUCCESS), /* Win9x, NT4 */
+       "Expected ERROR_INVALID_PARAMETER, got %d\n", ret);
     ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
 
     /* try an invalid list, only one null terminator */
-    init_shfo_tests();
-    shfo.pFrom = "";
+    if (0) {
+        /* this crashes on win9x */
+        init_shfo_tests();
+        shfo.pFrom = "";
+        shfo.wFunc = FO_DELETE;
+        ret = SHFileOperation(&shfo);
+        ok(ret == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", ret);
+        ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
+    }
+
+    /* delete a nonexistent file */
+    shfo.pFrom = "nonexistent.txt\0";
     shfo.wFunc = FO_DELETE;
     ret = SHFileOperation(&shfo);
-    ok(ret == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", ret);
-    ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
+    todo_wine
+    ok(ret == 1026 ||
+       ret == ERROR_FILE_NOT_FOUND || /* Vista */
+       broken(ret == ERROR_SUCCESS), /* NT4 */
+       "Expected 1026 or ERROR_FILE_NOT_FOUND, got %d\n", ret);
 
     /* delete a dir, and then a file inside the dir, same as
     * deleting a nonexistent file
     */
-    init_shfo_tests();
-    shfo.pFrom = "testdir2\0testdir2\\one.txt\0";
-    ret = SHFileOperation(&shfo);
-    ok(ret == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %d\n", ret);
-    ok(!file_exists("testdir2"), "Expected testdir2 to not exist\n");
-    ok(!file_exists("testdir2\\one.txt"), "Expected testdir2\\one.txt to not exist\n");
+    if (ret != ERROR_FILE_NOT_FOUND)
+    {
+        /* Vista would throw up a dialog box that we can't suppress */
+        init_shfo_tests();
+        shfo.pFrom = "testdir2\0testdir2\\one.txt\0";
+        ret = SHFileOperation(&shfo);
+        ok(ret == ERROR_PATH_NOT_FOUND ||
+           broken(ret == ERROR_SUCCESS), /* NT4 */
+           "Expected ERROR_PATH_NOT_FOUND, got %d\n", ret);
+        ok(!dir_exists("testdir2"), "Expected testdir2 to not exist\n");
+        ok(!file_exists("testdir2\\one.txt"), "Expected testdir2\\one.txt to not exist\n");
+    }
+    else
+        skip("Test would show a dialog box\n");
 
     /* try the FOF_NORECURSION flag, continues deleting subdirs */
     init_shfo_tests();
@@ -361,7 +638,7 @@ static void test_delete(void)
     ret = SHFileOperation(&shfo);
     ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
     ok(!file_exists("testdir2\\one.txt"), "Expected testdir2\\one.txt to not exist\n");
-    ok(!file_exists("testdir2\\nested"), "Expected testdir2\\nested to exist\n");
+    ok(!dir_exists("testdir2\\nested"), "Expected testdir2\\nested to not exist\n");
 }
 
 /* tests the FO_RENAME action */
@@ -382,20 +659,34 @@ static void test_rename(void)
 
     set_curr_dir_path(from, "test1.txt\0");
     set_curr_dir_path(to, "test4.txt\0");
-    ok(SHFileOperationA(&shfo), "File is not renamed moving to other directory "
-       "when specifying directory name only\n");
-    ok(file_exists("test1.txt"), "The file is removed\n");
+    retval = SHFileOperationA(&shfo);
+    ok(retval == ERROR_ALREADY_EXISTS ||
+       retval == DE_FILEDESTISFLD || /* Vista */
+       broken(retval == ERROR_INVALID_NAME), /* Win9x, NT4 */
+       "Expected ERROR_ALREADY_EXISTS or DE_FILEDESTISFLD, got %d\n", retval);
+    ok(file_exists("test1.txt"), "The file is renamed\n");
 
     set_curr_dir_path(from, "test3.txt\0");
     set_curr_dir_path(to, "test4.txt\\test1.txt\0");
-    ok(!SHFileOperationA(&shfo), "File is renamed moving to other directory\n");
-    ok(file_exists("test4.txt\\test1.txt"), "The file is not renamed\n");
+    retval = SHFileOperationA(&shfo);
+    if (retval == DE_DIFFDIR)
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(!file_exists("test4.txt\\test1.txt"), "The file is renamed\n");
+    }
+    else
+    {
+        ok(retval == ERROR_SUCCESS, "File is renamed moving to other directory\n");
+        ok(file_exists("test4.txt\\test1.txt"), "The file is not renamed\n");
+    }
 
     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
-    retval = SHFileOperationA(&shfo); /* W98 returns 0, W2K and newer returns ERROR_GEN_FAILURE, both do nothing */
-    ok(!retval || retval == ERROR_GEN_FAILURE || retval == ERROR_INVALID_TARGET_HANDLE,
-       "Can't rename many files, retval = %d\n", retval);
+    retval = SHFileOperationA(&shfo);
+    ok(retval == ERROR_GEN_FAILURE ||
+       retval == DE_MANYSRC1DEST || /* Vista */
+       broken(retval == ERROR_SUCCESS), /* Win9x */
+       "Expected ERROR_GEN_FAILURE or DE_MANYSRC1DEST , got %d\n", retval);
     ok(file_exists("test1.txt"), "The file is renamed - many files are specified\n");
 
     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
@@ -403,74 +694,103 @@ static void test_rename(void)
 
     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
-    retval = SHFileOperationA(&shfo2); /* W98 returns 0, W2K and newer returns ERROR_GEN_FAILURE, both do nothing */
-    ok(!retval || retval == ERROR_GEN_FAILURE || retval == ERROR_INVALID_TARGET_HANDLE,
-       "Can't rename many files, retval = %d\n", retval);
+    retval = SHFileOperationA(&shfo2);
+    ok(retval == ERROR_GEN_FAILURE ||
+       retval == DE_MANYSRC1DEST || /* Vista */
+       broken(retval == ERROR_SUCCESS), /* Win9x */
+       "Expected ERROR_GEN_FAILURE or DE_MANYSRC1DEST files, got %d\n", retval);
     ok(file_exists("test1.txt"), "The file is not renamed - many files are specified\n");
 
     set_curr_dir_path(from, "test1.txt\0");
     set_curr_dir_path(to, "test6.txt\0");
     retval = SHFileOperationA(&shfo);
-    ok(!retval, "Rename file failed, retval = %d\n", retval);
+    ok(retval == ERROR_SUCCESS, "Rename file failed, retval = %d\n", retval);
     ok(!file_exists("test1.txt"), "The file is not renamed\n");
     ok(file_exists("test6.txt"), "The file is not renamed\n");
 
     set_curr_dir_path(from, "test6.txt\0");
     set_curr_dir_path(to, "test1.txt\0");
     retval = SHFileOperationA(&shfo);
-    ok(!retval, "Rename file back failed, retval = %d\n", retval);
+    ok(retval == ERROR_SUCCESS, "Rename file back failed, retval = %d\n", retval);
 
     set_curr_dir_path(from, "test4.txt\0");
     set_curr_dir_path(to, "test6.txt\0");
     retval = SHFileOperationA(&shfo);
-    ok(!retval, "Rename dir failed, retval = %d\n", retval);
-    ok(!file_exists("test4.txt"), "The dir is not renamed\n");
-    ok(file_exists("test6.txt"), "The dir is not renamed\n");
+    ok(retval == ERROR_SUCCESS, "Rename dir failed, retval = %d\n", retval);
+    ok(!dir_exists("test4.txt"), "The dir is not renamed\n");
+    ok(dir_exists("test6.txt"), "The dir is not renamed\n");
 
     set_curr_dir_path(from, "test6.txt\0");
     set_curr_dir_path(to, "test4.txt\0");
     retval = SHFileOperationA(&shfo);
-    ok(!retval, "Rename dir back failed, retval = %d\n", retval);
+    ok(retval == ERROR_SUCCESS, "Rename dir back failed, retval = %d\n", retval);
+    ok(dir_exists("test4.txt"), "The dir is not renamed\n");
 
     /* try to rename more than one file to a single file */
     shfo.pFrom = "test1.txt\0test2.txt\0";
     shfo.pTo = "a.txt\0";
     retval = SHFileOperationA(&shfo);
-    ok(retval == ERROR_GEN_FAILURE, "Expected ERROR_GEN_FAILURE, got %d\n", retval);
+    ok(retval == ERROR_GEN_FAILURE ||
+       retval == DE_MANYSRC1DEST || /* Vista */
+       broken(retval == ERROR_SUCCESS), /* Win9x */
+       "Expected ERROR_GEN_FAILURE or DE_MANYSRC1DEST, got %d\n", retval);
     ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
     ok(file_exists("test2.txt"), "Expected test2.txt to exist\n");
+    ok(!file_exists("a.txt"), "Expected a.txt to not exist\n");
 
     /* pFrom doesn't exist */
     shfo.pFrom = "idontexist\0";
     shfo.pTo = "newfile\0";
     retval = SHFileOperationA(&shfo);
-    ok(retval == 1026, "Expected 1026, got %d\n", retval);
+    ok(retval == 1026 ||
+       retval == ERROR_FILE_NOT_FOUND || /* Vista */
+       broken(retval == ERROR_SUCCESS), /* NT4 */
+       "Expected 1026 or ERROR_FILE_NOT_FOUND, got %d\n", retval);
     ok(!file_exists("newfile"), "Expected newfile to not exist\n");
 
     /* pTo already exist */
     shfo.pFrom = "test1.txt\0";
     shfo.pTo = "test2.txt\0";
     retval = SHFileOperationA(&shfo);
-        ok(retval == ERROR_ALREADY_EXISTS, "Expected ERROR_ALREADY_EXISTS, got %d\n", retval);
+    if (retval == ERROR_SUCCESS)
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        createTestFile("test1.txt");
+    }
+    else
+    {
+        ok(retval == ERROR_ALREADY_EXISTS ||
+           broken(retval == DE_OPCANCELLED) || /* NT4 */
+           broken(retval == ERROR_INVALID_NAME), /* Win9x */
+           "Expected ERROR_ALREADY_EXISTS, got %d\n", retval);
+    }
 
     /* pFrom is valid, but pTo is empty */
     shfo.pFrom = "test1.txt\0";
     shfo.pTo = "\0";
     retval = SHFileOperationA(&shfo);
-        ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
+    ok(retval == ERROR_CANCELLED ||
+       retval == DE_DIFFDIR || /* Vista */
+       broken(retval == DE_OPCANCELLED) || /* Win9x */
+       broken(retval == 65652), /* NT4 */
+       "Expected ERROR_CANCELLED or DE_DIFFDIR\n");
     ok(file_exists("test1.txt"), "Expected test1.txt to exist\n");
 
     /* pFrom is empty */
     shfo.pFrom = "\0";
     retval = SHFileOperationA(&shfo);
-        ok(retval == ERROR_ACCESS_DENIED, "Expected ERROR_ACCESS_DENIED, got %d\n", retval);
+    ok(retval == ERROR_ACCESS_DENIED ||
+       retval == DE_MANYSRC1DEST || /* Vista */
+       broken(retval == ERROR_SUCCESS), /* Win9x */
+       "Expected ERROR_ACCESS_DENIED or DE_MANYSRC1DEST, got %d\n", retval);
 
     /* pFrom is NULL, commented out because it crashes on nt 4.0 */
-#if 0
-    shfo.pFrom = NULL;
-    retval = SHFileOperationA(&shfo);
-    ok(retval == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", retval);
-#endif
+    if (0)
+    {
+        shfo.pFrom = NULL;
+        retval = SHFileOperationA(&shfo);
+        ok(retval == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", retval);
+    }
 }
 
 /* tests the FO_COPY action */
@@ -482,6 +802,7 @@ static void test_copy(void)
     FILEOP_FLAGS tmp_flags;
     DWORD retval;
     LPSTR ptr;
+    BOOL on_nt4 = FALSE;
 
     shfo.hwnd = NULL;
     shfo.wFunc = FO_COPY;
@@ -493,9 +814,23 @@ static void test_copy(void)
 
     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
-    ok(SHFileOperationA(&shfo), "Can't copy many files\n");
-    ok(!file_exists("test6.txt"), "The file is not copied - many files are "
-       "specified as a target\n");
+    retval = SHFileOperationA(&shfo);
+    if (dir_exists("test6.txt"))
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+        ok(DeleteFileA("test6.txt\\test1.txt"), "The file is not copied - many files "
+           "are specified as a target\n");
+        DeleteFileA("test6.txt\\test2.txt");
+        RemoveDirectoryA("test6.txt\\test4.txt");
+        RemoveDirectoryA("test6.txt");
+    }
+    else
+    {
+        expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
+        ok(!file_exists("test6.txt"), "The file is copied - many files are "
+           "specified as a target\n");
+    }
 
     memcpy(&shfo2, &shfo, sizeof(SHFILEOPSTRUCTA));
     shfo2.fFlags |= FOF_MULTIDESTFILES;
@@ -503,7 +838,7 @@ static void test_copy(void)
     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
     ok(!SHFileOperationA(&shfo2), "Can't copy many files\n");
-    ok(file_exists("test6.txt"), "The file is copied - many files are "
+    ok(file_exists("test6.txt"), "The file is not copied - many files are "
        "specified as a target\n");
     DeleteFileA("test6.txt");
     DeleteFileA("test7.txt");
@@ -512,9 +847,24 @@ static void test_copy(void)
     /* number of sources do not correspond to number of targets */
     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
     set_curr_dir_path(to, "test6.txt\0test7.txt\0");
-    ok(SHFileOperationA(&shfo2), "Can't copy many files\n");
-    ok(!file_exists("test6.txt"), "The file is not copied - many files are "
-       "specified as a target\n");
+    retval = SHFileOperationA(&shfo2);
+    if (dir_exists("test6.txt"))
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(retval == DE_DESTSAMETREE, "Expected DE_DESTSAMETREE, got %d\n", retval);
+        ok(DeleteFileA("test6.txt\\test1.txt"), "The file is not copied - many files "
+           "are specified as a target\n");
+        RemoveDirectoryA("test6.txt");
+        ok(DeleteFileA("test7.txt\\test2.txt"), "The file is not copied - many files "
+           "are specified as a target\n");
+        RemoveDirectoryA("test7.txt");
+    }
+    else
+    {
+        expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
+        ok(!file_exists("test6.txt"), "The file is copied - many files are "
+           "specified as a target\n");
+    }
 
     set_curr_dir_path(from, "test1.txt\0");
     set_curr_dir_path(to, "test4.txt\0");
@@ -557,13 +907,15 @@ static void test_copy(void)
     ok(!file_exists("testdir2\\test1.txt"), "The file is not copied yet\n");
     ok(!file_exists("testdir2\\test2.txt"), "The file is not copied yet\n");
     retval = SHFileOperationA(&shfo);
-    if (!retval)
+    if (retval == ERROR_SUCCESS)
         /* Win 95/NT returns success but copies only the files up to the nonexistent source */
         ok(file_exists("testdir2\\test1.txt"), "The file is not copied\n");
     else
     {
-        /* Win 98/ME/2K/XP fail the entire operation with return code 1026 if one source file does not exist */
-        ok(retval == 1026, "Files are copied to other directory\n");
+        /* Failure if one source file does not exist */
+        ok(retval == 1026 || /* Win 98/ME/2K/XP */
+           retval == ERROR_FILE_NOT_FOUND, /* Vista and W2K8 */
+           "Files are copied to other directory\n");
         ok(!file_exists("testdir2\\test1.txt"), "The file is copied\n");
     }
     ok(!file_exists("testdir2\\test2.txt"), "The file is copied\n");
@@ -575,10 +927,10 @@ static void test_copy(void)
     set_curr_dir_path(from, "test1.txt\0");
     set_curr_dir_path(to, "nonexistent\\notreal\\test2.txt\0");
     retval= SHFileOperation(&shfo);
-        ok(!retval, "Error copying into nonexistent directory\n");
-        ok(file_exists("nonexistent"), "nonexistent not created\n");
-        ok(file_exists("nonexistent\\notreal"), "nonexistent\\notreal not created\n");
-        ok(file_exists("nonexistent\\notreal\\test2.txt"), "Directory not created\n");
+    ok(!retval, "Error copying into nonexistent directory\n");
+    ok(file_exists("nonexistent"), "nonexistent not created\n");
+    ok(file_exists("nonexistent\\notreal"), "nonexistent\\notreal not created\n");
+    ok(file_exists("nonexistent\\notreal\\test2.txt"), "Directory not created\n");
     ok(!file_exists("nonexistent\\notreal\\test1.txt"), "test1.txt should not exist\n");
 
     /* a relative dest directory is OK */
@@ -595,21 +947,32 @@ static void test_copy(void)
     init_shfo_tests();
     shfo.pFrom = from;
     shfo.pTo = to;
+    /* suppress the error-dialog in win9x here */
+    shfo.fFlags |= FOF_NOERRORUI;
     set_curr_dir_path(from, "test1.txt\0test2.txt\0");
     set_curr_dir_path(to, "test3.txt\0");
     retval = SHFileOperation(&shfo);
-        ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
-    ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
+    if (retval == DE_FLDDESTISFILE)
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(!shfo.fAnyOperationsAborted, "Didn't expect aborted operations\n");
+    }
+    else
+    {
+        expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
+        ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
+    }
     ok(!file_exists("test3.txt\\test2.txt"), "Expected test3.txt\\test2.txt to not exist\n");
 
     /* try to copy many files to nonexistent directory */
     DeleteFile(to);
+    shfo.fFlags &= ~FOF_NOERRORUI;
     shfo.fAnyOperationsAborted = FALSE;
     retval = SHFileOperation(&shfo);
-        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
-        ok(DeleteFile("test3.txt\\test1.txt"), "Expected test3.txt\\test1.txt to exist\n");
-        ok(DeleteFile("test3.txt\\test2.txt"), "Expected test3.txt\\test1.txt to exist\n");
-        ok(RemoveDirectory(to), "Expected test3.txt to exist\n");
+    ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+    ok(DeleteFile("test3.txt\\test1.txt"), "Expected test3.txt\\test1.txt to exist\n");
+    ok(DeleteFile("test3.txt\\test2.txt"), "Expected test3.txt\\test1.txt to exist\n");
+    ok(RemoveDirectory(to), "Expected test3.txt to exist\n");
 
     /* send in FOF_MULTIDESTFILES with too many destination files */
     init_shfo_tests();
@@ -617,18 +980,49 @@ static void test_copy(void)
     shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0testdir2\\d.txt\0";
     shfo.fFlags |= FOF_NOERRORUI | FOF_MULTIDESTFILES;
     retval = SHFileOperation(&shfo);
-        ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
-    ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
-    ok(!file_exists("testdir2\\a.txt"), "Expected testdir2\\a.txt to not exist\n");
+    if (dir_exists("testdir2\\a.txt"))
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+        ok(DeleteFile("testdir2\\a.txt\\test1.txt"), "Expected testdir2\\a.txt\\test1.txt to exist\n");
+        RemoveDirectory("testdir2\\a.txt");
+        ok(DeleteFile("testdir2\\b.txt\\test2.txt"), "Expected testdir2\\b.txt\\test2.txt to exist\n");
+        RemoveDirectory("testdir2\\b.txt");
+        ok(DeleteFile("testdir2\\c.txt\\test3.txt"), "Expected testdir2\\c.txt\\test3.txt to exist\n");
+        RemoveDirectory("testdir2\\c.txt");
+        ok(!file_exists("testdir2\\d.txt"), "Expected testdir2\\d.txt to not exist\n");
+    }
+    else
+    {
+        expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
+        ok(shfo.fAnyOperationsAborted ||
+           broken(!shfo.fAnyOperationsAborted), /* NT4 */
+           "Expected aborted operations\n");
+        ok(!file_exists("testdir2\\a.txt"), "Expected testdir2\\a.txt to not exist\n");
+    }
 
     /* send in FOF_MULTIDESTFILES with too many destination files */
     shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
     shfo.pTo = "e.txt\0f.txt\0";
     shfo.fAnyOperationsAborted = FALSE;
     retval = SHFileOperation(&shfo);
-        ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
-    ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
-    ok(!file_exists("e.txt"), "Expected e.txt to not exist\n");
+    if (dir_exists("e.txt"))
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(retval == DE_SAMEFILE, "Expected DE_SAMEFILE, got %d\n", retval);
+        ok(DeleteFile("e.txt\\test1.txt"), "Expected e.txt\\test1.txt to exist\n");
+        RemoveDirectory("e.txt");
+        ok(DeleteFile("f.txt\\test2.txt"), "Expected f.txt\\test2.txt to exist\n");
+        RemoveDirectory("f.txt");
+    }
+    else
+    {
+        expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
+        ok(shfo.fAnyOperationsAborted ||
+           broken(!shfo.fAnyOperationsAborted), /* NT4 */
+           "Expected aborted operations\n");
+        ok(!file_exists("e.txt"), "Expected e.txt to not exist\n");
+    }
 
     /* use FOF_MULTIDESTFILES with files and a source directory */
     shfo.pFrom = "test1.txt\0test2.txt\0test4.txt\0";
@@ -646,16 +1040,28 @@ static void test_copy(void)
     shfo.fAnyOperationsAborted = FALSE;
     shfo.fFlags &= ~FOF_MULTIDESTFILES;
     retval = SHFileOperation(&shfo);
-        ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
-    ok(!file_exists("a.txt"), "Expected a.txt to not exist\n");
+    if (dir_exists("a.txt"))
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+        ok(DeleteFile("a.txt\\test1.txt"), "Expected a.txt\\test1.txt to exist\n");
+        ok(DeleteFile("a.txt\\test2.txt"), "Expected a.txt\\test2.txt to exist\n");
+        ok(DeleteFile("a.txt\\test3.txt"), "Expected a.txt\\test3.txt to exist\n");
+        RemoveDirectory("a.txt");
+    }
+    else
+    {
+        expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
+        ok(!file_exists("a.txt"), "Expected a.txt to not exist\n");
+    }
 
     /* try a glob */
     shfo.pFrom = "test?.txt\0";
     shfo.pTo = "testdir2\0";
     shfo.fFlags &= ~FOF_MULTIDESTFILES;
     retval = SHFileOperation(&shfo);
-        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
-        ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
+    ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+    ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
 
     /* try a glob with FOF_FILESONLY */
     clean_after_shfo_tests();
@@ -663,9 +1069,9 @@ static void test_copy(void)
     shfo.pFrom = "test?.txt\0";
     shfo.fFlags |= FOF_FILESONLY;
     retval = SHFileOperation(&shfo);
-        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
-        ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
-    ok(!file_exists("testdir2\\test4.txt"), "Expected testdir2\\test4.txt to not exist\n");
+    ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+    ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
+    ok(!dir_exists("testdir2\\test4.txt"), "Expected testdir2\\test4.txt to not exist\n");
 
     /* try a glob with FOF_MULTIDESTFILES and the same number
     * of dest files that we would expect
@@ -676,9 +1082,24 @@ static void test_copy(void)
     shfo.fFlags &= ~FOF_FILESONLY;
     shfo.fFlags |= FOF_MULTIDESTFILES;
     retval = SHFileOperation(&shfo);
-        ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
-    ok(shfo.fAnyOperationsAborted, "Expected aborted operations\n");
-    ok(!file_exists("testdir2\\a.txt"), "Expected testdir2\\test1.txt to not exist\n");
+    if (dir_exists("testdir2\\a.txt"))
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+        ok(DeleteFile("testdir2\\a.txt\\test1.txt"), "Expected testdir2\\a.txt\\test1.txt to exist\n");
+        ok(DeleteFile("testdir2\\a.txt\\test2.txt"), "Expected testdir2\\a.txt\\test2.txt to exist\n");
+        ok(DeleteFile("testdir2\\a.txt\\test3.txt"), "Expected testdir2\\a.txt\\test3.txt to exist\n");
+        ok(RemoveDirectory("testdir2\\a.txt\\test4.txt"), "Expected testdir2\\a.txt\\test4.txt to exist\n");
+        RemoveDirectory("testdir2\\a.txt");
+    }
+    else
+    {
+        expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
+        ok(shfo.fAnyOperationsAborted ||
+           broken(!shfo.fAnyOperationsAborted), /* NT4 */
+           "Expected aborted operations\n");
+        ok(!file_exists("testdir2\\a.txt"), "Expected testdir2\\test1.txt to not exist\n");
+    }
     ok(!RemoveDirectory("b.txt"), "b.txt should not exist\n");
 
     /* copy one file to two others, second is ignored */
@@ -688,27 +1109,66 @@ static void test_copy(void)
     shfo.pTo = "b.txt\0c.txt\0";
     shfo.fAnyOperationsAborted = FALSE;
     retval = SHFileOperation(&shfo);
+    if (retval == DE_OPCANCELLED)
+    {
+        /* NT4 fails and doesn't copy any files */
+        ok(!file_exists("b.txt"), "Expected b.txt to not exist\n");
+        /* Needed to skip some tests */
+        win_skip("Skipping some tests on NT4\n");
+        on_nt4 = TRUE;
+    }
+    else
+    {
         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
         ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
+    }
     ok(!DeleteFile("c.txt"), "Expected c.txt to not exist\n");
 
     /* copy two file to three others, all fail */
     shfo.pFrom = "test1.txt\0test2.txt\0";
     shfo.pTo = "b.txt\0c.txt\0d.txt\0";
     retval = SHFileOperation(&shfo);
-        ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
-    ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
-    ok(!DeleteFile("b.txt"), "Expected b.txt to not exist\n");
+    if (dir_exists("b.txt"))
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+        ok(DeleteFile("b.txt\\test1.txt"), "Expected b.txt\\test1.txt to exist\n");
+        RemoveDirectory("b.txt");
+        ok(DeleteFile("c.txt\\test2.txt"), "Expected c.txt\\test2.txt to exist\n");
+        RemoveDirectory("c.txt");
+    }
+    else
+    {
+        expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
+        ok(shfo.fAnyOperationsAborted ||
+           broken(!shfo.fAnyOperationsAborted), /* NT4 */
+           "Expected aborted operations\n");
+        ok(!DeleteFile("b.txt"), "Expected b.txt to not exist\n");
+    }
 
     /* copy one file and one directory to three others */
     shfo.pFrom = "test1.txt\0test4.txt\0";
     shfo.pTo = "b.txt\0c.txt\0d.txt\0";
     shfo.fAnyOperationsAborted = FALSE;
     retval = SHFileOperation(&shfo);
-        ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
-    ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
-    ok(!DeleteFile("b.txt"), "Expected b.txt to not exist\n");
-    ok(!DeleteFile("c.txt"), "Expected c.txt to not exist\n");
+    if (dir_exists("b.txt"))
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+        ok(DeleteFile("b.txt\\test1.txt"), "Expected b.txt\\test1.txt to exist\n");
+        RemoveDirectory("b.txt");
+        ok(RemoveDirectory("c.txt\\test4.txt"), "Expected c.txt\\test4.txt to exist\n");
+        RemoveDirectory("c.txt");
+    }
+    else
+    {
+        expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
+        ok(shfo.fAnyOperationsAborted ||
+           broken(!shfo.fAnyOperationsAborted), /* NT4 */
+           "Expected aborted operations\n");
+        ok(!DeleteFile("b.txt"), "Expected b.txt to not exist\n");
+        ok(!DeleteFile("c.txt"), "Expected c.txt to not exist\n");
+    }
 
     /* copy a directory with a file beneath it, plus some files */
     createTestFile("test4.txt\\a.txt");
@@ -718,7 +1178,7 @@ static void test_copy(void)
     shfo.fAnyOperationsAborted = FALSE;
     retval = SHFileOperation(&shfo);
     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
-    ok(DeleteFile("testdir2\\test1.txt"), "Expected newdir\\test1.txt to exist\n");
+    ok(DeleteFile("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
     ok(DeleteFile("testdir2\\test4.txt\\a.txt"), "Expected a.txt to exist\n");
     ok(RemoveDirectory("testdir2\\test4.txt"), "Expected testdir2\\test4.txt to exist\n");
 
@@ -734,9 +1194,23 @@ static void test_copy(void)
     shfo.pFrom = "test4.txt\\a.txt\0test4.txt\0";
     shfo.pTo = "nonexistent\0";
     retval = SHFileOperation(&shfo);
-        ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
-    ok(shfo.fAnyOperationsAborted, "Expected operations to be aborted\n");
-    ok(!file_exists("nonexistent\\test4.txt"), "Expected nonexistent\\test4.txt to not exist\n");
+    if (dir_exists("nonexistent"))
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+        ok(DeleteFile("nonexistent\\test4.txt\\a.txt"), "Expected nonexistent\\test4.txt\\a.txt to exist\n");
+        RemoveDirectory("nonexistent\\test4.txt");
+        ok(DeleteFile("nonexistent\\a.txt"), "Expected nonexistent\\a.txt to exist\n");
+        RemoveDirectory("nonexistent");
+    }
+    else
+    {
+        expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
+        ok(shfo.fAnyOperationsAborted ||
+           broken(!shfo.fAnyOperationsAborted), /* NT4 */
+           "Expected aborted operations\n");
+        ok(!file_exists("nonexistent\\test4.txt"), "Expected nonexistent\\test4.txt to not exist\n");
+    }
     DeleteFile("test4.txt\\a.txt");
 
     /* destination is same as source file */
@@ -745,10 +1219,17 @@ static void test_copy(void)
     shfo.fAnyOperationsAborted = FALSE;
     shfo.fFlags = FOF_NOERRORUI | FOF_MULTIDESTFILES;
     retval = SHFileOperation(&shfo);
-        ok(retval == ERROR_NO_MORE_SEARCH_HANDLES,
-           "Expected ERROR_NO_MORE_SEARCH_HANDLES, got %d\n", retval);
-        ok(!shfo.fAnyOperationsAborted, "Expected no operations to be aborted\n");
+    if (retval == DE_OPCANCELLED)
+    {
+        /* NT4 fails and doesn't copy any files */
+        ok(!file_exists("b.txt"), "Expected b.txt to not exist\n");
+    }
+    else
+    {
+        ok(retval == DE_SAMEFILE, "Expected DE_SAMEFILE, got %d\n", retval);
         ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
+    }
+    ok(!shfo.fAnyOperationsAborted, "Expected no operations to be aborted\n");
     ok(!file_exists("c.txt"), "Expected c.txt to not exist\n");
 
     /* destination is same as source directory */
@@ -756,8 +1237,18 @@ static void test_copy(void)
     shfo.pTo = "b.txt\0test4.txt\0c.txt\0";
     shfo.fAnyOperationsAborted = FALSE;
     retval = SHFileOperation(&shfo);
-        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+    if (retval == DE_OPCANCELLED)
+    {
+        /* NT4 fails and doesn't copy any files */
+        ok(!file_exists("b.txt"), "Expected b.txt to not exist\n");
+    }
+    else
+    {
+        ok(retval == ERROR_SUCCESS ||
+           retval == DE_DESTSAMETREE, /* Vista */
+           "Expected ERROR_SUCCESS or DE_DESTSAMETREE, got %d\n", retval);
         ok(DeleteFile("b.txt"), "Expected b.txt to exist\n");
+    }
     ok(!file_exists("c.txt"), "Expected c.txt to not exist\n");
 
     /* copy a directory into itself, error displayed in UI */
@@ -766,7 +1257,9 @@ static void test_copy(void)
     shfo.fFlags &= ~FOF_MULTIDESTFILES;
     shfo.fAnyOperationsAborted = FALSE;
     retval = SHFileOperation(&shfo);
-        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+    ok(retval == ERROR_SUCCESS ||
+       retval == DE_DESTSUBTREE, /* Vista */
+       "Expected ERROR_SUCCESS or DE_DESTSUBTREE, got %d\n", retval);
     ok(!RemoveDirectory("test4.txt\\newdir"), "Expected test4.txt\\newdir to not exist\n");
 
     /* copy a directory to itself, error displayed in UI */
@@ -774,7 +1267,9 @@ static void test_copy(void)
     shfo.pTo = "test4.txt\0";
     shfo.fAnyOperationsAborted = FALSE;
     retval = SHFileOperation(&shfo);
-        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+    ok(retval == ERROR_SUCCESS ||
+       retval == DE_DESTSUBTREE, /* Vista */
+       "Expected ERROR_SUCCESS or DE_DESTSUBTREE, got %d\n", retval);
 
     /* copy a file into a directory, and the directory into itself */
     shfo.pFrom = "test1.txt\0test4.txt\0";
@@ -782,7 +1277,9 @@ static void test_copy(void)
     shfo.fAnyOperationsAborted = FALSE;
     shfo.fFlags |= FOF_NOCONFIRMATION;
     retval = SHFileOperation(&shfo);
-        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+    ok(retval == ERROR_SUCCESS ||
+       retval == DE_DESTSUBTREE, /* Vista */
+       "Expected ERROR_SUCCESS or DE_DESTSUBTREE, got %d\n", retval);
     ok(DeleteFile("test4.txt\\test1.txt"), "Expected test4.txt\\test1.txt to exist\n");
 
     /* copy a file to a file, and the directory into itself */
@@ -790,45 +1287,64 @@ static void test_copy(void)
     shfo.pTo = "test4.txt\\a.txt\0";
     shfo.fAnyOperationsAborted = FALSE;
     retval = SHFileOperation(&shfo);
-        ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
-    ok(!file_exists("test4.txt\\a.txt"), "Expected test4.txt\\a.txt to not exist\n");
+    if (dir_exists("test4.txt\\a.txt"))
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(retval == DE_DESTSUBTREE, "Expected DE_DESTSUBTREE, got %d\n", retval);
+        ok(DeleteFile("test4.txt\\a.txt\\test1.txt"), "Expected test4.txt\\a.txt\\test1.txt to exist\n");
+        RemoveDirectory("test4.txt\\a.txt");
+    }
+    else
+    {
+        expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
+        ok(!file_exists("test4.txt\\a.txt"), "Expected test4.txt\\a.txt to not exist\n");
+    }
 
     /* copy a nonexistent file to a nonexistent directory */
     shfo.pFrom = "e.txt\0";
     shfo.pTo = "nonexistent\0";
     shfo.fAnyOperationsAborted = FALSE;
     retval = SHFileOperation(&shfo);
-    ok(retval == 1026, "Expected 1026, got %d\n", retval);
+    ok(retval == 1026 ||
+       retval == ERROR_FILE_NOT_FOUND || /* Vista */
+       broken(retval == ERROR_SUCCESS), /* NT4 */
+       "Expected 1026 or ERROR_FILE_NOT_FOUND, got %d\n", retval);
     ok(!file_exists("nonexistent\\e.txt"), "Expected nonexistent\\e.txt to not exist\n");
     ok(!file_exists("nonexistent"), "Expected nonexistent to not exist\n");
 
     /* Overwrite tests */
     clean_after_shfo_tests();
     init_shfo_tests();
-    shfo.fFlags = FOF_NOCONFIRMATION;
-    shfo.pFrom = "test1.txt\0";
-    shfo.pTo = "test2.txt\0";
-    shfo.fAnyOperationsAborted = FALSE;
-    /* without FOF_NOCONFIRMATION the confirmation is Yes/No */
-    retval = SHFileOperation(&shfo);
-    ok(retval == 0, "Expected 0, got %d\n", retval);
-    ok(file_has_content("test2.txt", "test1.txt\n"), "The file was not copied\n");
-
-    shfo.pFrom = "test3.txt\0test1.txt\0";
-    shfo.pTo = "test2.txt\0one.txt\0";
-    shfo.fFlags = FOF_NOCONFIRMATION | FOF_MULTIDESTFILES;
-    /* without FOF_NOCONFIRMATION the confirmation is Yes/Yes to All/No/Cancel */
-    retval = SHFileOperation(&shfo);
-    ok(retval == 0, "Expected 0, got %d\n", retval);
-    ok(file_has_content("test2.txt", "test3.txt\n"), "The file was not copied\n");
+    if (!on_nt4)
+    {
+        /* NT4 would throw up some dialog boxes and doesn't copy files that are needed
+         * in subsequent tests.
+         */
+        shfo.fFlags = FOF_NOCONFIRMATION;
+        shfo.pFrom = "test1.txt\0";
+        shfo.pTo = "test2.txt\0";
+        shfo.fAnyOperationsAborted = FALSE;
+        /* without FOF_NOCONFIRMATION the confirmation is Yes/No */
+        retval = SHFileOperation(&shfo);
+        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+        ok(file_has_content("test2.txt", "test1.txt\n"), "The file was not copied\n");
 
-    shfo.pFrom = "one.txt\0";
-    shfo.pTo = "testdir2\0";
-    shfo.fFlags = FOF_NOCONFIRMATION;
-    /* without FOF_NOCONFIRMATION the confirmation is Yes/No */
-    retval = SHFileOperation(&shfo);
-    ok(retval == 0, "Expected 0, got %d\n", retval);
-    ok(file_has_content("testdir2\\one.txt", "test1.txt\n"), "The file was not copied\n");
+        shfo.pFrom = "test3.txt\0test1.txt\0";
+        shfo.pTo = "test2.txt\0one.txt\0";
+        shfo.fFlags = FOF_NOCONFIRMATION | FOF_MULTIDESTFILES;
+        /* without FOF_NOCONFIRMATION the confirmation is Yes/Yes to All/No/Cancel */
+        retval = SHFileOperation(&shfo);
+        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+        ok(file_has_content("test2.txt", "test3.txt\n"), "The file was not copied\n");
+
+        shfo.pFrom = "one.txt\0";
+        shfo.pTo = "testdir2\0";
+        shfo.fFlags = FOF_NOCONFIRMATION;
+        /* without FOF_NOCONFIRMATION the confirmation is Yes/No */
+        retval = SHFileOperation(&shfo);
+        ok(retval == 0, "Expected 0, got %d\n", retval);
+        ok(file_has_content("testdir2\\one.txt", "test1.txt\n"), "The file was not copied\n");
+    }
 
     createTestFile("test4.txt\\test1.txt");
     shfo.pFrom = "test4.txt\0";
@@ -843,29 +1359,46 @@ static void test_copy(void)
 
     createTestFile("one.txt");
 
-    /* no double-NULL terminator for pFrom */
-    memset(from, 'a', MAX_PATH);
+    /* pFrom contains bogus 2nd name longer than MAX_PATH */
+    memset(from, 'a', MAX_PATH*2);
+    memset(from+MAX_PATH*2, 0, 2);
     lstrcpyA(from, "one.txt");
     shfo.pFrom = from;
     shfo.pTo = "two.txt\0";
     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
     retval = SHFileOperation(&shfo);
-    ok(retval == 1148 || retval == 1026, "Expected 1148 or 1026, got %d\n", retval);
+    ok(retval == 1148 || retval == 1026 ||
+       retval == ERROR_ACCESS_DENIED || /* win2k */
+       retval == DE_INVALIDFILES, /* Vista */
+       "Unexpected return value, got %d\n", retval);
     ok(DeleteFileA("one.txt"), "Expected file to exist\n");
-    ok(!DeleteFileA("two.txt"), "Expected file to not exist\n");
+    if (dir_exists("two.txt"))
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(RemoveDirectory("two.txt"), "Expected two.txt to exist\n");
+    else
+        ok(!DeleteFileA("two.txt"), "Expected file to not exist\n");
 
     createTestFile("one.txt");
 
-    /* no double-NULL terminator for pTo */
-    memset(to, 'a', MAX_PATH);
+    /* pTo contains bogus 2nd name longer than MAX_PATH */
+    memset(to, 'a', MAX_PATH*2);
+    memset(to+MAX_PATH*2, 0, 2);
     lstrcpyA(to, "two.txt");
     shfo.pFrom = "one.txt\0";
     shfo.pTo = to;
     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
     retval = SHFileOperation(&shfo);
-    ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+    if (retval == DE_OPCANCELLED)
+    {
+        /* NT4 fails and doesn't copy any files */
+        ok(!file_exists("two.txt"), "Expected two.txt to not exist\n");
+    }
+    else
+    {
+        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+        ok(DeleteFileA("two.txt"), "Expected file to exist\n");
+    }
     ok(DeleteFileA("one.txt"), "Expected file to exist\n");
-    ok(DeleteFileA("two.txt"), "Expected file to exist\n");
 
     createTestFile("one.txt");
 
@@ -874,69 +1407,108 @@ static void test_copy(void)
     shfo.pTo = "two.txt\0three.txt\0";
     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
     retval = SHFileOperation(&shfo);
-    ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+    if (retval == DE_OPCANCELLED)
+    {
+        /* NT4 fails and doesn't copy any files */
+        ok(!file_exists("two.txt"), "Expected two.txt to not exist\n");
+    }
+    else
+    {
+        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+        ok(DeleteFileA("two.txt"), "Expected file to exist\n");
+    }
     ok(DeleteFileA("one.txt"), "Expected file to exist\n");
-    ok(DeleteFileA("two.txt"), "Expected file to exist\n");
 
     createTestFile("one.txt");
 
-    /* no double-NULL terminator for pFrom and pTo */
-    memset(from, 'a', MAX_PATH);
-    memset(to, 'a', MAX_PATH);
+    /* both pFrom and pTo contain bogus 2nd names longer than MAX_PATH */
+    memset(from, 'a', MAX_PATH*2);
+    memset(from+MAX_PATH*2, 0, 2);
+    memset(to, 'a', MAX_PATH*2);
+    memset(to+MAX_PATH*2, 0, 2);
     lstrcpyA(from, "one.txt");
     lstrcpyA(to, "two.txt");
     shfo.pFrom = from;
     shfo.pTo = to;
     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
     retval = SHFileOperation(&shfo);
-    ok(retval == 1148 || retval == 1026, "Expected 1148 or 1026, got %d\n", retval);
+    ok(retval == 1148 || retval == 1026 ||
+       retval == ERROR_ACCESS_DENIED ||  /* win2k */
+       retval == DE_INVALIDFILES, /* Vista */
+       "Unexpected return value, got %d\n", retval);
     ok(DeleteFileA("one.txt"), "Expected file to exist\n");
-    ok(!DeleteFileA("two.txt"), "Expected file to not exist\n");
+    if (dir_exists("two.txt"))
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(RemoveDirectory("two.txt"), "Expected two.txt to exist\n");
+    else
+        ok(!DeleteFileA("two.txt"), "Expected file to not exist\n");
 
     createTestFile("one.txt");
 
-    /* no double-NULL terminator for pTo, FOF_MULTIDESTFILES */
-    memset(to, 'a', MAX_PATH);
+    /* pTo contains bogus 2nd name longer than MAX_PATH, FOF_MULTIDESTFILES */
+    memset(to, 'a', MAX_PATH*2);
+    memset(to+MAX_PATH*2, 0, 2);
     lstrcpyA(to, "two.txt");
     shfo.pFrom = "one.txt\0";
     shfo.pTo = to;
     shfo.fFlags = FOF_MULTIDESTFILES | FOF_NOCONFIRMATION |
                   FOF_SILENT | FOF_NOERRORUI;
     retval = SHFileOperation(&shfo);
-    ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+    if (retval == DE_OPCANCELLED)
+    {
+        /* NT4 fails and doesn't copy any files */
+        ok(!file_exists("two.txt"), "Expected two.txt to not exist\n");
+    }
+    else
+    {
+        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+        ok(DeleteFileA("two.txt"), "Expected file to exist\n");
+    }
     ok(DeleteFileA("one.txt"), "Expected file to exist\n");
-    ok(DeleteFileA("two.txt"), "Expected file to exist\n");
 
     createTestFile("one.txt");
     createTestFile("two.txt");
 
-    /* no double-NULL terminator for pTo,
+    /* pTo contains bogus 2nd name longer than MAX_PATH,
      * multiple source files,
      * dest directory does not exist
      */
     memset(to, 'a', 2 * MAX_PATH);
+    memset(to+MAX_PATH*2, 0, 2);
     lstrcpyA(to, "threedir");
     shfo.pFrom = "one.txt\0two.txt\0";
     shfo.pTo = to;
     shfo.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
     retval = SHFileOperation(&shfo);
-    ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
-    ok(!DeleteFileA("threedir\\one.txt"), "Expected file to not exist\n");
-    ok(!DeleteFileA("threedir\\two.txt"), "Expected file to not exist\n");
+    if (dir_exists("threedir"))
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+        ok(DeleteFileA("threedir\\one.txt"), "Expected file to exist\n");
+        ok(DeleteFileA("threedir\\two.txt"), "Expected file to exist\n");
+        ok(RemoveDirectoryA("threedir"), "Expected dir to exist\n");
+    }
+    else
+    {
+        expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
+        ok(!DeleteFileA("threedir\\one.txt"), "Expected file to not exist\n");
+        ok(!DeleteFileA("threedir\\two.txt"), "Expected file to not exist\n");
+        ok(!DeleteFileA("threedir"), "Expected file to not exist\n");
+        ok(!RemoveDirectoryA("threedir"), "Expected dir to not exist\n");
+    }
     ok(DeleteFileA("one.txt"), "Expected file to exist\n");
     ok(DeleteFileA("two.txt"), "Expected file to exist\n");
-    ok(!DeleteFileA("threedir"), "Expected file to not exist\n");
-    ok(!RemoveDirectoryA("threedir"), "Expected dir to not exist\n");
 
     createTestFile("one.txt");
     createTestFile("two.txt");
     CreateDirectoryA("threedir", NULL);
 
-    /* no double-NULL terminator for pTo,
+    /* pTo contains bogus 2nd name longer than MAX_PATH,
      * multiple source files,
      * dest directory does exist
      */
     memset(to, 'a', 2 * MAX_PATH);
+    memset(to+MAX_PATH*2, 0, 2);
     lstrcpyA(to, "threedir");
     shfo.pFrom = "one.txt\0two.txt\0";
     shfo.pTo = to;
@@ -949,41 +1521,48 @@ static void test_copy(void)
     ok(DeleteFileA("two.txt"), "Expected file to exist\n");
     ok(RemoveDirectoryA("threedir"), "Expected dir to exist\n");
 
-    createTestFile("one.txt");
-    createTestFile("two.txt");
-
-    /* no double-NULL terminator for pTo,
-     * multiple source files, FOF_MULTIDESTFILES
-     * dest dir does not exist
-     */
-    memset(to, 'a', 2 * MAX_PATH);
-    lstrcpyA(to, "threedir");
-    shfo.pFrom = "one.txt\0two.txt\0";
-    shfo.pTo = to;
-    shfo.fFlags = FOF_MULTIDESTFILES | FOF_NOCONFIRMATION |
-                  FOF_SILENT | FOF_NOERRORUI;
-    retval = SHFileOperation(&shfo);
-    ok(retval == ERROR_CANCELLED ||
-       retval == ERROR_SUCCESS, /* win2k3 */
-       "Expected ERROR_CANCELLED or ERROR_SUCCESS, got %d\n", retval);
-    ok(!DeleteFileA("threedir\\one.txt"), "Expected file to not exist\n");
-    ok(!DeleteFileA("threedir\\two.txt"), "Expected file to not exist\n");
-    ok(DeleteFileA("one.txt"), "Expected file to exist\n");
-    ok(DeleteFileA("two.txt"), "Expected file to exist\n");
-    ok(!RemoveDirectoryA("threedir"), "Expected dir to not exist\n");
+    if (0) {
+        /* this crashes on win9x */
+        createTestFile("one.txt");
+        createTestFile("two.txt");
+
+        /* pTo contains bogus 2nd name longer than MAX_PATH,
+         * multiple source files, FOF_MULTIDESTFILES
+         * dest dir does not exist
+         */
+
+        memset(to, 'a', 2 * MAX_PATH);
+        memset(to+MAX_PATH*2, 0, 2);
+        lstrcpyA(to, "threedir");
+        shfo.pFrom = "one.txt\0two.txt\0";
+        shfo.pTo = to;
+        shfo.fFlags = FOF_MULTIDESTFILES | FOF_NOCONFIRMATION |
+                      FOF_SILENT | FOF_NOERRORUI;
+        retval = SHFileOperation(&shfo);
+        ok(retval == ERROR_CANCELLED ||
+           retval == ERROR_SUCCESS, /* win2k3 */
+           "Expected ERROR_CANCELLED or ERROR_SUCCESS, got %d\n", retval);
+        ok(!DeleteFileA("threedir\\one.txt"), "Expected file to not exist\n");
+        ok(!DeleteFileA("threedir\\two.txt"), "Expected file to not exist\n");
+        ok(DeleteFileA("one.txt"), "Expected file to exist\n");
+        ok(DeleteFileA("two.txt"), "Expected file to exist\n");
+        ok(!RemoveDirectoryA("threedir"), "Expected dir to not exist\n");
+
+        /* file exists in win2k */
+        DeleteFileA("threedir");
+    }
 
-    /* file exists in win2k */
-    DeleteFileA("threedir");
 
     createTestFile("one.txt");
     createTestFile("two.txt");
     CreateDirectoryA("threedir", NULL);
 
-    /* no double-NULL terminator for pTo,
+    /* pTo contains bogus 2nd name longer than MAX_PATH,
      * multiple source files, FOF_MULTIDESTFILES
      * dest dir does exist
      */
     memset(to, 'a', 2 * MAX_PATH);
+    memset(to+MAX_PATH*2, 0, 2);
     lstrcpyA(to, "threedir");
     ptr = to + lstrlenA(to) + 1;
     lstrcpyA(ptr, "fourdir");
@@ -993,13 +1572,23 @@ static void test_copy(void)
                   FOF_SILENT | FOF_NOERRORUI;
     retval = SHFileOperation(&shfo);
     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
-    ok(DeleteFileA("threedir\\one.txt"), "Expected file to exist\n");
-    ok(DeleteFileA("threedir\\two.txt"), "Expected file to exist\n");
     ok(DeleteFileA("one.txt"), "Expected file to exist\n");
     ok(DeleteFileA("two.txt"), "Expected file to exist\n");
+    ok(DeleteFileA("threedir\\one.txt"), "Expected file to exist\n");
+    if (dir_exists("fourdir"))
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(!DeleteFileA("threedir\\two.txt"), "Expected file to not exist\n");
+        ok(DeleteFileA("fourdir\\two.txt"), "Expected file to exist\n");
+        RemoveDirectoryA("fourdir");
+    }
+    else
+    {
+        ok(DeleteFileA("threedir\\two.txt"), "Expected file to exist\n");
+        ok(!DeleteFileA("fourdir"), "Expected file to not exist\n");
+        ok(!RemoveDirectoryA("fourdir"), "Expected dir to not exist\n");
+    }
     ok(RemoveDirectoryA("threedir"), "Expected dir to exist\n");
-    ok(!DeleteFileA("fourdir"), "Expected file to not exist\n");
-    ok(!RemoveDirectoryA("fourdir"), "Expected dir to not exist\n");
 
     createTestFile("one.txt");
     createTestFile("two.txt");
@@ -1014,14 +1603,22 @@ static void test_copy(void)
     shfo.fFlags = FOF_MULTIDESTFILES | FOF_NOCONFIRMATION |
                   FOF_SILENT | FOF_NOERRORUI;
     retval = SHFileOperation(&shfo);
-    ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
+    ok(retval == ERROR_CANCELLED ||
+       retval == DE_FILEDESTISFLD || /* Vista */
+       broken(retval == DE_OPCANCELLED), /* Win9x, NT4 */
+       "Expected ERROR_CANCELLED or DE_FILEDESTISFLD. got %d\n", retval);
+    if (file_exists("threedir\\threedir"))
+    {
+        /* NT4 */
+        ok(DeleteFileA("threedir\\threedir"), "Expected file to exist\n");
+    }
     ok(!DeleteFileA("threedir\\one.txt"), "Expected file to not exist\n");
     ok(!DeleteFileA("threedir\\two.txt"), "Expected file to not exist\n");
     ok(DeleteFileA("one.txt"), "Expected file to exist\n");
     ok(DeleteFileA("two.txt"), "Expected file to exist\n");
     ok(RemoveDirectoryA("threedir"), "Expected dir to exist\n");
     ok(!DeleteFileA("fourdir"), "Expected file to not exist\n");
-    ok(!RemoveDirectoryA("fourdir"), "Expected dit to not exist\n");
+    ok(!RemoveDirectoryA("fourdir"), "Expected dir to not exist\n");
 
     createTestFile("one.txt");
     createTestFile("two.txt");
@@ -1037,13 +1634,23 @@ static void test_copy(void)
                   FOF_SILENT | FOF_NOERRORUI;
     retval = SHFileOperation(&shfo);
     ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
-    ok(DeleteFileA("threedir\\one.txt"), "Expected file to exist\n");
-    ok(DeleteFileA("threedir\\two.txt"), "Expected file to exist\n");
     ok(DeleteFileA("one.txt"), "Expected file to exist\n");
     ok(DeleteFileA("two.txt"), "Expected file to exist\n");
+    ok(DeleteFileA("threedir\\one.txt"), "Expected file to exist\n");
+    if (dir_exists("fourdir"))
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(!DeleteFileA("threedir\\two.txt"), "Expected file to not exist\n");
+        ok(DeleteFileA("fourdir\\two.txt"), "Expected file to exist\n");
+        RemoveDirectoryA("fourdir");
+    }
+    else
+    {
+        ok(DeleteFileA("threedir\\two.txt"), "Expected file to exist\n");
+        ok(!DeleteFileA("fourdir"), "Expected file to not exist\n");
+        ok(!RemoveDirectoryA("fourdir"), "Expected dit to not exist\n");
+    }
     ok(RemoveDirectoryA("threedir"), "Expected dir to exist\n");
-    ok(!DeleteFileA("fourdir"), "Expected file to not exist\n");
-    ok(!RemoveDirectoryA("fourdir"), "Expected dit to not exist\n");
     ok(!DeleteFileA("five"), "Expected file to not exist\n");
     ok(!RemoveDirectoryA("five"), "Expected dit to not exist\n");
 
@@ -1108,107 +1715,203 @@ static void test_move(void)
     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
     ok(!SHFileOperationA(&shfo2), "Move many files\n");
-    ok(file_exists("test6.txt"), "The file is moved - many files are "
+    ok(DeleteFileA("test6.txt"), "The file is not moved - many files are "
        "specified as a target\n");
-    DeleteFileA("test6.txt");
-    DeleteFileA("test7.txt");
-    RemoveDirectoryA("test8.txt");
+    ok(DeleteFileA("test7.txt"), "The file is not moved\n");
+    ok(RemoveDirectoryA("test8.txt"), "The directory is not moved\n");
 
     init_shfo_tests();
 
     /* number of sources do not correspond to number of targets */
     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
     set_curr_dir_path(to, "test6.txt\0test7.txt\0");
-    ok(SHFileOperationA(&shfo2), "Can't move many files\n");
-    ok(!file_exists("test6.txt"), "The file is not moved - many files are "
-       "specified as a target\n");
+    retval = SHFileOperationA(&shfo2);
+    if (dir_exists("test6.txt"))
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(retval == DE_DESTSAMETREE, "Expected DE_DESTSAMETREE, got %d\n", retval);
+        ok(DeleteFileA("test6.txt\\test1.txt"), "The file is not moved\n");
+        RemoveDirectoryA("test6.txt");
+        ok(DeleteFileA("test7.txt\\test2.txt"), "The file is not moved\n");
+        RemoveDirectoryA("test7.txt");
+    }
+    else
+    {
+        expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
+        ok(!file_exists("test6.txt"), "The file is not moved - many files are "
+           "specified as a target\n");
+    }
 
     init_shfo_tests();
 
     set_curr_dir_path(from, "test3.txt\0");
     set_curr_dir_path(to, "test4.txt\\test1.txt\0");
-    ok(!SHFileOperationA(&shfo), "File is moved moving to other directory\n");
-    ok(file_exists("test4.txt\\test1.txt"), "The file is moved\n");
+    ok(!SHFileOperationA(&shfo), "Can't move file to other directory\n");
+    ok(file_exists("test4.txt\\test1.txt"), "The file is not moved\n");
 
     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
     set_curr_dir_path(to, "test6.txt\0test7.txt\0test8.txt\0");
-    ok(SHFileOperationA(&shfo), "Cannot move many files\n");
-    ok(file_exists("test1.txt"), "The file is not moved. Many files are specified\n");
-    ok(file_exists("test4.txt"), "The directory is not moved. Many files are specified\n");
+    retval = SHFileOperationA(&shfo);
+    if (dir_exists("test6.txt"))
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+        ok(DeleteFileA("test6.txt\\test1.txt"), "The file is not moved. Many files are specified\n");
+        ok(DeleteFileA("test6.txt\\test2.txt"), "The file is not moved. Many files are specified\n");
+        ok(DeleteFileA("test6.txt\\test4.txt\\test1.txt"), "The file is not moved. Many files are specified\n");
+        ok(RemoveDirectoryA("test6.txt\\test4.txt"), "The directory is not moved. Many files are specified\n");
+        RemoveDirectoryA("test6.txt");
+        init_shfo_tests();
+    }
+    else
+    {
+        expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
+        ok(file_exists("test1.txt"), "The file is moved. Many files are specified\n");
+        ok(dir_exists("test4.txt"), "The directory is moved. Many files are specified\n");
+    }
 
     set_curr_dir_path(from, "test1.txt\0");
     set_curr_dir_path(to, "test6.txt\0");
-    ok(!SHFileOperationA(&shfo), "Move file\n");
-    ok(!file_exists("test1.txt"), "The file is moved\n");
-    ok(file_exists("test6.txt"), "The file is moved\n");
+    ok(!SHFileOperationA(&shfo), "Move file failed\n");
+    ok(!file_exists("test1.txt"), "The file is not moved\n");
+    ok(file_exists("test6.txt"), "The file is not moved\n");
     set_curr_dir_path(from, "test6.txt\0");
     set_curr_dir_path(to, "test1.txt\0");
-    ok(!SHFileOperationA(&shfo), "Move file back\n");
+    ok(!SHFileOperationA(&shfo), "Move file back failed\n");
 
     set_curr_dir_path(from, "test4.txt\0");
     set_curr_dir_path(to, "test6.txt\0");
-    ok(!SHFileOperationA(&shfo), "Move dir\n");
-    ok(!file_exists("test4.txt"), "The dir is moved\n");
-    ok(file_exists("test6.txt"), "The dir is moved\n");
+    ok(!SHFileOperationA(&shfo), "Move dir failed\n");
+    ok(!dir_exists("test4.txt"), "The dir is not moved\n");
+    ok(dir_exists("test6.txt"), "The dir is moved\n");
     set_curr_dir_path(from, "test6.txt\0");
     set_curr_dir_path(to, "test4.txt\0");
-    ok(!SHFileOperationA(&shfo), "Move dir back\n");
+    ok(!SHFileOperationA(&shfo), "Move dir back failed\n");
 
     /* move one file to two others */
     init_shfo_tests();
     shfo.pFrom = "test1.txt\0";
     shfo.pTo = "a.txt\0b.txt\0";
     retval = SHFileOperationA(&shfo);
+    if (retval == DE_OPCANCELLED)
+    {
+        /* NT4 fails and doesn't move any files */
+        ok(!file_exists("a.txt"), "Expected a.txt to not exist\n");
+        DeleteFileA("test1.txt");
+    }
+    else
+    {
         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
         ok(!file_exists("test1.txt"), "Expected test1.txt to not exist\n");
         ok(DeleteFile("a.txt"), "Expected a.txt to exist\n");
+    }
     ok(!file_exists("b.txt"), "Expected b.txt to not exist\n");
 
     /* move two files to one other */
     shfo.pFrom = "test2.txt\0test3.txt\0";
     shfo.pTo = "test1.txt\0";
     retval = SHFileOperationA(&shfo);
-        ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
+    if (dir_exists("test1.txt"))
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+        ok(DeleteFileA("test1.txt\\test2.txt"), "Expected test1.txt\\test2.txt to exist\n");
+        ok(DeleteFileA("test1.txt\\test3.txt"), "Expected test1.txt\\test3.txt to exist\n");
+        RemoveDirectoryA("test1.txt");
+        createTestFile("test2.txt");
+        createTestFile("test3.txt");
+    }
+    else
+    {
+        expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
         ok(!file_exists("test1.txt"), "Expected test1.txt to not exist\n");
-    ok(file_exists("test2.txt"), "Expected test2.txt to exist\n");
-    ok(file_exists("test3.txt"), "Expected test3.txt to exist\n");
+        ok(file_exists("test2.txt"), "Expected test2.txt to exist\n");
+        ok(file_exists("test3.txt"), "Expected test3.txt to exist\n");
+    }
 
     /* move a directory into itself */
     shfo.pFrom = "test4.txt\0";
     shfo.pTo = "test4.txt\\b.txt\0";
     retval = SHFileOperationA(&shfo);
-        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+    ok(retval == ERROR_SUCCESS ||
+       retval == DE_DESTSUBTREE, /* Vista */
+       "Expected ERROR_SUCCESS or DE_DESTSUBTREE, got %d\n", retval);
     ok(!RemoveDirectory("test4.txt\\b.txt"), "Expected test4.txt\\b.txt to not exist\n");
-    ok(file_exists("test4.txt"), "Expected test4.txt to exist\n");
+    ok(dir_exists("test4.txt"), "Expected test4.txt to exist\n");
 
     /* move many files without FOF_MULTIDESTFILES */
     shfo.pFrom = "test2.txt\0test3.txt\0";
     shfo.pTo = "d.txt\0e.txt\0";
     retval = SHFileOperationA(&shfo);
-        ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
-    ok(!DeleteFile("d.txt"), "Expected d.txt to not exist\n");
-    ok(!DeleteFile("e.txt"), "Expected e.txt to not exist\n");
+    if (dir_exists("d.txt"))
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+        ok(DeleteFileA("d.txt\\test2.txt"), "Expected d.txt\\test2.txt to exist\n");
+        ok(DeleteFileA("d.txt\\test3.txt"), "Expected d.txt\\test3.txt to exist\n");
+        RemoveDirectoryA("d.txt");
+        createTestFile("test2.txt");
+        createTestFile("test3.txt");
+    }
+    else
+    {
+        expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
+        ok(!DeleteFile("d.txt"), "Expected d.txt to not exist\n");
+        ok(!DeleteFile("e.txt"), "Expected e.txt to not exist\n");
+    }
 
     /* number of sources != number of targets */
     shfo.pTo = "d.txt\0";
     shfo.fFlags |= FOF_MULTIDESTFILES;
     retval = SHFileOperationA(&shfo);
-        ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
-    ok(!DeleteFile("d.txt"), "Expected d.txt to not exist\n");
+    if (dir_exists("d.txt"))
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(retval == DE_SAMEFILE,
+           "Expected DE_SAMEFILE, got %d\n", retval);
+        ok(DeleteFileA("d.txt\\test2.txt"), "Expected d.txt\\test2.txt to exist\n");
+        ok(!file_exists("d.txt\\test3.txt"), "Expected d.txt\\test3.txt to not exist\n");
+        RemoveDirectoryA("d.txt");
+        createTestFile("test2.txt");
+    }
+    else
+    {
+        expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
+        ok(!DeleteFile("d.txt"), "Expected d.txt to not exist\n");
+    }
 
     /* FO_MOVE does not create dest directories */
     shfo.pFrom = "test2.txt\0";
     shfo.pTo = "dir1\\dir2\\test2.txt\0";
     retval = SHFileOperationA(&shfo);
-        ok(retval == ERROR_CANCELLED, "Expected ERROR_CANCELLED, got %d\n", retval);
-    ok(!file_exists("dir1"), "Expected dir1 to not exist\n");
+    if (dir_exists("dir1"))
+    {
+        /* Vista and W2K8 (broken or new behavior ?) */
+        ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
+        ok(DeleteFileA("dir1\\dir2\\test2.txt"), "Expected dir1\\dir2\\test2.txt to exist\n");
+        RemoveDirectoryA("dir1\\dir2");
+        RemoveDirectoryA("dir1");
+        createTestFile("test2.txt");
+    }
+    else
+    {
+        expect_retval(ERROR_CANCELLED, DE_OPCANCELLED /* Win9x, NT4 */);
+    }
 
     /* try to overwrite an existing file */
     shfo.pTo = "test3.txt\0";
     retval = SHFileOperationA(&shfo);
+    if (retval == DE_OPCANCELLED)
+    {
+        /* NT4 fails and doesn't move any files */
+        ok(file_exists("test2.txt"), "Expected test2.txt to exist\n");
+    }
+    else
+    {
         ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
         ok(!file_exists("test2.txt"), "Expected test2.txt to not exist\n");
-    ok(file_exists("test3.txt"), "Expected test3.txt to exist\n");
+        ok(file_exists("test3.txt"), "Expected test3.txt to exist\n");
+    }
 }
 
 static void test_sh_create_dir(void)
@@ -1218,8 +1921,8 @@ static void test_sh_create_dir(void)
 
     if(!pSHCreateDirectoryExA)
     {
-       trace("skipping SHCreateDirectoryExA tests\n");
-       return;
+        win_skip("skipping SHCreateDirectoryExA tests\n");
+        return;
     }
 
     set_curr_dir_path(path, "testdir2\\test4.txt\0");
@@ -1242,8 +1945,8 @@ static void test_sh_path_prepare(void)
 
     if(!pSHPathPrepareForWriteA)
     {
-       trace("skipping SHPathPrepareForWriteA tests\n");
-           return;
+       win_skip("skipping SHPathPrepareForWriteA tests\n");
+       return;
     }
 
     /* directory exists, SHPPFW_NONE */
@@ -1270,16 +1973,22 @@ static void test_sh_path_prepare(void)
     /* file exists, SHPPFW_NONE */
     set_curr_dir_path(path, "test1.txt\0");
     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
-    ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_DIRECTORY)\n", res);
+    ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY) ||
+       res == HRESULT_FROM_WIN32(ERROR_INVALID_NAME), /* Vista */
+       "Unexpected result : 0x%08x\n", res);
 
     /* file exists, SHPPFW_DIRCREATE */
     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_DIRCREATE);
-    ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_DIRECTORY)\n", res);
+    ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY) ||
+       res == HRESULT_FROM_WIN32(ERROR_INVALID_NAME), /* Vista */
+       "Unexpected result : 0x%08x\n", res);
 
     /* file exists, SHPPFW_NONE, trailing \ */
     set_curr_dir_path(path, "test1.txt\\\0");
     res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
-    ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_DIRECTORY)\n", res);
+    ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY) ||
+       res == HRESULT_FROM_WIN32(ERROR_INVALID_NAME), /* Vista */
+       "Unexpected result : 0x%08x\n", res);
 
     /* relative path exists, SHPPFW_DIRCREATE */
     res = pSHPathPrepareForWriteA(0, 0, ".\\testdir2", SHPPFW_DIRCREATE);
@@ -1342,6 +2051,62 @@ static void test_sh_path_prepare(void)
     RemoveDirectoryW(UNICODE_PATH);
 }
 
+static void test_sh_new_link_info(void)
+{
+    BOOL ret, mustcopy=TRUE;
+    CHAR linkto[MAX_PATH];
+    CHAR destdir[MAX_PATH];
+    CHAR result[MAX_PATH];
+    CHAR result2[MAX_PATH];
+
+    /* source file does not exist */
+    set_curr_dir_path(linkto, "nosuchfile.txt\0");
+    set_curr_dir_path(destdir, "testdir2\0");
+    ret = SHGetNewLinkInfoA(linkto, destdir, result, &mustcopy, 0);
+    ok(ret == FALSE ||
+       broken(ret == lstrlenA(result) + 1), /* NT4 */
+       "SHGetNewLinkInfoA succeeded\n");
+    ok(mustcopy == FALSE, "mustcopy should be FALSE\n");
+
+    /* dest dir does not exist */
+    set_curr_dir_path(linkto, "test1.txt\0");
+    set_curr_dir_path(destdir, "nosuchdir\0");
+    ret = SHGetNewLinkInfoA(linkto, destdir, result, &mustcopy, 0);
+    ok(ret == TRUE ||
+       broken(ret == lstrlenA(result) + 1), /* NT4 */
+       "SHGetNewLinkInfoA failed, err=%i\n", GetLastError());
+    ok(mustcopy == FALSE, "mustcopy should be FALSE\n");
+
+    /* source file exists */
+    set_curr_dir_path(linkto, "test1.txt\0");
+    set_curr_dir_path(destdir, "testdir2\0");
+    ret = SHGetNewLinkInfoA(linkto, destdir, result, &mustcopy, 0);
+    ok(ret == TRUE ||
+       broken(ret == lstrlenA(result) + 1), /* NT4 */
+       "SHGetNewLinkInfoA failed, err=%i\n", GetLastError());
+    ok(mustcopy == FALSE, "mustcopy should be FALSE\n");
+    ok(CompareStringA(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, destdir,
+                      lstrlenA(destdir), result, lstrlenA(destdir)) == CSTR_EQUAL,
+       "%s does not start with %s\n", result, destdir);
+    ok(lstrlenA(result) > 4 && lstrcmpiA(result+lstrlenA(result)-4, ".lnk") == 0,
+       "%s does not end with .lnk\n", result);
+
+    /* preferred target name already exists */
+    createTestFile(result);
+    ret = SHGetNewLinkInfoA(linkto, destdir, result2, &mustcopy, 0);
+    ok(ret == TRUE ||
+       broken(ret == lstrlenA(result2) + 1), /* NT4 */
+       "SHGetNewLinkInfoA failed, err=%i\n", GetLastError());
+    ok(mustcopy == FALSE, "mustcopy should be FALSE\n");
+    ok(CompareStringA(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, destdir,
+                      lstrlenA(destdir), result2, lstrlenA(destdir)) == CSTR_EQUAL,
+       "%s does not start with %s\n", result2, destdir);
+    ok(lstrlenA(result2) > 4 && lstrcmpiA(result2+lstrlenA(result2)-4, ".lnk") == 0,
+       "%s does not end with .lnk\n", result2);
+    ok(lstrcmpiA(result, result2) != 0, "%s and %s are the same\n", result, result2);
+    DeleteFileA(result);
+}
+
 static void test_unicode(void)
 {
     SHFILEOPSTRUCTW shfoW;
@@ -1423,6 +2188,7 @@ START_TEST(shlfileop)
 
     init_shfo_tests();
     test_get_file_info();
+    test_get_file_info_iconlist();
     clean_after_shfo_tests();
 
     init_shfo_tests();
@@ -1448,5 +2214,9 @@ START_TEST(shlfileop)
     test_sh_path_prepare();
     clean_after_shfo_tests();
 
+    init_shfo_tests();
+    test_sh_new_link_info();
+    clean_after_shfo_tests();
+
     test_unicode();
 }
index 5c43d38..0536d2e 100644 (file)
@@ -46,6 +46,7 @@ static HRESULT (WINAPI *pSHBindToParent)(LPCITEMIDLIST, REFIID, LPVOID*, LPCITEM
 static HRESULT (WINAPI *pSHGetFolderPathA)(HWND, int, HANDLE, DWORD, LPSTR);
 static HRESULT (WINAPI *pSHGetFolderPathAndSubDirA)(HWND, int, HANDLE, DWORD, LPCSTR, LPSTR);
 static BOOL (WINAPI *pSHGetPathFromIDListW)(LPCITEMIDLIST,LPWSTR);
+static BOOL (WINAPI *pSHGetSpecialFolderPathA)(HWND, LPSTR, int, BOOL);
 static BOOL (WINAPI *pSHGetSpecialFolderPathW)(HWND, LPWSTR, int, BOOL);
 static HRESULT (WINAPI *pStrRetToBufW)(STRRET*,LPCITEMIDLIST,LPWSTR,UINT);
 static LPITEMIDLIST (WINAPI *pILFindLastID)(LPCITEMIDLIST);
@@ -62,6 +63,7 @@ static void init_function_pointers(void)
     pSHGetFolderPathA = (void*)GetProcAddress(hmod, "SHGetFolderPathA");
     pSHGetFolderPathAndSubDirA = (void*)GetProcAddress(hmod, "SHGetFolderPathAndSubDirA");
     pSHGetPathFromIDListW = (void*)GetProcAddress(hmod, "SHGetPathFromIDListW");
+    pSHGetSpecialFolderPathA = (void*)GetProcAddress(hmod, "SHGetSpecialFolderPathA");
     pSHGetSpecialFolderPathW = (void*)GetProcAddress(hmod, "SHGetSpecialFolderPathW");
     pILFindLastID = (void *)GetProcAddress(hmod, (LPCSTR)16);
     pILFree = (void*)GetProcAddress(hmod, (LPSTR)155);
@@ -80,6 +82,8 @@ static void test_ParseDisplayName(void)
     IShellFolder *IDesktopFolder;
     static const char *cNonExistDir1A = "c:\\nonexist_subdir";
     static const char *cNonExistDir2A = "c:\\\\nonexist_subdir";
+    static const char *cInetTestA = "http:\\yyy";
+    static const char *cInetTest2A = "xx:yyy";
     DWORD res;
     WCHAR cTestDirW [MAX_PATH] = {0};
     ITEMIDLIST *newPIDL;
@@ -88,6 +92,30 @@ static void test_ParseDisplayName(void)
     hr = SHGetDesktopFolder(&IDesktopFolder);
     if(hr != S_OK) return;
 
+    MultiByteToWideChar(CP_ACP, 0, cInetTestA, -1, cTestDirW, MAX_PATH);
+    hr = IShellFolder_ParseDisplayName(IDesktopFolder,
+        NULL, NULL, cTestDirW, NULL, &newPIDL, 0);
+    todo_wine ok((SUCCEEDED(hr) || broken(hr == E_FAIL) /* NT4 */),
+        "ParseDisplayName returned %08x, expected SUCCESS or E_FAIL\n", hr);
+    if (SUCCEEDED(hr))
+    {
+        ok(pILFindLastID(newPIDL)->mkid.abID[0] == 0x61, "Last pidl should be of type "
+           "PT_IESPECIAL1, but is: %02x\n", pILFindLastID(newPIDL)->mkid.abID[0]);
+        IMalloc_Free(ppM, newPIDL);
+    }
+
+    MultiByteToWideChar(CP_ACP, 0, cInetTest2A, -1, cTestDirW, MAX_PATH);
+    hr = IShellFolder_ParseDisplayName(IDesktopFolder,
+        NULL, NULL, cTestDirW, NULL, &newPIDL, 0);
+    todo_wine ok((SUCCEEDED(hr) || broken(hr == E_FAIL) /* NT4 */),
+        "ParseDisplayName returned %08x, expected SUCCESS or E_FAIL\n", hr);
+    if (SUCCEEDED(hr))
+    {
+        ok(pILFindLastID(newPIDL)->mkid.abID[0] == 0x61, "Last pidl should be of type "
+           "PT_IESPECIAL1, but is: %02x\n", pILFindLastID(newPIDL)->mkid.abID[0]);
+        IMalloc_Free(ppM, newPIDL);
+    }
+
     res = GetFileAttributesA(cNonExistDir1A);
     if(res != INVALID_FILE_ATTRIBUTES) return;
 
@@ -119,8 +147,10 @@ static void test_ParseDisplayName(void)
     ok(SUCCEEDED(hr), "DesktopFolder->ParseDisplayName failed. hr = %08x.\n", hr);
     if (FAILED(hr)) goto finished;
 
-    ok(pILFindLastID(newPIDL)->mkid.abID[0] == 0x31, "Last pidl should be of type "
-       "PT_FOLDER, but is: %02x\n", pILFindLastID(newPIDL)->mkid.abID[0]);
+    ok(pILFindLastID(newPIDL)->mkid.abID[0] == 0x31 ||
+       pILFindLastID(newPIDL)->mkid.abID[0] == 0xb1, /* Win98 */
+       "Last pidl should be of type PT_FOLDER or PT_IESPECIAL2, but is: %02x\n",
+       pILFindLastID(newPIDL)->mkid.abID[0]);
     IMalloc_Free(ppM, newPIDL);
     
 finished:
@@ -235,13 +265,17 @@ static void test_EnumObjects(IShellFolder *iFolder)
         hr = IShellFolder_GetAttributesOf(iFolder, 1, (LPCITEMIDLIST*)(idlArr + i), &flags);
         flags &= SFGAO_testfor;
         ok(hr == S_OK, "GetAttributesOf returns %08x\n", hr);
-        ok(flags == (attrs[i]), "GetAttributesOf[%i] got %08x, expected %08x\n", i, flags, attrs[i]);
+        ok(flags == (attrs[i]) ||
+           flags == (attrs[i] & ~SFGAO_FILESYSANCESTOR), /* Win9x, NT4 */
+           "GetAttributesOf[%i] got %08x, expected %08x\n", i, flags, attrs[i]);
 
         flags = SFGAO_testfor;
         hr = IShellFolder_GetAttributesOf(iFolder, 1, (LPCITEMIDLIST*)(idlArr + i), &flags);
         flags &= SFGAO_testfor;
         ok(hr == S_OK, "GetAttributesOf returns %08x\n", hr);
-        ok(flags == attrs[i], "GetAttributesOf[%i] got %08x, expected %08x\n", i, flags, attrs[i]);
+        ok(flags == attrs[i] ||
+           flags == (attrs[i] & ~SFGAO_FILESYSANCESTOR), /* Win9x, NT4 */
+           "GetAttributesOf[%i] got %08x, expected %08x\n", i, flags, attrs[i]);
     }
 
     for (i=0;i<5;i++)
@@ -356,7 +390,7 @@ static void test_GetDisplayName(void)
     BOOL result;
     HRESULT hr;
     HANDLE hTestFile;
-    WCHAR wszTestFile[MAX_PATH], wszTestFile2[MAX_PATH], wszTestDir[MAX_PATH];
+    WCHAR wszTestFile[MAX_PATH], wszTestFile2[MAX_PATH];
     char szTestFile[MAX_PATH], szTestDir[MAX_PATH];
     DWORD attr;
     STRRET strret;
@@ -365,6 +399,7 @@ static void test_GetDisplayName(void)
     SHITEMID emptyitem = { 0, { 0 } };
     LPITEMIDLIST pidlTestFile, pidlEmpty = (LPITEMIDLIST)&emptyitem;
     LPCITEMIDLIST pidlLast;
+    static const CHAR szFileName[] = "winetest.foo";
     static const WCHAR wszFileName[] = { 'w','i','n','e','t','e','s','t','.','f','o','o',0 };
     static const WCHAR wszDirName[] = { 'w','i','n','e','t','e','s','t',0 };
 
@@ -376,17 +411,18 @@ static void test_GetDisplayName(void)
      * no functional difference in this respect.
      */
 
-    if(!pSHGetSpecialFolderPathW) return;
+    if(!pSHGetSpecialFolderPathA) {
+        win_skip("SHGetSpecialFolderPathA is not available\n");
+        return;
+    }
 
     /* First creating a directory in MyDocuments and a file in this directory. */
-    result = pSHGetSpecialFolderPathW(NULL, wszTestDir, CSIDL_PERSONAL, FALSE);
-    ok(result, "SHGetSpecialFolderPathW failed! Last error: %u\n", GetLastError());
+    result = pSHGetSpecialFolderPathA(NULL, szTestDir, CSIDL_PERSONAL, FALSE);
+    ok(result, "SHGetSpecialFolderPathA failed! Last error: %u\n", GetLastError());
     if (!result) return;
 
-    myPathAddBackslashW(wszTestDir);
-    lstrcatW(wszTestDir, wszDirName);
     /* Use ANSI file functions so this works on Windows 9x */
-    WideCharToMultiByte(CP_ACP, 0, wszTestDir, -1, szTestDir, MAX_PATH, 0, 0);
+    lstrcatA(szTestDir, "\\winetest");
     CreateDirectoryA(szTestDir, NULL);
     attr=GetFileAttributesA(szTestDir);
     if (attr == INVALID_FILE_ATTRIBUTES || !(attr & FILE_ATTRIBUTE_DIRECTORY))
@@ -395,11 +431,9 @@ static void test_GetDisplayName(void)
         return;
     }
 
-    lstrcpyW(wszTestFile, wszTestDir);
-    myPathAddBackslashW(wszTestFile);
-    lstrcatW(wszTestFile, wszFileName);
-    WideCharToMultiByte(CP_ACP, 0, wszTestFile, -1, szTestFile, MAX_PATH, 0, 0);
-
+    lstrcpyA(szTestFile, szTestDir);
+    lstrcatA(szTestFile, "\\");
+    lstrcatA(szTestFile, szFileName);
     hTestFile = CreateFileA(szTestFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
     ok((hTestFile != INVALID_HANDLE_VALUE), "CreateFileA failed! Last error: %u\n", GetLastError());
     if (hTestFile == INVALID_HANDLE_VALUE) return;
@@ -410,6 +444,8 @@ static void test_GetDisplayName(void)
     ok(SUCCEEDED(hr), "SHGetDesktopFolder failed! hr = %08x\n", hr);
     if (FAILED(hr)) return;
 
+    MultiByteToWideChar(CP_ACP, 0, szTestFile, -1, wszTestFile, MAX_PATH);
+
     hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, wszTestFile, NULL, &pidlTestFile, NULL);
     ok(SUCCEEDED(hr), "Desktop->ParseDisplayName failed! hr = %08x\n", hr);
     if (FAILED(hr)) {
@@ -417,50 +453,77 @@ static void test_GetDisplayName(void)
         return;
     }
 
-    /* WinXP stores the filenames as both ANSI and UNICODE in the pidls */
     pidlLast = pILFindLastID(pidlTestFile);
-    ok(pidlLast->mkid.cb >=76, "Expected pidl length of at least 76, got %d.\n", pidlLast->mkid.cb);
+    ok(pidlLast->mkid.cb >=76 ||
+        broken(pidlLast->mkid.cb == 28) || /* W2K */
+        broken(pidlLast->mkid.cb == 40), /* Win9x, WinME */
+        "Expected pidl length of at least 76, got %d.\n", pidlLast->mkid.cb);
+    if (pidlLast->mkid.cb >= 28) {
+        ok(!lstrcmpA((CHAR*)&pidlLast->mkid.abID[12], szFileName),
+            "Filename should be stored as ansi-string at this position!\n");
+    }
+    /* WinXP and up store the filenames as both ANSI and UNICODE in the pidls */
     if (pidlLast->mkid.cb >= 76) {
         ok(!lstrcmpW((WCHAR*)&pidlLast->mkid.abID[46], wszFileName),
-            "WinXP stores the filename as a wchar-string at this position!\n");
+            "Filename should be stored as wchar-string at this position!\n");
     }
     
     /* It seems as if we cannot bind to regular files on windows, but only directories. 
      */
     hr = IShellFolder_BindToObject(psfDesktop, pidlTestFile, NULL, &IID_IUnknown, (VOID**)&psfFile);
-    todo_wine { ok (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "hr = %08x\n", hr); }
+    todo_wine
+    ok (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) ||
+        broken(SUCCEEDED(hr)), /* Win9x, W2K */
+        "hr = %08x\n", hr);
     if (SUCCEEDED(hr)) {
         IShellFolder_Release(psfFile);
     }
+
+    if (!pSHBindToParent)
+    {
+        win_skip("SHBindToParent is missing\n");
+        DeleteFileA(szTestFile);
+        RemoveDirectoryA(szTestDir);
+        return;
+    }
   
     /* Some tests for IShellFolder::SetNameOf */
-    hr = pSHBindToParent(pidlTestFile, &IID_IShellFolder, (VOID**)&psfPersonal, &pidlLast);
-    ok(SUCCEEDED(hr), "SHBindToParent failed! hr = %08x\n", hr);
-    if (SUCCEEDED(hr)) {
-        /* It's ok to use this fixed path. Call will fail anyway. */
-        WCHAR wszAbsoluteFilename[] = { 'C',':','\\','w','i','n','e','t','e','s','t', 0 };
-        LPITEMIDLIST pidlNew;
-
-        /* The pidl returned through the last parameter of SetNameOf is a simple one. */
-        hr = IShellFolder_SetNameOf(psfPersonal, NULL, pidlLast, wszDirName, SHGDN_NORMAL, &pidlNew);
-        ok (SUCCEEDED(hr), "SetNameOf failed! hr = %08x\n", hr);
-        ok (((LPITEMIDLIST)((LPBYTE)pidlNew+pidlNew->mkid.cb))->mkid.cb == 0, 
-            "pidl returned from SetNameOf should be simple!\n");
-
-        /* Passing an absolute path to SetNameOf fails. The HRESULT code indicates that SetNameOf
-         * is implemented on top of SHFileOperation in WinXP. */
-        hr = IShellFolder_SetNameOf(psfPersonal, NULL, pidlNew, wszAbsoluteFilename, 
-                SHGDN_FORPARSING, NULL);
-        ok (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED), "SetNameOf succeeded! hr = %08x\n", hr);
-
-        /* Rename the file back to its original name. SetNameOf ignores the fact, that the
-         * SHGDN flags specify an absolute path. */
-        hr = IShellFolder_SetNameOf(psfPersonal, NULL, pidlNew, wszFileName, SHGDN_FORPARSING, NULL);
-        ok (SUCCEEDED(hr), "SetNameOf failed! hr = %08x\n", hr);
-
-        pILFree(pidlNew);
-        IShellFolder_Release(psfPersonal);
+    if (pSHGetFolderPathAndSubDirA)
+    {
+        hr = pSHBindToParent(pidlTestFile, &IID_IShellFolder, (VOID**)&psfPersonal, &pidlLast);
+        ok(SUCCEEDED(hr), "SHBindToParent failed! hr = %08x\n", hr);
+        if (SUCCEEDED(hr)) {
+            /* It's ok to use this fixed path. Call will fail anyway. */
+            WCHAR wszAbsoluteFilename[] = { 'C',':','\\','w','i','n','e','t','e','s','t', 0 };
+            LPITEMIDLIST pidlNew;
+
+            /* The pidl returned through the last parameter of SetNameOf is a simple one. */
+            hr = IShellFolder_SetNameOf(psfPersonal, NULL, pidlLast, wszDirName, SHGDN_NORMAL, &pidlNew);
+            ok (SUCCEEDED(hr), "SetNameOf failed! hr = %08x\n", hr);
+            if (hr == S_OK)
+            {
+                ok (((LPITEMIDLIST)((LPBYTE)pidlNew+pidlNew->mkid.cb))->mkid.cb == 0,
+                    "pidl returned from SetNameOf should be simple!\n");
+
+                /* Passing an absolute path to SetNameOf fails. The HRESULT code indicates that SetNameOf
+                 * is implemented on top of SHFileOperation in WinXP. */
+                hr = IShellFolder_SetNameOf(psfPersonal, NULL, pidlNew, wszAbsoluteFilename,
+                        SHGDN_FORPARSING, NULL);
+                ok (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED), "SetNameOf succeeded! hr = %08x\n", hr);
+
+                /* Rename the file back to its original name. SetNameOf ignores the fact, that the
+                 * SHGDN flags specify an absolute path. */
+                hr = IShellFolder_SetNameOf(psfPersonal, NULL, pidlNew, wszFileName, SHGDN_FORPARSING, NULL);
+                ok (SUCCEEDED(hr), "SetNameOf failed! hr = %08x\n", hr);
+
+                pILFree(pidlNew);
+            }
+
+            IShellFolder_Release(psfPersonal);
+        }
     }
+    else
+        win_skip("Avoid needs of interaction on Win2k\n");
 
     /* Deleting the file and the directory */
     DeleteFileA(szTestFile);
@@ -474,8 +537,6 @@ static void test_GetDisplayName(void)
         ok (!lstrcmpiW(wszTestFile, wszTestFile2), "SHGetPathFromIDListW returns incorrect path!\n");
     }
 
-    if(!pSHBindToParent) return;
-
     /* SHBindToParent fails, if called with a NULL PIDL. */
     hr = pSHBindToParent(NULL, &IID_IShellFolder, (VOID**)&psfPersonal, &pidlLast);
     ok (FAILED(hr), "SHBindToParent(NULL) should fail!\n");
@@ -554,7 +615,8 @@ static void test_CallForAttributes(void)
     
     hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, wszMyDocuments, NULL, 
                                        &pidlMyDocuments, NULL);
-    ok (SUCCEEDED(hr), 
+    ok (SUCCEEDED(hr) ||
+        broken(hr == E_INVALIDARG), /* Win95, NT4 */
         "Desktop's ParseDisplayName failed to parse MyDocuments's CLSID! hr = %08x\n", hr);
     if (FAILED(hr)) {
         IShellFolder_Release(psfDesktop);
@@ -645,22 +707,41 @@ static void test_GetAttributesOf(void)
     LPCITEMIDLIST pidlEmpty = (LPCITEMIDLIST)&emptyitem;
     LPITEMIDLIST pidlMyComputer;
     DWORD dwFlags;
-    static const DWORD dwDesktopFlags = /* As observed on WinXP SP2 */
-        SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR |
-        SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER;
-    static const DWORD dwMyComputerFlags = /* As observed on WinXP SP2 */
-        SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET |
-        SFGAO_DROPTARGET | SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
+    static const DWORD desktopFlags[] = {
+        /* WinXP */
+        SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR | SFGAO_FILESYSANCESTOR |
+        SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER,
+        /* Win2k */
+        SFGAO_CANRENAME | SFGAO_HASPROPSHEET | SFGAO_STREAM | SFGAO_FILESYSANCESTOR |
+        SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER,
+        /* WinMe, Win9x, WinNT*/
+        SFGAO_CANRENAME | SFGAO_HASPROPSHEET | SFGAO_FILESYSANCESTOR |
+        SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER
+    };
+    static const DWORD myComputerFlags[] = {
+        /* WinXP */
+        SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET | SFGAO_DROPTARGET |
+        SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER,
+        /* Win2k */
+        SFGAO_CANRENAME | SFGAO_HASPROPSHEET | SFGAO_DROPTARGET | SFGAO_STREAM |
+        SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER,
+        /* WinMe, Win9x, WinNT */
+        SFGAO_CANRENAME | SFGAO_HASPROPSHEET | SFGAO_DROPTARGET | SFGAO_FILESYSANCESTOR |
+        SFGAO_FOLDER | SFGAO_HASSUBFOLDER,
+        /* Win95, WinNT when queried directly */
+        SFGAO_CANLINK | SFGAO_HASPROPSHEET | SFGAO_DROPTARGET | SFGAO_FILESYSANCESTOR |
+        SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER
+    };
     WCHAR wszMyComputer[] = { 
         ':',':','{','2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-',
         'A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D','}',0 };
     char  cCurrDirA [MAX_PATH] = {0};
     WCHAR cCurrDirW [MAX_PATH];
     static WCHAR cTestDirW[] = {'t','e','s','t','d','i','r',0};
-    static const WCHAR cBackSlash[] = {'\\',0};
     IShellFolder *IDesktopFolder, *testIShellFolder;
     ITEMIDLIST *newPIDL;
-    int len;
+    int len, i;
+    BOOL foundFlagsMatch;
 
     hr = SHGetDesktopFolder(&psfDesktop);
     ok (SUCCEEDED(hr), "SHGetDesktopFolder failed! hr = %08x\n", hr);
@@ -670,15 +751,25 @@ static void test_GetAttributesOf(void)
     dwFlags = 0xffffffff;
     hr = IShellFolder_GetAttributesOf(psfDesktop, 1, &pidlEmpty, &dwFlags);
     ok (SUCCEEDED(hr), "Desktop->GetAttributesOf(empty pidl) failed! hr = %08x\n", hr);
-    ok (dwFlags == dwDesktopFlags, "Wrong Desktop attributes: %08x, expected: %08x\n", 
-        dwFlags, dwDesktopFlags);
+    for (i = 0, foundFlagsMatch = FALSE; !foundFlagsMatch &&
+         i < sizeof(desktopFlags) / sizeof(desktopFlags[0]); i++)
+    {
+        if (desktopFlags[i] == dwFlags)
+            foundFlagsMatch = TRUE;
+    }
+    ok (foundFlagsMatch, "Wrong Desktop attributes: %08x\n", dwFlags);
 
     /* .. or with no itemidlist at all. */
     dwFlags = 0xffffffff;
     hr = IShellFolder_GetAttributesOf(psfDesktop, 0, NULL, &dwFlags);
     ok (SUCCEEDED(hr), "Desktop->GetAttributesOf(NULL) failed! hr = %08x\n", hr);
-    ok (dwFlags == dwDesktopFlags, "Wrong Desktop attributes: %08x, expected: %08x\n", 
-        dwFlags, dwDesktopFlags);
+    for (i = 0, foundFlagsMatch = FALSE; !foundFlagsMatch &&
+         i < sizeof(desktopFlags) / sizeof(desktopFlags[0]); i++)
+    {
+        if (desktopFlags[i] == dwFlags)
+            foundFlagsMatch = TRUE;
+    }
+    ok (foundFlagsMatch, "Wrong Desktop attributes: %08x\n", dwFlags);
    
     /* Testing the attributes of the MyComputer shellfolder */
     hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL, wszMyComputer, NULL, &pidlMyComputer, NULL);
@@ -688,18 +779,20 @@ static void test_GetAttributesOf(void)
         return;
     }
 
-    /* WinXP SP2 sets the SFGAO_CANLINK flag, when MyComputer is queried via the Desktop 
+    /* Windows sets the SFGAO_CANLINK flag, when MyComputer is queried via the Desktop
      * folder object. It doesn't do this, if MyComputer is queried directly (see below).
-     * SFGAO_CANLINK is the same as DROPEFFECT_LINK, which MSDN says means: "Drag source
-     * should create a link to the original data". You can't create links on MyComputer on
-     * Windows, so this flag shouldn't be set. Seems like a bug in Windows. As long as nobody
-     * depends on this bug, we probably shouldn't imitate it.
      */
     dwFlags = 0xffffffff;
     hr = IShellFolder_GetAttributesOf(psfDesktop, 1, (LPCITEMIDLIST*)&pidlMyComputer, &dwFlags);
     ok (SUCCEEDED(hr), "Desktop->GetAttributesOf(MyComputer) failed! hr = %08x\n", hr);
-    ok ((dwFlags & ~(DWORD)SFGAO_CANLINK) == dwMyComputerFlags, 
-                    "Wrong MyComputer attributes: %08x, expected: %08x\n", dwFlags, dwMyComputerFlags);
+    for (i = 0, foundFlagsMatch = FALSE; !foundFlagsMatch &&
+         i < sizeof(myComputerFlags) / sizeof(myComputerFlags[0]); i++)
+    {
+        if ((myComputerFlags[i] | SFGAO_CANLINK) == dwFlags)
+            foundFlagsMatch = TRUE;
+    }
+    todo_wine
+    ok (foundFlagsMatch, "Wrong MyComputer attributes: %08x\n", dwFlags);
 
     hr = IShellFolder_BindToObject(psfDesktop, pidlMyComputer, NULL, &IID_IShellFolder, (LPVOID*)&psfMyComputer);
     ok (SUCCEEDED(hr), "Desktop failed to bind to MyComputer object! hr = %08x\n", hr);
@@ -708,28 +801,37 @@ static void test_GetAttributesOf(void)
     if (FAILED(hr)) return;
 
     hr = IShellFolder_GetAttributesOf(psfMyComputer, 1, &pidlEmpty, &dwFlags);
-    todo_wine {ok (hr == E_INVALIDARG, "MyComputer->GetAttributesOf(emtpy pidl) should fail! hr = %08x\n", hr); }
+    todo_wine
+    ok (hr == E_INVALIDARG ||
+        broken(SUCCEEDED(hr)), /* W2K and earlier */
+        "MyComputer->GetAttributesOf(emtpy pidl) should fail! hr = %08x\n", hr);
 
     dwFlags = 0xffffffff;
     hr = IShellFolder_GetAttributesOf(psfMyComputer, 0, NULL, &dwFlags);
     ok (SUCCEEDED(hr), "MyComputer->GetAttributesOf(NULL) failed! hr = %08x\n", hr); 
-    todo_wine { ok (dwFlags == dwMyComputerFlags, 
-                    "Wrong MyComputer attributes: %08x, expected: %08x\n", dwFlags, dwMyComputerFlags); }
+    for (i = 0, foundFlagsMatch = FALSE; !foundFlagsMatch &&
+         i < sizeof(myComputerFlags) / sizeof(myComputerFlags[0]); i++)
+    {
+        if (myComputerFlags[i] == dwFlags)
+            foundFlagsMatch = TRUE;
+    }
+    todo_wine
+    ok (foundFlagsMatch, "Wrong MyComputer attributes: %08x\n", dwFlags);
 
     IShellFolder_Release(psfMyComputer);
 
-    /* create test directory */
-    CreateFilesFolders();
-
     GetCurrentDirectoryA(MAX_PATH, cCurrDirA);
     len = lstrlenA(cCurrDirA);
 
     if (len == 0) {
-       trace("GetCurrentDirectoryA returned empty string. Skipping test_EnumObjects_and_CompareIDs\n");
-       return;
+        win_skip("GetCurrentDirectoryA returned empty string. Skipping test_GetAttributesOf\n");
+        return;
     }
-    if(cCurrDirA[len-1] == '\\')
-       cCurrDirA[len-1] = 0;
+    if (len > 3 && cCurrDirA[len-1] == '\\')
+        cCurrDirA[len-1] = 0;
+
+    /* create test directory */
+    CreateFilesFolders();
 
     MultiByteToWideChar(CP_ACP, 0, cCurrDirA, -1, cCurrDirW, MAX_PATH);
  
@@ -758,8 +860,10 @@ static void test_GetAttributesOf(void)
     IMalloc_Free(ppM, newPIDL);
 
     /* append testdirectory name to path */
-    lstrcatW(cCurrDirW, cBackSlash);
-    lstrcatW(cCurrDirW, cTestDirW);
+    if (cCurrDirA[len-1] == '\\')
+        cCurrDirA[len-1] = 0;
+    lstrcatA(cCurrDirA, "\\testdir");
+    MultiByteToWideChar(CP_ACP, 0, cCurrDirA, -1, cCurrDirW, MAX_PATH);
 
     hr = IShellFolder_ParseDisplayName(IDesktopFolder, NULL, NULL, cCurrDirW, NULL, &newPIDL, 0);
     ok(hr == S_OK, "ParseDisplayName failed %08x\n", hr);
@@ -769,7 +873,7 @@ static void test_GetAttributesOf(void)
     hr = IShellFolder_GetAttributesOf(IDesktopFolder, 1, (LPCITEMIDLIST*)&newPIDL, &dwFlags);
     ok (SUCCEEDED(hr), "Desktop->GetAttributesOf() failed! hr = %08x\n", hr);
     ok ((dwFlags&SFGAO_FOLDER), "Wrong directory attribute for absolute PIDL: %08x\n", dwFlags);
-        
+
     /* free memory */
     IMalloc_Free(ppM, newPIDL);
 
@@ -778,7 +882,7 @@ static void test_GetAttributesOf(void)
     Cleanup();
 
     IShellFolder_Release(IDesktopFolder);
-}    
+}
 
 static void test_SHGetPathFromIDList(void)
 {
@@ -804,7 +908,7 @@ static void test_SHGetPathFromIDList(void)
 
     if(!pSHGetPathFromIDListW || !pSHGetSpecialFolderPathW)
     {
-        skip("SHGetPathFromIDListW() or SHGetSpecialFolderPathW() is missing\n");
+        win_skip("SHGetPathFromIDListW() or SHGetSpecialFolderPathW() is missing\n");
         return;
     }
 
@@ -819,7 +923,16 @@ static void test_SHGetPathFromIDList(void)
     result = pSHGetSpecialFolderPathW(NULL, wszDesktop, CSIDL_DESKTOP, FALSE);
     ok(result, "SHGetSpecialFolderPathW(CSIDL_DESKTOP) failed! Last error: %u\n", GetLastError());
     if (!result) return;
-    
+
+    /* Check if we are on Win9x */
+    SetLastError(0xdeadbeef);
+    lstrcmpiW(wszDesktop, wszDesktop);
+    if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+    {
+        win_skip("Most W-calls are not implemented\n");
+        return;
+    }
+
     result = pSHGetPathFromIDListW(pidlEmpty, wszPath);
     ok(result, "SHGetPathFromIDListW failed! Last error: %u\n", GetLastError());
     if (!result) return;
@@ -919,8 +1032,8 @@ static void test_EnumObjects_and_CompareIDs(void)
     ITEMIDLIST *newPIDL;
     IShellFolder *IDesktopFolder, *testIShellFolder;
     char  cCurrDirA [MAX_PATH] = {0};
-    WCHAR cCurrDirW [MAX_PATH];
-    static const WCHAR cTestDirW[] = {'\\','t','e','s','t','d','i','r',0};
+    static const CHAR cTestDirA[] = "\\testdir";
+    WCHAR cTestDirW[MAX_PATH];
     int len;
     HRESULT hr;
 
@@ -928,21 +1041,21 @@ static void test_EnumObjects_and_CompareIDs(void)
     len = lstrlenA(cCurrDirA);
 
     if(len == 0) {
-        trace("GetCurrentDirectoryA returned empty string. Skipping test_EnumObjects_and_CompareIDs\n");
+        win_skip("GetCurrentDirectoryA returned empty string. Skipping test_EnumObjects_and_CompareIDs\n");
         return;
     }
     if(cCurrDirA[len-1] == '\\')
         cCurrDirA[len-1] = 0;
 
-    MultiByteToWideChar(CP_ACP, 0, cCurrDirA, -1, cCurrDirW, MAX_PATH);
-    lstrcatW(cCurrDirW, cTestDirW);
+    lstrcatA(cCurrDirA, cTestDirA);
+    MultiByteToWideChar(CP_ACP, 0, cCurrDirA, -1, cTestDirW, MAX_PATH);
 
     hr = SHGetDesktopFolder(&IDesktopFolder);
     ok(hr == S_OK, "SHGetDesktopfolder failed %08x\n", hr);
 
     CreateFilesFolders();
 
-    hr = IShellFolder_ParseDisplayName(IDesktopFolder, NULL, NULL, cCurrDirW, NULL, &newPIDL, 0);
+    hr = IShellFolder_ParseDisplayName(IDesktopFolder, NULL, NULL, cTestDirW, NULL, &newPIDL, 0);
     ok(hr == S_OK, "ParseDisplayName failed %08x\n", hr);
 
     hr = IShellFolder_BindToObject(IDesktopFolder, newPIDL, NULL, (REFIID)&IID_IShellFolder, (LPVOID *)&testIShellFolder);
@@ -1000,7 +1113,9 @@ static HRESULT WINAPI InitPropertyBag_IPropertyBag_Read(IPropertyBag *iface, LPC
         'R','e','s','o','l','v','e','L','i','n','k','F','l','a','g','s',0 };
        
     if (!lstrcmpW(pszPropName, wszTargetSpecialFolder)) {
-        ok(V_VT(pVar) == VT_I4, "Wrong variant type for 'TargetSpecialFolder' property!\n");
+        ok(V_VT(pVar) == VT_I4 ||
+           broken(V_VT(pVar) == VT_BSTR),   /* Win2k */
+           "Wrong variant type for 'TargetSpecialFolder' property!\n");
         return E_INVALIDARG;
     }
     
@@ -1014,7 +1129,9 @@ static HRESULT WINAPI InitPropertyBag_IPropertyBag_Read(IPropertyBag *iface, LPC
         WCHAR wszPath[MAX_PATH];
         BOOL result;
         
-        ok(V_VT(pVar) == VT_BSTR, "Wrong variant type for 'Target' property!\n");
+        ok(V_VT(pVar) == VT_BSTR ||
+           broken(V_VT(pVar) == VT_EMPTY),  /* Win2k */
+           "Wrong variant type for 'Target' property!\n");
         if (V_VT(pVar) != VT_BSTR) return E_INVALIDARG;
 
         result = pSHGetSpecialFolderPathW(NULL, wszPath, CSIDL_DESKTOPDIRECTORY, FALSE);
@@ -1082,14 +1199,27 @@ static void test_FolderShortcut(void) {
     static const GUID CLSID_UnixDosFolder = 
         {0x9d20aae8, 0x0625, 0x44b0, {0x9c, 0xa7, 0x71, 0x88, 0x9c, 0x22, 0x54, 0xd9}};
 
-    if (!pSHGetSpecialFolderPathW || !pStrRetToBufW) return;
-   
+    if (!pSHGetSpecialFolderPathW || !pStrRetToBufW) {
+        win_skip("SHGetSpecialFolderPathW and/or StrRetToBufW are not available\n");
+        return;
+    }
+
+    if (!pSHGetFolderPathAndSubDirA)
+    {
+        win_skip("FolderShortcut test doesn't work on Win2k\n");
+        return;
+    }
+
     /* These tests basically show, that CLSID_FolderShortcuts are initialized
      * via their IPersistPropertyBag interface. And that the target folder
      * is taken from the IPropertyBag's 'Target' property.
      */
     hr = CoCreateInstance(&CLSID_FolderShortcut, NULL, CLSCTX_INPROC_SERVER, 
                           &IID_IPersistPropertyBag, (LPVOID*)&pPersistPropertyBag);
+    if (hr == REGDB_E_CLASSNOTREG) {
+        win_skip("CLSID_FolderShortcut is not implemented\n");
+        return;
+    }
     ok (SUCCEEDED(hr), "CoCreateInstance failed! hr = 0x%08x\n", hr);
     if (FAILED(hr)) return;
 
@@ -1099,7 +1229,7 @@ static void test_FolderShortcut(void) {
         IPersistPropertyBag_Release(pPersistPropertyBag);
         return;
     }
-    
+
     hr = IPersistPropertyBag_QueryInterface(pPersistPropertyBag, &IID_IShellFolder, 
                                             (LPVOID*)&pShellFolder);
     IPersistPropertyBag_Release(pPersistPropertyBag);
@@ -1253,17 +1383,22 @@ static void test_ITEMIDLIST_format(void) {
     HANDLE hFile;
     HRESULT hr;
     BOOL bResult;
-    WCHAR wszFile[3][17] = { { 'e','v','e','n','_',0 }, { 'o','d','d','_',0 }, 
+    WCHAR wszFile[3][17] = { { 'e','v','e','n','_',0 }, { 'o','d','d','_',0 },
         { 'l','o','n','g','e','r','_','t','h','a','n','.','8','_','3',0 } };
     int i;
-    
-    if(!pSHGetSpecialFolderPathW) return;
+
+    if (!pSHGetSpecialFolderPathW) return;
 
     bResult = pSHGetSpecialFolderPathW(NULL, wszPersonal, CSIDL_PERSONAL, FALSE);
     ok(bResult, "SHGetSpecialFolderPathW failed! Last error: %u\n", GetLastError());
     if (!bResult) return;
 
+    SetLastError(0xdeadbeef);
     bResult = SetCurrentDirectoryW(wszPersonal);
+    if (!bResult && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
+        win_skip("Most W-calls are not implemented\n");
+        return;
+    }
     ok(bResult, "SetCurrentDirectory failed! Last error: %u\n", GetLastError());
     if (!bResult) return;
 
@@ -1289,9 +1424,9 @@ static void test_ITEMIDLIST_format(void) {
         CHAR szFile[MAX_PATH];
         struct FileStructA *pFileStructA;
         WORD cbOffset;
-        
+
         WideCharToMultiByte(CP_ACP, 0, wszFile[i], -1, szFile, MAX_PATH, NULL, NULL);
-        
+
         hFile = CreateFileW(wszFile[i], GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_FLAG_WRITE_THROUGH, NULL);
         ok(hFile != INVALID_HANDLE_VALUE, "CreateFile failed! (%u)\n", GetLastError());
         if (hFile == INVALID_HANDLE_VALUE) {
@@ -1311,56 +1446,63 @@ static void test_ITEMIDLIST_format(void) {
         pFileStructA = (struct FileStructA *)pidlFile->mkid.abID;
         ok(pFileStructA->type == 0x32, "PIDLTYPE should be 0x32!\n");
         ok(pFileStructA->dummy == 0x00, "Dummy Byte should be 0x00!\n");
-        ok(pFileStructA->dwFileSize == 0, "Filesize should be zero!\n"); 
+        ok(pFileStructA->dwFileSize == 0, "Filesize should be zero!\n");
 
-        if (i < 2) /* First two file names are already in valid 8.3 format */ 
+        if (i < 2) /* First two file names are already in valid 8.3 format */
             ok(!strcmp(szFile, (CHAR*)&pidlFile->mkid.abID[12]), "Wrong file name!\n");
-        else 
+        else
             /* WinXP stores a derived 8.3 dos name (LONGER~1.8_3) here. We probably
              * can't implement this correctly, since unix filesystems don't support
              * this nasty short/long filename stuff. So we'll probably stay with our
              * current habbit of storing the long filename here, which seems to work
              * just fine. */
-            todo_wine { ok(pidlFile->mkid.abID[18] == '~', "Should be derived 8.3 name!\n"); }
+            todo_wine
+            ok(pidlFile->mkid.abID[18] == '~' ||
+               broken(pidlFile->mkid.abID[34] == '~'),  /* Win2k */
+               "Should be derived 8.3 name!\n");
 
         if (i == 0) /* First file name has an even number of chars. No need for alignment. */
-            ok(pidlFile->mkid.abID[12 + strlen(szFile) + 1] != '\0', 
-                "Alignment byte, where there shouldn't be!\n"); 
-        
+            ok(pidlFile->mkid.abID[12 + strlen(szFile) + 1] != '\0' ||
+               broken(pidlFile->mkid.cb == 2 + 12 + strlen(szFile) + 1 + 1),    /* Win2k */
+                "Alignment byte, where there shouldn't be!\n");
+
         if (i == 1) /* Second file name has an uneven number of chars => alignment byte */
-            ok(pidlFile->mkid.abID[12 + strlen(szFile) + 1] == '\0', 
+            ok(pidlFile->mkid.abID[12 + strlen(szFile) + 1] == '\0',
                 "There should be an alignment byte, but isn't!\n");
 
         /* The offset of the FileStructW member is stored as a WORD at the end of the pidl. */
         cbOffset = *(WORD*)(((LPBYTE)pidlFile)+pidlFile->mkid.cb-sizeof(WORD));
-        ok (cbOffset >= sizeof(struct FileStructA) &&
-            cbOffset <= pidlFile->mkid.cb - sizeof(struct FileStructW),
+        ok ((cbOffset >= sizeof(struct FileStructA) &&
+            cbOffset <= pidlFile->mkid.cb - sizeof(struct FileStructW)) ||
+            broken(pidlFile->mkid.cb == 2 + 12 + strlen(szFile) + 1 + 1) ||     /* Win2k on short names */
+            broken(pidlFile->mkid.cb == 2 + 12 + strlen(szFile) + 1 + 12 + 1),  /* Win2k on long names */
             "Wrong offset value (%d) stored at the end of the PIDL\n", cbOffset);
 
         if (cbOffset >= sizeof(struct FileStructA) &&
-            cbOffset <= pidlFile->mkid.cb - sizeof(struct FileStructW)) 
+            cbOffset <= pidlFile->mkid.cb - sizeof(struct FileStructW))
         {
             struct FileStructW *pFileStructW = (struct FileStructW *)(((LPBYTE)pidlFile)+cbOffset);
 
-            ok(pidlFile->mkid.cb == cbOffset + pFileStructW->cbLen, 
+            ok(pidlFile->mkid.cb == cbOffset + pFileStructW->cbLen,
                 "FileStructW's offset and length should add up to the PIDL's length!\n");
 
             if (pidlFile->mkid.cb == cbOffset + pFileStructW->cbLen) {
                 /* Since we just created the file, time of creation,
-                 * time of last access and time of last write access just be the same. 
-                 * These tests seem to fail sometimes (on WinXP), if the test is run again shortly 
+                 * time of last access and time of last write access just be the same.
+                 * These tests seem to fail sometimes (on WinXP), if the test is run again shortly
                  * after the first run. I do remember something with NTFS keeping the creation time
                  * if a file is deleted and then created again within a couple of seconds or so.
                  * Might be the reason. */
                 ok (pFileStructA->uFileDate == pFileStructW->uDate &&
                     pFileStructA->uFileTime == pFileStructW->uTime,
                     "Last write time should match creation time!\n");
-    
+
                 ok (pFileStructA->uFileDate == pFileStructW->uDate2 &&
                     pFileStructA->uFileTime == pFileStructW->uTime2,
                     "Last write time should match last access time!\n");
 
-                ok (!lstrcmpW(wszFile[i], pFileStructW->wszName),
+                ok (!lstrcmpW(wszFile[i], pFileStructW->wszName) ||
+                    !lstrcmpW(wszFile[i], (WCHAR *)(pFileStructW->abFooBar2 + 22)), /* Vista */
                     "The filename should be stored in unicode at this position!\n");
             }
         }
@@ -1385,7 +1527,7 @@ static void testSHGetFolderPathAndSubDirA(void)
         skip("SHGetFolderPathA not present!\n");
         return;
     }
-    if(!SUCCEEDED(pSHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, appdata)))
+    if(FAILED(pSHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, appdata)))
     {
         skip("SHGetFolderPathA failed for CSIDL_LOCAL_APPDATA!\n");
         return;
@@ -1475,6 +1617,129 @@ static void testSHGetFolderPathAndSubDirA(void)
     RemoveDirectoryA(testpath);
 }
 
+static const char *wine_dbgstr_w(LPCWSTR str)
+{
+    static char buf[512];
+    if (!str)
+        return "(null)";
+    WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL);
+    return buf;
+}
+
+static void test_LocalizedNames(void)
+{
+    static char cCurrDirA[MAX_PATH];
+    WCHAR cCurrDirW[MAX_PATH], tempbufW[25];
+    IShellFolder *IDesktopFolder, *testIShellFolder;
+    ITEMIDLIST *newPIDL;
+    int len;
+    HRESULT hr;
+    static char resourcefile[MAX_PATH];
+    DWORD res;
+    HANDLE file;
+    STRRET strret;
+
+    static const char desktopini_contents1[] =
+        "[.ShellClassInfo]\r\n"
+        "LocalizedResourceName=@";
+    static const char desktopini_contents2[] =
+        ",-1\r\n";
+    static WCHAR foldernameW[] = {'t','e','s','t','f','o','l','d','e','r',0};
+    static const WCHAR folderdisplayW[] = {'F','o','l','d','e','r',' ','N','a','m','e',' ','R','e','s','o','u','r','c','e',0};
+
+    /* create folder with desktop.ini and localized name in GetModuleFileNameA(NULL) */
+    CreateDirectoryA(".\\testfolder", NULL);
+
+    SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")|FILE_ATTRIBUTE_SYSTEM);
+
+    GetModuleFileNameA(NULL, resourcefile, MAX_PATH);
+
+    file = CreateFileA(".\\testfolder\\desktop.ini", GENERIC_WRITE, 0, NULL,
+                         CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+    ok(file != INVALID_HANDLE_VALUE, "CreateFileA failed %i\n", GetLastError());
+    ok(WriteFile(file, desktopini_contents1, strlen(desktopini_contents1), &res, NULL) &&
+       WriteFile(file, resourcefile, strlen(resourcefile), &res, NULL) &&
+       WriteFile(file, desktopini_contents2, strlen(desktopini_contents2), &res, NULL),
+       "WriteFile failed %i\n", GetLastError());
+    CloseHandle(file);
+
+    /* get IShellFolder for parent */
+    GetCurrentDirectoryA(MAX_PATH, cCurrDirA);
+    len = lstrlenA(cCurrDirA);
+
+    if (len == 0) {
+        trace("GetCurrentDirectoryA returned empty string. Skipping test_LocalizedNames\n");
+        goto cleanup;
+    }
+    if(cCurrDirA[len-1] == '\\')
+        cCurrDirA[len-1] = 0;
+
+    MultiByteToWideChar(CP_ACP, 0, cCurrDirA, -1, cCurrDirW, MAX_PATH);
+
+    hr = SHGetDesktopFolder(&IDesktopFolder);
+    ok(hr == S_OK, "SHGetDesktopfolder failed %08x\n", hr);
+
+    hr = IShellFolder_ParseDisplayName(IDesktopFolder, NULL, NULL, cCurrDirW, NULL, &newPIDL, 0);
+    ok(hr == S_OK, "ParseDisplayName failed %08x\n", hr);
+
+    hr = IShellFolder_BindToObject(IDesktopFolder, newPIDL, NULL, (REFIID)&IID_IShellFolder, (LPVOID *)&testIShellFolder);
+    ok(hr == S_OK, "BindToObject failed %08x\n", hr);
+
+    IMalloc_Free(ppM, newPIDL);
+
+    /* windows reads the display name from the resource */
+    hr = IShellFolder_ParseDisplayName(testIShellFolder, NULL, NULL, foldernameW, NULL, &newPIDL, 0);
+    ok(hr == S_OK, "ParseDisplayName failed %08x\n", hr);
+
+    hr = IShellFolder_GetDisplayNameOf(testIShellFolder, newPIDL, SHGDN_INFOLDER, &strret);
+    ok(hr == S_OK, "GetDisplayNameOf failed %08x\n", hr);
+
+    if (SUCCEEDED(hr) && pStrRetToBufW)
+    {
+        hr = pStrRetToBufW(&strret, newPIDL, tempbufW, sizeof(tempbufW)/sizeof(WCHAR));
+        ok (SUCCEEDED(hr), "StrRetToBufW failed! hr = %08x\n", hr);
+        todo_wine
+        ok (!lstrcmpiW(tempbufW, folderdisplayW) ||
+            broken(!lstrcmpiW(tempbufW, foldernameW)), /* W2K */
+            "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW));
+    }
+
+    /* editing name is also read from the resource */
+    hr = IShellFolder_GetDisplayNameOf(testIShellFolder, newPIDL, SHGDN_INFOLDER|SHGDN_FOREDITING, &strret);
+    ok(hr == S_OK, "GetDisplayNameOf failed %08x\n", hr);
+
+    if (SUCCEEDED(hr) && pStrRetToBufW)
+    {
+        hr = pStrRetToBufW(&strret, newPIDL, tempbufW, sizeof(tempbufW)/sizeof(WCHAR));
+        ok (SUCCEEDED(hr), "StrRetToBufW failed! hr = %08x\n", hr);
+        todo_wine
+        ok (!lstrcmpiW(tempbufW, folderdisplayW) ||
+            broken(!lstrcmpiW(tempbufW, foldernameW)), /* W2K */
+            "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW));
+    }
+
+    /* parsing name is unchanged */
+    hr = IShellFolder_GetDisplayNameOf(testIShellFolder, newPIDL, SHGDN_INFOLDER|SHGDN_FORPARSING, &strret);
+    ok(hr == S_OK, "GetDisplayNameOf failed %08x\n", hr);
+
+    if (SUCCEEDED(hr) && pStrRetToBufW)
+    {
+        hr = pStrRetToBufW(&strret, newPIDL, tempbufW, sizeof(tempbufW)/sizeof(WCHAR));
+        ok (SUCCEEDED(hr), "StrRetToBufW failed! hr = %08x\n", hr);
+        ok (!lstrcmpiW(tempbufW, foldernameW), "GetDisplayNameOf returned %s\n", wine_dbgstr_w(tempbufW));
+    }
+
+    IShellFolder_Release(IDesktopFolder);
+    IShellFolder_Release(testIShellFolder);
+
+    IMalloc_Free(ppM, newPIDL);
+
+cleanup:
+    DeleteFileA(".\\testfolder\\desktop.ini");
+    SetFileAttributesA(".\\testfolder", GetFileAttributesA(".\\testfolder")&~FILE_ATTRIBUTE_SYSTEM);
+    RemoveDirectoryA(".\\testfolder");
+}
+
 
 START_TEST(shlfolder)
 {
@@ -1496,6 +1761,7 @@ START_TEST(shlfolder)
         testSHGetFolderPathAndSubDirA();
     else
         skip("SHGetFolderPathAndSubDirA not present\n");
+    test_LocalizedNames();
 
     OleUninitialize();
 }
index c748f35..1d55ecf 100755 (executable)
@@ -37,7 +37,7 @@ static HRESULT (WINAPI *pStrRetToStrNAW)(LPVOID,DWORD,LPSTRRET,const ITEMIDLIST
 static WCHAR *CoDupStrW(const char* src)
 {
   INT len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);
-  WCHAR* szTemp = (WCHAR*)CoTaskMemAlloc(len * sizeof(WCHAR));
+  WCHAR* szTemp = CoTaskMemAlloc(len * sizeof(WCHAR));
   MultiByteToWideChar(CP_ACP, 0, src, -1, szTemp, len);
   return szTemp;
 }
@@ -110,4 +110,6 @@ START_TEST(string)
         else
             test_StrRetToStringNA();
     }
+
+    CoUninitialize();
 }
index c672d67..1f505ec 100644 (file)
 
 static HWND hMainWnd;
 static BOOL (WINAPI *pShell_NotifyIconW)(DWORD,PNOTIFYICONDATAW);
-static HMONITOR (WINAPI *pMonitorFromWindow)(HWND, DWORD);
 
-void test_cbsize(void)
+static void test_cbsize(void)
 {
     NOTIFYICONDATAA nidA;
+    BOOL ret;
 
     if (pShell_NotifyIconW)
     {
@@ -44,16 +44,20 @@ void test_cbsize(void)
         nidW.uFlags = NIF_ICON|NIF_MESSAGE;
         nidW.hIcon = LoadIcon(NULL, IDI_APPLICATION);
         nidW.uCallbackMessage = WM_USER+17;
-        ok(pShell_NotifyIconW(NIM_ADD, &nidW), "NIM_ADD failed!\n");
-
-        /* using an invalid cbSize does work */
-        nidW.cbSize = 3;
-        nidW.hWnd = hMainWnd;
-        nidW.uID = 1;
-        ok(pShell_NotifyIconW(NIM_DELETE, &nidW), "NIM_DELETE failed!\n");
-        /* as icon doesn't exist anymore - now there will be an error */
-        nidW.cbSize = sizeof(nidW);
-        ok(!pShell_NotifyIconW(NIM_DELETE, &nidW), "The icon was not deleted\n");
+        ret = pShell_NotifyIconW(NIM_ADD, &nidW);
+        if (ret)
+        {
+            /* using an invalid cbSize does work */
+            nidW.cbSize = 3;
+            nidW.hWnd = hMainWnd;
+            nidW.uID = 1;
+            ret = pShell_NotifyIconW(NIM_DELETE, &nidW);
+            ok( ret || broken(!ret), /* nt4 */ "NIM_DELETE failed!\n");
+            /* as icon doesn't exist anymore - now there will be an error */
+            nidW.cbSize = sizeof(nidW);
+            ok(!pShell_NotifyIconW(NIM_DELETE, &nidW) != !ret, "The icon was not deleted\n");
+        }
+        else win_skip( "Shell_NotifyIconW not working\n" );  /* win9x */
     }
 
     /* same for Shell_NotifyIconA */
@@ -70,65 +74,11 @@ void test_cbsize(void)
     nidA.cbSize = 3;
     nidA.hWnd = hMainWnd;
     nidA.uID = 1;
-    ok(Shell_NotifyIconA(NIM_DELETE, &nidA), "NIM_DELETE failed!\n");
+    ret = Shell_NotifyIconA(NIM_DELETE, &nidA);
+    ok( ret || broken(!ret),  /* win9x */ "NIM_DELETE failed!\n");
     /* as icon doesn't exist anymore - now there will be an error */
     nidA.cbSize = sizeof(nidA);
-    ok(!Shell_NotifyIconA(NIM_DELETE, &nidA), "The icon was not deleted\n");
-}
-
-static void test_SHAppBarMessage(void)
-{
-    APPBARDATA abd;
-    HWND hwnd, foregnd;
-    UINT_PTR ret;
-
-    memset(&abd, 0xcc, sizeof(abd));
-    abd.cbSize = sizeof(abd);
-    abd.uEdge = ABE_BOTTOM;
-
-    hwnd = (HWND)SHAppBarMessage(ABM_GETAUTOHIDEBAR, &abd);
-    ok(hwnd == NULL || IsWindow(hwnd), "ret %p which is not a window\n", hwnd);
-    ok(abd.hWnd == (HWND)0xcccccccc, "hWnd overwritten\n");
-
-    if (!pMonitorFromWindow)
-    {
-        skip("MonitorFromWindow is not available\n");
-    }
-    else
-    {
-        /* Presumably one can pass a hwnd with ABM_GETAUTOHIDEBAR to specify a monitor.
-           Pass the foreground window and check */
-        foregnd = GetForegroundWindow();
-        if(foregnd)
-        {
-            abd.hWnd = foregnd;
-            hwnd = (HWND)SHAppBarMessage(ABM_GETAUTOHIDEBAR, &abd);
-            ok(hwnd == NULL || IsWindow(hwnd), "ret %p which is not a window\n", hwnd);
-            ok(abd.hWnd == foregnd, "hWnd overwritten\n");
-            if(hwnd)
-            {
-                HMONITOR appbar_mon, foregnd_mon;
-                appbar_mon = pMonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
-                foregnd_mon = pMonitorFromWindow(foregnd, MONITOR_DEFAULTTONEAREST);
-                ok(appbar_mon == foregnd_mon, "Windows on different monitors\n");
-            }
-        }
-    }
-
-    memset(&abd, 0xcc, sizeof(abd));
-    abd.cbSize = sizeof(abd);
-    ret = SHAppBarMessage(ABM_GETTASKBARPOS, &abd);
-    if(ret)
-    {
-        ok(abd.hWnd == (HWND)0xcccccccc, "hWnd overwritten\n");
-todo_wine
-{
-        ok(abd.uEdge >= ABE_LEFT && abd.uEdge <= ABE_BOTTOM, "uEdge not returned\n");
-        ok(abd.rc.left != 0xcccccccc, "rc not updated\n");
-}
-    }
-
-    return;
+    ok(!Shell_NotifyIconA(NIM_DELETE, &nidA) != !ret, "The icon was not deleted\n");
 }
 
 START_TEST(systray)
@@ -136,14 +86,11 @@ START_TEST(systray)
     WNDCLASSA wc;
     MSG msg;
     RECT rc;
-    HMODULE huser32, hshell32;
+    HMODULE hshell32;
 
     hshell32 = GetModuleHandleA("shell32.dll");
     pShell_NotifyIconW = (void*)GetProcAddress(hshell32, "Shell_NotifyIconW");
 
-    huser32 = GetModuleHandleA("user32.dll");
-    pMonitorFromWindow = (void*)GetProcAddress(huser32, "MonitorFromWindow");
-
     wc.style = CS_HREDRAW | CS_VREDRAW;
     wc.cbClsExtra = 0;
     wc.cbWndExtra = 0;
@@ -169,6 +116,4 @@ START_TEST(systray)
         DispatchMessageA(&msg);
     }
     DestroyWindow(hMainWnd);
-
-    test_SHAppBarMessage();
 }
index 7de794d..2ffe480 100644 (file)
@@ -6,10 +6,13 @@
 #define STANDALONE
 #include "wine/test.h"
 
+extern void func_appbar(void);
+extern void func_autocomplete(void);
 extern void func_generated(void);
 extern void func_shelllink(void);
 extern void func_shellpath(void);
 extern void func_shfldr_netplaces(void);
+extern void func_shfldr_special(void);
 extern void func_shlexec(void);
 extern void func_shlfileop(void);
 extern void func_shlfolder(void);
@@ -18,10 +21,13 @@ extern void func_systray(void);
 
 const struct test winetest_testlist[] =
 {
-    { "generated", func_generated },
+    { "appbar", func_appbar },  
+       { "autocomplete", func_autocomplete },
+       { "generated", func_generated },
     { "shelllink", func_shelllink },
     { "shellpath", func_shellpath },
     { "shfldr_netplaces", func_shfldr_netplaces },
+       { "shfldr_special", func_shfldr_special },
     { "shlexec", func_shlexec },
     { "shlfileop", func_shlfileop },
     { "shlfolder", func_shlfolder },