[KERNEL32_WINETEST]
authorAmine Khaldi <amine.khaldi@reactos.org>
Fri, 18 Apr 2014 22:50:27 +0000 (22:50 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Fri, 18 Apr 2014 22:50:27 +0000 (22:50 +0000)
* Sync with Wine 1.7.17.
CORE-8080

svn path=/trunk/; revision=62787

32 files changed:
rostests/winetests/kernel32/CMakeLists.txt
rostests/winetests/kernel32/actctx.c
rostests/winetests/kernel32/alloc.c [deleted file]
rostests/winetests/kernel32/change.c
rostests/winetests/kernel32/codepage.c
rostests/winetests/kernel32/comm.c
rostests/winetests/kernel32/console.c
rostests/winetests/kernel32/debugger.c
rostests/winetests/kernel32/drive.c
rostests/winetests/kernel32/environ.c
rostests/winetests/kernel32/fiber.c
rostests/winetests/kernel32/file.c
rostests/winetests/kernel32/format_msg.c
rostests/winetests/kernel32/heap.c
rostests/winetests/kernel32/loader.c
rostests/winetests/kernel32/locale.c
rostests/winetests/kernel32/mailslot.c
rostests/winetests/kernel32/module.c
rostests/winetests/kernel32/path.c
rostests/winetests/kernel32/pipe.c
rostests/winetests/kernel32/process.c
rostests/winetests/kernel32/profile.c
rostests/winetests/kernel32/resource.c
rostests/winetests/kernel32/sync.c
rostests/winetests/kernel32/testlist.c
rostests/winetests/kernel32/thread.c
rostests/winetests/kernel32/time.c
rostests/winetests/kernel32/timer.c
rostests/winetests/kernel32/toolhelp.c
rostests/winetests/kernel32/version.c
rostests/winetests/kernel32/virtual.c
rostests/winetests/kernel32/volume.c

index 2eec893..1b98b38 100644 (file)
@@ -1,12 +1,8 @@
 
-add_definitions(
-    -D__ROS_LONG64__)
-
 remove_definitions(-DWINVER=0x502 -D_WIN32_IE=0x600 -D_WIN32_WINNT=0x502)
 
 list(APPEND SOURCE
     actctx.c
-    alloc.c
     atom.c
     change.c
     codepage.c
@@ -40,12 +36,7 @@ list(APPEND SOURCE
     volume.c
     testlist.c)
 
-add_executable(kernel32_winetest
-    ${SOURCE}
-    resource.rc)
-
-target_link_libraries(kernel32_winetest wine)
+add_executable(kernel32_winetest ${SOURCE} resource.rc)
 set_module_type(kernel32_winetest win32cui)
 add_importlibs(kernel32_winetest user32 advapi32 msvcrt kernel32 ntdll)
-
 add_cd_file(TARGET kernel32_winetest DESTINATION reactos/bin FOR all)
index d0e8433..792a292 100644 (file)
 #include <initguid.h>
 
 static BOOL   (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
+static HANDLE (WINAPI *pCreateActCtxA)(PCACTCTXA);
 static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
 static BOOL   (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
+static BOOL   (WINAPI *pFindActCtxSectionStringA)(DWORD,const GUID *,ULONG,LPCSTR,PACTCTX_SECTION_KEYED_DATA);
 static BOOL   (WINAPI *pFindActCtxSectionStringW)(DWORD,const GUID *,ULONG,LPCWSTR,PACTCTX_SECTION_KEYED_DATA);
 static BOOL   (WINAPI *pGetCurrentActCtx)(HANDLE *);
 static BOOL   (WINAPI *pIsDebuggerPresent)(void);
@@ -47,18 +49,6 @@ static const char* strw(LPCWSTR x)
     return buffer;
 }
 
-static const char *debugstr_guid(REFIID riid)
-{
-    static char buf[50];
-
-    sprintf(buf, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
-            riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
-            riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
-            riid->Data4[5], riid->Data4[6], riid->Data4[7]);
-
-    return buf;
-}
-
 #ifdef __i386__
 #define ARCH "x86"
 #elif defined __x86_64__
@@ -72,6 +62,11 @@ static const char manifest1[] =
 "<assemblyIdentity version=\"1.0.0.0\"  name=\"Wine.Test\" type=\"win32\"></assemblyIdentity>"
 "</assembly>";
 
+static const char manifest1_1[] =
+"<assembly xmlns = \"urn:schemas-microsoft-com:asm.v1\" manifestVersion = \"1.0\">"
+"<assemblyIdentity version = \"1.0.0.0\" name = \"Wine.Test\" type = \"win32\"></assemblyIdentity>"
+"</assembly>";
+
 static const char manifest2[] =
 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\">"
@@ -84,11 +79,19 @@ static const char manifest2[] =
 "</dependency>"
 "</assembly>";
 
-DEFINE_GUID(IID_CoTest, 0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33);
-DEFINE_GUID(IID_TlibTest, 0x99999999, 0x8888, 0x7777, 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55);
+DEFINE_GUID(IID_CoTest,    0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33);
+DEFINE_GUID(IID_CoTest2,   0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x11, 0x11, 0x22, 0x22, 0x33, 0x34);
+DEFINE_GUID(CLSID_clrclass,0x22345678, 0x1234, 0x5678, 0x12, 0x34, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33);
+DEFINE_GUID(IID_TlibTest,  0x99999999, 0x8888, 0x7777, 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55);
 DEFINE_GUID(IID_TlibTest2, 0x99999999, 0x8888, 0x7777, 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x56);
 DEFINE_GUID(IID_TlibTest3, 0x99999999, 0x8888, 0x7777, 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x57);
 DEFINE_GUID(IID_TlibTest4, 0x99999999, 0x8888, 0x7777, 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x58);
+DEFINE_GUID(IID_Iifaceps,  0x66666666, 0x8888, 0x7777, 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55);
+DEFINE_GUID(IID_Ibifaceps, 0x66666666, 0x8888, 0x7777, 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x57);
+DEFINE_GUID(IID_Iifaceps2, 0x76666666, 0x8888, 0x7777, 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55);
+DEFINE_GUID(IID_Iifaceps3, 0x86666666, 0x8888, 0x7777, 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55);
+DEFINE_GUID(IID_Iiface,    0x96666666, 0x8888, 0x7777, 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55);
+DEFINE_GUID(IID_PS32,      0x66666666, 0x8888, 0x7777, 0x66, 0x66, 0x55, 0x55, 0x55, 0x55, 0x55, 0x56);
 
 static const char manifest3[] =
 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
@@ -106,8 +109,63 @@ static const char manifest3[] =
 "              miscStatusContent=\"insideout\""
 "              miscStatusThumbnail=\"alignable\""
 "              miscStatusDocPrint=\"simpleframe,setclientsitefirst\""
+"    >"
+"        <progid>ProgId.ProgId.1</progid>"
+"        <progid>ProgId.ProgId.2</progid>"
+"        <progid>ProgId.ProgId.3</progid>"
+"        <progid>ProgId.ProgId.4</progid>"
+"        <progid>ProgId.ProgId.5</progid>"
+"        <progid>ProgId.ProgId.6</progid>"
+"    </comClass>"
+"    <comClass clsid=\"{12345678-1234-5678-1234-111122223334}\" threadingModel=\"Neutral\" >"
+"        <progid>ProgId.ProgId.7</progid>"
+"    </comClass>"
+"    <comInterfaceProxyStub "
+"        name=\"Iifaceps\""
+"        tlbid=\"{99999999-8888-7777-6666-555555555558}\""
+"        iid=\"{66666666-8888-7777-6666-555555555555}\""
+"        proxyStubClsid32=\"{66666666-8888-7777-6666-555555555556}\""
+"        threadingModel=\"Free\""
+"        numMethods=\"10\""
+"        baseInterface=\"{66666666-8888-7777-6666-555555555557}\""
 "    />"
 "</file>"
+"    <comInterfaceExternalProxyStub "
+"        name=\"Iifaceps2\""
+"        tlbid=\"{99999999-8888-7777-6666-555555555558}\""
+"        iid=\"{76666666-8888-7777-6666-555555555555}\""
+"        proxyStubClsid32=\"{66666666-8888-7777-6666-555555555556}\""
+"        numMethods=\"10\""
+"        baseInterface=\"{66666666-8888-7777-6666-555555555557}\""
+"    />"
+"    <comInterfaceExternalProxyStub "
+"        name=\"Iifaceps3\""
+"        tlbid=\"{99999999-8888-7777-6666-555555555558}\""
+"        iid=\"{86666666-8888-7777-6666-555555555555}\""
+"        numMethods=\"10\""
+"        baseInterface=\"{66666666-8888-7777-6666-555555555557}\""
+"    />"
+"    <clrSurrogate "
+"        clsid=\"{96666666-8888-7777-6666-555555555555}\""
+"        name=\"testsurrogate\""
+"        runtimeVersion=\"v2.0.50727\""
+"    />"
+"    <clrClass "
+"        clsid=\"{22345678-1234-5678-1234-111122223333}\""
+"        name=\"clrclass\""
+"        progid=\"clrprogid\""
+"        description=\"test description\""
+"        tlbid=\"{99999999-8888-7777-6666-555555555555}\""
+"        runtimeVersion=\"1.2.3.4\""
+"        threadingModel=\"Neutral\""
+"    >"
+"        <progid>clrprogid.1</progid>"
+"        <progid>clrprogid.2</progid>"
+"        <progid>clrprogid.3</progid>"
+"        <progid>clrprogid.4</progid>"
+"        <progid>clrprogid.5</progid>"
+"        <progid>clrprogid.6</progid>"
+"    </clrClass>"
 "</assembly>";
 
 static const char manifest_wndcls1[] =
@@ -128,7 +186,7 @@ static const char manifest_wndcls2[] =
 " <windowClass versioned=\"no\">wndClass3</windowClass>"
 " <windowClass>wndClass4</windowClass>"
 " <typelib tlbid=\"{99999999-8888-7777-6666-555555555555}\" version=\"1.0\" helpdir=\"help\" resourceid=\"409\""
-"          flags=\"HIDDEN,CONTROL,RESTRICTED\" />"
+"          flags=\"HiddeN,CoNTROL,rESTRICTED\" />"
 " <typelib tlbid=\"{99999999-8888-7777-6666-555555555556}\" version=\"1.0\" helpdir=\"help1\" resourceid=\"409\" />"
 " <typelib tlbid=\"{99999999-8888-7777-6666-555555555557}\" version=\"1.0\" helpdir=\"\" />"
 "</file>"
@@ -665,7 +723,8 @@ static HANDLE test_create(const char *file)
     actctx.lpSource = path;
 
     handle = pCreateActCtxW(&actctx);
-    ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
+    /* to be tested outside of this helper, including last error */
+    if (handle == INVALID_HANDLE_VALUE) return handle;
 
     ok(actctx.cbSize == sizeof(actctx), "actctx.cbSize=%d\n", actctx.cbSize);
     ok(actctx.dwFlags == 0, "actctx.dwFlags=%d\n", actctx.dwFlags);
@@ -777,7 +836,9 @@ struct strsection_header
     DWORD unk1[3];
     ULONG count;
     ULONG index_offset;
-    DWORD unk2[4];
+    DWORD unk2[2];
+    ULONG global_offset;
+    ULONG global_len;
 };
 
 struct string_index
@@ -841,6 +902,13 @@ struct tlibredirect_data
     WORD   minor_version;
 };
 
+struct progidredirect_data
+{
+    ULONG size;
+    DWORD reserved;
+    ULONG clsid_offset;
+};
+
 static void test_find_dll_redirection(HANDLE handle, LPCWSTR libname, ULONG exid, int line)
 {
     ACTCTX_SECTION_KEYED_DATA data;
@@ -1107,7 +1175,8 @@ struct comclassredirect_data {
     ULONG name_offset;
     ULONG progid_len;
     ULONG progid_offset;
-    DWORD res2[2];
+    ULONG clrdata_len;
+    ULONG clrdata_offset;
     DWORD miscstatus;
     DWORD miscstatuscontent;
     DWORD miscstatusthumbnail;
@@ -1115,10 +1184,23 @@ struct comclassredirect_data {
     DWORD miscstatusdocprint;
 };
 
-static void test_find_com_redirection(HANDLE handle, const GUID *clsid, const GUID *tlid, ULONG exid, int line)
+struct clrclass_data {
+    ULONG size;
+    DWORD res[2];
+    ULONG module_len;
+    ULONG module_offset;
+    ULONG name_len;
+    ULONG name_offset;
+    ULONG version_len;
+    ULONG version_offset;
+    DWORD res2[2];
+};
+
+static void test_find_com_redirection(HANDLE handle, const GUID *clsid, const GUID *tlid, const WCHAR *progid, ULONG exid, int line)
 {
     struct comclassredirect_data *comclass, *comclass2;
     ACTCTX_SECTION_KEYED_DATA data, data2;
+    struct guidsection_header *header;
     BOOL ret;
 
     memset(&data, 0xfe, sizeof(data));
@@ -1127,6 +1209,11 @@ static void test_find_com_redirection(HANDLE handle, const GUID *clsid, const GU
     ret = pFindActCtxSectionGuid(0, NULL,
                                     ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION,
                                     clsid, &data);
+    if (!ret)
+    {
+        skip("failed for guid %s\n", wine_dbgstr_guid(clsid));
+        return;
+    }
     ok_(__FILE__, line)(ret, "FindActCtxSectionGuid failed: %u\n", GetLastError());
 
     comclass = (struct comclassredirect_data*)data.lpData;
@@ -1137,7 +1224,6 @@ static void test_find_com_redirection(HANDLE handle, const GUID *clsid, const GU
     ok_(__FILE__, line)(comclass->size == sizeof(*comclass), "got %d for header size\n", comclass->size);
     if (data.lpData && comclass->size == sizeof(*comclass))
     {
-        static const WCHAR progid[] = {'P','r','o','g','I','d','.','P','r','o','g','I','d',0};
         WCHAR *ptr;
         ULONG len;
 
@@ -1145,19 +1231,31 @@ static void test_find_com_redirection(HANDLE handle, const GUID *clsid, const GU
         ok_(__FILE__, line)(comclass->res1[0] == 0, "got res1[0] as %02x\n", comclass->res1[0]);
         ok_(__FILE__, line)(comclass->res1[1] == 0, "got res1[1] as %02x\n", comclass->res1[1]);
         ok_(__FILE__, line)(comclass->model == ThreadingModel_Neutral, "got model %d\n", comclass->model);
-        ok_(__FILE__, line)(IsEqualGUID(&comclass->clsid, clsid), "got wrong clsid %s\n", debugstr_guid(&comclass->clsid));
-        ok_(__FILE__, line)(IsEqualGUID(&comclass->clsid2, clsid), "got wrong clsid2 %s\n", debugstr_guid(&comclass->clsid2));
-        ok_(__FILE__, line)(IsEqualGUID(&comclass->tlid, tlid), "got wrong tlid %s\n", debugstr_guid(&comclass->tlid));
+        ok_(__FILE__, line)(IsEqualGUID(&comclass->clsid, clsid), "got wrong clsid %s\n", wine_dbgstr_guid(&comclass->clsid));
+        ok_(__FILE__, line)(IsEqualGUID(&comclass->clsid2, clsid), "got wrong clsid2 %s\n", wine_dbgstr_guid(&comclass->clsid2));
+        if (tlid)
+            ok_(__FILE__, line)(IsEqualGUID(&comclass->tlid, tlid), "got wrong tlid %s\n", wine_dbgstr_guid(&comclass->tlid));
         ok_(__FILE__, line)(comclass->name_len > 0, "got modulename len %d\n", comclass->name_len);
-        ok_(__FILE__, line)(comclass->progid_offset == comclass->size, "got progid offset %d\n", comclass->progid_offset);
 
-        ptr = (WCHAR*)((BYTE*)comclass + comclass->size);
-        ok_(__FILE__, line)(!lstrcmpW(ptr, progid), "got wrong progid %s, expected %s\n", wine_dbgstr_w(ptr), wine_dbgstr_w(progid));
-        ok_(__FILE__, line)(lstrlenW(ptr)*sizeof(WCHAR) == comclass->progid_len,
-            "got progid name length %d, expected %d\n", comclass->progid_len, lstrlenW(ptr));
+        if (progid)
+        {
+            len = comclass->size + comclass->clrdata_len;
+            ok_(__FILE__, line)(comclass->progid_offset == len, "got progid offset %d, expected %d\n", comclass->progid_offset, len);
+        }
+        else
+            ok_(__FILE__, line)(comclass->progid_offset == 0, "got progid offset %d, expected 0\n", comclass->progid_offset);
+
+        if (comclass->progid_offset)
+        {
+            ptr = (WCHAR*)((BYTE*)comclass + comclass->progid_offset);
+            ok_(__FILE__, line)(!lstrcmpW(ptr, progid), "got wrong progid %s, expected %s\n", wine_dbgstr_w(ptr), wine_dbgstr_w(progid));
+            ok_(__FILE__, line)(lstrlenW(progid)*sizeof(WCHAR) == comclass->progid_len,
+                "got progid name length %d\n", comclass->progid_len);
+        }
 
         /* data length is simply header length + string data length including nulls */
-        len = comclass->size + comclass->progid_len + sizeof(WCHAR);
+        len = comclass->size + comclass->clrdata_len;
+        if (comclass->progid_len) len += comclass->progid_len + sizeof(WCHAR);
         ok_(__FILE__, line)(data.ulLength == len, "got wrong data length %d, expected %d\n", data.ulLength, len);
 
         /* keyed data structure doesn't include module name, it's available from section data */
@@ -1177,12 +1275,47 @@ static void test_find_com_redirection(HANDLE handle, const GUID *clsid, const GU
             if (comclass->miscmask & MiscStatusDocPrint)
                 ok_(__FILE__, line)(comclass->miscstatusdocprint != 0, "got miscstatusdocprint 0x%08x\n", comclass->miscstatusdocprint);
         }
+
+        /* part used for clrClass only */
+        if (comclass->clrdata_len)
+        {
+            static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
+            static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
+            struct clrclass_data *clrclass;
+            WCHAR *ptrW;
+
+            clrclass = (struct clrclass_data*)((BYTE*)data.lpData + comclass->clrdata_offset);
+            ok_(__FILE__, line)(clrclass->size == sizeof(*clrclass), "clrclass: got size %d\n", clrclass->size);
+            ok_(__FILE__, line)(clrclass->res[0] == 0, "clrclass: got res[0]=0x%08x\n", clrclass->res[0]);
+            ok_(__FILE__, line)(clrclass->res[1] == 2, "clrclass: got res[1]=0x%08x\n", clrclass->res[1]);
+            ok_(__FILE__, line)(clrclass->module_len == lstrlenW(mscoreeW)*sizeof(WCHAR), "clrclass: got module len %d\n", clrclass->module_len);
+            ok_(__FILE__, line)(clrclass->module_offset > 0, "clrclass: got module offset %d\n", clrclass->module_offset);
+
+            ok_(__FILE__, line)(clrclass->name_len > 0, "clrclass: got name len %d\n", clrclass->name_len);
+            ok_(__FILE__, line)(clrclass->name_offset == clrclass->size, "clrclass: got name offset %d\n", clrclass->name_offset);
+            ok_(__FILE__, line)(clrclass->version_len > 0, "clrclass: got version len %d\n", clrclass->version_len);
+            ok_(__FILE__, line)(clrclass->version_offset > 0, "clrclass: got version offset %d\n", clrclass->version_offset);
+
+            ok_(__FILE__, line)(clrclass->res2[0] == 0, "clrclass: got res2[0]=0x%08x\n", clrclass->res2[0]);
+            ok_(__FILE__, line)(clrclass->res2[1] == 0, "clrclass: got res2[1]=0x%08x\n", clrclass->res2[1]);
+
+            /* clrClass uses mscoree.dll as module name, but in two variants - comclass data points to module name
+               in lower case, clsclass subsection - in upper case */
+            ok_(__FILE__, line)(comclass->name_len == lstrlenW(mscoree2W)*sizeof(WCHAR), "clrclass: got com name len %d\n", comclass->name_len);
+            ok_(__FILE__, line)(comclass->name_offset > 0, "clrclass: got name offset %d\n", clrclass->name_offset);
+
+            ptrW = (WCHAR*)((BYTE*)data.lpSectionBase + comclass->name_offset);
+            ok_(__FILE__, line)(!lstrcmpW(ptrW, mscoreeW), "clrclass: module name %s\n", wine_dbgstr_w(ptrW));
+
+            ptrW = (WCHAR*)((BYTE*)data.lpSectionBase + clrclass->module_offset);
+            ok_(__FILE__, line)(!lstrcmpW(ptrW, mscoree2W), "clrclass: module name2 %s\n", wine_dbgstr_w(ptrW));
+        }
     }
-todo_wine {
-    ok_(__FILE__, line)(data.lpSectionGlobalData != NULL, "data.lpSectionGlobalData == NULL\n");
-    ok_(__FILE__, line)(data.ulSectionGlobalDataLength > 0, "data.ulSectionGlobalDataLength=%u\n",
+
+    header = (struct guidsection_header*)data.lpSectionBase;
+    ok_(__FILE__, line)(data.lpSectionGlobalData == ((BYTE*)header + header->names_offset), "data.lpSectionGlobalData == NULL\n");
+    ok_(__FILE__, line)(data.ulSectionGlobalDataLength == header->names_len, "data.ulSectionGlobalDataLength=%u\n",
        data.ulSectionGlobalDataLength);
-}
     ok_(__FILE__, line)(data.lpSectionBase != NULL, "data.lpSectionBase == NULL\n");
     ok_(__FILE__, line)(data.ulSectionTotalLength > 0, "data.ulSectionTotalLength=%u\n",
        data.ulSectionTotalLength);
@@ -1203,6 +1336,210 @@ todo_wine {
     ok_(__FILE__, line)(!memcmp(comclass, comclass2, comclass->size), "got wrong data\n");
 }
 
+enum ifaceps_mask
+{
+    NumMethods = 1,
+    BaseIface  = 2
+};
+
+struct ifacepsredirect_data
+{
+    ULONG size;
+    DWORD mask;
+    GUID  iid;
+    ULONG nummethods;
+    GUID  tlbid;
+    GUID  base;
+    ULONG name_len;
+    ULONG name_offset;
+};
+
+static void test_find_ifaceps_redirection(HANDLE handle, const GUID *iid, const GUID *tlbid, const GUID *base,
+    const GUID *ps32, ULONG exid, int line)
+{
+    struct ifacepsredirect_data *ifaceps;
+    ACTCTX_SECTION_KEYED_DATA data;
+    BOOL ret;
+
+    memset(&data, 0xfe, sizeof(data));
+    data.cbSize = sizeof(data);
+
+    ret = pFindActCtxSectionGuid(0, NULL,
+                                    ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION,
+                                    iid, &data);
+    ok_(__FILE__, line)(ret, "FindActCtxSectionGuid failed: %u\n", GetLastError());
+
+    ifaceps = (struct ifacepsredirect_data*)data.lpData;
+
+    ok_(__FILE__, line)(data.cbSize == sizeof(data), "data.cbSize=%u\n", data.cbSize);
+    ok_(__FILE__, line)(data.ulDataFormatVersion == 1, "data.ulDataFormatVersion=%u\n", data.ulDataFormatVersion);
+    ok_(__FILE__, line)(data.lpData != NULL, "data.lpData == NULL\n");
+    ok_(__FILE__, line)(ifaceps->size == sizeof(*ifaceps), "got %d for header size\n", ifaceps->size);
+    if (data.lpData && ifaceps->size == sizeof(*ifaceps))
+    {
+        ULONG len;
+
+        /* for external proxy stubs it contains a value from 'proxyStubClsid32' */
+        if (ps32)
+        {
+            ok_(__FILE__, line)(IsEqualGUID(&ifaceps->iid, ps32), "got wrong iid %s\n", wine_dbgstr_guid(&ifaceps->iid));
+        }
+        else
+            ok_(__FILE__, line)(IsEqualGUID(&ifaceps->iid, iid), "got wrong iid %s\n", wine_dbgstr_guid(&ifaceps->iid));
+
+        ok_(__FILE__, line)(IsEqualGUID(&ifaceps->tlbid, tlbid), "got wrong tlid %s\n", wine_dbgstr_guid(&ifaceps->tlbid));
+        ok_(__FILE__, line)(ifaceps->name_len > 0, "got modulename len %d\n", ifaceps->name_len);
+        ok_(__FILE__, line)(ifaceps->name_offset == ifaceps->size, "got progid offset %d\n", ifaceps->name_offset);
+
+        /* data length is simply header length + string data length including nulls */
+        len = ifaceps->size + ifaceps->name_len + sizeof(WCHAR);
+        ok_(__FILE__, line)(data.ulLength == len, "got wrong data length %d, expected %d\n", data.ulLength, len);
+
+        /* mask purpose is to indicate if attribute was specified, for testing purposes assume that manifest
+           always has non-zero value for it */
+        if (ifaceps->mask & NumMethods)
+            ok_(__FILE__, line)(ifaceps->nummethods != 0, "got nummethods %d\n", ifaceps->nummethods);
+        if (ifaceps->mask & BaseIface)
+            ok_(__FILE__, line)(IsEqualGUID(&ifaceps->base, base), "got base %s\n", wine_dbgstr_guid(&ifaceps->base));
+    }
+
+    ok_(__FILE__, line)(data.lpSectionGlobalData == NULL, "data.lpSectionGlobalData != NULL\n");
+    ok_(__FILE__, line)(data.ulSectionGlobalDataLength == 0, "data.ulSectionGlobalDataLength=%u\n",
+       data.ulSectionGlobalDataLength);
+    ok_(__FILE__, line)(data.lpSectionBase != NULL, "data.lpSectionBase == NULL\n");
+    ok_(__FILE__, line)(data.ulSectionTotalLength > 0, "data.ulSectionTotalLength=%u\n",
+       data.ulSectionTotalLength);
+    ok_(__FILE__, line)(data.hActCtx == NULL, "data.hActCtx=%p\n", data.hActCtx);
+    ok_(__FILE__, line)(data.ulAssemblyRosterIndex == exid, "data.ulAssemblyRosterIndex=%u, expected %u\n",
+       data.ulAssemblyRosterIndex, exid);
+}
+
+struct clrsurrogate_data
+{
+    ULONG size;
+    DWORD res;
+    GUID  clsid;
+    ULONG version_offset;
+    ULONG version_len;
+    ULONG name_offset;
+    ULONG name_len;
+};
+
+static void test_find_surrogate(HANDLE handle, const GUID *clsid, const WCHAR *name, const WCHAR *version,
+    ULONG exid, int line)
+{
+    struct clrsurrogate_data *surrogate;
+    ACTCTX_SECTION_KEYED_DATA data;
+    BOOL ret;
+
+    memset(&data, 0xfe, sizeof(data));
+    data.cbSize = sizeof(data);
+
+    ret = pFindActCtxSectionGuid(0, NULL,
+                                    ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES,
+                                    clsid, &data);
+    if (!ret)
+    {
+        skip("surrogate sections are not supported\n");
+        return;
+    }
+    ok_(__FILE__, line)(ret, "FindActCtxSectionGuid failed: %u\n", GetLastError());
+
+    surrogate = (struct clrsurrogate_data*)data.lpData;
+
+    ok_(__FILE__, line)(data.cbSize == sizeof(data), "data.cbSize=%u\n", data.cbSize);
+    ok_(__FILE__, line)(data.ulDataFormatVersion == 1, "data.ulDataFormatVersion=%u\n", data.ulDataFormatVersion);
+    ok_(__FILE__, line)(data.lpData != NULL, "data.lpData == NULL\n");
+    ok_(__FILE__, line)(surrogate->size == sizeof(*surrogate), "got %d for header size\n", surrogate->size);
+    if (data.lpData && surrogate->size == sizeof(*surrogate))
+    {
+        WCHAR *ptrW;
+        ULONG len;
+
+        ok_(__FILE__, line)(surrogate->res == 0, "invalid res value %d\n", surrogate->res);
+        ok_(__FILE__, line)(IsEqualGUID(&surrogate->clsid, clsid), "got wrong clsid %s\n", wine_dbgstr_guid(&surrogate->clsid));
+
+        ok_(__FILE__, line)(surrogate->version_len == lstrlenW(version)*sizeof(WCHAR), "got version len %d\n", surrogate->version_len);
+        ok_(__FILE__, line)(surrogate->version_offset == surrogate->size, "got version offset %d\n", surrogate->version_offset);
+
+        ok_(__FILE__, line)(surrogate->name_len == lstrlenW(name)*sizeof(WCHAR), "got name len %d\n", surrogate->name_len);
+        ok_(__FILE__, line)(surrogate->name_offset > surrogate->version_offset, "got name offset %d\n", surrogate->name_offset);
+
+        len = surrogate->size + surrogate->name_len + surrogate->version_len + 2*sizeof(WCHAR);
+        ok_(__FILE__, line)(data.ulLength == len, "got wrong data length %d, expected %d\n", data.ulLength, len);
+
+        ptrW = (WCHAR*)((BYTE*)surrogate + surrogate->name_offset);
+        ok(!lstrcmpW(ptrW, name), "got wrong name %s\n", wine_dbgstr_w(ptrW));
+
+        ptrW = (WCHAR*)((BYTE*)surrogate + surrogate->version_offset);
+        ok(!lstrcmpW(ptrW, version), "got wrong name %s\n", wine_dbgstr_w(ptrW));
+    }
+
+    ok_(__FILE__, line)(data.lpSectionGlobalData == NULL, "data.lpSectionGlobalData != NULL\n");
+    ok_(__FILE__, line)(data.ulSectionGlobalDataLength == 0, "data.ulSectionGlobalDataLength=%u\n",
+       data.ulSectionGlobalDataLength);
+    ok_(__FILE__, line)(data.lpSectionBase != NULL, "data.lpSectionBase == NULL\n");
+    ok_(__FILE__, line)(data.ulSectionTotalLength > 0, "data.ulSectionTotalLength=%u\n",
+       data.ulSectionTotalLength);
+    ok_(__FILE__, line)(data.hActCtx == NULL, "data.hActCtx=%p\n", data.hActCtx);
+    ok_(__FILE__, line)(data.ulAssemblyRosterIndex == exid, "data.ulAssemblyRosterIndex=%u, expected %u\n",
+       data.ulAssemblyRosterIndex, exid);
+}
+
+static void test_find_progid_redirection(HANDLE handle, const GUID *clsid, const char *progid, ULONG exid, int line)
+{
+    struct progidredirect_data *progiddata;
+    struct comclassredirect_data *comclass;
+    ACTCTX_SECTION_KEYED_DATA data, data2;
+    struct strsection_header *header;
+    BOOL ret;
+
+    memset(&data, 0xfe, sizeof(data));
+    data.cbSize = sizeof(data);
+
+    ret = pFindActCtxSectionStringA(0, NULL,
+                                       ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION,
+                                       progid, &data);
+    ok_(__FILE__, line)(ret, "FindActCtxSectionStringA failed: %u\n", GetLastError());
+
+    progiddata = (struct progidredirect_data*)data.lpData;
+
+    ok_(__FILE__, line)(data.cbSize == sizeof(data), "data.cbSize=%u\n", data.cbSize);
+    ok_(__FILE__, line)(data.ulDataFormatVersion == 1, "data.ulDataFormatVersion=%u\n", data.ulDataFormatVersion);
+    ok_(__FILE__, line)(data.lpData != NULL, "data.lpData == NULL\n");
+    ok_(__FILE__, line)(progiddata->size == sizeof(*progiddata), "got %d for header size\n", progiddata->size);
+    if (data.lpData && progiddata->size == sizeof(*progiddata))
+    {
+        GUID *guid;
+
+        ok_(__FILE__, line)(progiddata->reserved == 0, "got reserved as %d\n", progiddata->reserved);
+        ok_(__FILE__, line)(progiddata->clsid_offset > 0, "got clsid_offset as %d\n", progiddata->clsid_offset);
+
+        /* progid data points to generated alias guid */
+        guid = (GUID*)((BYTE*)data.lpSectionBase + progiddata->clsid_offset);
+
+        memset(&data2, 0, sizeof(data2));
+        data2.cbSize = sizeof(data2);
+        ret = pFindActCtxSectionGuid(0, NULL,
+                                        ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION,
+                                        guid, &data2);
+        ok_(__FILE__, line)(ret, "FindActCtxSectionGuid failed: %u\n", GetLastError());
+
+        comclass = (struct comclassredirect_data*)data2.lpData;
+        ok_(__FILE__, line)(IsEqualGUID(guid, &comclass->alias), "got wrong alias referenced from progid %s, %s\n", progid, wine_dbgstr_guid(guid));
+        ok_(__FILE__, line)(IsEqualGUID(clsid, &comclass->clsid), "got wrong class referenced from progid %s, %s\n", progid, wine_dbgstr_guid(clsid));
+    }
+
+    header = (struct strsection_header*)data.lpSectionBase;
+    ok_(__FILE__, line)(data.lpSectionGlobalData == (BYTE*)header + header->global_offset, "data.lpSectionGlobalData == NULL\n");
+    ok_(__FILE__, line)(data.ulSectionGlobalDataLength == header->global_len, "data.ulSectionGlobalDataLength=%u\n", data.ulSectionGlobalDataLength);
+    ok_(__FILE__, line)(data.lpSectionBase != NULL, "data.lpSectionBase == NULL\n");
+    ok_(__FILE__, line)(data.ulSectionTotalLength > 0, "data.ulSectionTotalLength=%u\n", data.ulSectionTotalLength);
+    ok_(__FILE__, line)(data.hActCtx == NULL, "data.hActCtx=%p\n", data.hActCtx);
+    ok_(__FILE__, line)(data.ulAssemblyRosterIndex == exid, "data.ulAssemblyRosterIndex=%u, expected %u\n",
+        data.ulAssemblyRosterIndex, exid);
+}
+
 static void test_wndclass_section(void)
 {
     static const WCHAR cls1W[] = {'1','.','2','.','3','.','4','!','w','n','d','C','l','a','s','s','1',0};
@@ -1220,6 +1557,8 @@ static void test_wndclass_section(void)
     create_manifest_file("main_wndcls.manifest", manifest_wndcls_main, -1, NULL, NULL);
 
     handle = test_create("main_wndcls.manifest");
+    ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
+
     DeleteFileA("testdep1.manifest");
     DeleteFileA("testdep2.manifest");
     DeleteFileA("main_wndcls.manifest");
@@ -1282,6 +1621,8 @@ static void test_dllredirect_section(void)
     create_manifest_file("main_wndcls.manifest", manifest_wndcls_main, -1, NULL, NULL);
 
     handle = test_create("main_wndcls.manifest");
+    ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
+
     DeleteFileA("testdep1.manifest");
     DeleteFileA("testdep2.manifest");
     DeleteFileA("main_wndcls.manifest");
@@ -1335,6 +1676,8 @@ static void test_typelib_section(void)
     create_manifest_file("main_wndcls.manifest", manifest_wndcls_main, -1, NULL, NULL);
 
     handle = test_create("main_wndcls.manifest");
+    ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
+
     DeleteFileA("testdep1.manifest");
     DeleteFileA("testdep2.manifest");
     DeleteFileA("main_wndcls.manifest");
@@ -1367,6 +1710,10 @@ static void test_typelib_section(void)
     ok(data.ulSectionTotalLength == data2.ulSectionTotalLength, "got %u, %u\n", data.ulSectionTotalLength,
         data2.ulSectionTotalLength);
 
+    ok(data.lpSectionGlobalData == ((BYTE*)section + section->names_offset), "data.lpSectionGlobalData == NULL\n");
+    ok(data.ulSectionGlobalDataLength == section->names_len, "data.ulSectionGlobalDataLength=%u\n",
+       data.ulSectionGlobalDataLength);
+
     /* test some actual data */
     tlib = (struct tlibredirect_data*)data.lpData;
     ok(tlib->size == sizeof(*tlib), "got %d\n", tlib->size);
@@ -1401,6 +1748,13 @@ static void test_actctx(void)
         pReleaseActCtx(handle);
     }
 
+    /* test for whitespace handling in Eq ::= S? '=' S? */
+    create_manifest_file("test1_1.manifest", manifest1_1, -1, NULL, NULL);
+    handle = test_create("test1_1.manifest");
+    ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
+    DeleteFileA("test1_1.manifest");
+    pReleaseActCtx(handle);
+
     if(!create_manifest_file("test1.manifest", manifest1, -1, NULL, NULL)) {
         skip("Could not create manifest file\n");
         return;
@@ -1409,6 +1763,7 @@ static void test_actctx(void)
     trace("manifest1\n");
 
     handle = test_create("test1.manifest");
+    ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
     DeleteFileA("test1.manifest");
     if(handle != INVALID_HANDLE_VALUE) {
         test_basic_info(handle, __LINE__);
@@ -1434,6 +1789,7 @@ static void test_actctx(void)
     trace("manifest2 depmanifest1\n");
 
     handle = test_create("test2.manifest");
+    ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
     DeleteFileA("test2.manifest");
     DeleteFileA("testdep.manifest");
     if(handle != INVALID_HANDLE_VALUE) {
@@ -1452,6 +1808,7 @@ static void test_actctx(void)
     trace("manifest2 depmanifest2\n");
 
     handle = test_create("test2-2.manifest");
+    ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
     DeleteFileA("test2-2.manifest");
     DeleteFileA("testdep.manifest");
     if(handle != INVALID_HANDLE_VALUE) {
@@ -1480,6 +1837,7 @@ static void test_actctx(void)
     }
 
     handle = test_create("test2-3.manifest");
+    ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
     DeleteFileA("test2-3.manifest");
     DeleteFileA("testdep.manifest");
     if(handle != INVALID_HANDLE_VALUE) {
@@ -1510,8 +1868,17 @@ static void test_actctx(void)
     }
 
     handle = test_create("test3.manifest");
+    ok(handle != INVALID_HANDLE_VALUE || broken(handle == INVALID_HANDLE_VALUE) /* XP pre-SP2, win2k3 w/o SP */,
+        "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
+    if (handle == INVALID_HANDLE_VALUE)
+        win_skip("Some activation context features not supported, skipping a test (possibly old XP/Win2k3 system\n");
     DeleteFileA("test3.manifest");
     if(handle != INVALID_HANDLE_VALUE) {
+        static const WCHAR nameW[] = {'t','e','s','t','s','u','r','r','o','g','a','t','e',0};
+        static const WCHAR versionW[] = {'v','2','.','0','.','5','0','7','2','7',0};
+        static const WCHAR progidW[] = {'P','r','o','g','I','d','.','P','r','o','g','I','d',0};
+        static const WCHAR clrprogidW[] = {'c','l','r','p','r','o','g','i','d',0};
+
         test_basic_info(handle, __LINE__);
         test_detailed_info(handle, &detailed_info1, __LINE__);
         test_info_in_assembly(handle, 1, &manifest3_info, __LINE__);
@@ -1521,11 +1888,31 @@ static void test_actctx(void)
         ok(b, "ActivateActCtx failed: %u\n", GetLastError());
         test_find_dll_redirection(handle, testlib_dll, 1, __LINE__);
         test_find_dll_redirection(handle, testlib_dll, 1, __LINE__);
-        test_find_com_redirection(handle, &IID_CoTest, &IID_TlibTest, 1, __LINE__);
+        test_find_com_redirection(handle, &IID_CoTest, &IID_TlibTest, progidW, 1, __LINE__);
+        test_find_com_redirection(handle, &IID_CoTest2, NULL, NULL, 1, __LINE__);
+        test_find_com_redirection(handle, &CLSID_clrclass, &IID_TlibTest, clrprogidW, 1, __LINE__);
+        test_find_progid_redirection(handle, &IID_CoTest, "ProgId.ProgId", 1, __LINE__);
+        test_find_progid_redirection(handle, &IID_CoTest, "ProgId.ProgId.1", 1, __LINE__);
+        test_find_progid_redirection(handle, &IID_CoTest, "ProgId.ProgId.2", 1, __LINE__);
+        test_find_progid_redirection(handle, &IID_CoTest, "ProgId.ProgId.3", 1, __LINE__);
+        test_find_progid_redirection(handle, &IID_CoTest, "ProgId.ProgId.4", 1, __LINE__);
+        test_find_progid_redirection(handle, &IID_CoTest, "ProgId.ProgId.5", 1, __LINE__);
+        test_find_progid_redirection(handle, &IID_CoTest, "ProgId.ProgId.6", 1, __LINE__);
+        test_find_progid_redirection(handle, &CLSID_clrclass, "clrprogid", 1, __LINE__);
+        test_find_progid_redirection(handle, &CLSID_clrclass, "clrprogid.1", 1, __LINE__);
+        test_find_progid_redirection(handle, &CLSID_clrclass, "clrprogid.2", 1, __LINE__);
+        test_find_progid_redirection(handle, &CLSID_clrclass, "clrprogid.3", 1, __LINE__);
+        test_find_progid_redirection(handle, &CLSID_clrclass, "clrprogid.4", 1, __LINE__);
+        test_find_progid_redirection(handle, &CLSID_clrclass, "clrprogid.5", 1, __LINE__);
+        test_find_progid_redirection(handle, &CLSID_clrclass, "clrprogid.6", 1, __LINE__);
+        test_find_surrogate(handle, &IID_Iiface, nameW, versionW, 1, __LINE__);
+        test_find_ifaceps_redirection(handle, &IID_Iifaceps, &IID_TlibTest4, &IID_Ibifaceps, NULL, 1, __LINE__);
+        test_find_ifaceps_redirection(handle, &IID_Iifaceps2, &IID_TlibTest4, &IID_Ibifaceps, &IID_PS32, 1, __LINE__);
+        test_find_ifaceps_redirection(handle, &IID_Iifaceps3, &IID_TlibTest4, &IID_Ibifaceps, NULL, 1, __LINE__);
         test_find_string_fail();
+
         b = pDeactivateActCtx(0, cookie);
         ok(b, "DeactivateActCtx failed: %u\n", GetLastError());
-
         pReleaseActCtx(handle);
     }
 
@@ -1537,6 +1924,7 @@ static void test_actctx(void)
     }
 
     handle = test_create("test4.manifest");
+    ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
     DeleteFileA("test4.manifest");
     DeleteFileA("testdep.manifest");
     if(handle != INVALID_HANDLE_VALUE) {
@@ -1557,6 +1945,7 @@ static void test_actctx(void)
             return;
         }
         handle = test_create("..\\test1.manifest");
+        ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
         DeleteFileA("..\\test1.manifest");
         if(handle != INVALID_HANDLE_VALUE) {
             test_basic_info(handle, __LINE__);
@@ -1577,6 +1966,7 @@ static void test_actctx(void)
     }
 
     handle = test_create("test1.manifest");
+    ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
     DeleteFileA("test1.manifest");
     if (handle != INVALID_HANDLE_VALUE) {
         test_basic_info(handle, __LINE__);
@@ -1592,6 +1982,7 @@ static void test_actctx(void)
     }
 
     handle = test_create("test1.manifest");
+    ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
     DeleteFileA("test1.manifest");
     if (handle != INVALID_HANDLE_VALUE) {
         test_basic_info(handle, __LINE__);
@@ -1629,7 +2020,7 @@ static void run_child_process(void)
     char path[MAX_PATH];
     char **argv;
     PROCESS_INFORMATION pi;
-    STARTUPINFO si = { 0 };
+    STARTUPINFOA si = { 0 };
     HANDLE file;
     FILETIME now;
     BOOL ret;
@@ -1653,7 +2044,7 @@ static void run_child_process(void)
         CloseHandle(file);
     }
     sprintf(cmdline, "\"%s\" %s manifest1", argv[0], argv[1]);
-    ret = CreateProcess(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+    ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
     ok(ret, "Could not create process: %u\n", GetLastError());
     winetest_wait_child_process( pi.hProcess );
     CloseHandle(pi.hThread);
@@ -1686,14 +2077,108 @@ static void init_paths(void)
     lstrcpyW(app_manifest_path+lstrlenW(app_manifest_path), dot_manifest);
 }
 
+static void write_manifest(const char *filename, const char *manifest)
+{
+    HANDLE file;
+    DWORD size;
+    CHAR path[MAX_PATH];
+
+    GetTempPathA(sizeof(path)/sizeof(CHAR), path);
+    strcat(path, filename);
+
+    file = CreateFileA(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+    ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
+    WriteFile(file, manifest, strlen(manifest), &size, NULL);
+    CloseHandle(file);
+}
+
+static void delete_manifest_file(const char *filename)
+{
+    CHAR path[MAX_PATH];
+
+    GetTempPathA(sizeof(path)/sizeof(CHAR), path);
+    strcat(path, filename);
+    DeleteFileA(path);
+}
+
+static void test_CreateActCtx(void)
+{
+    CHAR path[MAX_PATH], dir[MAX_PATH];
+    ACTCTXA actctx;
+    HANDLE handle;
+
+    GetTempPathA(sizeof(path)/sizeof(CHAR), path);
+    strcat(path, "main_wndcls.manifest");
+
+    write_manifest("testdep1.manifest", manifest_wndcls1);
+    write_manifest("testdep2.manifest", manifest_wndcls2);
+    write_manifest("main_wndcls.manifest", manifest_wndcls_main);
+
+    memset(&actctx, 0, sizeof(ACTCTXA));
+    actctx.cbSize = sizeof(ACTCTXA);
+    actctx.lpSource = path;
+
+    /* create using lpSource without specified directory */
+    handle = pCreateActCtxA(&actctx);
+    ok(handle != INVALID_HANDLE_VALUE, "failed to generate context, error %u\n", GetLastError());
+    pReleaseActCtx(handle);
+
+    /* with specified directory, that doesn't contain dependent assembly */
+    GetWindowsDirectoryA(dir, sizeof(dir)/sizeof(CHAR));
+
+    memset(&actctx, 0, sizeof(ACTCTXA));
+    actctx.cbSize = sizeof(ACTCTXA);
+    actctx.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID;
+    actctx.lpAssemblyDirectory = dir;
+    actctx.lpSource = path;
+
+    SetLastError(0xdeadbeef);
+    handle = pCreateActCtxA(&actctx);
+todo_wine {
+    ok(handle == INVALID_HANDLE_VALUE, "got handle %p\n", handle);
+    ok(GetLastError() == ERROR_SXS_CANT_GEN_ACTCTX, "got error %d\n", GetLastError());
+}
+    if (handle != INVALID_HANDLE_VALUE) pReleaseActCtx(handle);
+
+    delete_manifest_file("main_wndcls.manifest");
+    delete_manifest_file("testdep1.manifest");
+    delete_manifest_file("testdep2.manifest");
+
+    /* ACTCTX_FLAG_HMODULE_VALID but hModule is not set */
+    memset(&actctx, 0, sizeof(ACTCTXA));
+    actctx.cbSize = sizeof(ACTCTXA);
+    actctx.dwFlags = ACTCTX_FLAG_HMODULE_VALID;
+    SetLastError(0xdeadbeef);
+    handle = pCreateActCtxA(&actctx);
+    ok(handle == INVALID_HANDLE_VALUE, "got handle %p\n", handle);
+todo_wine
+    ok(GetLastError() == ERROR_SXS_CANT_GEN_ACTCTX || broken(GetLastError() == ERROR_NOT_ENOUGH_MEMORY) /* XP, win2k3 */,
+        "got error %d\n", GetLastError());
+
+    /* create from HMODULE - resource doesn't exist, lpSource is set */
+    memset(&actctx, 0, sizeof(ACTCTXA));
+    actctx.cbSize = sizeof(ACTCTXA);
+    actctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
+    actctx.lpSource = "dummyfile.dll";
+    actctx.lpResourceName = MAKEINTRESOURCEA(20);
+    actctx.hModule = GetModuleHandleA(NULL);
+
+    SetLastError(0xdeadbeef);
+    handle = pCreateActCtxA(&actctx);
+    ok(handle == INVALID_HANDLE_VALUE, "got handle %p\n", handle);
+    ok(GetLastError() == ERROR_RESOURCE_TYPE_NOT_FOUND, "got error %d\n", GetLastError());
+}
+
 static BOOL init_funcs(void)
 {
-    HMODULE hKernel32 = GetModuleHandle("kernel32");
+    HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
 
 #define X(f) if (!(p##f = (void*)GetProcAddress(hKernel32, #f))) return FALSE;
     X(ActivateActCtx);
+    X(CreateActCtxA);
     X(CreateActCtxW);
     X(DeactivateActCtx);
+    X(FindActCtxSectionStringA);
     X(FindActCtxSectionStringW);
     X(GetCurrentActCtx);
     X(IsDebuggerPresent);
@@ -1725,5 +2210,6 @@ START_TEST(actctx)
     }
 
     test_actctx();
+    test_CreateActCtx();
     run_child_process();
 }
diff --git a/rostests/winetests/kernel32/alloc.c b/rostests/winetests/kernel32/alloc.c
deleted file mode 100755 (executable)
index c1b2afc..0000000
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * Unit test suite for memory allocation functions.
- *
- * Copyright 2002 Geoffrey Hausheer
- *
- * 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 "wine/test.h"
-#include "windef.h"
-#include "winbase.h"
-#include "winerror.h"
-
-
- /* The following functions don't have tests, because either I don't know how
-   to test them, or they are WinNT only, or require multiple threads.
-   Since the last two issues shouldn't really stop the tests from being
-   written, assume for now that it is all due to the first case
-       HeapCompact
-       HeapLock
-       HeapQueryInformation
-       HeapSetInformation
-       HeapUnlock
-       HeapValidate
-       HeapWalk
-*/
-/* In addition, these features aren't being tested
-       HEAP_NO_SERIALIZE
-       HEAP_GENERATE_EXCEPTIONS
-       STATUS_ACCESS_VIOLATION (error code from HeapAlloc)
-*/
-
-static void test_Heap(void)
-{
-    SYSTEM_INFO sysInfo;
-    ULONG memchunk;
-    HANDLE heap;
-    LPVOID mem1,mem1a,mem3;
-    UCHAR *mem2,*mem2a;
-    UINT error,i;
-    DWORD dwSize;
-
-/* Retrieve the page size for this system */
-    sysInfo.dwPageSize=0;
-    GetSystemInfo(&sysInfo);
-    ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
-
-/* Create a Heap with a minimum and maximum size */
-/* Note that Windows and Wine seem to behave a bit differently with respect
-   to memory allocation.  In Windows, you can't access all the memory
-   specified in the heap (due to overhead), so choosing a reasonable maximum
-   size for the heap was done mostly by trial-and-error on Win2k.  It may need
-   more tweaking for otherWindows variants.
-*/
-    memchunk=10*sysInfo.dwPageSize;
-    heap=HeapCreate(0,2*memchunk,5*memchunk);
-
-/* Check that HeapCreate allocated the right amount of ram */
-    mem1=HeapAlloc(heap,0,5*memchunk+1);
-    ok(mem1==NULL,"HeapCreate allocated more Ram than it should have\n");
-    HeapFree(heap,0,mem1);
-
-/* Check that a normal alloc works */
-    mem1=HeapAlloc(heap,0,memchunk);
-    ok(mem1!=NULL,"HeapAlloc failed\n");
-    if(mem1) {
-      ok(HeapSize(heap,0,mem1)>=memchunk, "HeapAlloc should return a big enough memory block\n");
-    }
-
-/* Check that a 'zeroing' alloc works */
-    mem2=HeapAlloc(heap,HEAP_ZERO_MEMORY,memchunk);
-    ok(mem2!=NULL,"HeapAlloc failed\n");
-    if(mem2) {
-      ok(HeapSize(heap,0,mem2)>=memchunk,"HeapAlloc should return a big enough memory block\n");
-      error=0;
-      for(i=0;i<memchunk;i++) {
-        if(mem2[i]!=0) {
-          error=1;
-        }
-      }
-      ok(!error,"HeapAlloc should have zeroed out it's allocated memory\n");
-    }
-
-/* Check that HeapAlloc returns NULL when requested way too much memory */
-    mem3=HeapAlloc(heap,0,5*memchunk);
-    ok(mem3==NULL,"HeapAlloc should return NULL\n");
-    if(mem3) {
-      ok(HeapFree(heap,0,mem3),"HeapFree didn't pass successfully\n");
-    }
-
-/* Check that HeapRealloc works */
-    mem2a=HeapReAlloc(heap,HEAP_ZERO_MEMORY,mem2,memchunk+5*sysInfo.dwPageSize);
-    ok(mem2a!=NULL,"HeapReAlloc failed\n");
-    if(mem2a) {
-      ok(HeapSize(heap,0,mem2a)>=memchunk+5*sysInfo.dwPageSize,"HeapReAlloc failed\n");
-      error=0;
-      for(i=0;i<5*sysInfo.dwPageSize;i++) {
-        if(mem2a[memchunk+i]!=0) {
-          error=1;
-        }
-      }
-      ok(!error,"HeapReAlloc should have zeroed out it's allocated memory\n");
-    }
-
-/* Check that HeapRealloc honours HEAP_REALLOC_IN_PLACE_ONLY */
-    error=0;
-    mem1a=HeapReAlloc(heap,HEAP_REALLOC_IN_PLACE_ONLY,mem1,memchunk+sysInfo.dwPageSize);
-    if(mem1a!=NULL) {
-      if(mem1a!=mem1) {
-        error=1;
-      }
-    }
-    ok(mem1a==NULL || error==0,"HeapReAlloc didn't honour HEAP_REALLOC_IN_PLACE_ONLY\n");
-
-/* Check that HeapFree works correctly */
-   if(mem1a) {
-     ok(HeapFree(heap,0,mem1a),"HeapFree failed\n");
-   } else {
-     ok(HeapFree(heap,0,mem1),"HeapFree failed\n");
-   }
-   if(mem2a) {
-     ok(HeapFree(heap,0,mem2a),"HeapFree failed\n");
-   } else {
-     ok(HeapFree(heap,0,mem2),"HeapFree failed\n");
-   }
-
-   /* 0-length buffer */
-   mem1 = HeapAlloc(heap, 0, 0);
-   ok(mem1 != NULL, "Reserved memory\n");
-
-   dwSize = HeapSize(heap, 0, mem1);
-   /* should work with 0-length buffer */
-   ok(dwSize < 0xFFFFFFFF, "The size of the 0-length buffer\n");
-   ok(HeapFree(heap, 0, mem1), "Freed the 0-length buffer\n");
-
-/* Check that HeapDestry works */
-   ok(HeapDestroy(heap),"HeapDestroy failed\n");
-}
-
-/* The following functions don't have tests, because either I don't know how
-   to test them, or they are WinNT only, or require multiple threads.
-   Since the last two issues shouldn't really stop the tests from being
-   written, assume for now that it is all due to the first case
-       GlobalFlags
-       GlobalMemoryStatus
-       GlobalMemoryStatusEx
-*/
-/* In addition, these features aren't being tested
-       GMEM_DISCARDABLE
-       GMEM_NOCOMPACT
-*/
-static void test_Global(void)
-{
-    ULONG memchunk;
-    HGLOBAL mem1,mem2,mem2a,mem2b;
-    UCHAR *mem2ptr;
-    UINT error,i;
-    memchunk=100000;
-
-    SetLastError(NO_ERROR);
-/* Check that a normal alloc works */
-    mem1=GlobalAlloc(0,memchunk);
-    ok(mem1!=NULL,"GlobalAlloc failed\n");
-    if(mem1) {
-      ok(GlobalSize(mem1)>=memchunk, "GlobalAlloc should return a big enough memory block\n");
-    }
-
-/* Check that a 'zeroing' alloc works */
-    mem2=GlobalAlloc(GMEM_ZEROINIT,memchunk);
-    ok(mem2!=NULL,"GlobalAlloc failed: error=%d\n",GetLastError());
-    if(mem2) {
-      ok(GlobalSize(mem2)>=memchunk,"GlobalAlloc should return a big enough memory block\n");
-      mem2ptr=GlobalLock(mem2);
-      ok(mem2ptr==mem2,"GlobalLock should have returned the same memory as was allocated\n");
-      if(mem2ptr) {
-        error=0;
-        for(i=0;i<memchunk;i++) {
-          if(mem2ptr[i]!=0) {
-            error=1;
-          }
-        }
-        ok(!error,"GlobalAlloc should have zeroed out it's allocated memory\n");
-      }
-   }
-/* Check that GlobalReAlloc works */
-/* Check that we can change GMEM_FIXED to GMEM_MOVEABLE */
-    mem2a=GlobalReAlloc(mem2,0,GMEM_MODIFY | GMEM_MOVEABLE);
-    if(mem2a!=NULL) {
-      mem2=mem2a;
-      mem2ptr=GlobalLock(mem2a);
-      ok(mem2ptr!=NULL && !GlobalUnlock(mem2a)&&GetLastError()==NO_ERROR,
-         "Converting from FIXED to MOVEABLE didn't REALLY work\n");
-    }
-
-/* Check that ReAllocing memory works as expected */
-    mem2a=GlobalReAlloc(mem2,2*memchunk,GMEM_MOVEABLE | GMEM_ZEROINIT);
-    ok(mem2a!=NULL,"GlobalReAlloc failed\n");
-    if(mem2a) {
-      ok(GlobalSize(mem2a)>=2*memchunk,"GlobalReAlloc failed\n");
-      mem2ptr=GlobalLock(mem2a);
-      ok(mem2ptr!=NULL,"GlobalLock Failed\n");
-      if(mem2ptr) {
-        error=0;
-        for(i=0;i<memchunk;i++) {
-          if(mem2ptr[memchunk+i]!=0) {
-            error=1;
-          }
-        }
-        ok(!error,"GlobalReAlloc should have zeroed out it's allocated memory\n");
-
-/* Check that GlobalHandle works */
-        mem2b=GlobalHandle(mem2ptr);
-        ok(mem2b==mem2a,"GlobalHandle didn't return the correct memory handle\n");
-
-/* Check that we can't discard locked memory */
-        mem2b=GlobalDiscard(mem2a);
-        if(mem2b==NULL) {
-          ok(!GlobalUnlock(mem2a) && GetLastError()==NO_ERROR,"GlobalUnlock Failed\n");
-        }
-      }
-    }
-    if(mem1) {
-      ok(GlobalFree(mem1)==NULL,"GlobalFree failed\n");
-    }
-    if(mem2a) {
-      ok(GlobalFree(mem2a)==NULL,"GlobalFree failed\n");
-    } else {
-      ok(GlobalFree(mem2)==NULL,"GlobalFree failed\n");
-    }
-}
-
-
-/* The following functions don't have tests, because either I don't know how
-   to test them, or they are WinNT only, or require multiple threads.
-   Since the last two issues shouldn't really stop the tests from being
-   written, assume for now that it is all due to the first case
-       LocalDiscard
-       LocalFlags
-*/
-/* In addition, these features aren't being tested
-       LMEM_DISCARDABLE
-       LMEM_NOCOMPACT
-*/
-static void test_Local(void)
-{
-    ULONG memchunk;
-    HLOCAL mem1,mem2,mem2a,mem2b;
-    UCHAR *mem2ptr;
-    UINT error,i;
-    memchunk=100000;
-
-/* Check that a normal alloc works */
-    mem1=LocalAlloc(0,memchunk);
-    ok(mem1!=NULL,"LocalAlloc failed: error=%d\n",GetLastError());
-    if(mem1) {
-      ok(LocalSize(mem1)>=memchunk, "LocalAlloc should return a big enough memory block\n");
-    }
-
-/* Check that a 'zeroing' and lock alloc works */
-    mem2=LocalAlloc(LMEM_ZEROINIT|LMEM_MOVEABLE,memchunk);
-    ok(mem2!=NULL,"LocalAlloc failed: error=%d\n",GetLastError());
-    if(mem2) {
-      ok(LocalSize(mem2)>=memchunk,"LocalAlloc should return a big enough memory block\n");
-      mem2ptr=LocalLock(mem2);
-      ok(mem2ptr!=NULL,"LocalLock: error=%d\n",GetLastError());
-      if(mem2ptr) {
-        error=0;
-        for(i=0;i<memchunk;i++) {
-          if(mem2ptr[i]!=0) {
-            error=1;
-          }
-        }
-        ok(!error,"LocalAlloc should have zeroed out it's allocated memory\n");
-        SetLastError(0);
-        error=LocalUnlock(mem2);
-        ok(error==0 && GetLastError()==NO_ERROR,
-           "LocalUnlock Failed: rc=%d err=%d\n",error,GetLastError());
-      }
-    }
-   mem2a=LocalFree(mem2);
-   ok(mem2a==NULL, "LocalFree failed: %p\n",mem2a);
-
-/* Reallocate mem2 as moveable memory */
-   mem2=LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT,memchunk);
-   ok(mem2!=NULL, "LocalAlloc failed to create moveable memory, error=%d\n",GetLastError());
-
-/* Check that ReAllocing memory works as expected */
-    mem2a=LocalReAlloc(mem2,2*memchunk,LMEM_MOVEABLE | LMEM_ZEROINIT);
-    ok(mem2a!=NULL,"LocalReAlloc failed, error=%d\n",GetLastError());
-    if(mem2a) {
-      ok(LocalSize(mem2a)>=2*memchunk,"LocalReAlloc failed\n");
-      mem2ptr=LocalLock(mem2a);
-      ok(mem2ptr!=NULL,"LocalLock Failed\n");
-      if(mem2ptr) {
-        error=0;
-        for(i=0;i<memchunk;i++) {
-          if(mem2ptr[memchunk+i]!=0) {
-            error=1;
-          }
-        }
-        ok(!error,"LocalReAlloc should have zeroed out it's allocated memory\n");
-/* Check that LocalHandle works */
-        mem2b=LocalHandle(mem2ptr);
-        ok(mem2b==mem2a,"LocalHandle didn't return the correct memory handle\n");
-/* Check that we can't discard locked memory */
-        mem2b=LocalDiscard(mem2a);
-        ok(mem2b==NULL,"Discarded memory we shouldn't have\n");
-        SetLastError(NO_ERROR);
-        ok(!LocalUnlock(mem2a) && GetLastError()==NO_ERROR, "LocalUnlock Failed\n");
-      }
-    }
-    if(mem1) {
-      ok(LocalFree(mem1)==NULL,"LocalFree failed\n");
-    }
-    if(mem2a) {
-      ok(LocalFree(mem2a)==NULL,"LocalFree failed\n");
-    } else {
-      ok(LocalFree(mem2)==NULL,"LocalFree failed\n");
-    }
-}
-
-/* The Virtual* routines are not tested as thoroughly,
-   since I don't really understand how to use them correctly :)
-   The following routines are not tested at all
-      VirtualAllocEx
-      VirtualFreeEx
-      VirtualLock
-      VirtualProtect
-      VirtualProtectEx
-      VirtualQuery
-      VirtualQueryEx
-      VirtualUnlock
-    And the only features (flags) being tested are
-      MEM_COMMIT
-      MEM_RELEASE
-      PAGE_READWRITE
-    Testing the rest requires using exceptions, which I really don't
-    understand well
-*/
-static void test_Virtual(void)
-{
-    SYSTEM_INFO sysInfo;
-    ULONG memchunk;
-    UCHAR *mem1;
-    UINT error,i;
-
-/* Retrieve the page size for this system */
-    sysInfo.dwPageSize=0;
-    GetSystemInfo(&sysInfo);
-    ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
-
-/* Choose a reasonable allocation size */
-    memchunk=10*sysInfo.dwPageSize;
-
-/* Check that a normal alloc works */
-    mem1=VirtualAlloc(NULL,memchunk,MEM_COMMIT,PAGE_READWRITE);
-    ok(mem1!=NULL,"VirtualAlloc failed\n");
-    if(mem1) {
-/* check that memory is initialized to 0 */
-      error=0;
-      for(i=0;i<memchunk;i++) {
-        if(mem1[i]!=0) {
-          error=1;
-        }
-      }
-      ok(!error,"VirtualAlloc did not initialize memory to '0's\n");
-/* Check that we can read/write to memory */
-      error=0;
-      for(i=0;i<memchunk;i+=100) {
-        mem1[i]='a';
-        if(mem1[i]!='a') {
-          error=1;
-        }
-      }
-      ok(!error,"Virtual memory was not writable\n");
-    }
-    ok(VirtualFree(mem1,0,MEM_RELEASE),"VirtualFree failed\n");
-}
-START_TEST(alloc)
-{
-    test_Heap();
-    test_Global();
-    test_Local();
-    test_Virtual();
-}
index 6142e43..9226950 100755 (executable)
@@ -426,7 +426,7 @@ static void test_readdirectorychanges(void)
                         OPEN_EXISTING, fflags, NULL);
     ok( hdir != INVALID_HANDLE_VALUE, "failed to open directory\n");
 
-    ov.hEvent = CreateEvent( NULL, 1, 0, NULL );
+    ov.hEvent = CreateEventW( NULL, 1, 0, NULL );
 
     SetLastError(0xd0b00b00);
     r = pReadDirectoryChangesW(hdir,NULL,0,FALSE,0,NULL,NULL,NULL);
@@ -644,7 +644,7 @@ static void test_readdirectorychanges_null(void)
                         OPEN_EXISTING, fflags, NULL);
     ok( hdir != INVALID_HANDLE_VALUE, "failed to open directory\n");
 
-    ov.hEvent = CreateEvent( NULL, 1, 0, NULL );
+    ov.hEvent = CreateEventW( NULL, 1, 0, NULL );
 
     filter = FILE_NOTIFY_CHANGE_FILE_NAME;
     filter |= FILE_NOTIFY_CHANGE_DIR_NAME;
@@ -733,7 +733,7 @@ static void test_readdirectorychanges_filedir(void)
     DeleteFileW( file );
     RemoveDirectoryW( subdir );
     RemoveDirectoryW( path );
-    
+
     r = CreateDirectoryW(path, NULL);
     ok( r == TRUE, "failed to create directory\n");
 
@@ -743,7 +743,7 @@ static void test_readdirectorychanges_filedir(void)
                         OPEN_EXISTING, fflags, NULL);
     ok( hdir != INVALID_HANDLE_VALUE, "failed to open directory\n");
 
-    ov.hEvent = CreateEvent( NULL, 0, 0, NULL );
+    ov.hEvent = CreateEventW( NULL, 0, 0, NULL );
 
     filter = FILE_NOTIFY_CHANGE_FILE_NAME;
 
@@ -1088,7 +1088,7 @@ static void test_ffcn_directory_overlap(void)
 
 START_TEST(change)
 {
-    HMODULE hkernel32 = GetModuleHandle("kernel32");
+    HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
     pReadDirectoryChangesW = (void *)GetProcAddress(hkernel32, "ReadDirectoryChangesW");
 
     test_ffcnMultipleThreads();
index 36ea66d..8423c75 100755 (executable)
@@ -462,6 +462,147 @@ static void test_undefined_byte_char(void)
     }
 }
 
+static void test_threadcp(void)
+{
+    static const LCID ENGLISH  = MAKELCID(MAKELANGID(LANG_ENGLISH,  SUBLANG_ENGLISH_US),         SORT_DEFAULT);
+    static const LCID HINDI    = MAKELCID(MAKELANGID(LANG_HINDI,    SUBLANG_HINDI_INDIA),        SORT_DEFAULT);
+    static const LCID GEORGIAN = MAKELCID(MAKELANGID(LANG_GEORGIAN, SUBLANG_GEORGIAN_GEORGIA),   SORT_DEFAULT);
+    static const LCID RUSSIAN  = MAKELCID(MAKELANGID(LANG_RUSSIAN,  SUBLANG_RUSSIAN_RUSSIA),     SORT_DEFAULT);
+    static const LCID JAPANESE = MAKELCID(MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN),     SORT_DEFAULT);
+    static const LCID CHINESE  = MAKELCID(MAKELANGID(LANG_CHINESE,  SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT);
+
+    BOOL islead, islead_acp;
+    CPINFOEXA cpi;
+    UINT cp, acp;
+    int  i, num;
+    LCID last;
+    BOOL ret;
+
+    struct test {
+        LCID lcid;
+        UINT threadcp;
+    } lcids[] = {
+        { HINDI,    0    },
+        { GEORGIAN, 0    },
+        { ENGLISH,  1252 },
+        { RUSSIAN,  1251 },
+        { JAPANESE, 932  },
+        { CHINESE,  936  }
+    };
+
+    struct test_islead_nocp {
+        LCID lcid;
+        BYTE testchar;
+    } isleads_nocp[] = {
+        { HINDI,    0x00 },
+        { HINDI,    0x81 },
+        { HINDI,    0xa0 },
+        { HINDI,    0xe0 },
+
+        { GEORGIAN, 0x00 },
+        { GEORGIAN, 0x81 },
+        { GEORGIAN, 0xa0 },
+        { GEORGIAN, 0xe0 },
+    };
+
+    struct test_islead {
+        LCID lcid;
+        BYTE testchar;
+        BOOL islead;
+    } isleads[] = {
+        { ENGLISH,  0x00, FALSE },
+        { ENGLISH,  0x81, FALSE },
+        { ENGLISH,  0xa0, FALSE },
+        { ENGLISH,  0xe0, FALSE },
+
+        { RUSSIAN,  0x00, FALSE },
+        { RUSSIAN,  0x81, FALSE },
+        { RUSSIAN,  0xa0, FALSE },
+        { RUSSIAN,  0xe0, FALSE },
+
+        { JAPANESE, 0x00, FALSE },
+        { JAPANESE, 0x81,  TRUE },
+        { JAPANESE, 0xa0, FALSE },
+        { JAPANESE, 0xe0,  TRUE },
+
+        { CHINESE,  0x00, FALSE },
+        { CHINESE,  0x81,  TRUE },
+        { CHINESE,  0xa0,  TRUE },
+        { CHINESE,  0xe0,  TRUE },
+    };
+
+    last = GetThreadLocale();
+    acp  = GetACP();
+
+    for (i = 0; i < sizeof(lcids)/sizeof(lcids[0]); i++)
+    {
+        SetThreadLocale(lcids[i].lcid);
+
+        cp = 0xdeadbeef;
+        GetLocaleInfoA(lcids[i].lcid, LOCALE_IDEFAULTANSICODEPAGE|LOCALE_RETURN_NUMBER, (LPSTR)&cp, sizeof(cp));
+        ok(cp == lcids[i].threadcp, "wrong codepage %u for lcid %04x, should be %u\n", cp, lcids[i].threadcp, cp);
+
+        /* GetCPInfoEx/GetCPInfo - CP_ACP */
+        SetLastError(0xdeadbeef);
+        memset(&cpi, 0, sizeof(cpi));
+        ret = GetCPInfoExA(CP_ACP, 0, &cpi);
+        ok(ret, "GetCPInfoExA failed for lcid %04x, error %d\n", lcids[i].lcid, GetLastError());
+        ok(cpi.CodePage == acp, "wrong codepage %u for lcid %04x, should be %u\n", cpi.CodePage, lcids[i].lcid, acp);
+
+        /* WideCharToMultiByte - CP_ACP */
+        num = WideCharToMultiByte(CP_ACP, 0, foobarW, -1, NULL, 0, NULL, NULL);
+        ok(num == 7, "ret is %d (%04x)\n", num, lcids[i].lcid);
+
+        /* MultiByteToWideChar - CP_ACP */
+        num = MultiByteToWideChar(CP_ACP, 0, "foobar", -1, NULL, 0);
+        ok(num == 7, "ret is %d (%04x)\n", num, lcids[i].lcid);
+
+        /* GetCPInfoEx/GetCPInfo - CP_THREAD_ACP */
+        SetLastError(0xdeadbeef);
+        memset(&cpi, 0, sizeof(cpi));
+        ret = GetCPInfoExA(CP_THREAD_ACP, 0, &cpi);
+        ok(ret, "GetCPInfoExA failed for lcid %04x, error %d\n", lcids[i].lcid, GetLastError());
+        if (lcids[i].threadcp)
+            ok(cpi.CodePage == lcids[i].threadcp, "wrong codepage %u for lcid %04x, should be %u\n",
+               cpi.CodePage, lcids[i].lcid, lcids[i].threadcp);
+        else
+            ok(cpi.CodePage == acp, "wrong codepage %u for lcid %04x, should be %u\n",
+               cpi.CodePage, lcids[i].lcid, acp);
+
+        /* WideCharToMultiByte - CP_THREAD_ACP */
+        num = WideCharToMultiByte(CP_THREAD_ACP, 0, foobarW, -1, NULL, 0, NULL, NULL);
+        ok(num == 7, "ret is %d (%04x)\n", num, lcids[i].lcid);
+
+        /* MultiByteToWideChar - CP_THREAD_ACP */
+        num = MultiByteToWideChar(CP_THREAD_ACP, 0, "foobar", -1, NULL, 0);
+        ok(num == 7, "ret is %d (%04x)\n", num, lcids[i].lcid);
+    }
+
+    /* IsDBCSLeadByteEx - locales without codepage */
+    for (i = 0; i < sizeof(isleads_nocp)/sizeof(isleads_nocp[0]); i++)
+    {
+        SetThreadLocale(isleads_nocp[i].lcid);
+
+        islead_acp = IsDBCSLeadByteEx(CP_ACP,        isleads_nocp[i].testchar);
+        islead     = IsDBCSLeadByteEx(CP_THREAD_ACP, isleads_nocp[i].testchar);
+
+        ok(islead == islead_acp, "wrong islead %i for test char %x in lcid %04x.  should be %i\n",
+            islead, isleads_nocp[i].testchar, isleads_nocp[i].lcid, islead_acp);
+    }
+
+    /* IsDBCSLeadByteEx - locales with codepage */
+    for (i = 0; i < sizeof(isleads)/sizeof(isleads[0]); i++)
+    {
+        SetThreadLocale(isleads[i].lcid);
+
+        islead = IsDBCSLeadByteEx(CP_THREAD_ACP, isleads[i].testchar);
+        ok(islead == isleads[i].islead, "wrong islead %i for test char %x in lcid %04x.  should be %i\n",
+            islead, isleads[i].testchar, isleads[i].lcid, isleads[i].islead);
+    }
+
+    SetThreadLocale(last);
+}
+
 START_TEST(codepage)
 {
     BOOL bUsedDefaultChar;
@@ -478,4 +619,5 @@ START_TEST(codepage)
     test_string_conversion(&bUsedDefaultChar);
 
     test_undefined_byte_char();
+    test_threadcp();
 }
index e5264c8..cbd276b 100755 (executable)
 
 #include <stdio.h>
 
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
 #include "wine/test.h"
+#include "winternl.h"
 #include "winbase.h"
 #include "winnls.h"
 
@@ -48,6 +51,16 @@ static BOOL loopback_dtr_dsr  = LOOPBACK_DTR_DSR;
 static BOOL loopback_dtr_ring = LOOPBACK_DTR_RING;
 static BOOL loopback_dtr_dcd  = LOOPBACK_DTR_DCD;
 
+static NTSTATUS (WINAPI *pNtReadFile)(HANDLE hFile, HANDLE hEvent,
+                                      PIO_APC_ROUTINE apc, void* apc_user,
+                                      PIO_STATUS_BLOCK io_status, void* buffer, ULONG length,
+                                      PLARGE_INTEGER offset, PULONG key);
+static NTSTATUS (WINAPI *pNtWriteFile)(HANDLE hFile, HANDLE hEvent,
+                                       PIO_APC_ROUTINE apc, void* apc_user,
+                                       PIO_STATUS_BLOCK io_status,
+                                       const void* buffer, ULONG length,
+                                       PLARGE_INTEGER offset, PULONG key);
+
 typedef struct
 {
        char string[100];
@@ -633,7 +646,7 @@ static void test_BuildCommDCB(void)
                COMMCONFIG commconfig;
                DWORD size = sizeof(COMMCONFIG);
 
-               if(GetDefaultCommConfig(port_name, &commconfig, &size))
+               if(GetDefaultCommConfigA(port_name, &commconfig, &size))
                {
                        port = port_name[3];
                        break;
@@ -684,7 +697,7 @@ static HANDLE test_OpenComm(BOOL doOverlap)
     /* Try to find a port */
     for(port_name[3] = '1'; port_name[3] <= '9'; port_name[3]++)
     {
-       hcom = CreateFile( port_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
+       hcom = CreateFileA( port_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
                           (doOverlap)?FILE_FLAG_OVERLAPPED:0, NULL );
        if (hcom != INVALID_HANDLE_VALUE)
            break;
@@ -780,10 +793,11 @@ static void test_waittxempty(void)
     DCB dcb;
     COMMTIMEOUTS timeouts;
     char tbuf[]="test_waittxempty";
-    DWORD before, after, bytes, timediff, evtmask;
+    DWORD before, after, bytes, timediff, evtmask, errors, i;
     BOOL res;
     DWORD baud = SLOWBAUD;
-    OVERLAPPED ovl_write, ovl_wait;
+    OVERLAPPED ovl_write, ovl_wait, ovl_wait2;
+    COMSTAT stat;
 
     hcom = test_OpenComm(TRUE);
     if (hcom == INVALID_HANDLE_VALUE) return;
@@ -816,57 +830,62 @@ static void test_waittxempty(void)
 
     SetLastError(0xdeadbeef);
     res = WriteFile(hcom, tbuf, sizeof(tbuf), &bytes, NULL);
-todo_wine
     ok(!res, "WriteFile on an overlapped handle without ovl structure should fail\n");
-todo_wine
     ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
 
     S(U(ovl_write)).Offset = 0;
     S(U(ovl_write)).OffsetHigh = 0;
-    ovl_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+    ovl_write.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
     before = GetTickCount();
     SetLastError(0xdeadbeef);
     res = WriteFile(hcom, tbuf, sizeof(tbuf), &bytes, &ovl_write);
     after = GetTickCount();
-todo_wine
-    ok(!res && GetLastError() == ERROR_IO_PENDING, "WriteFile returned %d, error %d\n", res, GetLastError());
-todo_wine
-    ok(!bytes, "expected 0, got %u\n", bytes);
+    ok((!res && GetLastError() == ERROR_IO_PENDING) || (res && bytes == sizeof(tbuf)),
+       "WriteFile returned %d, written %u bytes, error %d\n", res, bytes, GetLastError());
+    if (!res) ok(!bytes, "expected 0, got %u\n", bytes);
     ok(after - before < 30, "WriteFile took %d ms to write %d Bytes at %d Baud\n",
        after - before, bytes, baud);
     /* don't wait for WriteFile completion */
 
     S(U(ovl_wait)).Offset = 0;
     S(U(ovl_wait)).OffsetHigh = 0;
-    ovl_wait.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+    ovl_wait.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
     evtmask = 0;
     before = GetTickCount();
     SetLastError(0xdeadbeef);
     res = WaitCommEvent(hcom, &evtmask, &ovl_wait);
     ok(!res && GetLastError() == ERROR_IO_PENDING, "WaitCommEvent error %d\n", GetLastError());
-    res = WaitForSingleObject(ovl_wait.hEvent, TIMEOUT);
-todo_wine
+    after = GetTickCount();
+    ok(after - before < 30, "WaitCommEvent should have returned immediately, took %d ms\n", after - before);
+    res = WaitForSingleObject(ovl_wait.hEvent, 1500);
     ok(res == WAIT_OBJECT_0, "WaitCommEvent failed with a timeout\n");
     if (res == WAIT_OBJECT_0)
     {
         res = GetOverlappedResult(hcom, &ovl_wait, &bytes, FALSE);
         ok(res, "GetOverlappedResult reported error %d\n", GetLastError());
-todo_wine
         ok(bytes == sizeof(evtmask), "expected %u, written %u\n", (UINT)sizeof(evtmask), bytes);
         res = TRUE;
     }
-    else res = FALSE;
+    else
+    {
+        /* unblock pending wait */
+        trace("recovering after WAIT_TIMEOUT...\n");
+        res = SetCommMask(hcom, EV_TXEMPTY);
+        ok(res, "SetCommMask error %d\n", GetLastError());
+
+        res = WaitForSingleObject(ovl_wait.hEvent, TIMEOUT);
+        ok(res == WAIT_OBJECT_0, "WaitCommEvent failed with a timeout\n");
+
+        res = FALSE;
+    }
     after = GetTickCount();
-todo_wine
     ok(res, "WaitCommEvent error %d\n", GetLastError());
-todo_wine
     ok(evtmask & EV_TXEMPTY, "WaitCommEvent: expected EV_TXEMPTY, got %#x\n", evtmask);
     CloseHandle(ovl_wait.hEvent);
 
     timediff = after - before;
-    trace("WaitCommEvent for EV_TXEMPTY took %d ms (timeout %d)\n", timediff, TIMEOUT);
-todo_wine
-    ok(timediff < 900, "WaitCommEvent used %d ms for waiting\n", timediff);
+    trace("WaitCommEvent for EV_TXEMPTY took %d ms (timeout 1500)\n", timediff);
+    ok(timediff < 1200, "WaitCommEvent used %d ms for waiting\n", timediff);
 
     res = WaitForSingleObject(ovl_write.hEvent, 0);
     ok(res == WAIT_OBJECT_0, "WriteFile failed with a timeout\n");
@@ -876,6 +895,92 @@ todo_wine
     CloseHandle(ovl_write.hEvent);
 
     CloseHandle(hcom);
+
+    for (i = 0; i < 2; i++)
+    {
+        hcom = test_OpenComm(TRUE);
+        if (hcom == INVALID_HANDLE_VALUE) return;
+
+        res = SetCommMask(hcom, EV_TXEMPTY);
+        ok(res, "SetCommMask error %d\n", GetLastError());
+
+        if (i == 0)
+        {
+            S(U(ovl_write)).Offset = 0;
+            S(U(ovl_write)).OffsetHigh = 0;
+            ovl_write.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
+            before = GetTickCount();
+            SetLastError(0xdeadbeef);
+            res = WriteFile(hcom, tbuf, sizeof(tbuf), &bytes, &ovl_write);
+            ok((!res && GetLastError() == ERROR_IO_PENDING) || (res && bytes == sizeof(tbuf)),
+               "WriteFile returned %d, written %u bytes, error %d\n", res, bytes, GetLastError());
+            if (!res) ok(!bytes, "expected 0, got %u\n", bytes);
+
+            ClearCommError(hcom, &errors, &stat);
+            ok(stat.cbInQue == 0, "InQueue should be empty, got %d bytes\n", stat.cbInQue);
+            ok(stat.cbOutQue != 0 || broken(stat.cbOutQue == 0) /* VM */, "OutQueue should not be empty\n");
+            ok(errors == 0, "ClearCommErrors: Unexpected error 0x%08x\n", errors);
+
+            res = GetOverlappedResult(hcom, &ovl_write, &bytes, TRUE);
+            ok(res, "GetOverlappedResult reported error %d\n", GetLastError());
+            ok(bytes == sizeof(tbuf), "expected %u, written %u\n", (UINT)sizeof(tbuf), bytes);
+            CloseHandle(ovl_write.hEvent);
+
+            res = FlushFileBuffers(hcom);
+            ok(res, "FlushFileBuffers error %d\n", GetLastError());
+        }
+
+        ClearCommError(hcom, &errors, &stat);
+        ok(stat.cbInQue == 0, "InQueue should be empty, got %d bytes\n", stat.cbInQue);
+        ok(stat.cbOutQue == 0, "OutQueue should be empty, got %d bytes\n", stat.cbOutQue);
+        ok(errors == 0, "ClearCommErrors: Unexpected error 0x%08x\n", errors);
+
+        S(U(ovl_wait)).Offset = 0;
+        S(U(ovl_wait)).OffsetHigh = 0;
+        ovl_wait.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
+        evtmask = 0;
+        SetLastError(0xdeadbeef);
+        res = WaitCommEvent(hcom, &evtmask, &ovl_wait);
+        ok((!res && GetLastError() == ERROR_IO_PENDING) || res /* busy system */, "%d: WaitCommEvent error %d\n", i, GetLastError());
+
+        res = WaitForSingleObject(ovl_wait.hEvent, TIMEOUT);
+        if (i == 0)
+            ok(res == WAIT_OBJECT_0, "WaitCommEvent failed with a timeout\n");
+        else
+            ok(res == WAIT_TIMEOUT, "WaitCommEvent should fail with a timeout\n");
+        if (res == WAIT_OBJECT_0)
+        {
+            res = GetOverlappedResult(hcom, &ovl_wait, &bytes, FALSE);
+            ok(res, "GetOverlappedResult reported error %d\n", GetLastError());
+            ok(bytes == sizeof(evtmask), "expected %u, written %u\n", (UINT)sizeof(evtmask), bytes);
+            ok(res, "WaitCommEvent error %d\n", GetLastError());
+            ok(evtmask & EV_TXEMPTY, "WaitCommEvent: expected EV_TXEMPTY, got %#x\n", evtmask);
+        }
+        else
+        {
+            ok(!evtmask, "WaitCommEvent: expected 0, got %#x\n", evtmask);
+
+            S(U(ovl_wait2)).Offset = 0;
+            S(U(ovl_wait2)).OffsetHigh = 0;
+            ovl_wait2.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
+            SetLastError(0xdeadbeef);
+            res = WaitCommEvent(hcom, &evtmask, &ovl_wait2);
+            ok(!res, "WaitCommEvent should fail if there is a pending wait\n");
+            ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+            CloseHandle(ovl_wait2.hEvent);
+
+            /* unblock pending wait */
+            trace("recovering after WAIT_TIMEOUT...\n");
+            res = SetCommMask(hcom, EV_TXEMPTY);
+            ok(res, "SetCommMask error %d\n", GetLastError());
+
+            res = WaitForSingleObject(ovl_wait.hEvent, TIMEOUT);
+            ok(res == WAIT_OBJECT_0, "WaitCommEvent failed with a timeout\n");
+            CloseHandle(ovl_wait.hEvent);
+        }
+
+        CloseHandle(hcom);
+    }
 }
 
 /* A new open handle should not return error or have bytes in the Queues */
@@ -964,7 +1069,7 @@ static void test_LoopbackRead(void)
     ok(read == sizeof(tbuf),"ReadFile read %d bytes, expected \"%s\"\n", read,rbuf);
 
     /* Now do the same with a slower Baud rate.
-       As we request more characters then written, we will hit the timeout
+       As we request more characters than written, we will hit the timeout
     */
 
     ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
@@ -1036,7 +1141,7 @@ static void test_LoopbackCtsRts(void)
     if (dcb.fRtsControl == RTS_CONTROL_HANDSHAKE)
     {
        trace("RTS_CONTROL_HANDSHAKE is set, so don't manipulate RTS\n");
-        CloseHandle(hcom);
+       CloseHandle(hcom);
        return;
     }
     ok(GetCommModemStatus(hcom, &defaultStat), "GetCommModemStatus failed\n");
@@ -1180,6 +1285,7 @@ static void test_LoopbackDtrRing(void)
     if (dcb.fDtrControl == DTR_CONTROL_HANDSHAKE)
     {
        trace("DTR_CONTROL_HANDSHAKE is set, so don't manipulate DTR\n");
+       CloseHandle(hcom);
        return;
     }
     ok(GetCommModemStatus(hcom, &defaultStat), "GetCommModemStatus failed\n");
@@ -1232,12 +1338,12 @@ static void test_WaitRx(void)
     if (hcom == INVALID_HANDLE_VALUE) return;
 
     ok(SetCommMask(hcom, EV_RXCHAR), "SetCommMask failed\n");
-    hComPortEvent =  CreateEvent( NULL, TRUE, FALSE, NULL );
+    hComPortEvent =  CreateEventW( NULL, TRUE, FALSE, NULL );
     ok(hComPortEvent != 0, "CreateEvent failed\n");
     ZeroMemory( &overlapped, sizeof(overlapped));
     overlapped.hEvent = hComPortEvent;
 
-    hComWriteEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
+    hComWriteEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
     ok(hComWriteEvent != NULL, "CreateEvent res %d\n", GetLastError());
     ZeroMemory( &overlapped_w, sizeof(overlapped_w));
     overlapped_w.hEvent = hComWriteEvent;
@@ -1352,7 +1458,7 @@ static void test_WaitCts(void)
     trace("test_WaitCts timeout %ld clt 0x%08lx handle %p\n",args[0], args[1], hcom);
 
     ok(SetCommMask(hcom, EV_CTS), "SetCommMask failed\n");
-    hComPortEvent =  CreateEvent( NULL, TRUE, FALSE, NULL );
+    hComPortEvent =  CreateEventW( NULL, TRUE, FALSE, NULL );
     ok(hComPortEvent != 0, "CreateEvent failed\n");
     args[3] = (DWORD_PTR)hComPortEvent;
     alarmThread = CreateThread(NULL, 0, toggle_ctlLine, args, 0, &alarmThreadId);
@@ -1446,7 +1552,7 @@ static void test_AbortWaitCts(void)
     trace("test_AbortWaitCts timeout %ld handle %p\n",args[0], hcom);
 
     ok(SetCommMask(hcom, EV_CTS), "SetCommMask failed\n");
-    hComPortEvent =  CreateEvent( NULL, TRUE, FALSE, NULL );
+    hComPortEvent =  CreateEventW( NULL, TRUE, FALSE, NULL );
     ok(hComPortEvent != 0, "CreateEvent failed\n");
     alarmThread = CreateThread(NULL, 0, reset_CommMask, args, 0, &alarmThreadId);
     /* Wait a minimum to let the thread start up */
@@ -1518,7 +1624,7 @@ static void test_WaitDsr(void)
     trace("test_WaitDsr timeout %ld clt 0x%08lx handle %p\n",args[0], args[1], hcom);
 
     ok(SetCommMask(hcom, EV_DSR), "SetCommMask failed\n");
-    hComPortEvent =  CreateEvent( NULL, TRUE, FALSE, NULL );
+    hComPortEvent =  CreateEventW( NULL, TRUE, FALSE, NULL );
     ok(hComPortEvent != 0, "CreateEvent failed\n");
     alarmThread = CreateThread(NULL, 0, toggle_ctlLine, args, 0, &alarmThreadId);
     ok(alarmThread !=0 , "CreateThread Failed\n");
@@ -1592,6 +1698,7 @@ static void test_WaitRing(void)
     ok((ret = GetCommModemStatus(hcom, &defaultStat)), "GetCommModemStatus failed\n");
     if (!ret) {
        skip("modem status failed -> skip.\n");
+       CloseHandle(hcom);
        return;
     }
     if(defaultStat & MS_RING_ON)
@@ -1603,7 +1710,7 @@ static void test_WaitRing(void)
     trace("test_WaitRing timeout %ld clt 0x%08lx handle %p\n",args[0], args[1], hcom);
 
     ok(SetCommMask(hcom, EV_RING), "SetCommMask failed\n");
-    hComPortEvent =  CreateEvent( NULL, TRUE, FALSE, NULL );
+    hComPortEvent =  CreateEventW( NULL, TRUE, FALSE, NULL );
     ok(hComPortEvent != 0, "CreateEvent failed\n");
     alarmThread = CreateThread(NULL, 0, toggle_ctlLine, args, 0, &alarmThreadId);
     ok(alarmThread !=0 , "CreateThread Failed\n");
@@ -1668,7 +1775,7 @@ static void test_WaitDcd(void)
     if (dcb.fDtrControl == DTR_CONTROL_DISABLE)
     {
        trace("DTR_CONTROL_HANDSHAKE is set, so don't manipulate DTR\n");
-        CloseHandle(hcom);
+       CloseHandle(hcom);
        return;
     }
     args[0]= TIMEOUT >>1;
@@ -1682,7 +1789,7 @@ static void test_WaitDcd(void)
     trace("test_WaitDcd timeout %ld clt 0x%08lx handle %p\n",args[0], args[1], hcom);
 
     ok(SetCommMask(hcom, EV_RLSD), "SetCommMask failed\n");
-    hComPortEvent =  CreateEvent( NULL, TRUE, FALSE, NULL );
+    hComPortEvent =  CreateEventW( NULL, TRUE, FALSE, NULL );
     ok(hComPortEvent != 0, "CreateEvent failed\n");
     alarmThread = CreateThread(NULL, 0, toggle_ctlLine, args, 0, &alarmThreadId);
     ok(alarmThread !=0 , "CreateThread Failed\n");
@@ -1761,7 +1868,7 @@ static void test_WaitBreak(void)
     if (hcom == INVALID_HANDLE_VALUE) return;
 
     ok(SetCommMask(hcom, EV_BREAK), "SetCommMask failed\n");
-    hComPortEvent =  CreateEvent( NULL, TRUE, FALSE, NULL );
+    hComPortEvent =  CreateEventW( NULL, TRUE, FALSE, NULL );
     ok(hComPortEvent != 0, "CreateEvent failed\n");
 
     trace("test_WaitBreak\n");
@@ -1834,7 +1941,7 @@ static void test_WaitCommEvent(void)
 
     S(U(ovl_wait)).Offset = 0;
     S(U(ovl_wait)).OffsetHigh = 0;
-    ovl_wait.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+    ovl_wait.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
 
     trace("waiting 10 secs for com port events (turn on/off the device)...\n");
     last_event_time = 0;
@@ -1897,8 +2004,200 @@ static void test_FlushFileBuffers(void)
     CloseHandle(hcom);
 }
 
+static void test_read_write(void)
+{
+    static const char atz[]="ATZ\r\n";
+    char buf[256];
+    HANDLE hcom;
+    DCB dcb;
+    COMMTIMEOUTS timeouts;
+    DWORD ret, bytes, status, evtmask, before, after, last_event_time;
+    OVERLAPPED ovl_wait;
+    IO_STATUS_BLOCK iob;
+    LARGE_INTEGER offset;
+    LONG i;
+
+    if (!pNtReadFile || !pNtWriteFile)
+    {
+        win_skip("not running on NT, skipping test\n");
+        return;
+    }
+
+    hcom = test_OpenComm(TRUE);
+    if (hcom == INVALID_HANDLE_VALUE) return;
+
+    ret = GetCommState(hcom, &dcb);
+    ok(ret, "GetCommState error %d\n", GetLastError());
+    dcb.BaudRate = 9600;
+    dcb.ByteSize = 8;
+    dcb.Parity = NOPARITY;
+    dcb.fRtsControl = RTS_CONTROL_ENABLE;
+    dcb.fDtrControl = DTR_CONTROL_ENABLE;
+    dcb.StopBits = ONESTOPBIT;
+    ret = SetCommState(hcom, &dcb);
+    ok(ret, "SetCommState error %d\n", GetLastError());
+
+    memset(&timeouts, 0, sizeof(timeouts));
+    timeouts.ReadTotalTimeoutConstant = TIMEOUT;
+    ret = SetCommTimeouts(hcom, &timeouts);
+    ok(ret,"SetCommTimeouts error %d\n", GetLastError());
+
+    ret = SetupComm(hcom, 1024, 1024);
+    ok(ret, "SetUpComm error %d\n", GetLastError());
+
+    bytes = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = WriteFile(hcom, atz, 0, &bytes, NULL);
+    ok(!ret, "WriteFile should fail\n");
+    ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+    ok(bytes == 0, "bytes %u\n", bytes);
+
+    U(iob).Status = -1;
+    iob.Information = -1;
+    status = pNtWriteFile(hcom, 0, NULL, NULL, &iob, atz, 0, NULL, NULL);
+    ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
+    ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
+    ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
+
+    for (i = -20; i < 20; i++)
+    {
+        U(iob).Status = -1;
+        iob.Information = -1;
+        offset.QuadPart = (LONGLONG)i;
+        status = pNtWriteFile(hcom, 0, NULL, NULL, &iob, atz, 0, &offset, NULL);
+        if (i >= 0 || i == -1)
+        {
+            ok(status == STATUS_SUCCESS, "%d: expected STATUS_SUCCESS, got %#x\n", i, status);
+            ok(U(iob).Status == STATUS_SUCCESS, "%d: expected STATUS_SUCCESS, got %#x\n", i, U(iob).Status);
+            ok(iob.Information == 0, "%d: expected 0, got %lu\n", i, iob.Information);
+        }
+        else
+        {
+            ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
+            ok(U(iob).Status == -1, "%d: expected -1, got %#x\n", i, U(iob).Status);
+            ok(iob.Information == -1, "%d: expected -1, got %ld\n", i, iob.Information);
+        }
+    }
+
+    U(iob).Status = -1;
+    iob.Information = -1;
+    offset.QuadPart = 0;
+    status = pNtWriteFile(hcom, 0, NULL, NULL, &iob, atz, sizeof(atz), &offset, NULL);
+    ok(status == STATUS_PENDING || status == STATUS_SUCCESS, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
+    /* Under Windows checking IO_STATUS_BLOCK right after the call leads
+     * to races, iob.Status is either -1 or STATUS_SUCCESS, which means
+     * that it's set only when the operation completes.
+     */
+    ret = WaitForSingleObject(hcom, TIMEOUT);
+    if (ret == WAIT_TIMEOUT)
+    {
+        skip("Probably modem is not connected.\n");
+        CloseHandle(hcom);
+        return;
+    }
+    ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
+    ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
+    ok(iob.Information == sizeof(atz), "expected sizeof(atz), got %lu\n", iob.Information);
+
+    ret = SetCommMask(hcom, EV_RXCHAR);
+    ok(ret, "SetCommMask error %d\n", GetLastError());
+
+    S(U(ovl_wait)).Offset = 0;
+    S(U(ovl_wait)).OffsetHigh = 0;
+    ovl_wait.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
+
+    trace("waiting 3 secs for modem response...\n");
+    last_event_time = 0;
+    before = GetTickCount();
+    do
+    {
+        evtmask = 0;
+        SetLastError(0xdeadbeef);
+        ret = WaitCommEvent(hcom, &evtmask, &ovl_wait);
+        ok(!ret && GetLastError() == ERROR_IO_PENDING, "WaitCommEvent returned %d, error %d\n", ret, GetLastError());
+        if (GetLastError() != ERROR_IO_PENDING) goto done; /* no point in further testing */
+        for (;;)
+        {
+            ret = WaitForSingleObject(ovl_wait.hEvent, 100);
+            after = GetTickCount();
+            if (ret == WAIT_OBJECT_0)
+            {
+                trace("got modem response.\n");
+
+                last_event_time = after;
+                ret = GetOverlappedResult(hcom, &ovl_wait, &bytes, FALSE);
+                ok(ret, "GetOverlappedResult reported error %d\n", GetLastError());
+                ok(bytes == sizeof(evtmask), "expected sizeof(evtmask), got %u\n", bytes);
+                ok(evtmask & EV_RXCHAR, "EV_RXCHAR should be set\n");
+
+                bytes = 0xdeadbeef;
+                SetLastError(0xdeadbeef);
+                ret = ReadFile(hcom, buf, 0, &bytes, NULL);
+                ok(!ret, "ReadFile should fail\n");
+                ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
+                ok(bytes == 0, "bytes %u\n", bytes);
+
+                U(iob).Status = -1;
+                iob.Information = -1;
+                status = pNtReadFile(hcom, 0, NULL, NULL, &iob, buf, 0, NULL, NULL);
+                ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
+                ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
+                ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
+
+                for (i = -20; i < 20; i++)
+                {
+                    U(iob).Status = -1;
+                    iob.Information = -1;
+                    offset.QuadPart = (LONGLONG)i;
+                    status = pNtReadFile(hcom, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
+                    /* FIXME: Remove once Wine is fixed */
+                    if (status == STATUS_PENDING) WaitForSingleObject(hcom, TIMEOUT);
+                    if (i >= 0)
+                    {
+todo_wine
+                        ok(status == STATUS_SUCCESS, "%d: expected STATUS_SUCCESS, got %#x\n", i, status);
+todo_wine
+                        ok(U(iob).Status == STATUS_SUCCESS, "%d: expected STATUS_SUCCESS, got %#x\n", i, U(iob).Status);
+                        ok(iob.Information == 0, "%d: expected 0, got %lu\n", i, iob.Information);
+                    }
+                    else
+                    {
+                        ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
+                        ok(U(iob).Status == -1, "%d: expected -1, got %#x\n", i, U(iob).Status);
+                        ok(iob.Information == -1, "%d: expected -1, got %ld\n", i, iob.Information);
+                    }
+                }
+
+                U(iob).Status = -1;
+                iob.Information = -1;
+                offset.QuadPart = 0;
+                status = pNtReadFile(hcom, 0, NULL, NULL, &iob, buf, 1, &offset, NULL);
+                ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", status);
+                ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
+                ok(iob.Information == 1, "expected 1, got %lu\n", iob.Information);
+                goto done;
+            }
+            else
+            {
+                if (last_event_time || after - before >= 3000) goto done;
+            }
+        }
+    } while (after - before < 3000);
+
+done:
+    CloseHandle(ovl_wait.hEvent);
+    CloseHandle(hcom);
+}
+
 START_TEST(comm)
 {
+    HMODULE ntdll = GetModuleHandleA("ntdll.dll");
+    if (ntdll)
+    {
+        pNtReadFile = (void *)GetProcAddress(ntdll, "NtReadFile");
+        pNtWriteFile = (void *)GetProcAddress(ntdll, "NtWriteFile");
+    }
+
     test_ClearCommError(); /* keep it the very first test */
     test_FlushFileBuffers();
     test_BuildCommDCB();
@@ -1918,6 +2217,7 @@ START_TEST(comm)
     test_WaitDcd();
     test_WaitBreak();
     test_stdio();
+    test_read_write();
 
     if (!winetest_interactive)
     {
index df752f4..5928e8c 100755 (executable)
@@ -50,7 +50,7 @@ static BOOL (WINAPI *pVerifyConsoleIoHandle)(HANDLE handle);
 
 #define okCHAR(hCon, c, ch, attr) do { \
   char __ch; WORD __attr; DWORD __len; BOOL expect; \
-  expect = ReadConsoleOutputCharacter((hCon), &__ch, 1, (c), &__len) == 1 && __len == 1 && __ch == (ch); \
+  expect = ReadConsoleOutputCharacterA((hCon), &__ch, 1, (c), &__len) == 1 && __len == 1 && __ch == (ch); \
   ok(expect, "At (%d,%d): expecting char '%c'/%02x got '%c'/%02x\n", (c).X, (c).Y, (ch), (ch), __ch, __ch); \
   expect = ReadConsoleOutputAttribute((hCon), &__attr, 1, (c), &__len) == 1 && __len == 1 && __attr == (attr); \
   ok(expect, "At (%d,%d): expecting attr %04x got %04x\n", (c).X, (c).Y, (attr), __attr); \
@@ -179,7 +179,7 @@ static void testEmptyWrite(HANDLE hCon)
     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left\n");
 
     len = -1;
-    ok(WriteConsole(hCon, NULL, 0, &len, NULL) != 0 && len == 0, "WriteConsole\n");
+    ok(WriteConsoleA(hCon, NULL, 0, &len, NULL) != 0 && len == 0, "WriteConsole\n");
     okCURSOR(hCon, c);
 
     /* Passing a NULL lpBuffer with sufficiently large non-zero length succeeds
@@ -188,22 +188,22 @@ static void testEmptyWrite(HANDLE hCon)
     if (0)
     {
         len = -1;
-        ok(!WriteConsole(hCon, NULL, 16, &len, NULL) && len == -1, "WriteConsole\n");
+        ok(!WriteConsoleA(hCon, NULL, 16, &len, NULL) && len == -1, "WriteConsole\n");
         okCURSOR(hCon, c);
 
         /* Cursor advances for this call. */
         len = -1;
-        ok(WriteConsole(hCon, NULL, 128, &len, NULL) != 0 && len == 128, "WriteConsole\n");
+        ok(WriteConsoleA(hCon, NULL, 128, &len, NULL) != 0 && len == 128, "WriteConsole\n");
     }
 
     len = -1;
-    ok(WriteConsole(hCon, emptybuf, 0, &len, NULL) != 0 && len == 0, "WriteConsole\n");
+    ok(WriteConsoleA(hCon, emptybuf, 0, &len, NULL) != 0 && len == 0, "WriteConsole\n");
     okCURSOR(hCon, c);
 
     /* WriteConsole does not halt on a null terminator and is happy to write
      * memory contents beyond the actual size of the buffer. */
     len = -1;
-    ok(WriteConsole(hCon, emptybuf, 16, &len, NULL) != 0 && len == 16, "WriteConsole\n");
+    ok(WriteConsoleA(hCon, emptybuf, 16, &len, NULL) != 0 && len == 16, "WriteConsole\n");
     c.X += 16;
     okCURSOR(hCon, c);
 }
@@ -219,7 +219,7 @@ static void testWriteSimple(HANDLE hCon)
     c.X = c.Y = 0;
     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left\n");
 
-    ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
+    ok(WriteConsoleA(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
     c.Y = 0;
     for (c.X = 0; c.X < mylen; c.X++)
     {
@@ -246,7 +246,7 @@ static void testWriteNotWrappedNotProcessed(HANDLE hCon, COORD sbSize)
     c.X = sbSize.X - 3; c.Y = 0;
     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3\n");
 
-    ret = WriteConsole(hCon, mytest, mylen, &len, NULL);
+    ret = WriteConsoleA(hCon, mytest, mylen, &len, NULL);
     ok(ret != 0 && len == mylen, "Couldn't write, ret = %d, len = %d\n", ret, len);
     c.Y = 0;
     for (p = mylen - 3; p < mylen; p++)
@@ -265,7 +265,7 @@ static void testWriteNotWrappedNotProcessed(HANDLE hCon, COORD sbSize)
     c.X = sbSize.X - mylen; c.Y = 0;
     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3\n");
 
-    ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
+    ok(WriteConsoleA(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
 }
 
 static void testWriteNotWrappedProcessed(HANDLE hCon, COORD sbSize)
@@ -285,7 +285,7 @@ static void testWriteNotWrappedProcessed(HANDLE hCon, COORD sbSize)
     c.X = sbSize.X - 5; c.Y = 0;
     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-5\n");
 
-    ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
+    ok(WriteConsoleA(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
     c.Y = 0;
     for (c.X = sbSize.X - 5; c.X < sbSize.X - 1; c.X++)
     {
@@ -316,7 +316,7 @@ static void testWriteNotWrappedProcessed(HANDLE hCon, COORD sbSize)
     c.X = sbSize.X - 4; c.Y = 0;
     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-4\n");
 
-    ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
+    ok(WriteConsoleA(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
     c.Y = 0;
     for (c.X = sbSize.X - 4; c.X < sbSize.X; c.X++)
     {
@@ -336,7 +336,7 @@ static void testWriteNotWrappedProcessed(HANDLE hCon, COORD sbSize)
     c.X = sbSize.X - 3; c.Y = 0;
     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-4\n");
 
-    ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
+    ok(WriteConsoleA(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
     c.Y = 0;
     for (p = mylen2 - 3; p < mylen2; p++)
     {
@@ -369,7 +369,7 @@ static void testWriteWrappedNotProcessed(HANDLE hCon, COORD sbSize)
     c.X = sbSize.X - 9; c.Y = 0;
     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-9\n");
 
-    ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
+    ok(WriteConsoleA(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
     c.Y = 0;
     for (p = 0; p < mylen; p++)
     {
@@ -406,7 +406,7 @@ static void testWriteWrappedProcessed(HANDLE hCon, COORD sbSize)
     c.X = sbSize.X - 9; c.Y = 0;
     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-9\n");
 
-    ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
+    ok(WriteConsoleA(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
     for (p = 0; p < 4; p++)
     {
         c.X = sbSize.X - 9 + p;
@@ -431,7 +431,7 @@ static void testWriteWrappedProcessed(HANDLE hCon, COORD sbSize)
     c.X = sbSize.X - 3; c.Y = 2;
     ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left-3\n");
 
-    ok(WriteConsole(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
+    ok(WriteConsoleA(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n");
     for (p = 0; p < 3; p++)
     {
         c.X = sbSize.X - 3 + p;
@@ -458,7 +458,7 @@ static void testWriteWrappedProcessed(HANDLE hCon, COORD sbSize)
 
 static void testWrite(HANDLE hCon, COORD sbSize)
 {
-    /* FIXME: should in fact insure that the sb is at least 10 character wide */
+    /* FIXME: should in fact ensure that the sb is at least 10 characters wide */
     ok(SetConsoleTextAttribute(hCon, TEST_ATTRIB), "Setting default text color\n");
     resetContent(hCon, sbSize, FALSE);
     testEmptyWrite(hCon);
@@ -504,7 +504,7 @@ static void testScroll(HANDLE hCon, COORD sbSize)
     clip.Top = 0;
     clip.Bottom = sbSize.Y - 1;
 
-    ok(ScrollConsoleScreenBuffer(hCon, &scroll, NULL, dst, &ci), "Scrolling SB\n");
+    ok(ScrollConsoleScreenBufferA(hCon, &scroll, NULL, dst, &ci), "Scrolling SB\n");
 
     for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
     {
@@ -539,7 +539,7 @@ static void testScroll(HANDLE hCon, COORD sbSize)
     clip.Top = 0;
     clip.Bottom = sbSize.Y - 1;
 
-    ok(ScrollConsoleScreenBuffer(hCon, &scroll, NULL, dst, &ci), "Scrolling SB\n");
+    ok(ScrollConsoleScreenBufferA(hCon, &scroll, NULL, dst, &ci), "Scrolling SB\n");
 
     for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
     {
@@ -574,7 +574,7 @@ static void testScroll(HANDLE hCon, COORD sbSize)
     clip.Bottom = min(H + H / 2, sbSize.Y - 1);
 
     SetLastError(0xdeadbeef);
-    ret = ScrollConsoleScreenBuffer(hCon, &scroll, &clip, dst, &ci);
+    ret = ScrollConsoleScreenBufferA(hCon, &scroll, &clip, dst, &ci);
     if (ret)
     {
         for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
@@ -617,7 +617,7 @@ static void testScroll(HANDLE hCon, COORD sbSize)
     clip.Top = H / 2;
     clip.Bottom = min(H + H / 2, sbSize.Y - 1);
 
-    ok(ScrollConsoleScreenBuffer(hCon, &scroll, &clip, dst, &ci), "Scrolling SB\n");
+    ok(ScrollConsoleScreenBufferA(hCon, &scroll, &clip, dst, &ci), "Scrolling SB\n");
 
     for (c.Y = 0; c.Y < sbSize.Y; c.Y++)
     {
@@ -654,8 +654,8 @@ static void testCtrlHandler(void)
     ok(!SetConsoleCtrlHandler(mch, FALSE), "Shouldn't succeed\n");
     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Bad error %u\n", GetLastError());
     ok(SetConsoleCtrlHandler(mch, TRUE), "Couldn't set handler\n");
-    /* wine requires the event for the test, as we cannot insure, so far, that event
-     * are processed synchronously in GenerateConsoleCtrlEvent()
+    /* wine requires the event for the test, as we cannot ensure, so far, that
+     * events are processed synchronously in GenerateConsoleCtrlEvent()
      */
     mch_event = CreateEventA(NULL, TRUE, FALSE, NULL);
     mch_count = 0;
@@ -704,7 +704,7 @@ static void testScreenBuffer(HANDLE hConOut)
     WCHAR test_unicode[] = {0x0442, 0x0435, 0x0441, 0x0442, 0};
     WCHAR str_wbuf[20];
     char str_buf[20];
-    DWORD len;
+    DWORD len, error;
     COORD c;
     BOOL ret;
     DWORD oldcp;
@@ -782,25 +782,25 @@ static void testScreenBuffer(HANDLE hConOut)
 
     /* trying to write non-console handle */
     SetLastError(0xdeadbeef);
-    ok(!WriteConsoleA(hFileOutRW, test_str1, lstrlenA(test_str1), &len, NULL),
-        "Shouldn't succeed\n");
-    ok(GetLastError() == ERROR_INVALID_HANDLE,
-       "GetLastError: expecting %u got %u\n",
-       ERROR_INVALID_HANDLE, GetLastError());
+    ret = WriteConsoleA(hFileOutRW, test_str1, lstrlenA(test_str1), &len, NULL);
+    error = GetLastError();
+    ok(!ret, "Shouldn't succeed\n");
+    ok(error == ERROR_INVALID_HANDLE || error == ERROR_INVALID_FUNCTION,
+       "GetLastError: got %u\n", error);
 
     SetLastError(0xdeadbeef);
-    ok(!WriteConsoleA(hFileOutRO, test_str1, lstrlenA(test_str1), &len, NULL),
-        "Shouldn't succeed\n");
-    ok(GetLastError() == ERROR_INVALID_HANDLE,
-       "GetLastError: expecting %u got %u\n",
-       ERROR_INVALID_HANDLE, GetLastError());
+    ret = WriteConsoleA(hFileOutRO, test_str1, lstrlenA(test_str1), &len, NULL);
+    error = GetLastError();
+    ok(!ret, "Shouldn't succeed\n");
+    ok(error == ERROR_INVALID_HANDLE || error == ERROR_INVALID_FUNCTION,
+       "GetLastError: got %u\n", error);
 
     SetLastError(0xdeadbeef);
-    ok(!WriteConsoleA(hFileOutWT, test_str1, lstrlenA(test_str1), &len, NULL),
-        "Shouldn't succeed\n");
-    todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE,
-       "GetLastError: expecting %u got %u\n",
-       ERROR_INVALID_HANDLE, GetLastError());
+    ret = WriteConsoleA(hFileOutWT, test_str1, lstrlenA(test_str1), &len, NULL);
+    error = GetLastError();
+    ok(!ret, "Shouldn't succeed\n");
+    todo_wine ok(error == ERROR_INVALID_HANDLE || error == ERROR_INVALID_FUNCTION,
+       "GetLastError: got %u\n", error);
 
     CloseHandle(hFileOutRW);
     CloseHandle(hFileOutRO);
@@ -927,7 +927,7 @@ static void test_GetSetConsoleInputExeName(void)
     ok(ret, "GetConsoleInputExeNameA failed\n");
     ok(error == ERROR_BUFFER_OVERFLOW, "got %u expected ERROR_BUFFER_OVERFLOW\n", error);
 
-    GetModuleFileNameA(GetModuleHandle(NULL), module, sizeof(module));
+    GetModuleFileNameA(GetModuleHandleA(NULL), module, sizeof(module));
     p = strrchr(module, '\\') + 1;
 
     ret = pGetConsoleInputExeNameA(sizeof(buffer)/sizeof(buffer[0]), buffer);
@@ -1025,7 +1025,8 @@ static void test_OpenCON(void)
     for (i = 0; i < sizeof(accesses) / sizeof(accesses[0]); i++)
     {
         h = CreateFileW(conW, GENERIC_WRITE, 0, NULL, accesses[i], 0, NULL);
-        ok(h != INVALID_HANDLE_VALUE, "Expected to open the CON device on write (%x)\n", accesses[i]);
+        ok(h != INVALID_HANDLE_VALUE || broken(accesses[i] == TRUNCATE_EXISTING /* Win8 */),
+           "Expected to open the CON device on write (%x)\n", accesses[i]);
         CloseHandle(h);
 
         h = CreateFileW(conW, GENERIC_READ, 0, NULL, accesses[i], 0, NULL);
@@ -1034,14 +1035,13 @@ static void test_OpenCON(void)
          * NT, XP, Vista comply, but Win7 doesn't and allows opening CON with TRUNCATE_EXISTING
          * So don't test when disposition is TRUNCATE_EXISTING
          */
-        if (accesses[i] != TRUNCATE_EXISTING)
-        {
-            ok(h != INVALID_HANDLE_VALUE, "Expected to open the CON device on read (%x)\n", accesses[i]);
-        }
+        ok(h != INVALID_HANDLE_VALUE || broken(accesses[i] == TRUNCATE_EXISTING /* Win7+ */),
+           "Expected to open the CON device on read (%x)\n", accesses[i]);
         CloseHandle(h);
         h = CreateFileW(conW, GENERIC_READ|GENERIC_WRITE, 0, NULL, accesses[i], 0, NULL);
         ok(h == INVALID_HANDLE_VALUE, "Expected not to open the CON device on read-write (%x)\n", accesses[i]);
-        ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Unexpected error %x\n", GetLastError());
+        ok(GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_INVALID_PARAMETER,
+           "Unexpected error %x\n", GetLastError());
     }
 }
 
@@ -1051,6 +1051,7 @@ static void test_OpenConsoleW(void)
     static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0};
     static const WCHAR emptyW[] = {0};
     static const WCHAR invalidW[] = {'I','N','V','A','L','I','D',0};
+    DWORD gle;
 
     static const struct
     {
@@ -1058,42 +1059,63 @@ static void test_OpenConsoleW(void)
         DWORD access;
         BOOL inherit;
         DWORD creation;
-        DWORD gle;
+        DWORD gle, gle2;
     } invalid_table[] = {
-        {NULL,     0,                            FALSE,      0,                 ERROR_INVALID_PARAMETER},
-        {NULL,     0xdeadbeef,                   0xdeadbeef, 0xdeadbeef,        ERROR_INVALID_PARAMETER},
-        {NULL,     0,                            FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
-        {NULL,     GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_INVALID_PARAMETER},
-        {NULL,     GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
-        {NULL,     GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_EXISTING,     ERROR_INVALID_PARAMETER},
-        {emptyW,   0,                            FALSE,      0,                 ERROR_INVALID_PARAMETER},
-        {emptyW,   0xdeadbeef,                   0xdeadbeef, 0xdeadbeef,        ERROR_INVALID_PARAMETER},
-        {emptyW,   0,                            FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
-        {emptyW,   GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_INVALID_PARAMETER},
-        {emptyW,   GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
-        {emptyW,   GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_EXISTING,     ERROR_INVALID_PARAMETER},
-        {invalidW, 0,                            FALSE,      0,                 ERROR_INVALID_PARAMETER},
-        {invalidW, 0xdeadbeef,                   0xdeadbeef, 0xdeadbeef,        ERROR_INVALID_PARAMETER},
-        {invalidW, 0,                            FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
-        {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_INVALID_PARAMETER},
-        {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
-        {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_EXISTING,     ERROR_INVALID_PARAMETER},
-        {coninW,   0,                            FALSE,      0,                 ERROR_SHARING_VIOLATION},
-        {coninW,   0xdeadbeef,                   0xdeadbeef, 0xdeadbeef,        ERROR_INVALID_PARAMETER},
-        {coninW,   0,                            FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
-        {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_SHARING_VIOLATION},
-        {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_NEW,        ERROR_SHARING_VIOLATION},
-        {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_ALWAYS,     ERROR_SHARING_VIOLATION},
-        {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
-        {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      TRUNCATE_EXISTING, ERROR_INVALID_PARAMETER},
-        {conoutW,  0,                            FALSE,      0,                 ERROR_SHARING_VIOLATION},
-        {conoutW,  0xdeadbeef,                   0xdeadbeef, 0xdeadbeef,        ERROR_INVALID_PARAMETER},
-        {conoutW,  0,                            FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
-        {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_SHARING_VIOLATION},
-        {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_NEW,        ERROR_SHARING_VIOLATION},
-        {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_ALWAYS,     ERROR_SHARING_VIOLATION},
-        {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER},
-        {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      TRUNCATE_EXISTING, ERROR_INVALID_PARAMETER},
+        {NULL,     0,                            FALSE,      0,                 ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
+        {NULL,     0,                            FALSE,      0xdeadbeef,        ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
+        {NULL,     0xdeadbeef,                   FALSE,      0,                 ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
+        {NULL,     0xdeadbeef,                   TRUE,       0xdeadbeef,        ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
+        {NULL,     0,                            FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
+        {NULL,     GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
+        {NULL,     GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
+        {NULL,     GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_EXISTING,     ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
+        {emptyW,   0,                            FALSE,      0,                 ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
+        {emptyW,   0,                            FALSE,      0xdeadbeef,        ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
+        {emptyW,   0xdeadbeef,                   FALSE,      0,                 ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
+        {emptyW,   0xdeadbeef,                   TRUE,       0xdeadbeef,        ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
+        {emptyW,   0,                            FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
+        {emptyW,   GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
+        {emptyW,   GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
+        {emptyW,   GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_EXISTING,     ERROR_INVALID_PARAMETER, ERROR_PATH_NOT_FOUND},
+        {invalidW, 0,                            FALSE,      0,                 ERROR_INVALID_PARAMETER, ERROR_FILE_NOT_FOUND},
+        {invalidW, 0,                            FALSE,      0xdeadbeef,        ERROR_INVALID_PARAMETER, 0},
+        {invalidW, 0xdeadbeef,                   FALSE,      0,                 ERROR_INVALID_PARAMETER, ERROR_FILE_NOT_FOUND},
+        {invalidW, 0xdeadbeef,                   TRUE,       0xdeadbeef,        ERROR_INVALID_PARAMETER, 0},
+        {invalidW, 0,                            FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER, ERROR_FILE_NOT_FOUND},
+        {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_INVALID_PARAMETER, ERROR_FILE_NOT_FOUND},
+        {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       ERROR_INVALID_PARAMETER, ERROR_FILE_NOT_FOUND},
+        {invalidW, GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_EXISTING,     ERROR_INVALID_PARAMETER, ERROR_FILE_NOT_FOUND},
+        {coninW,   0,                            FALSE,      0xdeadbeef,        ERROR_INVALID_PARAMETER, 0},
+        {coninW,   0xdeadbeef,                   FALSE,      0,                 ERROR_INVALID_PARAMETER, ERROR_ACCESS_DENIED},
+        {coninW,   0xdeadbeef,                   TRUE,       0xdeadbeef,        ERROR_INVALID_PARAMETER, 0},
+        {conoutW,  0,                            FALSE,      0xdeadbeef,        ERROR_INVALID_PARAMETER, 0},
+        {conoutW,  0xceadbeef,                   FALSE,      0,                 ERROR_INVALID_PARAMETER, ERROR_ACCESS_DENIED},
+        {conoutW,  0xdeadbeef,                   TRUE,       0xdeadbeef,        ERROR_INVALID_PARAMETER, 0},
+    };
+    static const struct
+    {
+        LPCWSTR name;
+        DWORD access;
+        BOOL inherit;
+        DWORD creation;
+    } valid_table[] = {
+        {coninW,   0,                            FALSE,      0                },
+        {coninW,   0,                            TRUE,       0                },
+        {coninW,   GENERIC_EXECUTE,              TRUE,       0                },
+        {coninW,   GENERIC_ALL,                  TRUE,       0                },
+        {coninW,   0,                            FALSE,      OPEN_ALWAYS      },
+        {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      0                },
+        {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_NEW       },
+        {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_ALWAYS    },
+        {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS      },
+        {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      TRUNCATE_EXISTING},
+        {conoutW,  0,                            FALSE,      0                },
+        {conoutW,  0,                            FALSE,      OPEN_ALWAYS      },
+        {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      0                },
+        {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_NEW,      },
+        {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_ALWAYS    },
+        {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS      },
+        {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      TRUNCATE_EXISTING},
     };
 
     int index;
@@ -1110,30 +1132,33 @@ static void test_OpenConsoleW(void)
         SetLastError(0xdeadbeef);
         ret = pOpenConsoleW(invalid_table[index].name, invalid_table[index].access,
                             invalid_table[index].inherit, invalid_table[index].creation);
+        gle = GetLastError();
         ok(ret == INVALID_HANDLE_VALUE,
            "Expected OpenConsoleW to return INVALID_HANDLE_VALUE for index %d, got %p\n",
            index, ret);
-        ok(GetLastError() == invalid_table[index].gle,
-           "Expected GetLastError() to return %u for index %d, got %u\n",
-           invalid_table[index].gle, index, GetLastError());
+        ok(gle == invalid_table[index].gle || (gle != 0 && gle == invalid_table[index].gle2),
+           "Expected GetLastError() to return %u/%u for index %d, got %u\n",
+           invalid_table[index].gle, invalid_table[index].gle2, index, gle);
+    }
+
+    for (index = 0; index < sizeof(valid_table)/sizeof(valid_table[0]); index++)
+    {
+        ret = pOpenConsoleW(valid_table[index].name, valid_table[index].access,
+                            valid_table[index].inherit, valid_table[index].creation);
+        todo_wine
+        ok(ret != INVALID_HANDLE_VALUE || broken(ret == INVALID_HANDLE_VALUE /* until Win7 */),
+           "Expected OpenConsoleW to succeed for index %d, got %p\n", index, ret);
+        if (ret != INVALID_HANDLE_VALUE)
+            CloseHandle(ret);
     }
 
-    /* OpenConsoleW should not touch the last error on success. */
-    SetLastError(0xdeadbeef);
     ret = pOpenConsoleW(coninW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING);
-    ok(ret != INVALID_HANDLE_VALUE,
-       "Expected OpenConsoleW to return a valid handle\n");
-    ok(GetLastError() == 0xdeadbeef,
-       "Expected the last error to be untouched, got %u\n", GetLastError());
+    ok(ret != INVALID_HANDLE_VALUE, "Expected OpenConsoleW to return a valid handle\n");
     if (ret != INVALID_HANDLE_VALUE)
         CloseHandle(ret);
 
-    SetLastError(0xdeadbeef);
     ret = pOpenConsoleW(conoutW, GENERIC_READ | GENERIC_WRITE, FALSE, OPEN_EXISTING);
-    ok(ret != INVALID_HANDLE_VALUE,
-       "Expected OpenConsoleW to return a valid handle\n");
-    ok(GetLastError() == 0xdeadbeef,
-       "Expected the last error to be untouched, got %u\n", GetLastError());
+    ok(ret != INVALID_HANDLE_VALUE, "Expected OpenConsoleW to return a valid handle\n");
     if (ret != INVALID_HANDLE_VALUE)
         CloseHandle(ret);
 }
@@ -1158,14 +1183,13 @@ static void test_CreateFileW(void)
         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_NEW,        0,                              FALSE},
         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_ALWAYS,     0,                              FALSE},
         {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       0,                              FALSE},
-        {coninW,   GENERIC_READ | GENERIC_WRITE, FALSE,      TRUNCATE_EXISTING, 0,                              FALSE},
         {conoutW,  0,                            FALSE,      0,                 ERROR_INVALID_PARAMETER,        TRUE},
         {conoutW,  0,                            FALSE,      OPEN_ALWAYS,       0,                              FALSE},
         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      0,                 ERROR_INVALID_PARAMETER,        TRUE},
         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_NEW,        0,                              FALSE},
         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      CREATE_ALWAYS,     0,                              FALSE},
         {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      OPEN_ALWAYS,       0,                              FALSE},
-        {conoutW,  GENERIC_READ | GENERIC_WRITE, FALSE,      TRUNCATE_EXISTING, 0,                              FALSE},
+        /* TRUNCATE_EXISTING is forbidden starting with Windows 8 */
     };
 
     int index;
@@ -1342,7 +1366,7 @@ static void test_WriteConsoleInputA(HANDLE input_handle)
     INPUT_RECORD event_list[5];
     MOUSE_EVENT_RECORD mouse_event = { {0, 0}, 0, 0, MOUSE_MOVED };
     KEY_EVENT_RECORD key_event;
-    DWORD count, console_mode;
+    DWORD count, console_mode, gle;
     BOOL ret;
     int i;
 
@@ -1353,31 +1377,31 @@ static void test_WriteConsoleInputA(HANDLE input_handle)
         DWORD count;
         LPDWORD written;
         DWORD expected_count;
-        DWORD last_error;
+        DWORD gle, gle2;
         int win_crash;
     } invalid_table[] =
     {
-        {NULL, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+        {NULL, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
         {NULL, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
-        {NULL, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
-        {NULL, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
-        {NULL, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+        {NULL, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
+        {NULL, NULL, 1, &count, 0xdeadbeef, ERROR_NOACCESS, ERROR_INVALID_ACCESS},
+        {NULL, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
         {NULL, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
-        {NULL, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+        {NULL, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
         {NULL, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
-        {INVALID_HANDLE_VALUE, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+        {INVALID_HANDLE_VALUE, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
         {INVALID_HANDLE_VALUE, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
-        {INVALID_HANDLE_VALUE, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
-        {INVALID_HANDLE_VALUE, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
-        {INVALID_HANDLE_VALUE, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+        {INVALID_HANDLE_VALUE, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
+        {INVALID_HANDLE_VALUE, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_HANDLE, ERROR_INVALID_ACCESS},
+        {INVALID_HANDLE_VALUE, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
         {INVALID_HANDLE_VALUE, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
-        {INVALID_HANDLE_VALUE, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+        {INVALID_HANDLE_VALUE, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
         {INVALID_HANDLE_VALUE, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
-        {input_handle, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
-        {input_handle, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
-        {input_handle, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
-        {input_handle, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
-        {input_handle, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+        {input_handle, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
+        {input_handle, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
+        {input_handle, NULL, 1, &count, 0xdeadbeef, ERROR_NOACCESS, ERROR_INVALID_ACCESS},
+        {input_handle, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
+        {input_handle, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
     };
 
     /* Suppress external sources of input events for the duration of the test. */
@@ -1422,9 +1446,10 @@ static void test_WriteConsoleInputA(HANDLE input_handle)
                "[%d] Expected output count to be %u, got %u\n",
                i, invalid_table[i].expected_count, count);
         }
-        ok(GetLastError() == invalid_table[i].last_error,
-           "[%d] Expected last error to be %u, got %u\n",
-           i, invalid_table[i].last_error, GetLastError());
+        gle = GetLastError();
+        ok(gle == invalid_table[i].gle || (gle != 0 && gle == invalid_table[i].gle2),
+           "[%d] Expected last error to be %u or %u, got %u\n",
+           i, invalid_table[i].gle, invalid_table[i].gle2, gle);
     }
 
     count = 0xdeadbeef;
@@ -1585,7 +1610,7 @@ static void test_WriteConsoleInputW(HANDLE input_handle)
     INPUT_RECORD event_list[5];
     MOUSE_EVENT_RECORD mouse_event = { {0, 0}, 0, 0, MOUSE_MOVED };
     KEY_EVENT_RECORD key_event;
-    DWORD count, console_mode;
+    DWORD count, console_mode, gle;
     BOOL ret;
     int i;
 
@@ -1596,31 +1621,31 @@ static void test_WriteConsoleInputW(HANDLE input_handle)
         DWORD count;
         LPDWORD written;
         DWORD expected_count;
-        DWORD last_error;
+        DWORD gle, gle2;
         int win_crash;
     } invalid_table[] =
     {
-        {NULL, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+        {NULL, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
         {NULL, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
-        {NULL, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
-        {NULL, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
-        {NULL, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+        {NULL, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
+        {NULL, NULL, 1, &count, 0xdeadbeef, ERROR_NOACCESS, ERROR_INVALID_ACCESS},
+        {NULL, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
         {NULL, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
-        {NULL, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+        {NULL, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
         {NULL, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
-        {INVALID_HANDLE_VALUE, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+        {INVALID_HANDLE_VALUE, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
         {INVALID_HANDLE_VALUE, NULL, 0, &count, 0, ERROR_INVALID_HANDLE},
-        {INVALID_HANDLE_VALUE, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
-        {INVALID_HANDLE_VALUE, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
-        {INVALID_HANDLE_VALUE, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+        {INVALID_HANDLE_VALUE, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
+        {INVALID_HANDLE_VALUE, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_HANDLE, ERROR_INVALID_ACCESS},
+        {INVALID_HANDLE_VALUE, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
         {INVALID_HANDLE_VALUE, &event, 0, &count, 0, ERROR_INVALID_HANDLE},
-        {INVALID_HANDLE_VALUE, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+        {INVALID_HANDLE_VALUE, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
         {INVALID_HANDLE_VALUE, &event, 1, &count, 0, ERROR_INVALID_HANDLE},
-        {input_handle, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
-        {input_handle, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
-        {input_handle, NULL, 1, &count, 0xdeadbeef, ERROR_INVALID_ACCESS},
-        {input_handle, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
-        {input_handle, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 1},
+        {input_handle, NULL, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
+        {input_handle, NULL, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
+        {input_handle, NULL, 1, &count, 0xdeadbeef, ERROR_NOACCESS, ERROR_INVALID_ACCESS},
+        {input_handle, &event, 0, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
+        {input_handle, &event, 1, NULL, 0xdeadbeef, ERROR_INVALID_ACCESS, 0, 1},
     };
 
     /* Suppress external sources of input events for the duration of the test. */
@@ -1665,9 +1690,10 @@ static void test_WriteConsoleInputW(HANDLE input_handle)
                "[%d] Expected output count to be %u, got %u\n",
                i, invalid_table[i].expected_count, count);
         }
-        ok(GetLastError() == invalid_table[i].last_error,
-           "[%d] Expected last error to be %u, got %u\n",
-           i, invalid_table[i].last_error, GetLastError());
+        gle = GetLastError();
+        ok(gle == invalid_table[i].gle || (gle != 0 && gle == invalid_table[i].gle2),
+           "[%d] Expected last error to be %u or %u, got %u\n",
+           i, invalid_table[i].gle, invalid_table[i].gle2, gle);
     }
 
     count = 0xdeadbeef;
@@ -2001,7 +2027,7 @@ static void test_WriteConsoleOutputAttribute(HANDLE output_handle)
     const struct
     {
         HANDLE hConsoleOutput;
-        CONST WORD *attr;
+        const WORD *attr;
         DWORD length;
         COORD coord;
         LPDWORD lpNumAttrsWritten;
@@ -2527,6 +2553,41 @@ static void test_ReadConsoleOutputAttribute(HANDLE output_handle)
     ok(count == 1, "Expected count to be 1, got %u\n", count);
 }
 
+static void test_ReadConsole(void)
+{
+    HANDLE std_input;
+    DWORD ret, bytes;
+    char buf[1024];
+
+    std_input = GetStdHandle(STD_INPUT_HANDLE);
+
+    SetLastError(0xdeadbeef);
+    ret = GetFileSize(std_input, NULL);
+    ok(ret == INVALID_FILE_SIZE, "expected INVALID_FILE_SIZE, got %#x\n", ret);
+    ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
+
+    bytes = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = ReadFile(std_input, buf, -128, &bytes, NULL);
+    ok(!ret, "expected 0, got %u\n", ret);
+    ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError());
+    ok(!bytes, "expected 0, got %u\n", bytes);
+
+    bytes = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = ReadConsoleA(std_input, buf, -128, &bytes, NULL);
+    ok(!ret, "expected 0, got %u\n", ret);
+    ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError());
+    ok(bytes == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", bytes);
+
+    bytes = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = ReadConsoleW(std_input, buf, -128, &bytes, NULL);
+    ok(!ret, "expected 0, got %u\n", ret);
+    ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError());
+    ok(bytes == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", bytes);
+}
+
 START_TEST(console)
 {
     static const char font_name[] = "Lucida Console";
@@ -2620,6 +2681,7 @@ START_TEST(console)
     ok(sbi.dwSize.Y == size, "Unexpected buffer size: %d instead of %d\n", sbi.dwSize.Y, size);
     if (!ret) return;
 
+    test_ReadConsole();
     /* Non interactive tests */
     testCursor(hConOut, sbi.dwSize);
     /* test parameters (FIXME: test functionality) */
index e578cdd..011ed5f 100644 (file)
@@ -113,9 +113,9 @@ static void get_events(const char* name, HANDLE *start_event, HANDLE *done_event
     event_name=HeapAlloc(GetProcessHeap(), 0, 6+strlen(basename)+1);
 
     sprintf(event_name, "start_%s", basename);
-    *start_event=CreateEvent(NULL, 0,0, event_name);
+    *start_event=CreateEventA(NULL, 0,0, event_name);
     sprintf(event_name, "done_%s", basename);
-    *done_event=CreateEvent(NULL, 0,0, event_name);
+    *done_event=CreateEventA(NULL, 0,0, event_name);
     HeapFree(GetProcessHeap(), 0, event_name);
 }
 
@@ -429,8 +429,8 @@ static void test_ExitCode(void)
     reg_save_value auto_value;
     reg_save_value debugger_value;
 
-    GetModuleFileNameA(GetModuleHandle(NULL), test_exe, sizeof(test_exe));
-    if (GetFileAttributes(test_exe) == INVALID_FILE_ATTRIBUTES)
+    GetModuleFileNameA(GetModuleHandleA(NULL), test_exe, sizeof(test_exe));
+    if (GetFileAttributesA(test_exe) == INVALID_FILE_ATTRIBUTES)
         strcat(test_exe, ".so");
     if (GetFileAttributesA(test_exe) == INVALID_FILE_ATTRIBUTES)
     {
@@ -686,7 +686,7 @@ static void doChildren(int argc, char **argv)
     p = p ? p+1 : blackbox_file;
     strcpy(event_name, p);
     strcat(event_name, "_init");
-    event = OpenEvent(EVENT_ALL_ACCESS, FALSE, event_name);
+    event = OpenEventA(EVENT_ALL_ACCESS, FALSE, event_name);
     child_ok(event != NULL, "OpenEvent failed, last error %d.\n", GetLastError());
     SetEvent(event);
     CloseHandle(event);
@@ -695,7 +695,7 @@ static void doChildren(int argc, char **argv)
     p = p ? p+1 : blackbox_file;
     strcpy(event_name, p);
     strcat(event_name, "_attach");
-    event = OpenEvent(EVENT_ALL_ACCESS, FALSE, event_name);
+    event = OpenEventA(EVENT_ALL_ACCESS, FALSE, event_name);
     child_ok(event != NULL, "OpenEvent failed, last error %d.\n", GetLastError());
     WaitForSingleObject(event, INFINITE);
     CloseHandle(event);
@@ -747,14 +747,14 @@ static void test_debug_children(char *name, DWORD flag, BOOL debug_child)
     p = p ? p+1 : blackbox_file;
     strcpy(event_name, p);
     strcat(event_name, "_init");
-    event_init = CreateEvent(NULL, FALSE, FALSE, event_name);
+    event_init = CreateEventA(NULL, FALSE, FALSE, event_name);
     ok(event_init != NULL, "OpenEvent failed, last error %d.\n", GetLastError());
 
     p = strrchr(blackbox_file, '\\');
     p = p ? p+1 : blackbox_file;
     strcpy(event_name, p);
     strcat(event_name, "_attach");
-    event_attach = CreateEvent(NULL, FALSE, flag!=0, event_name);
+    event_attach = CreateEventA(NULL, FALSE, flag!=0, event_name);
     ok(event_attach != NULL, "CreateEvent failed, last error %d.\n", GetLastError());
 
     memset(&si, 0, sizeof(si));
@@ -814,12 +814,12 @@ START_TEST(debugger)
 {
     HMODULE hdll;
 
-    hdll=GetModuleHandle("kernel32.dll");
+    hdll=GetModuleHandleA("kernel32.dll");
     pCheckRemoteDebuggerPresent=(void*)GetProcAddress(hdll, "CheckRemoteDebuggerPresent");
     pDebugActiveProcessStop=(void*)GetProcAddress(hdll, "DebugActiveProcessStop");
     pDebugSetProcessKillOnExit=(void*)GetProcAddress(hdll, "DebugSetProcessKillOnExit");
     pIsDebuggerPresent=(void*)GetProcAddress(hdll, "IsDebuggerPresent");
-    hdll=GetModuleHandle("ntdll.dll");
+    hdll=GetModuleHandleA("ntdll.dll");
     if (hdll) pNtCurrentTeb = (void*)GetProcAddress(hdll, "NtCurrentTeb");
 
     myARGC=winetest_get_mainargs(&myARGV);
@@ -846,6 +846,7 @@ START_TEST(debugger)
         test_debug_loop(myARGC, myARGV);
         test_debug_children(myARGV[0], DEBUG_PROCESS, TRUE);
         test_debug_children(myARGV[0], DEBUG_ONLY_THIS_PROCESS, FALSE);
+        test_debug_children(myARGV[0], DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS, FALSE);
         test_debug_children(myARGV[0], 0, FALSE);
     }
 }
index ca6cb44..4acd3e8 100755 (executable)
@@ -117,7 +117,7 @@ static void test_GetDiskFreeSpaceA(void)
 
                 if (!ret)
                     /* GetDiskFreeSpaceA() should succeed, but it can fail with too many
-                       different GetLastError() results to be usable for a ok() */
+                       different GetLastError() results to be usable for an ok() */
                     trace("GetDiskFreeSpaceA(%s) failed with %d\n", drive, GetLastError());
 
                 if( GetVersion() & 0x80000000)
@@ -134,7 +134,7 @@ static void test_GetDiskFreeSpaceA(void)
 
                     if (!ret)
                         /* GetDiskFreeSpaceExA() should succeed, but it can fail with too many
-                           different GetLastError() results to be usable for a ok() */
+                           different GetLastError() results to be usable for an ok() */
                         trace("GetDiskFreeSpaceExA(%s) failed with %d\n", drive, GetLastError());
 
                     ok( bytes_per_sector == 0 || /* empty cd rom drive */
@@ -192,7 +192,7 @@ static void test_GetDiskFreeSpaceW(void)
                    drive[0], ret, GetLastError());
             else if (!ret)
                 /* GetDiskFreeSpaceW() should succeed, but it can fail with too many
-                   different GetLastError() results to be usable for a ok() */
+                   different GetLastError() results to be usable for an ok() */
                 trace("GetDiskFreeSpaceW(%c) failed with %d\n", drive[0], GetLastError());
         }
         logical_drives >>= 1;
index 3ac86cd..f8452be 100755 (executable)
@@ -357,7 +357,7 @@ static void test_ExpandEnvironmentStringsA(void)
     ret_size = ExpandEnvironmentStringsA(buf, buf1, sizeof(buf1));
     ok(ret_size == strlen(buf2)+1 ||
        ret_size == (strlen(buf2)+1)*2 /* NT4 */,
-       "ExpandEnvironmentStrings returned %d instead of %d\n", ret_size, lstrlen(buf2)+1);
+       "ExpandEnvironmentStrings returned %d instead of %d\n", ret_size, lstrlenA(buf2)+1);
     ok(!strcmp(buf1, buf2), "ExpandEnvironmentStrings returned [%s]\n", buf1);
     SetEnvironmentVariableA("IndirectVar", NULL);
 
index 0e68535..1e4ca66 100644 (file)
@@ -39,7 +39,7 @@ static WORD cbCount;
 
 static VOID init_funcs(void)
 {
-    HMODULE hKernel32 = GetModuleHandle("kernel32");
+    HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
 
 #define X(f) p##f = (void*)GetProcAddress(hKernel32, #f);
     X(CreateFiber);
@@ -181,6 +181,35 @@ static void test_FiberLocalStorage(PFLS_CALLBACK_FUNCTION cbfunc)
     ok(ret, "FlsFree failed\n");
     if (cbfunc)
         todo_wine ok(cbCount == 1, "Wrong callback count: %d\n", cbCount);
+
+    /* test index 0 */
+    SetLastError( 0xdeadbeef );
+    val = pFlsGetValue( 0 );
+    ok( !val, "fls index 0 set to %p\n", val );
+    ok( GetLastError() == ERROR_INVALID_PARAMETER, "setting fls index wrong error %u\n", GetLastError() );
+    SetLastError( 0xdeadbeef );
+    ret = pFlsSetValue( 0, (void *)0xdeadbeef );
+    ok( !ret, "setting fls index 0 succeeded\n" );
+    ok( GetLastError() == ERROR_INVALID_PARAMETER, "setting fls index wrong error %u\n", GetLastError() );
+    SetLastError( 0xdeadbeef );
+    val = pFlsGetValue( 0 );
+    ok( !val, "fls index 0 wrong value %p\n", val );
+    ok( GetLastError() == ERROR_INVALID_PARAMETER, "setting fls index wrong error %u\n", GetLastError() );
+
+    fls = pFlsAlloc( NULL );
+    ok( fls != FLS_OUT_OF_INDEXES, "FlsAlloc failed\n" );
+    ok( fls != 0, "fls index 0 allocated\n" );
+    val = pFlsGetValue( fls );
+    ok( !val, "fls index %u wrong value %p\n", fls, val );
+    ret = pFlsSetValue( fls, (void *)0xdeadbeef );
+    ok( ret, "setting fls index %u failed\n", fls );
+    val = pFlsGetValue( fls );
+    ok( val == (void *)0xdeadbeef, "fls index %u wrong value %p\n", fls, val );
+    pFlsFree( fls );
+    ret = pFlsSetValue( fls, (void *)0xdeadbabe );
+    ok( ret, "setting fls index %u failed\n", fls );
+    val = pFlsGetValue( fls );
+    ok( val == (void *)0xdeadbabe, "fls index %u wrong value %p\n", fls, val );
 }
 
 START_TEST(fiber)
index d0a025c..883aa57 100755 (executable)
@@ -21,7 +21,7 @@
  */
 
 /* ReplaceFile requires Windows 2000 or newer */
-#define _WIN32_WINNT 0x0600
+#define _WIN32_WINNT 0x0601
 
 #include <stdarg.h>
 #include <stdlib.h>
@@ -33,6 +33,7 @@
 #include "winbase.h"
 #include "winerror.h"
 #include "winnls.h"
+#include "fileapi.h"
 
 static HANDLE (WINAPI *pFindFirstFileExA)(LPCSTR,FINDEX_INFO_LEVELS,LPVOID,FINDEX_SEARCH_OPS,LPVOID,DWORD);
 static BOOL (WINAPI *pReplaceFileA)(LPCSTR, LPCSTR, LPCSTR, DWORD, LPVOID, LPVOID);
@@ -43,6 +44,8 @@ static DWORD (WINAPI *pQueueUserAPC)(PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR
 static BOOL (WINAPI *pGetFileInformationByHandleEx)(HANDLE, FILE_INFO_BY_HANDLE_CLASS, LPVOID, DWORD);
 static HANDLE (WINAPI *pOpenFileById)(HANDLE, LPFILE_ID_DESCRIPTOR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD);
 static BOOL (WINAPI *pSetFileValidData)(HANDLE, LONGLONG);
+static HRESULT (WINAPI *pCopyFile2)(PCWSTR,PCWSTR,COPYFILE2_EXTENDED_PARAMETERS*);
+static HANDLE (WINAPI *pCreateFile2)(LPCWSTR, DWORD, DWORD, DWORD, CREATEFILE2_EXTENDED_PARAMETERS*);
 
 /* keep filename and filenameW the same */
 static const char filename[] = "testfile.xxx";
@@ -80,6 +83,8 @@ static void InitFunctionPointers(void)
     pGetFileInformationByHandleEx = (void *) GetProcAddress(hkernel32, "GetFileInformationByHandleEx");
     pOpenFileById = (void *) GetProcAddress(hkernel32, "OpenFileById");
     pSetFileValidData = (void *) GetProcAddress(hkernel32, "SetFileValidData");
+    pCopyFile2 = (void *) GetProcAddress(hkernel32, "CopyFile2");
+    pCreateFile2 = (void *) GetProcAddress(hkernel32, "CreateFile2");
 }
 
 static void test__hread( void )
@@ -721,7 +726,7 @@ static void test_CopyFileA(void)
     ok(!memcmp(prefix, buf, sizeof(prefix)), "buffer contents mismatch\n");
 
     /* check error on copying over a mapped file that was opened with FILE_SHARE_READ */
-    hmapfile = CreateFileMapping(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
+    hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
     ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
 
     ret = CopyFileA(source, dest, FALSE);
@@ -735,7 +740,7 @@ static void test_CopyFileA(void)
     ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n");
 
     /* check error on copying over a mapped file that was opened with FILE_SHARE_WRITE */
-    hmapfile = CreateFileMapping(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
+    hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
     ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
 
     ret = CopyFileA(source, dest, FALSE);
@@ -788,6 +793,234 @@ static void test_CopyFileW(void)
     ok(ret, "DeleteFileW: error %d\n", GetLastError());
 }
 
+static void test_CopyFile2(void)
+{
+    static const WCHAR doesntexistW[] = {'d','o','e','s','n','t','e','x','i','s','t',0};
+    static const WCHAR prefix[] = {'p','f','x',0};
+    WCHAR source[MAX_PATH], dest[MAX_PATH], temp_path[MAX_PATH];
+    COPYFILE2_EXTENDED_PARAMETERS params;
+    HANDLE hfile, hmapfile;
+    FILETIME ft1, ft2;
+    DWORD ret, len;
+    char buf[10];
+    HRESULT hr;
+
+    if (!pCopyFile2)
+    {
+        skip("CopyFile2 is not available\n");
+        return;
+    }
+
+    ret = GetTempPathW(MAX_PATH, temp_path);
+    ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
+    ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
+
+    ret = GetTempFileNameW(temp_path, prefix, 0, source);
+    ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
+
+    ret = GetTempFileNameW(temp_path, prefix, 0, dest);
+    ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
+
+    /* fail if exists */
+    memset(&params, 0, sizeof(params));
+    params.dwSize = sizeof(params);
+    params.dwCopyFlags = COPY_FILE_FAIL_IF_EXISTS;
+
+    SetLastError(0xdeadbeef);
+    hr = pCopyFile2(source, dest, &params);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "CopyFile2: unexpected error 0x%08x\n", hr);
+    ok(GetLastError() == ERROR_FILE_EXISTS, "CopyFile2: last error %d\n", GetLastError());
+
+    /* don't fail if exists */
+    params.dwSize = sizeof(params);
+    params.dwCopyFlags = 0;
+
+    hr = pCopyFile2(source, dest, &params);
+    ok(hr == S_OK, "CopyFile2: error 0x%08x\n", hr);
+
+    /* copying a file to itself must fail */
+    params.dwSize = sizeof(params);
+    params.dwCopyFlags = 0;
+
+    SetLastError(0xdeadbeef);
+    hr = pCopyFile2(source, source, &params);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: copying a file to itself didn't fail, 0x%08x\n", hr);
+    ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
+
+    /* make the source have not zero size */
+    hfile = CreateFileW(source, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
+    ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file\n");
+    ret = WriteFile(hfile, prefix, sizeof(prefix), &len, NULL );
+    ok(ret && len == sizeof(prefix), "WriteFile error %d\n", GetLastError());
+    ok(GetFileSize(hfile, NULL) == sizeof(prefix), "source file has wrong size\n");
+
+    /* get the file time and change it to prove the difference */
+    ret = GetFileTime(hfile, NULL, NULL, &ft1);
+    ok(ret, "GetFileTime error %d\n", GetLastError());
+    ft1.dwLowDateTime -= 600000000; /* 60 second */
+    ret = SetFileTime(hfile, NULL, NULL, &ft1);
+    ok(ret, "SetFileTime error %d\n", GetLastError());
+    GetFileTime(hfile, NULL, NULL, &ft1);  /* get the actual time back */
+    CloseHandle(hfile);
+
+    ret = GetTempFileNameW(temp_path, prefix, 0, dest);
+    ok(ret != 0, "GetTempFileNameA error %d\n", GetLastError());
+
+    params.dwSize = sizeof(params);
+    params.dwCopyFlags = COPY_FILE_FAIL_IF_EXISTS;
+
+    SetLastError(0xdeadbeef);
+    hr = pCopyFile2(source, dest, &params);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "CopyFile2: unexpected error 0x%08x\n", hr);
+    ok(GetLastError() == ERROR_FILE_EXISTS, "CopyFile2: last error %d\n", GetLastError());
+
+    params.dwSize = sizeof(params);
+    params.dwCopyFlags = 0;
+    hr = pCopyFile2(source, dest, &params);
+    ok(ret, "CopyFile2: error 0x%08x\n", hr);
+
+    /* copying from a read-locked source fails */
+    hfile = CreateFileW(source, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
+    ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
+
+    params.dwSize = sizeof(params);
+    params.dwCopyFlags = 0;
+    SetLastError(0xdeadbeef);
+    hr = pCopyFile2(source, dest, &params);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr);
+    ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
+
+    /* in addition, the source is opened before the destination */
+    params.dwSize = sizeof(params);
+    params.dwCopyFlags = 0;
+    SetLastError(0xdeadbeef);
+    hr = pCopyFile2(doesntexistW, dest, &params);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr);
+    ok(GetLastError() == ERROR_FILE_NOT_FOUND, "CopyFile2: last error %d\n", GetLastError());
+    CloseHandle(hfile);
+
+    /* copying from a r+w opened, r shared source succeeds */
+    hfile = CreateFileW(source, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+    ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
+
+    params.dwSize = sizeof(params);
+    params.dwCopyFlags = 0;
+    hr = pCopyFile2(source, dest, &params);
+    ok(hr == S_OK, "failed 0x%08x\n", hr);
+    CloseHandle(hfile);
+
+    /* copying from a delete-locked source mostly succeeds */
+    hfile = CreateFileW(source, DELETE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+    ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file, error %d\n", GetLastError());
+
+    params.dwSize = sizeof(params);
+    params.dwCopyFlags = 0;
+    hr = pCopyFile2(source, dest, &params);
+    ok(hr == S_OK, "failed 0x%08x\n", hr);
+    CloseHandle(hfile);
+
+    /* copying to a write-locked destination fails */
+    hfile = CreateFileW(dest, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+    ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
+
+    params.dwSize = sizeof(params);
+    params.dwCopyFlags = 0;
+    SetLastError(0xdeadbeef);
+    hr = pCopyFile2(source, dest, FALSE);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr);
+    ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
+    CloseHandle(hfile);
+
+    /* copying to a r+w opened, w shared destination mostly succeeds */
+    hfile = CreateFileW(dest, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
+    ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
+
+    params.dwSize = sizeof(params);
+    params.dwCopyFlags = 0;
+    hr = pCopyFile2(source, dest, FALSE);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    CloseHandle(hfile);
+
+    /* copying to a delete-locked destination fails, even when the destination is delete-shared */
+    hfile = CreateFileW(dest, DELETE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, 0);
+    ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
+
+    params.dwSize = sizeof(params);
+    params.dwCopyFlags = 0;
+    SetLastError(0xdeadbeef);
+    hr = pCopyFile2(source, dest, &params);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr);
+    ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
+    CloseHandle(hfile);
+
+    /* copy to a file that's opened the way Wine opens the source */
+    hfile = CreateFileW(dest, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
+    ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %d\n", GetLastError());
+
+    params.dwSize = sizeof(params);
+    params.dwCopyFlags = 0;
+    hr = pCopyFile2(source, dest, &params);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    CloseHandle(hfile);
+
+    /* make sure that destination has correct size */
+    hfile = CreateFileW(dest, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+    ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n");
+    ret = GetFileSize(hfile, NULL);
+    ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret);
+
+    /* make sure that destination has the same filetime */
+    ret = GetFileTime(hfile, NULL, NULL, &ft2);
+    ok(ret, "GetFileTime error %d\n", GetLastError());
+    ok(CompareFileTime(&ft1, &ft2) == 0, "destination file has wrong filetime\n");
+
+    params.dwSize = sizeof(params);
+    params.dwCopyFlags = 0;
+    SetLastError(0xdeadbeef);
+    hr = pCopyFile2(source, dest, &params);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr);
+    ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
+
+    /* make sure that destination still has correct size */
+    ret = GetFileSize(hfile, NULL);
+    ok(ret == sizeof(prefix), "destination file has wrong size %d\n", ret);
+    ret = ReadFile(hfile, buf, sizeof(buf), &len, NULL);
+    ok(ret && len == sizeof(prefix), "ReadFile: error %d\n", GetLastError());
+    ok(!memcmp(prefix, buf, sizeof(prefix)), "buffer contents mismatch\n");
+
+    /* check error on copying over a mapped file that was opened with FILE_SHARE_READ */
+    hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
+    ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
+
+    params.dwSize = sizeof(params);
+    params.dwCopyFlags = 0;
+    SetLastError(0xdeadbeef);
+    hr = pCopyFile2(source, dest, &params);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION), "CopyFile2: unexpected error 0x%08x\n", hr);
+    ok(GetLastError() == ERROR_SHARING_VIOLATION, "CopyFile2: last error %d\n", GetLastError());
+
+    CloseHandle(hmapfile);
+    CloseHandle(hfile);
+
+    hfile = CreateFileW(dest, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
+    ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file\n");
+
+    /* check error on copying over a mapped file that was opened with FILE_SHARE_WRITE */
+    hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
+    ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
+
+    params.dwSize = sizeof(params);
+    params.dwCopyFlags = 0;
+    hr = pCopyFile2(source, dest, &params);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_USER_MAPPED_FILE), "CopyFile2: unexpected error 0x%08x\n", hr);
+    ok(GetLastError() == ERROR_USER_MAPPED_FILE, "CopyFile2: last error %d\n", GetLastError());
+
+    CloseHandle(hmapfile);
+    CloseHandle(hfile);
+
+    DeleteFileW(source);
+    DeleteFileW(dest);
+}
 
 /*
  *   Debugging routine to dump a buffer in a hexdump-like fashion.
@@ -891,7 +1124,7 @@ static void test_CreateFileA(void)
         "LastError should have been ERROR_INVALID_NAME or ERROR_FILE_NOT_FOUND but got %u\n", GetLastError());
 
     /* get windows drive letter */
-    ret = GetWindowsDirectory(windowsdir, sizeof(windowsdir));
+    ret = GetWindowsDirectoryA(windowsdir, sizeof(windowsdir));
     ok(ret < sizeof(windowsdir), "windowsdir is abnormally long!\n");
     ok(ret != 0, "GetWindowsDirectory: error %d\n", GetLastError());
 
@@ -900,7 +1133,7 @@ static void test_CreateFileA(void)
     ok(ret != 0, "GetTempPathA error %d\n", GetLastError());
     strcpy(dirname, temp_path);
     strcat(dirname, directory);
-    ret = CreateDirectory(dirname, NULL);
+    ret = CreateDirectoryA(dirname, NULL);
     ok( ret, "Createdirectory failed, gle=%d\n", GetLastError() );
     /* set current drive & directory to known location */
     SetCurrentDirectoryA( temp_path );
@@ -1258,6 +1491,87 @@ static void test_CreateFileW(void)
     ok(ret, "DeleteFileW: error %d\n", GetLastError());
 }
 
+static void test_CreateFile2(void)
+{
+    HANDLE hFile;
+    WCHAR temp_path[MAX_PATH];
+    WCHAR filename[MAX_PATH];
+    CREATEFILE2_EXTENDED_PARAMETERS exparams;
+    static const WCHAR emptyW[]={'\0'};
+    static const WCHAR prefix[] = {'p','f','x',0};
+    static const WCHAR bogus[] = { '\\', '\\', '.', '\\', 'B', 'O', 'G', 'U', 'S', 0 };
+    DWORD ret;
+
+    if (!pCreateFile2)
+    {
+        win_skip("CreateFile2 is missing\n");
+        return;
+    }
+
+    ret = GetTempPathW(MAX_PATH, temp_path);
+    ok(ret != 0, "GetTempPathW error %d\n", GetLastError());
+    ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
+
+    ret = GetTempFileNameW(temp_path, prefix, 0, filename);
+    ok(ret != 0, "GetTempFileNameW error %d\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    exparams.dwSize = sizeof(exparams);
+    exparams.dwFileAttributes = FILE_FLAG_RANDOM_ACCESS;
+    exparams.dwFileFlags = 0;
+    exparams.dwSecurityQosFlags = 0;
+    exparams.lpSecurityAttributes = NULL;
+    exparams.hTemplateFile = 0;
+    hFile = pCreateFile2(filename, GENERIC_READ, 0, CREATE_NEW, &exparams);
+    ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS,
+       "CREATE_NEW should fail if file exists and last error value should be ERROR_FILE_EXISTS\n");
+
+    SetLastError(0xdeadbeef);
+    hFile = pCreateFile2(filename, GENERIC_READ, FILE_SHARE_READ, CREATE_ALWAYS, &exparams);
+    ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS,
+       "hFile %p, last error %u\n", hFile, GetLastError());
+    CloseHandle(hFile);
+
+    SetLastError(0xdeadbeef);
+    hFile = pCreateFile2(filename, GENERIC_READ, FILE_SHARE_READ, OPEN_ALWAYS, &exparams);
+    ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == ERROR_ALREADY_EXISTS,
+       "hFile %p, last error %u\n", hFile, GetLastError());
+    CloseHandle(hFile);
+
+    ret = DeleteFileW(filename);
+    ok(ret, "DeleteFileW: error %d\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    hFile = pCreateFile2(filename, GENERIC_READ, FILE_SHARE_READ, OPEN_ALWAYS, &exparams);
+    ok(hFile != INVALID_HANDLE_VALUE && GetLastError() == 0,
+       "hFile %p, last error %u\n", hFile, GetLastError());
+    CloseHandle(hFile);
+
+    ret = DeleteFileW(filename);
+    ok(ret, "DeleteFileW: error %d\n", GetLastError());
+
+    hFile = pCreateFile2(emptyW, GENERIC_READ, 0, CREATE_NEW, &exparams);
+    ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_PATH_NOT_FOUND,
+       "CreateFile2(\"\") returned ret=%p error=%d\n",hFile,GetLastError());
+
+    /* test the result of opening a nonexistent driver name */
+    exparams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
+    hFile = pCreateFile2(bogus, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING, &exparams);
+    ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND,
+       "CreateFile2 on invalid VxD name returned ret=%p error=%d\n",hFile,GetLastError());
+
+    ret = CreateDirectoryW(filename, NULL);
+    ok(ret == TRUE, "couldn't create temporary directory\n");
+    exparams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS;
+    hFile = pCreateFile2(filename, GENERIC_READ | GENERIC_WRITE, 0, OPEN_ALWAYS, &exparams);
+    todo_wine
+    ok(hFile == INVALID_HANDLE_VALUE,
+       "expected CreateFile2 to fail on existing directory, error: %d\n", GetLastError());
+    CloseHandle(hFile);
+    ret = RemoveDirectoryW(filename);
+    ok(ret, "DeleteFileW: error %d\n", GetLastError());
+}
+
 static void test_GetTempFileNameA(void)
 {
     UINT result;
@@ -1266,7 +1580,7 @@ static void test_GetTempFileNameA(void)
     char windowsdir[MAX_PATH + 10];
     char windowsdrive[3];
 
-    result = GetWindowsDirectory(windowsdir, sizeof(windowsdir));
+    result = GetWindowsDirectoryA(windowsdir, sizeof(windowsdir));
     ok(result < sizeof(windowsdir), "windowsdir is abnormally long!\n");
     ok(result != 0, "GetWindowsDirectory: error %d\n", GetLastError());
 
@@ -1318,24 +1632,36 @@ static void test_DeleteFileA( void )
                 GetLastError() == ERROR_INVALID_FUNCTION),
        "DeleteFileA(\"nul\") returned ret=%d error=%d\n",ret,GetLastError());
 
+    ret = DeleteFileA("nonexist.txt");
+    ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, "DeleteFileA(\"nonexist.txt\") returned ret=%d error=%d\n",ret,GetLastError());
+
     GetTempPathA(MAX_PATH, temp_path);
-    GetTempFileName(temp_path, "tst", 0, temp_file);
+    GetTempFileNameA(temp_path, "tst", 0, temp_file);
 
     SetLastError(0xdeadbeef);
-    hfile = CreateFile(temp_file, GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+    hfile = CreateFileA(temp_file, GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
     ok(hfile != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
 
     SetLastError(0xdeadbeef);
-    ret = DeleteFile(temp_file);
+    ret = DeleteFileA(temp_file);
 todo_wine
     ok(ret, "DeleteFile error %d\n", GetLastError());
 
     SetLastError(0xdeadbeef);
     ret = CloseHandle(hfile);
     ok(ret, "CloseHandle error %d\n", GetLastError());
-    ret = DeleteFile(temp_file);
+    ret = DeleteFileA(temp_file);
 todo_wine
     ok(!ret, "DeleteFile should fail\n");
+
+    SetLastError(0xdeadbeef);
+    ret = CreateDirectoryA("testdir", NULL);
+    ok(ret, "CreateDirectory failed, got err %d\n", GetLastError());
+    ret = DeleteFileA("testdir");
+    ok(!ret && GetLastError() == ERROR_ACCESS_DENIED,
+        "Expected ERROR_ACCESS_DENIED, got error %d\n", GetLastError());
+    ret = RemoveDirectoryA("testdir");
+    ok(ret, "Remove a directory failed, got error %d\n", GetLastError());
 }
 
 static void test_DeleteFileW( void )
@@ -1426,7 +1752,7 @@ static void test_MoveFileA(void)
     ok( retok && ret == sizeof(prefix),
        "WriteFile error %d\n", GetLastError());
 
-    hmapfile = CreateFileMapping(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
+    hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
     ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
 
     ret = MoveFileA(source, dest);
@@ -1441,12 +1767,12 @@ static void test_MoveFileA(void)
     CloseHandle(hfile);
 
     /* if MoveFile succeeded, move back to dest */
-    if (ret) MoveFile(dest, source);
+    if (ret) MoveFileA(dest, source);
 
     hfile = CreateFileA(source, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
     ok(hfile != INVALID_HANDLE_VALUE, "failed to open source file\n");
 
-    hmapfile = CreateFileMapping(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
+    hmapfile = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
     ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
 
     ret = MoveFileA(source, dest);
@@ -1461,7 +1787,7 @@ static void test_MoveFileA(void)
     CloseHandle(hfile);
 
     /* if MoveFile succeeded, move back to dest */
-    if (ret) MoveFile(dest, source);
+    if (ret) MoveFileA(dest, source);
 
     ret = MoveFileA(source, dest);
     ok(ret, "MoveFileA: failed, error %d\n", GetLastError());
@@ -1833,7 +2159,7 @@ static unsigned int map_file_access( unsigned int access )
     return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
 }
 
-static int is_sharing_compatible( DWORD access1, DWORD sharing1, DWORD access2, DWORD sharing2 )
+static BOOL is_sharing_compatible( DWORD access1, DWORD sharing1, DWORD access2, DWORD sharing2 )
 {
     access1 = map_file_access( access1 );
     access2 = map_file_access( access2 );
@@ -1843,22 +2169,22 @@ static int is_sharing_compatible( DWORD access1, DWORD sharing1, DWORD access2,
     if (!access1) sharing1 = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
     if (!access2) sharing2 = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
 
-    if ((access1 & (FILE_READ_DATA|FILE_EXECUTE)) && !(sharing2 & FILE_SHARE_READ)) return 0;
-    if ((access1 & (FILE_WRITE_DATA|FILE_APPEND_DATA)) && !(sharing2 & FILE_SHARE_WRITE)) return 0;
-    if ((access1 & DELETE) && !(sharing2 & FILE_SHARE_DELETE)) return 0;
-    if ((access2 & (FILE_READ_DATA|FILE_EXECUTE)) && !(sharing1 & FILE_SHARE_READ)) return 0;
-    if ((access2 & (FILE_WRITE_DATA|FILE_APPEND_DATA)) && !(sharing1 & FILE_SHARE_WRITE)) return 0;
-    if ((access2 & DELETE) && !(sharing1 & FILE_SHARE_DELETE)) return 0;
-    return 1;
+    if ((access1 & (FILE_READ_DATA|FILE_EXECUTE)) && !(sharing2 & FILE_SHARE_READ)) return FALSE;
+    if ((access1 & (FILE_WRITE_DATA|FILE_APPEND_DATA)) && !(sharing2 & FILE_SHARE_WRITE)) return FALSE;
+    if ((access1 & DELETE) && !(sharing2 & FILE_SHARE_DELETE)) return FALSE;
+    if ((access2 & (FILE_READ_DATA|FILE_EXECUTE)) && !(sharing1 & FILE_SHARE_READ)) return FALSE;
+    if ((access2 & (FILE_WRITE_DATA|FILE_APPEND_DATA)) && !(sharing1 & FILE_SHARE_WRITE)) return FALSE;
+    if ((access2 & DELETE) && !(sharing1 & FILE_SHARE_DELETE)) return FALSE;
+    return TRUE;
 }
 
-static int is_sharing_map_compatible( DWORD map_access, DWORD access2, DWORD sharing2 )
+static BOOL is_sharing_map_compatible( DWORD map_access, DWORD access2, DWORD sharing2 )
 {
     if ((map_access == PAGE_READWRITE || map_access == PAGE_EXECUTE_READWRITE) &&
-        !(sharing2 & FILE_SHARE_WRITE)) return 0;
+        !(sharing2 & FILE_SHARE_WRITE)) return FALSE;
     access2 = map_file_access( access2 );
-    if ((map_access & SEC_IMAGE) && (access2 & FILE_WRITE_DATA)) return 0;
-    return 1;
+    if ((map_access & SEC_IMAGE) && (access2 & FILE_WRITE_DATA)) return FALSE;
+    return TRUE;
 }
 
 static void test_file_sharing(void)
@@ -2039,7 +2365,7 @@ static void test_file_sharing(void)
 static char get_windows_drive(void)
 {
     char windowsdir[MAX_PATH];
-    GetWindowsDirectory(windowsdir, sizeof(windowsdir));
+    GetWindowsDirectoryA(windowsdir, sizeof(windowsdir));
     return windowsdir[0];
 }
 
@@ -2074,7 +2400,7 @@ static void test_FindFirstFileA(void)
     ok ( FindClose(handle) == TRUE, "Failed to close handle %s\n", buffer2 );
 
     /* try FindFirstFileA on windows dir */
-    GetWindowsDirectory( buffer2, sizeof(buffer2) );
+    GetWindowsDirectoryA( buffer2, sizeof(buffer2) );
     strcat(buffer2, "\\*");
     handle = FindFirstFileA(buffer2, &data);
     ok( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s should succeed\n", buffer2 );
@@ -2099,18 +2425,26 @@ static void test_FindFirstFileA(void)
     strcat(buffer2, "\\");
     handle = FindFirstFileA(buffer2, &data);
     err = GetLastError();
-    ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
+    ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
     todo_wine {
         ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
     }
 
+    /* try FindFirstFileA without trailing backslash */
+    SetLastError( 0xdeadbeaf );
+    strcpy(buffer2, nonexistent);
+    handle = FindFirstFileA(buffer2, &data);
+    err = GetLastError();
+    ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
+    ok ( err == ERROR_FILE_NOT_FOUND, "Bad Error number %d\n", err );
+
     /* try FindFirstFileA on "C:\foo\bar.txt" */
     SetLastError( 0xdeadbeaf );
     strcpy(buffer2, nonexistent);
     strcat(buffer2, "\\bar.txt");
     handle = FindFirstFileA(buffer2, &data);
     err = GetLastError();
-    ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
+    ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
     ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
 
     /* try FindFirstFileA on "C:\foo\*.*" */
@@ -2119,7 +2453,7 @@ static void test_FindFirstFileA(void)
     strcat(buffer2, "\\*.*");
     handle = FindFirstFileA(buffer2, &data);
     err = GetLastError();
-    ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
+    ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
     ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
 
     /* try FindFirstFileA on "foo\bar.txt" */
@@ -2128,7 +2462,7 @@ static void test_FindFirstFileA(void)
     strcat(buffer2, "\\bar.txt");
     handle = FindFirstFileA(buffer2, &data);
     err = GetLastError();
-    ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
+    ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
     ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
 
     /* try FindFirstFileA on "c:\nul" */
@@ -2178,7 +2512,7 @@ static void test_FindFirstFileA(void)
     strcat(buffer2, "nul\\*");
     handle = FindFirstFileA(buffer2, &data);
     err = GetLastError();
-    ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
+    ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
     ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
 
     /* try FindFirstFileA on "c:\nul*" */
@@ -2187,7 +2521,7 @@ static void test_FindFirstFileA(void)
     strcat(buffer2, "nul*");
     handle = FindFirstFileA(buffer2, &data);
     err = GetLastError();
-    ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
+    ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
     ok ( err == ERROR_FILE_NOT_FOUND, "Bad Error number %d\n", err );
 
     /* try FindFirstFileA on "c:\foo\bar\nul" */
@@ -2196,7 +2530,7 @@ static void test_FindFirstFileA(void)
     strcat(buffer2, "foo\\bar\\nul");
     handle = FindFirstFileA(buffer2, &data);
     err = GetLastError();
-    ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
+    ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
     ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
 
     /* try FindFirstFileA on "c:\foo\nul\bar" */
@@ -2205,7 +2539,7 @@ static void test_FindFirstFileA(void)
     strcat(buffer2, "foo\\nul\\bar");
     handle = FindFirstFileA(buffer2, &data);
     err = GetLastError();
-    ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should Fail\n", buffer2 );
+    ok ( handle == INVALID_HANDLE_VALUE, "FindFirstFile on %s should fail\n", buffer2 );
     ok ( err == ERROR_PATH_NOT_FOUND, "Bad Error number %d\n", err );
 }
 
@@ -2219,7 +2553,7 @@ static void test_FindNextFileA(void)
     buffer[0] = get_windows_drive();
     handle = FindFirstFileA(buffer,&search_results);
     ok ( handle != INVALID_HANDLE_VALUE, "FindFirstFile on C:\\* should succeed\n" );
-    while (FindNextFile(handle, &search_results))
+    while (FindNextFileA(handle, &search_results))
     {
         /* get to the end of the files */
     }
@@ -2256,14 +2590,14 @@ static void test_FindFirstFileExA(FINDEX_SEARCH_OPS search_ops)
 
 #define CHECK_NAME(fn) (strcmp((fn), "file1") == 0 || strcmp((fn), "file2") == 0 || strcmp((fn), "dir1") == 0)
 
-    ok(FindNextFile(handle, &search_results), "Fetching second file failed\n");
+    ok(FindNextFileA(handle, &search_results), "Fetching second file failed\n");
     ok(strcmp(search_results.cFileName, "..") == 0, "Second entry should be '..' is %s\n", search_results.cFileName);
 
-    ok(FindNextFile(handle, &search_results), "Fetching third file failed\n");
+    ok(FindNextFileA(handle, &search_results), "Fetching third file failed\n");
     ok(CHECK_NAME(search_results.cFileName), "Invalid third entry - %s\n", search_results.cFileName);
 
     SetLastError(0xdeadbeef);
-    ret = FindNextFile(handle, &search_results);
+    ret = FindNextFileA(handle, &search_results);
     if (!ret && (GetLastError() == ERROR_NO_MORE_FILES) && (search_ops == FindExSearchLimitToDirectories))
     {
         skip("File system supports directory filtering\n");
@@ -2276,12 +2610,12 @@ static void test_FindFirstFileExA(FINDEX_SEARCH_OPS search_ops)
     ok(ret, "Fetching fourth file failed\n");
     ok(CHECK_NAME(search_results.cFileName), "Invalid fourth entry - %s\n", search_results.cFileName);
 
-    ok(FindNextFile(handle, &search_results), "Fetching fifth file failed\n");
+    ok(FindNextFileA(handle, &search_results), "Fetching fifth file failed\n");
     ok(CHECK_NAME(search_results.cFileName), "Invalid fifth entry - %s\n", search_results.cFileName);
 
 #undef CHECK_NAME
 
-    ok(FindNextFile(handle, &search_results) == FALSE, "Fetching sixth file should fail\n");
+    ok(FindNextFileA(handle, &search_results) == FALSE, "Fetching sixth file should fail\n");
 
     FindClose( handle );
 
@@ -2295,8 +2629,8 @@ cleanup:
 static int test_Mapfile_createtemp(HANDLE *handle)
 {
     SetFileAttributesA(filename,FILE_ATTRIBUTE_NORMAL);
-    DeleteFile(filename);
-    *handle = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, 0,
+    DeleteFileA(filename);
+    *handle = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, 0, 0,
                          CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
     if (*handle != INVALID_HANDLE_VALUE) {
 
@@ -2313,14 +2647,14 @@ static void test_MapFile(void)
 
     ok(test_Mapfile_createtemp(&handle), "Couldn't create test file.\n");
 
-    hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0, 0x1000, "named_file_map" );
+    hmap = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 0x1000, "named_file_map" );
     ok( hmap != NULL, "mapping should work, I named it!\n" );
 
     ok( CloseHandle( hmap ), "can't close mapping handle\n");
 
     /* We have to close file before we try new stuff with mapping again.
        Else we would always succeed on XP or block descriptors on 95. */
-    hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0, 0, NULL );
+    hmap = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 0, NULL );
     ok( hmap != NULL, "We should still be able to map!\n" );
     ok( CloseHandle( hmap ), "can't close mapping handle\n");
     ok( CloseHandle( handle ), "can't close file handle\n");
@@ -2328,17 +2662,17 @@ static void test_MapFile(void)
 
     ok(test_Mapfile_createtemp(&handle), "Couldn't create test file.\n");
 
-    hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0, 0, NULL );
+    hmap = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0, 0, NULL );
     ok( hmap == NULL, "mapped zero size file\n");
     ok( GetLastError() == ERROR_FILE_INVALID, "not ERROR_FILE_INVALID\n");
 
-    hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0x80000000, 0, NULL );
+    hmap = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0x80000000, 0, NULL );
     ok( hmap == NULL || broken(hmap != NULL) /* NT4 */, "mapping should fail\n");
     /* GetLastError() varies between win9x and WinNT and also depends on the filesystem */
     if ( hmap )
         CloseHandle( hmap );
 
-    hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0x80000000, 0x10000, NULL );
+    hmap = CreateFileMappingA( handle, NULL, PAGE_READWRITE, 0x80000000, 0x10000, NULL );
     ok( hmap == NULL || broken(hmap != NULL) /* NT4 */, "mapping should fail\n");
     /* GetLastError() varies between win9x and WinNT and also depends on the filesystem */
     if ( hmap )
@@ -2352,7 +2686,7 @@ static void test_MapFile(void)
 
 static void test_GetFileType(void)
 {
-    DWORD type;
+    DWORD type, type2;
     HANDLE h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
     ok( h != INVALID_HANDLE_VALUE, "open %s failed\n", filename );
     type = GetFileType(h);
@@ -2364,6 +2698,11 @@ static void test_GetFileType(void)
     ok( type == FILE_TYPE_CHAR, "expected type char for nul got %d\n", type );
     CloseHandle( h );
     DeleteFileA( filename );
+    h = GetStdHandle( STD_OUTPUT_HANDLE );
+    ok( h != INVALID_HANDLE_VALUE, "GetStdHandle failed\n" );
+    type = GetFileType( (HANDLE)STD_OUTPUT_HANDLE );
+    type2 = GetFileType( h );
+    ok(type == type2, "expected type %d for STD_OUTPUT_HANDLE got %d\n", type2, type);
 }
 
 static int completion_count;
@@ -2830,7 +3169,7 @@ static void test_overlapped(void)
     ok( result == 0, "wrong result %u\n", result );
 
     SetLastError( 0xb00 );
-    ov.hEvent = CreateEvent( NULL, 1, 1, NULL );
+    ov.hEvent = CreateEventW( NULL, 1, 1, NULL );
     ov.Internal = STATUS_PENDING;
     ov.InternalHigh = 0xabcd;
     r = GetOverlappedResult(0, &ov, &result, 0);
@@ -2857,19 +3196,19 @@ static void test_RemoveDirectory(void)
     int rc;
     char directory[] = "removeme";
 
-    rc = CreateDirectory(directory, NULL);
+    rc = CreateDirectoryA(directory, NULL);
     ok( rc, "Createdirectory failed, gle=%d\n", GetLastError() );
 
-    rc = SetCurrentDirectory(directory);
+    rc = SetCurrentDirectoryA(directory);
     ok( rc, "SetCurrentDirectory failed, gle=%d\n", GetLastError() );
 
-    rc = RemoveDirectory(".");
+    rc = RemoveDirectoryA(".");
     if (!rc)
     {
-        rc = SetCurrentDirectory("..");
+        rc = SetCurrentDirectoryA("..");
         ok( rc, "SetCurrentDirectory failed, gle=%d\n", GetLastError() );
 
-        rc = RemoveDirectory(directory);
+        rc = RemoveDirectoryA(directory);
         ok( rc, "RemoveDirectory failed, gle=%d\n", GetLastError() );
     }
 }
@@ -3179,7 +3518,7 @@ static void test_ReplaceFileW(void)
     }
 }
 
-static void test_CreatFile(void)
+static void test_CreateFile(void)
 {
     static const struct test_data
     {
@@ -3211,20 +3550,61 @@ static void test_CreatFile(void)
     /* 22*/ { TRUNCATE_EXISTING, 0, ERROR_INVALID_PARAMETER, 0 },
     /* 23*/ { TRUNCATE_EXISTING, GENERIC_READ, ERROR_INVALID_PARAMETER, 0 },
     /* 24*/ { TRUNCATE_EXISTING, GENERIC_WRITE, 0, 0 },
-    /* 25*/ { TRUNCATE_EXISTING, GENERIC_READ|GENERIC_WRITE, 0, 0 }
+    /* 25*/ { TRUNCATE_EXISTING, GENERIC_READ|GENERIC_WRITE, 0, 0 },
+    /* 26*/ { TRUNCATE_EXISTING, FILE_WRITE_DATA, ERROR_INVALID_PARAMETER, 0 }
     };
     char temp_path[MAX_PATH];
     char file_name[MAX_PATH];
     DWORD i, ret, written;
     HANDLE hfile;
 
-    GetTempPath(MAX_PATH, temp_path);
-    GetTempFileName(temp_path, "tmp", 0, file_name);
+    GetTempPathA(MAX_PATH, temp_path);
+    GetTempFileNameA(temp_path, "tmp", 0, file_name);
+
+    i = strlen(temp_path);
+    if (i && temp_path[i - 1] == '\\') temp_path[i - 1] = 0;
+
+    for (i = 0; i <= 5; i++)
+    {
+        SetLastError(0xdeadbeef);
+        hfile = CreateFileA(temp_path, GENERIC_READ, 0, NULL, i, 0, 0);
+        ok(hfile == INVALID_HANDLE_VALUE, "CreateFile should fail\n");
+        if (i == 0 || i == 5)
+        {
+/* FIXME: remove once Wine is fixed */
+if (i == 5) todo_wine
+            ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
+else
+            ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
+        }
+        else
+        {
+/* FIXME: remove once Wine is fixed */
+if (i == 1) todo_wine
+            ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError());
+else
+            ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError());
+        }
+
+        SetLastError(0xdeadbeef);
+        hfile = CreateFileA(temp_path, GENERIC_WRITE, 0, NULL, i, 0, 0);
+        ok(hfile == INVALID_HANDLE_VALUE, "CreateFile should fail\n");
+        if (i == 0)
+            ok(GetLastError() == ERROR_INVALID_PARAMETER, "%d: expected ERROR_INVALID_PARAMETER, got %d\n", i, GetLastError());
+        else
+        {
+/* FIXME: remove once Wine is fixed */
+if (i == 1) todo_wine
+            ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError());
+else
+            ok(GetLastError() == ERROR_ACCESS_DENIED, "%d: expected ERROR_ACCESS_DENIED, got %d\n", i, GetLastError());
+        }
+    }
 
     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
     {
         SetLastError(0xdeadbeef);
-        hfile = CreateFile(file_name, td[i].access, 0, NULL, td[i].disposition, 0, 0);
+        hfile = CreateFileA(file_name, td[i].access, 0, NULL, td[i].disposition, 0, 0);
         if (!td[i].error)
         {
             ok(hfile != INVALID_HANDLE_VALUE, "%d: CreateFile error %d\n", i, GetLastError());
@@ -3232,7 +3612,7 @@ static void test_CreatFile(void)
             SetLastError(0xdeadbeef);
             ret = WriteFile(hfile, &td[i].error, sizeof(td[i].error), &written, NULL);
             if (td[i].access & GENERIC_WRITE)
-            ok(ret, "%d: WriteFile error %d\n", i, GetLastError());
+                ok(ret, "%d: WriteFile error %d\n", i, GetLastError());
             else
             {
                 ok(!ret, "%d: WriteFile should fail\n", i);
@@ -3259,10 +3639,10 @@ static void test_CreatFile(void)
             }
         }
 
-        if (td[i].clean_up) DeleteFile(file_name);
+        if (td[i].clean_up) DeleteFileA(file_name);
     }
 
-    DeleteFile(file_name);
+    DeleteFileA(file_name);
 }
 
 static void test_GetFileInformationByHandleEx(void)
@@ -3335,7 +3715,7 @@ static void test_GetFileInformationByHandleEx(void)
     }
 
     CloseHandle(directory);
-    DeleteFile(tempFileName);
+    DeleteFileA(tempFileName);
 }
 
 static void test_OpenFileById(void)
@@ -3439,7 +3819,7 @@ static void test_OpenFileById(void)
 
     CloseHandle(handle);
     CloseHandle(directory);
-    DeleteFile(tempFileName);
+    DeleteFileA(tempFileName);
 }
 
 static void test_SetFileValidData(void)
@@ -3503,12 +3883,13 @@ static void test_SetFileValidData(void)
     privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
 
     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token) ||
-        !LookupPrivilegeValue(NULL, SE_MANAGE_VOLUME_NAME, &privs.Privileges[0].Luid) ||
+        !LookupPrivilegeValueA(NULL, SE_MANAGE_VOLUME_NAME, &privs.Privileges[0].Luid) ||
         !AdjustTokenPrivileges(token, FALSE, &privs, sizeof(privs), NULL, NULL) ||
         GetLastError() == ERROR_NOT_ALL_ASSIGNED)
     {
         win_skip("cannot enable SE_MANAGE_VOLUME_NAME privilege\n");
         CloseHandle(token);
+        DeleteFileA(filename);
         return;
     }
     handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
@@ -3572,8 +3953,139 @@ static void test_SetFileValidData(void)
 
     privs.Privileges[0].Attributes = 0;
     AdjustTokenPrivileges(token, FALSE, &privs, sizeof(privs), NULL, NULL);
+
     CloseHandle(token);
-    DeleteFile(filename);
+    CloseHandle(handle);
+    DeleteFileA(filename);
+}
+
+static unsigned file_map_access(unsigned access)
+{
+    if (access & GENERIC_READ)    access |= FILE_GENERIC_READ;
+    if (access & GENERIC_WRITE)   access |= FILE_GENERIC_WRITE;
+    if (access & GENERIC_EXECUTE) access |= FILE_GENERIC_EXECUTE;
+    if (access & GENERIC_ALL)     access |= FILE_ALL_ACCESS;
+    return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
+}
+
+static BOOL is_access_compatible(unsigned obj_access, unsigned desired_access)
+{
+    obj_access = file_map_access(obj_access);
+    desired_access = file_map_access(desired_access);
+    return (obj_access & desired_access) == desired_access;
+}
+
+static void test_file_access(void)
+{
+    static const struct
+    {
+        unsigned access, create_error, write_error, read_error;
+    } td[] =
+    {
+        { GENERIC_READ | GENERIC_WRITE, 0, 0, 0 },
+        { GENERIC_WRITE, 0, 0, ERROR_ACCESS_DENIED },
+        { GENERIC_READ, 0, ERROR_ACCESS_DENIED, 0 },
+        { FILE_READ_DATA | FILE_WRITE_DATA, 0, 0, 0 },
+        { FILE_WRITE_DATA, 0, 0, ERROR_ACCESS_DENIED },
+        { FILE_READ_DATA, 0, ERROR_ACCESS_DENIED, 0 },
+        { FILE_APPEND_DATA, 0, 0, ERROR_ACCESS_DENIED },
+        { FILE_READ_DATA | FILE_APPEND_DATA, 0, 0, 0 },
+        { FILE_WRITE_DATA | FILE_APPEND_DATA, 0, 0, ERROR_ACCESS_DENIED },
+        { 0, 0, ERROR_ACCESS_DENIED, ERROR_ACCESS_DENIED },
+    };
+    char path[MAX_PATH], fname[MAX_PATH];
+    unsigned char buf[16];
+    HANDLE hfile, hdup;
+    DWORD i, j, ret, bytes;
+
+    GetTempPathA(MAX_PATH, path);
+    GetTempFileNameA(path, "foo", 0, fname);
+
+    for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+    {
+        SetLastError(0xdeadbeef);
+        hfile = CreateFileA(fname, td[i].access, 0, NULL, CREATE_ALWAYS,
+                           FILE_FLAG_DELETE_ON_CLOSE, 0);
+        if (td[i].create_error)
+        {
+            ok(hfile == INVALID_HANDLE_VALUE, "%d: CreateFile should fail\n", i);
+            ok(td[i].create_error == GetLastError(), "%d: expected %d, got %d\n", i, td[i].create_error, GetLastError());
+            continue;
+        }
+        else
+            ok(hfile != INVALID_HANDLE_VALUE, "%d: CreateFile error %d\n", i, GetLastError());
+
+        for (j = 0; j < sizeof(td)/sizeof(td[0]); j++)
+        {
+            SetLastError(0xdeadbeef);
+            ret = DuplicateHandle(GetCurrentProcess(), hfile, GetCurrentProcess(), &hdup,
+                                  td[j].access, 0, 0);
+            if (is_access_compatible(td[i].access, td[j].access))
+                ok(ret, "DuplicateHandle(%#x => %#x) error %d\n", td[i].access, td[j].access, GetLastError());
+            else
+            {
+                /* FIXME: Remove once Wine is fixed */
+                if ((td[j].access & (GENERIC_READ | GENERIC_WRITE)) ||
+                    (!(td[i].access & (GENERIC_WRITE | FILE_WRITE_DATA)) && (td[j].access & FILE_WRITE_DATA)) ||
+                    (!(td[i].access & (GENERIC_READ | FILE_READ_DATA)) && (td[j].access & FILE_READ_DATA)) ||
+                    (!(td[i].access & (GENERIC_WRITE)) && (td[j].access & FILE_APPEND_DATA)))
+                {
+todo_wine
+                ok(!ret, "DuplicateHandle(%#x => %#x) should fail\n", td[i].access, td[j].access);
+todo_wine
+                ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
+                }
+                else
+                {
+                ok(!ret, "DuplicateHandle(%#x => %#x) should fail\n", td[i].access, td[j].access);
+                ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
+                }
+            }
+            if (ret) CloseHandle(hdup);
+        }
+
+        SetLastError(0xdeadbeef);
+        bytes = 0xdeadbeef;
+        ret = WriteFile(hfile, "\x5e\xa7", 2, &bytes, NULL);
+        if (td[i].write_error)
+        {
+            ok(!ret, "%d: WriteFile should fail\n", i);
+            ok(td[i].write_error == GetLastError(), "%d: expected %d, got %d\n", i, td[i].write_error, GetLastError());
+            ok(bytes == 0, "%d: expected 0, got %u\n", i, bytes);
+        }
+        else
+        {
+            ok(ret, "%d: WriteFile error %d\n", i, GetLastError());
+            ok(bytes == 2, "%d: expected 2, got %u\n", i, bytes);
+        }
+
+        SetLastError(0xdeadbeef);
+        ret = SetFilePointer(hfile, 0, NULL, FILE_BEGIN);
+        ok(ret != INVALID_SET_FILE_POINTER, "SetFilePointer error %d\n", GetLastError());
+
+        SetLastError(0xdeadbeef);
+        bytes = 0xdeadbeef;
+        ret = ReadFile(hfile, buf, sizeof(buf), &bytes, NULL);
+        if (td[i].read_error)
+        {
+            ok(!ret, "%d: ReadFile should fail\n", i);
+            ok(td[i].read_error == GetLastError(), "%d: expected %d, got %d\n", i, td[i].read_error, GetLastError());
+            ok(bytes == 0, "%d: expected 0, got %u\n", i, bytes);
+        }
+        else
+        {
+            ok(ret, "%d: ReadFile error %d\n", i, GetLastError());
+            if (td[i].write_error)
+                ok(bytes == 0, "%d: expected 0, got %u\n", i, bytes);
+            else
+            {
+                ok(bytes == 2, "%d: expected 2, got %u\n", i, bytes);
+                ok(buf[0] == 0x5e && buf[1] == 0xa7, "%d: expected 5ea7, got %02x%02x\n", i, buf[0], buf[1]);
+            }
+        }
+
+        CloseHandle(hfile);
+    }
 }
 
 START_TEST(file)
@@ -3591,9 +4103,11 @@ START_TEST(file)
     test_GetTempFileNameA();
     test_CopyFileA();
     test_CopyFileW();
-    test_CreatFile();
+    test_CopyFile2();
+    test_CreateFile();
     test_CreateFileA();
     test_CreateFileW();
+    test_CreateFile2();
     test_DeleteFileA();
     test_DeleteFileW();
     test_MoveFileA();
@@ -3618,4 +4132,5 @@ START_TEST(file)
     test_GetFileInformationByHandleEx();
     test_OpenFileById();
     test_SetFileValidData();
+    test_file_access();
 }
index 005e6c4..e98e083 100755 (executable)
@@ -1543,7 +1543,7 @@ static void test_message_from_hmodule(void)
     HMODULE h;
     CHAR out[0x100] = {0};
 
-    h = GetModuleHandle("kernel32.dll");
+    h = GetModuleHandleA("kernel32.dll");
     ok(h != 0, "GetModuleHandle failed\n");
 
     /*Test existing messageID; as the message strings from wine's kernel32 differ from windows' kernel32 we don't compare
index e36336c..a36c373 100755 (executable)
@@ -1,6 +1,7 @@
 /*
  * Unit test suite for heap functions
  *
+ * Copyright 2002 Geoffrey Hausheer
  * Copyright 2003 Dimitrie O. Paun
  * Copyright 2006 Detlef Riekenberg
  *
@@ -56,7 +57,7 @@ static SIZE_T resize_9x(SIZE_T size)
 
 static void test_sized_HeapAlloc(int nbytes)
 {
-    int success;
+    BOOL success;
     char *buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nbytes);
     ok(buf != NULL, "allocate failed\n");
     ok(buf[0] == 0, "buffer not zeroed\n");
@@ -66,7 +67,7 @@ static void test_sized_HeapAlloc(int nbytes)
 
 static void test_sized_HeapReAlloc(int nbytes1, int nbytes2)
 {
-    int success;
+    BOOL success;
     char *buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nbytes1);
     ok(buf != NULL, "allocate failed\n");
     ok(buf[0] == 0, "buffer not zeroed\n");
@@ -480,6 +481,278 @@ static void test_heap(void)
 
 }
 
+
+static void test_HeapCreate(void)
+{
+    SYSTEM_INFO sysInfo;
+    ULONG memchunk;
+    HANDLE heap;
+    LPVOID mem1,mem1a,mem3;
+    UCHAR *mem2,*mem2a;
+    UINT i;
+    BOOL error;
+    DWORD dwSize;
+
+    /* Retrieve the page size for this system */
+    GetSystemInfo(&sysInfo);
+    ok(sysInfo.dwPageSize>0,"GetSystemInfo should return a valid page size\n");
+
+    /* Create a Heap with a minimum and maximum size */
+    /* Note that Windows and Wine seem to behave a bit differently with respect
+       to memory allocation.  In Windows, you can't access all the memory
+       specified in the heap (due to overhead), so choosing a reasonable maximum
+       size for the heap was done mostly by trial-and-error on Win2k.  It may need
+       more tweaking for otherWindows variants.
+    */
+    memchunk=10*sysInfo.dwPageSize;
+    heap=HeapCreate(0,2*memchunk,5*memchunk);
+    ok( !((ULONG_PTR)heap & 0xffff), "heap %p not 64K aligned\n", heap );
+
+    /* Check that HeapCreate allocated the right amount of ram */
+    mem1=HeapAlloc(heap,0,5*memchunk+1);
+    ok(mem1==NULL,"HeapCreate allocated more Ram than it should have\n");
+    HeapFree(heap,0,mem1);
+
+    /* Check that a normal alloc works */
+    mem1=HeapAlloc(heap,0,memchunk);
+    ok(mem1!=NULL,"HeapAlloc failed\n");
+    if(mem1) {
+      ok(HeapSize(heap,0,mem1)>=memchunk, "HeapAlloc should return a big enough memory block\n");
+    }
+
+    /* Check that a 'zeroing' alloc works */
+    mem2=HeapAlloc(heap,HEAP_ZERO_MEMORY,memchunk);
+    ok(mem2!=NULL,"HeapAlloc failed\n");
+    if(mem2) {
+      ok(HeapSize(heap,0,mem2)>=memchunk,"HeapAlloc should return a big enough memory block\n");
+      error=FALSE;
+      for(i=0;i<memchunk;i++) {
+        if(mem2[i]!=0) {
+          error=TRUE;
+        }
+      }
+      ok(!error,"HeapAlloc should have zeroed out its allocated memory\n");
+    }
+
+    /* Check that HeapAlloc returns NULL when requested way too much memory */
+    mem3=HeapAlloc(heap,0,5*memchunk);
+    ok(mem3==NULL,"HeapAlloc should return NULL\n");
+    if(mem3) {
+      ok(HeapFree(heap,0,mem3),"HeapFree didn't pass successfully\n");
+    }
+
+    /* Check that HeapRealloc works */
+    mem2a=HeapReAlloc(heap,HEAP_ZERO_MEMORY,mem2,memchunk+5*sysInfo.dwPageSize);
+    ok(mem2a!=NULL,"HeapReAlloc failed\n");
+    if(mem2a) {
+      ok(HeapSize(heap,0,mem2a)>=memchunk+5*sysInfo.dwPageSize,"HeapReAlloc failed\n");
+      error=FALSE;
+      for(i=0;i<5*sysInfo.dwPageSize;i++) {
+        if(mem2a[memchunk+i]!=0) {
+          error=TRUE;
+        }
+      }
+      ok(!error,"HeapReAlloc should have zeroed out its allocated memory\n");
+    }
+
+    /* Check that HeapRealloc honours HEAP_REALLOC_IN_PLACE_ONLY */
+    error=FALSE;
+    mem1a=HeapReAlloc(heap,HEAP_REALLOC_IN_PLACE_ONLY,mem1,memchunk+sysInfo.dwPageSize);
+    if(mem1a!=NULL) {
+      if(mem1a!=mem1) {
+        error=TRUE;
+      }
+    }
+    ok(mem1a==NULL || !error,"HeapReAlloc didn't honour HEAP_REALLOC_IN_PLACE_ONLY\n");
+
+    /* Check that HeapFree works correctly */
+   if(mem1a) {
+     ok(HeapFree(heap,0,mem1a),"HeapFree failed\n");
+   } else {
+     ok(HeapFree(heap,0,mem1),"HeapFree failed\n");
+   }
+   if(mem2a) {
+     ok(HeapFree(heap,0,mem2a),"HeapFree failed\n");
+   } else {
+     ok(HeapFree(heap,0,mem2),"HeapFree failed\n");
+   }
+
+   /* 0-length buffer */
+   mem1 = HeapAlloc(heap, 0, 0);
+   ok(mem1 != NULL, "Reserved memory\n");
+
+   dwSize = HeapSize(heap, 0, mem1);
+   /* should work with 0-length buffer */
+   ok(dwSize < 0xFFFFFFFF, "The size of the 0-length buffer\n");
+   ok(HeapFree(heap, 0, mem1), "Freed the 0-length buffer\n");
+
+   /* Check that HeapDestroy works */
+   ok(HeapDestroy(heap),"HeapDestroy failed\n");
+}
+
+
+static void test_GlobalAlloc(void)
+{
+    ULONG memchunk;
+    HGLOBAL mem1,mem2,mem2a,mem2b;
+    UCHAR *mem2ptr;
+    UINT i;
+    BOOL error;
+    memchunk=100000;
+
+    SetLastError(NO_ERROR);
+    /* Check that a normal alloc works */
+    mem1=GlobalAlloc(0,memchunk);
+    ok(mem1!=NULL,"GlobalAlloc failed\n");
+    if(mem1) {
+      ok(GlobalSize(mem1)>=memchunk, "GlobalAlloc should return a big enough memory block\n");
+    }
+
+    /* Check that a 'zeroing' alloc works */
+    mem2=GlobalAlloc(GMEM_ZEROINIT,memchunk);
+    ok(mem2!=NULL,"GlobalAlloc failed: error=%d\n",GetLastError());
+    if(mem2) {
+      ok(GlobalSize(mem2)>=memchunk,"GlobalAlloc should return a big enough memory block\n");
+      mem2ptr=GlobalLock(mem2);
+      ok(mem2ptr==mem2,"GlobalLock should have returned the same memory as was allocated\n");
+      if(mem2ptr) {
+        error=FALSE;
+        for(i=0;i<memchunk;i++) {
+          if(mem2ptr[i]!=0) {
+            error=TRUE;
+          }
+        }
+        ok(!error,"GlobalAlloc should have zeroed out its allocated memory\n");
+      }
+   }
+    /* Check that GlobalReAlloc works */
+    /* Check that we can change GMEM_FIXED to GMEM_MOVEABLE */
+    mem2a=GlobalReAlloc(mem2,0,GMEM_MODIFY | GMEM_MOVEABLE);
+    if(mem2a!=NULL) {
+      mem2=mem2a;
+      mem2ptr=GlobalLock(mem2a);
+      ok(mem2ptr!=NULL && !GlobalUnlock(mem2a)&&GetLastError()==NO_ERROR,
+         "Converting from FIXED to MOVEABLE didn't REALLY work\n");
+    }
+
+    /* Check that ReAllocing memory works as expected */
+    mem2a=GlobalReAlloc(mem2,2*memchunk,GMEM_MOVEABLE | GMEM_ZEROINIT);
+    ok(mem2a!=NULL,"GlobalReAlloc failed\n");
+    if(mem2a) {
+      ok(GlobalSize(mem2a)>=2*memchunk,"GlobalReAlloc failed\n");
+      mem2ptr=GlobalLock(mem2a);
+      ok(mem2ptr!=NULL,"GlobalLock Failed\n");
+      if(mem2ptr) {
+        error=FALSE;
+        for(i=0;i<memchunk;i++) {
+          if(mem2ptr[memchunk+i]!=0) {
+            error=TRUE;
+          }
+        }
+        ok(!error,"GlobalReAlloc should have zeroed out its allocated memory\n");
+
+        /* Check that GlobalHandle works */
+        mem2b=GlobalHandle(mem2ptr);
+        ok(mem2b==mem2a,"GlobalHandle didn't return the correct memory handle %p/%p for %p\n",
+           mem2a, mem2b, mem2ptr);
+        /* Check that we can't discard locked memory */
+        mem2b=GlobalDiscard(mem2a);
+        if(mem2b==NULL) {
+          ok(!GlobalUnlock(mem2a) && GetLastError()==NO_ERROR,"GlobalUnlock Failed\n");
+        }
+      }
+    }
+    if(mem1) {
+      ok(GlobalFree(mem1)==NULL,"GlobalFree failed\n");
+    }
+    if(mem2a) {
+      ok(GlobalFree(mem2a)==NULL,"GlobalFree failed\n");
+    } else {
+      ok(GlobalFree(mem2)==NULL,"GlobalFree failed\n");
+    }
+}
+
+
+static void test_LocalAlloc(void)
+{
+    ULONG memchunk;
+    HLOCAL mem1,mem2,mem2a,mem2b;
+    UCHAR *mem2ptr;
+    UINT i;
+    BOOL error;
+    memchunk=100000;
+
+    /* Check that a normal alloc works */
+    mem1=LocalAlloc(0,memchunk);
+    ok(mem1!=NULL,"LocalAlloc failed: error=%d\n",GetLastError());
+    if(mem1) {
+      ok(LocalSize(mem1)>=memchunk, "LocalAlloc should return a big enough memory block\n");
+    }
+
+    /* Check that a 'zeroing' and lock alloc works */
+    mem2=LocalAlloc(LMEM_ZEROINIT|LMEM_MOVEABLE,memchunk);
+    ok(mem2!=NULL,"LocalAlloc failed: error=%d\n",GetLastError());
+    if(mem2) {
+      ok(LocalSize(mem2)>=memchunk,"LocalAlloc should return a big enough memory block\n");
+      mem2ptr=LocalLock(mem2);
+      ok(mem2ptr!=NULL,"LocalLock: error=%d\n",GetLastError());
+      if(mem2ptr) {
+        error=FALSE;
+        for(i=0;i<memchunk;i++) {
+          if(mem2ptr[i]!=0) {
+            error=TRUE;
+          }
+        }
+        ok(!error,"LocalAlloc should have zeroed out its allocated memory\n");
+        SetLastError(0);
+        error=LocalUnlock(mem2);
+        ok(!error && GetLastError()==NO_ERROR,
+           "LocalUnlock Failed: rc=%d err=%d\n",error,GetLastError());
+      }
+    }
+   mem2a=LocalFree(mem2);
+   ok(mem2a==NULL, "LocalFree failed: %p\n",mem2a);
+
+   /* Reallocate mem2 as moveable memory */
+   mem2=LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT,memchunk);
+   ok(mem2!=NULL, "LocalAlloc failed to create moveable memory, error=%d\n",GetLastError());
+
+   /* Check that ReAllocing memory works as expected */
+    mem2a=LocalReAlloc(mem2,2*memchunk,LMEM_MOVEABLE | LMEM_ZEROINIT);
+    ok(mem2a!=NULL,"LocalReAlloc failed, error=%d\n",GetLastError());
+    if(mem2a) {
+      ok(LocalSize(mem2a)>=2*memchunk,"LocalReAlloc failed\n");
+      mem2ptr=LocalLock(mem2a);
+      ok(mem2ptr!=NULL,"LocalLock Failed\n");
+      if(mem2ptr) {
+        error=FALSE;
+        for(i=0;i<memchunk;i++) {
+          if(mem2ptr[memchunk+i]!=0) {
+            error=TRUE;
+          }
+        }
+        ok(!error,"LocalReAlloc should have zeroed out its allocated memory\n");
+        /* Check that LocalHandle works */
+        mem2b=LocalHandle(mem2ptr);
+        ok(mem2b==mem2a,"LocalHandle didn't return the correct memory handle %p/%p for %p\n",
+           mem2a, mem2b, mem2ptr);
+        /* Check that we can't discard locked memory */
+        mem2b=LocalDiscard(mem2a);
+        ok(mem2b==NULL,"Discarded memory we shouldn't have\n");
+        SetLastError(NO_ERROR);
+        ok(!LocalUnlock(mem2a) && GetLastError()==NO_ERROR, "LocalUnlock Failed\n");
+      }
+    }
+    if(mem1) {
+      ok(LocalFree(mem1)==NULL,"LocalFree failed\n");
+    }
+    if(mem2a) {
+      ok(LocalFree(mem2a)==NULL,"LocalFree failed\n");
+    } else {
+      ok(LocalFree(mem2)==NULL,"LocalFree failed\n");
+    }
+}
+
 static void test_obsolete_flags(void)
 {
     static struct {
@@ -534,7 +807,7 @@ static void test_HeapQueryInformation(void)
     SIZE_T size;
     BOOL ret;
 
-    pHeapQueryInformation = (void *)GetProcAddress(GetModuleHandle("kernel32.dll"), "HeapQueryInformation");
+    pHeapQueryInformation = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "HeapQueryInformation");
     if (!pHeapQueryInformation)
     {
         win_skip("HeapQueryInformation is not available\n");
@@ -888,6 +1161,9 @@ START_TEST(heap)
 
     test_heap();
     test_obsolete_flags();
+    test_HeapCreate();
+    test_GlobalAlloc();
+    test_LocalAlloc();
 
     /* Test both short and very long blocks */
     test_sized_HeapAlloc(1);
index 24821b4..e749238 100644 (file)
@@ -18,6 +18,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#define NONAMELESSUNION
 #include <stdarg.h>
 #include <stdio.h>
 #include <assert.h>
 #include "winbase.h"
 #include "winternl.h"
 #include "wine/test.h"
+#include "delayloadhandler.h"
+
+/* PROCESS_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */
+#define PROCESS_ALL_ACCESS_NT4 (PROCESS_ALL_ACCESS & ~0xf000)
 
 #define ALIGN_SIZE(size, alignment) (((size) + (alignment - 1)) & ~((alignment - 1)))
 
@@ -41,9 +46,12 @@ struct PROCESS_BASIC_INFORMATION_PRIVATE
     ULONG_PTR InheritedFromUniqueProcessId;
 };
 
-static BOOL is_child;
 static LONG *child_failures;
+static WORD cb_count;
+static DWORD page_size;
 
+static NTSTATUS (WINAPI *pNtCreateSection)(HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *,
+                                           const LARGE_INTEGER *, ULONG, ULONG, HANDLE );
 static NTSTATUS (WINAPI *pNtMapViewOfSection)(HANDLE, HANDLE, PVOID *, ULONG, SIZE_T, const LARGE_INTEGER *, SIZE_T *, ULONG, ULONG, ULONG);
 static NTSTATUS (WINAPI *pNtUnmapViewOfSection)(HANDLE, PVOID);
 static NTSTATUS (WINAPI *pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
@@ -57,6 +65,9 @@ static NTSTATUS (WINAPI *pLdrLockLoaderLock)(ULONG, ULONG *, ULONG *);
 static NTSTATUS (WINAPI *pLdrUnlockLoaderLock)(ULONG, ULONG);
 static void (WINAPI *pRtlAcquirePebLock)(void);
 static void (WINAPI *pRtlReleasePebLock)(void);
+static PVOID    (WINAPI *pResolveDelayLoadedAPI)(PVOID, PCIMAGE_DELAYLOAD_DESCRIPTOR,
+                                                 PDELAYLOAD_FAILURE_DLL_CALLBACK, PVOID,
+                                                 PIMAGE_THUNK_DATA ThunkAddress,ULONG);
 
 static PVOID RVAToAddr(DWORD_PTR rva, HMODULE module)
 {
@@ -65,15 +76,7 @@ static PVOID RVAToAddr(DWORD_PTR rva, HMODULE module)
     return ((char*) module) + rva;
 }
 
-static const struct
-{
-    WORD e_magic;      /* 00: MZ Header signature */
-    WORD unused[29];
-    DWORD e_lfanew;    /* 3c: Offset to extended header */
-} dos_header =
-{
-    IMAGE_DOS_SIGNATURE, { 0 }, sizeof(dos_header)
-};
+static IMAGE_DOS_HEADER dos_header;
 
 static IMAGE_NT_HEADERS nt_header =
 {
@@ -149,11 +152,107 @@ static IMAGE_SECTION_HEADER section =
     IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ, /* Characteristics */
 };
 
+
+static const char filler[0x1000];
+static const char section_data[0x10] = "section data";
+
+static DWORD create_test_dll( const IMAGE_DOS_HEADER *dos_header, UINT dos_size,
+                              const IMAGE_NT_HEADERS *nt_header, const char *dll_name )
+{
+    DWORD dummy, size, file_align;
+    HANDLE hfile;
+    BOOL ret;
+
+    hfile = CreateFileA(dll_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, 0);
+    if (hfile == INVALID_HANDLE_VALUE) return 0;
+
+    SetLastError(0xdeadbeef);
+    ret = WriteFile(hfile, dos_header, dos_size, &dummy, NULL);
+    ok(ret, "WriteFile error %d\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    ret = WriteFile(hfile, nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL);
+    ok(ret, "WriteFile error %d\n", GetLastError());
+
+    if (nt_header->FileHeader.SizeOfOptionalHeader)
+    {
+        SetLastError(0xdeadbeef);
+        ret = WriteFile(hfile, &nt_header->OptionalHeader,
+                        min(nt_header->FileHeader.SizeOfOptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER)),
+                        &dummy, NULL);
+        ok(ret, "WriteFile error %d\n", GetLastError());
+        if (nt_header->FileHeader.SizeOfOptionalHeader > sizeof(IMAGE_OPTIONAL_HEADER))
+        {
+            file_align = nt_header->FileHeader.SizeOfOptionalHeader - sizeof(IMAGE_OPTIONAL_HEADER);
+            assert(file_align < sizeof(filler));
+            SetLastError(0xdeadbeef);
+            ret = WriteFile(hfile, filler, file_align, &dummy, NULL);
+            ok(ret, "WriteFile error %d\n", GetLastError());
+        }
+    }
+
+    assert(nt_header->FileHeader.NumberOfSections <= 1);
+    if (nt_header->FileHeader.NumberOfSections)
+    {
+        if (nt_header->OptionalHeader.SectionAlignment >= page_size)
+        {
+            section.PointerToRawData = dos_size;
+            section.VirtualAddress = nt_header->OptionalHeader.SectionAlignment;
+            section.Misc.VirtualSize = section.SizeOfRawData * 10;
+        }
+        else
+        {
+            section.PointerToRawData = nt_header->OptionalHeader.SizeOfHeaders;
+            section.VirtualAddress = nt_header->OptionalHeader.SizeOfHeaders;
+            section.Misc.VirtualSize = 5;
+        }
+
+        SetLastError(0xdeadbeef);
+        ret = WriteFile(hfile, &section, sizeof(section), &dummy, NULL);
+        ok(ret, "WriteFile error %d\n", GetLastError());
+
+        /* section data */
+        SetLastError(0xdeadbeef);
+        ret = WriteFile(hfile, section_data, sizeof(section_data), &dummy, NULL);
+        ok(ret, "WriteFile error %d\n", GetLastError());
+    }
+    size = GetFileSize(hfile, NULL);
+    CloseHandle(hfile);
+    return size;
+}
+
+/* helper to test image section mapping */
+static NTSTATUS map_image_section( const IMAGE_NT_HEADERS *nt_header )
+{
+    char temp_path[MAX_PATH];
+    char dll_name[MAX_PATH];
+    LARGE_INTEGER size;
+    HANDLE file, map;
+    NTSTATUS status;
+
+    GetTempPathA(MAX_PATH, temp_path);
+    GetTempFileNameA(temp_path, "ldr", 0, dll_name);
+
+    size.u.LowPart = create_test_dll( &dos_header, sizeof(dos_header), nt_header, dll_name );
+    ok( size.u.LowPart, "could not create %s\n", dll_name);
+    size.u.HighPart = 0;
+
+    file = CreateFileA(dll_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+    ok(file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
+
+    status = pNtCreateSection(&map, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ, NULL, &size,
+                              PAGE_READONLY, SEC_IMAGE, file );
+    if (map) CloseHandle( map );
+    CloseHandle( file );
+    DeleteFileA( dll_name );
+    return status;
+}
+
+
 static void test_Loader(void)
 {
     static const struct test_data
     {
-        const void *dos_header;
         DWORD size_of_dos_header;
         WORD number_of_sections, size_of_optional_header;
         DWORD section_alignment, file_alignment;
@@ -161,47 +260,47 @@ static void test_Loader(void)
         DWORD errors[4]; /* 0 means LoadLibrary should succeed */
     } td[] =
     {
-        { &dos_header, sizeof(dos_header),
+        { sizeof(dos_header),
           1, 0, 0, 0, 0, 0,
           { ERROR_BAD_EXE_FORMAT }
         },
-        { &dos_header, sizeof(dos_header),
+        { sizeof(dos_header),
           1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x1000,
           sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0xe00,
           sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
           { ERROR_BAD_EXE_FORMAT } /* XP doesn't like too small image size */
         },
-        { &dos_header, sizeof(dos_header),
+        { sizeof(dos_header),
           1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x1000,
           sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
           sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
           { ERROR_SUCCESS }
         },
-        { &dos_header, sizeof(dos_header),
+        { sizeof(dos_header),
           1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x1000,
           0x1f00,
           0x1000,
           { ERROR_SUCCESS }
         },
-        { &dos_header, sizeof(dos_header),
+        { sizeof(dos_header),
           1, sizeof(IMAGE_OPTIONAL_HEADER), 0x200, 0x200,
           sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x200,
           sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
           { ERROR_SUCCESS, ERROR_INVALID_ADDRESS } /* vista is more strict */
         },
-        { &dos_header, sizeof(dos_header),
+        { sizeof(dos_header),
           1, sizeof(IMAGE_OPTIONAL_HEADER), 0x200, 0x1000,
           sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
           sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
           { ERROR_BAD_EXE_FORMAT } /* XP doesn't like alignments */
         },
-        { &dos_header, sizeof(dos_header),
+        { sizeof(dos_header),
           1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x200,
           sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
           sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER),
           { ERROR_SUCCESS }
         },
-        { &dos_header, sizeof(dos_header),
+        { sizeof(dos_header),
           1, sizeof(IMAGE_OPTIONAL_HEADER), 0x1000, 0x200,
           sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
           0x200,
@@ -210,66 +309,66 @@ static void test_Loader(void)
         /* Mandatory are all fields up to SizeOfHeaders, everything else
          * is really optional (at least that's true for XP).
          */
-        { &dos_header, sizeof(dos_header),
+        { sizeof(dos_header),
           1, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
           sizeof(dos_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum) + sizeof(IMAGE_SECTION_HEADER) + 0x10,
           sizeof(dos_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum) + sizeof(IMAGE_SECTION_HEADER),
           { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT, ERROR_INVALID_ADDRESS,
             ERROR_NOACCESS }
         },
-        { &dos_header, sizeof(dos_header),
+        { sizeof(dos_header),
           0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
           0xd0, /* beyond of the end of file */
           0xc0, /* beyond of the end of file */
           { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */
         },
-        { &dos_header, sizeof(dos_header),
+        { sizeof(dos_header),
           0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
           0x1000,
           0,
           { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */
         },
-        { &dos_header, sizeof(dos_header),
+        { sizeof(dos_header),
           0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
           1,
           0,
           { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */
         },
 #if 0 /* not power of 2 alignments need more test cases */
-        { &dos_header, sizeof(dos_header),
+        { sizeof(dos_header),
           0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x300, 0x300,
           1,
           0,
           { ERROR_BAD_EXE_FORMAT } /* alignment is not power of 2 */
         },
 #endif
-        { &dos_header, sizeof(dos_header),
+        { sizeof(dos_header),
           0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 4, 4,
           1,
           0,
           { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */
         },
-        { &dos_header, sizeof(dos_header),
+        { sizeof(dos_header),
           0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 1, 1,
           1,
           0,
           { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */
         },
-        { &dos_header, sizeof(dos_header),
+        { sizeof(dos_header),
           0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum), 0x200, 0x200,
           0,
           0,
           { ERROR_BAD_EXE_FORMAT } /* image size == 0 -> failure */
         },
         /* the following data mimics the PE image which upack creates */
-        { &dos_header, 0x10,
+        { 0x10,
           1, 0x148, 0x1000, 0x200,
           sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x1000,
           0x200,
           { ERROR_SUCCESS }
         },
         /* Minimal PE image that XP is able to load: 92 bytes */
-        { &dos_header, 0x04,
+        { 0x04,
           0, FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, CheckSum),
           0x04 /* also serves as e_lfanew in the truncated MZ header */, 0x04,
           1,
@@ -277,40 +376,24 @@ static void test_Loader(void)
           { ERROR_SUCCESS, ERROR_BAD_EXE_FORMAT } /* vista is more strict */
         }
     };
-    static const char filler[0x1000];
-    static const char section_data[0x10] = "section data";
     int i;
-    DWORD dummy, file_size, file_align;
-    HANDLE hfile;
+    DWORD file_size;
     HMODULE hlib, hlib_as_data_file;
-    SYSTEM_INFO si;
     char temp_path[MAX_PATH];
     char dll_name[MAX_PATH];
     SIZE_T size;
     BOOL ret;
-
-    GetSystemInfo(&si);
+    NTSTATUS status;
+    WORD orig_machine = nt_header.FileHeader.Machine;
 
     /* prevent displaying of the "Unable to load this DLL" message box */
     SetErrorMode(SEM_FAILCRITICALERRORS);
 
-    GetTempPath(MAX_PATH, temp_path);
+    GetTempPathA(MAX_PATH, temp_path);
 
     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
     {
-        GetTempFileName(temp_path, "ldr", 0, dll_name);
-
-        /*trace("creating %s\n", dll_name);*/
-        hfile = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
-        if (hfile == INVALID_HANDLE_VALUE)
-        {
-            ok(0, "could not create %s\n", dll_name);
-            break;
-        }
-
-        SetLastError(0xdeadbeef);
-        ret = WriteFile(hfile, td[i].dos_header, td[i].size_of_dos_header, &dummy, NULL);
-        ok(ret, "WriteFile error %d\n", GetLastError());
+        GetTempFileNameA(temp_path, "ldr", 0, dll_name);
 
         nt_header.FileHeader.NumberOfSections = td[i].number_of_sections;
         nt_header.FileHeader.SizeOfOptionalHeader = td[i].size_of_optional_header;
@@ -319,58 +402,16 @@ static void test_Loader(void)
         nt_header.OptionalHeader.FileAlignment = td[i].file_alignment;
         nt_header.OptionalHeader.SizeOfImage = td[i].size_of_image;
         nt_header.OptionalHeader.SizeOfHeaders = td[i].size_of_headers;
-        SetLastError(0xdeadbeef);
-        ret = WriteFile(hfile, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL);
-        ok(ret, "WriteFile error %d\n", GetLastError());
-
-        if (nt_header.FileHeader.SizeOfOptionalHeader)
-        {
-            SetLastError(0xdeadbeef);
-            ret = WriteFile(hfile, &nt_header.OptionalHeader,
-                            min(nt_header.FileHeader.SizeOfOptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER)),
-                            &dummy, NULL);
-            ok(ret, "WriteFile error %d\n", GetLastError());
-            if (nt_header.FileHeader.SizeOfOptionalHeader > sizeof(IMAGE_OPTIONAL_HEADER))
-            {
-                file_align = nt_header.FileHeader.SizeOfOptionalHeader - sizeof(IMAGE_OPTIONAL_HEADER);
-                assert(file_align < sizeof(filler));
-                SetLastError(0xdeadbeef);
-                ret = WriteFile(hfile, filler, file_align, &dummy, NULL);
-                ok(ret, "WriteFile error %d\n", GetLastError());
-            }
-        }
 
-        assert(nt_header.FileHeader.NumberOfSections <= 1);
-        if (nt_header.FileHeader.NumberOfSections)
+        file_size = create_test_dll( &dos_header, td[i].size_of_dos_header, &nt_header, dll_name );
+        if (!file_size)
         {
-            if (nt_header.OptionalHeader.SectionAlignment >= si.dwPageSize)
-            {
-                section.PointerToRawData = td[i].size_of_dos_header;
-                section.VirtualAddress = nt_header.OptionalHeader.SectionAlignment;
-                section.Misc.VirtualSize = section.SizeOfRawData * 10;
-            }
-            else
-            {
-                section.PointerToRawData = nt_header.OptionalHeader.SizeOfHeaders;
-                section.VirtualAddress = nt_header.OptionalHeader.SizeOfHeaders;
-                section.Misc.VirtualSize = 5;
-            }
-
-            SetLastError(0xdeadbeef);
-            ret = WriteFile(hfile, &section, sizeof(section), &dummy, NULL);
-            ok(ret, "WriteFile error %d\n", GetLastError());
-
-            /* section data */
-            SetLastError(0xdeadbeef);
-            ret = WriteFile(hfile, section_data, sizeof(section_data), &dummy, NULL);
-            ok(ret, "WriteFile error %d\n", GetLastError());
+            ok(0, "could not create %s\n", dll_name);
+            break;
         }
 
-        file_size = GetFileSize(hfile, NULL);
-        CloseHandle(hfile);
-
         SetLastError(0xdeadbeef);
-        hlib = LoadLibrary(dll_name);
+        hlib = LoadLibraryA(dll_name);
         if (hlib)
         {
             MEMORY_BASIC_INFORMATION info;
@@ -385,17 +426,17 @@ static void test_Loader(void)
             ok(info.BaseAddress == hlib, "%d: %p != %p\n", i, info.BaseAddress, hlib);
             ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib);
             ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
-            ok(info.RegionSize == ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, si.dwPageSize), "%d: got %lx != expected %x\n",
-               i, info.RegionSize, ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, si.dwPageSize));
+            ok(info.RegionSize == ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size), "%d: got %lx != expected %x\n",
+               i, info.RegionSize, ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size));
             ok(info.State == MEM_COMMIT, "%d: %x != MEM_COMMIT\n", i, info.State);
-            if (nt_header.OptionalHeader.SectionAlignment < si.dwPageSize)
+            if (nt_header.OptionalHeader.SectionAlignment < page_size)
                 ok(info.Protect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.Protect);
             else
                 ok(info.Protect == PAGE_READONLY, "%d: %x != PAGE_READONLY\n", i, info.Protect);
             ok(info.Type == SEC_IMAGE, "%d: %x != SEC_IMAGE\n", i, info.Type);
 
             SetLastError(0xdeadbeef);
-            ptr = VirtualAlloc(hlib, si.dwPageSize, MEM_COMMIT, info.Protect);
+            ptr = VirtualAlloc(hlib, page_size, MEM_COMMIT, info.Protect);
             ok(!ptr, "%d: VirtualAlloc should fail\n", i);
             /* FIXME: Remove once Wine is fixed */
             if (info.Protect == PAGE_WRITECOPY || info.Protect == PAGE_EXECUTE_WRITECOPY)
@@ -408,11 +449,11 @@ todo_wine
             size = VirtualQuery((char *)hlib + info.RegionSize, &info, sizeof(info));
             ok(size == sizeof(info),
                 "%d: VirtualQuery error %d\n", i, GetLastError());
-            if (nt_header.OptionalHeader.SectionAlignment == si.dwPageSize ||
+            if (nt_header.OptionalHeader.SectionAlignment == page_size ||
                 nt_header.OptionalHeader.SectionAlignment == nt_header.OptionalHeader.FileAlignment)
             {
-                ok(info.BaseAddress == (char *)hlib + ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, si.dwPageSize), "%d: got %p != expected %p\n",
-                   i, info.BaseAddress, (char *)hlib + ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, si.dwPageSize));
+                ok(info.BaseAddress == (char *)hlib + ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size), "%d: got %p != expected %p\n",
+                   i, info.BaseAddress, (char *)hlib + ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size));
                 ok(info.AllocationBase == 0, "%d: %p != 0\n", i, info.AllocationBase);
                 ok(info.AllocationProtect == 0, "%d: %x != 0\n", i, info.AllocationProtect);
                 /*ok(info.RegionSize == not_practical_value, "%d: %lx != not_practical_value\n", i, info.RegionSize);*/
@@ -426,20 +467,20 @@ todo_wine
                 ok(info.BaseAddress == hlib, "%d: got %p != expected %p\n", i, info.BaseAddress, hlib);
                 ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib);
                 ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
-                ok(info.RegionSize == ALIGN_SIZE(file_size, si.dwPageSize), "%d: got %lx != expected %x\n",
-                   i, info.RegionSize, ALIGN_SIZE(file_size, si.dwPageSize));
+                ok(info.RegionSize == ALIGN_SIZE(file_size, page_size), "%d: got %lx != expected %x\n",
+                   i, info.RegionSize, ALIGN_SIZE(file_size, page_size));
                 ok(info.State == MEM_COMMIT, "%d: %x != MEM_COMMIT\n", i, info.State);
                 ok(info.Protect == PAGE_READONLY, "%d: %x != PAGE_READONLY\n", i, info.Protect);
                 ok(info.Type == SEC_IMAGE, "%d: %x != SEC_IMAGE\n", i, info.Type);
             }
 
             /* header: check the zeroing of alignment */
-            if (nt_header.OptionalHeader.SectionAlignment >= si.dwPageSize)
+            if (nt_header.OptionalHeader.SectionAlignment >= page_size)
             {
                 const char *start;
 
                 start = (const char *)hlib + nt_header.OptionalHeader.SizeOfHeaders;
-                size = ALIGN_SIZE((ULONG_PTR)start, si.dwPageSize) - (ULONG_PTR)start;
+                size = ALIGN_SIZE((ULONG_PTR)start, page_size) - (ULONG_PTR)start;
                 ok(!memcmp(start, filler, size), "%d: header alignment is not cleared\n", i);
             }
 
@@ -449,18 +490,18 @@ todo_wine
                 size = VirtualQuery((char *)hlib + section.VirtualAddress, &info, sizeof(info));
                 ok(size == sizeof(info),
                     "%d: VirtualQuery error %d\n", i, GetLastError());
-                if (nt_header.OptionalHeader.SectionAlignment < si.dwPageSize)
+                if (nt_header.OptionalHeader.SectionAlignment < page_size)
                 {
                     ok(info.BaseAddress == hlib, "%d: got %p != expected %p\n", i, info.BaseAddress, hlib);
-                    ok(info.RegionSize == ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, si.dwPageSize), "%d: got %lx != expected %x\n",
-                       i, info.RegionSize, ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, si.dwPageSize));
+                    ok(info.RegionSize == ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size), "%d: got %lx != expected %x\n",
+                       i, info.RegionSize, ALIGN_SIZE(nt_header.OptionalHeader.SizeOfImage, page_size));
                     ok(info.Protect == PAGE_EXECUTE_WRITECOPY, "%d: %x != PAGE_EXECUTE_WRITECOPY\n", i, info.Protect);
                 }
                 else
                 {
                     ok(info.BaseAddress == (char *)hlib + section.VirtualAddress, "%d: got %p != expected %p\n", i, info.BaseAddress, (char *)hlib + section.VirtualAddress);
-                    ok(info.RegionSize == ALIGN_SIZE(section.Misc.VirtualSize, si.dwPageSize), "%d: got %lx != expected %x\n",
-                       i, info.RegionSize, ALIGN_SIZE(section.Misc.VirtualSize, si.dwPageSize));
+                    ok(info.RegionSize == ALIGN_SIZE(section.Misc.VirtualSize, page_size), "%d: got %lx != expected %x\n",
+                       i, info.RegionSize, ALIGN_SIZE(section.Misc.VirtualSize, page_size));
                     ok(info.Protect == PAGE_READONLY, "%d: %x != PAGE_READONLY\n", i, info.Protect);
                 }
                 ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib);
@@ -468,23 +509,23 @@ todo_wine
                 ok(info.State == MEM_COMMIT, "%d: %x != MEM_COMMIT\n", i, info.State);
                 ok(info.Type == SEC_IMAGE, "%d: %x != SEC_IMAGE\n", i, info.Type);
 
-                if (nt_header.OptionalHeader.SectionAlignment >= si.dwPageSize)
+                if (nt_header.OptionalHeader.SectionAlignment >= page_size)
                     ok(!memcmp((const char *)hlib + section.VirtualAddress + section.PointerToRawData, &nt_header, section.SizeOfRawData), "wrong section data\n");
                 else
                     ok(!memcmp((const char *)hlib + section.PointerToRawData, section_data, section.SizeOfRawData), "wrong section data\n");
 
                 /* check the zeroing of alignment */
-                if (nt_header.OptionalHeader.SectionAlignment >= si.dwPageSize)
+                if (nt_header.OptionalHeader.SectionAlignment >= page_size)
                 {
                     const char *start;
 
                     start = (const char *)hlib + section.VirtualAddress + section.PointerToRawData + section.SizeOfRawData;
-                    size = ALIGN_SIZE((ULONG_PTR)start, si.dwPageSize) - (ULONG_PTR)start;
+                    size = ALIGN_SIZE((ULONG_PTR)start, page_size) - (ULONG_PTR)start;
                     ok(memcmp(start, filler, size), "%d: alignment should not be cleared\n", i);
                 }
 
                 SetLastError(0xdeadbeef);
-                ptr = VirtualAlloc((char *)hlib + section.VirtualAddress, si.dwPageSize, MEM_COMMIT, info.Protect);
+                ptr = VirtualAlloc((char *)hlib + section.VirtualAddress, page_size, MEM_COMMIT, info.Protect);
                 ok(!ptr, "%d: VirtualAlloc should fail\n", i);
                 /* FIXME: Remove once Wine is fixed */
                 if (info.Protect == PAGE_WRITECOPY || info.Protect == PAGE_EXECUTE_WRITECOPY)
@@ -497,7 +538,7 @@ todo_wine
             }
 
             SetLastError(0xdeadbeef);
-            hlib_as_data_file = LoadLibraryEx(dll_name, 0, LOAD_LIBRARY_AS_DATAFILE);
+            hlib_as_data_file = LoadLibraryExA(dll_name, 0, LOAD_LIBRARY_AS_DATAFILE);
             ok(hlib_as_data_file != 0, "LoadLibraryEx error %u\n", GetLastError());
             ok(hlib_as_data_file == hlib, "hlib_as_file and hlib are different\n");
 
@@ -506,22 +547,22 @@ todo_wine
             ok(ret, "FreeLibrary error %d\n", GetLastError());
 
             SetLastError(0xdeadbeef);
-            hlib = GetModuleHandle(dll_name);
+            hlib = GetModuleHandleA(dll_name);
             ok(hlib != 0, "GetModuleHandle error %u\n", GetLastError());
 
             SetLastError(0xdeadbeef);
             ret = FreeLibrary(hlib_as_data_file);
             ok(ret, "FreeLibrary error %d\n", GetLastError());
 
-            hlib = GetModuleHandle(dll_name);
+            hlib = GetModuleHandleA(dll_name);
             ok(!hlib, "GetModuleHandle should fail\n");
 
             SetLastError(0xdeadbeef);
-            hlib_as_data_file = LoadLibraryEx(dll_name, 0, LOAD_LIBRARY_AS_DATAFILE);
+            hlib_as_data_file = LoadLibraryExA(dll_name, 0, LOAD_LIBRARY_AS_DATAFILE);
             ok(hlib_as_data_file != 0, "LoadLibraryEx error %u\n", GetLastError());
             ok((ULONG_PTR)hlib_as_data_file & 1, "hlib_as_data_file is even\n");
 
-            hlib = GetModuleHandle(dll_name);
+            hlib = GetModuleHandleA(dll_name);
             ok(!hlib, "GetModuleHandle should fail\n");
 
             SetLastError(0xdeadbeef);
@@ -544,9 +585,105 @@ todo_wine
         }
 
         SetLastError(0xdeadbeef);
-        ret = DeleteFile(dll_name);
+        ret = DeleteFileA(dll_name);
         ok(ret, "DeleteFile error %d\n", GetLastError());
     }
+
+    nt_header.FileHeader.NumberOfSections = 1;
+    nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
+
+    nt_header.OptionalHeader.SectionAlignment = page_size;
+    nt_header.OptionalHeader.FileAlignment = page_size;
+    nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER);
+    nt_header.OptionalHeader.SizeOfImage = nt_header.OptionalHeader.SizeOfImage + page_size;
+
+    status = map_image_section( &nt_header );
+    ok( status == STATUS_SUCCESS, "NtCreateSection error %08x\n", status );
+
+    dos_header.e_magic = 0;
+    status = map_image_section( &nt_header );
+    ok( status == STATUS_INVALID_IMAGE_NOT_MZ, "NtCreateSection error %08x\n", status );
+
+    dos_header.e_magic = IMAGE_DOS_SIGNATURE;
+    nt_header.Signature = IMAGE_OS2_SIGNATURE;
+    status = map_image_section( &nt_header );
+    ok( status == STATUS_INVALID_IMAGE_NE_FORMAT, "NtCreateSection error %08x\n", status );
+
+    nt_header.Signature = 0xdeadbeef;
+    status = map_image_section( &nt_header );
+    ok( status == STATUS_INVALID_IMAGE_PROTECT, "NtCreateSection error %08x\n", status );
+
+    nt_header.Signature = IMAGE_NT_SIGNATURE;
+    nt_header.OptionalHeader.Magic = 0xdead;
+    status = map_image_section( &nt_header );
+    ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08x\n", status );
+
+    nt_header.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
+    nt_header.FileHeader.Machine = 0xdead;
+    status = map_image_section( &nt_header );
+    ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */
+        "NtCreateSection error %08x\n", status );
+
+    nt_header.FileHeader.Machine = IMAGE_FILE_MACHINE_UNKNOWN;
+    status = map_image_section( &nt_header );
+    ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */
+        "NtCreateSection error %08x\n", status );
+
+    switch (orig_machine)
+    {
+    case IMAGE_FILE_MACHINE_I386: nt_header.FileHeader.Machine = IMAGE_FILE_MACHINE_AMD64; break;
+    case IMAGE_FILE_MACHINE_AMD64: nt_header.FileHeader.Machine = IMAGE_FILE_MACHINE_I386; break;
+    case IMAGE_FILE_MACHINE_ARMNT: nt_header.FileHeader.Machine = IMAGE_FILE_MACHINE_ARM64; break;
+    case IMAGE_FILE_MACHINE_ARM64: nt_header.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMNT; break;
+    }
+    status = map_image_section( &nt_header );
+    ok( status == STATUS_INVALID_IMAGE_FORMAT || broken(status == STATUS_SUCCESS), /* win2k */
+                  "NtCreateSection error %08x\n", status );
+
+    if (nt_header.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+    {
+        IMAGE_NT_HEADERS64 nt64;
+
+        memset( &nt64, 0, sizeof(nt64) );
+        nt64.Signature = IMAGE_NT_SIGNATURE;
+        nt64.FileHeader.Machine = orig_machine;
+        nt64.FileHeader.NumberOfSections = 1;
+        nt64.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER64);
+        nt64.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+        nt64.OptionalHeader.MajorLinkerVersion = 1;
+        nt64.OptionalHeader.ImageBase = 0x10000000;
+        nt64.OptionalHeader.MajorOperatingSystemVersion = 4;
+        nt64.OptionalHeader.MajorImageVersion = 1;
+        nt64.OptionalHeader.MajorSubsystemVersion = 4;
+        nt64.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt64) + sizeof(IMAGE_SECTION_HEADER);
+        nt64.OptionalHeader.SizeOfImage = nt64.OptionalHeader.SizeOfHeaders + 0x1000;
+        nt64.OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
+        status = map_image_section( (IMAGE_NT_HEADERS *)&nt64 );
+        ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08x\n", status );
+    }
+    else
+    {
+        IMAGE_NT_HEADERS32 nt32;
+
+        memset( &nt32, 0, sizeof(nt32) );
+        nt32.Signature = IMAGE_NT_SIGNATURE;
+        nt32.FileHeader.Machine = orig_machine;
+        nt32.FileHeader.NumberOfSections = 1;
+        nt32.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER32);
+        nt32.OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC;
+        nt32.OptionalHeader.MajorLinkerVersion = 1;
+        nt32.OptionalHeader.ImageBase = 0x10000000;
+        nt32.OptionalHeader.MajorOperatingSystemVersion = 4;
+        nt32.OptionalHeader.MajorImageVersion = 1;
+        nt32.OptionalHeader.MajorSubsystemVersion = 4;
+        nt32.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt32) + sizeof(IMAGE_SECTION_HEADER);
+        nt32.OptionalHeader.SizeOfImage = nt32.OptionalHeader.SizeOfHeaders + 0x1000;
+        nt32.OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
+        status = map_image_section( (IMAGE_NT_HEADERS *)&nt32 );
+        ok( status == STATUS_INVALID_IMAGE_FORMAT, "NtCreateSection error %08x\n", status );
+    }
+
+    nt_header.FileHeader.Machine = orig_machine;  /* restore it for the next tests */
 }
 
 /* Verify linking style of import descriptors */
@@ -612,18 +749,15 @@ static void test_image_mapping(const char *dll_name, DWORD scn_page_access, BOOL
     SIZE_T size;
     void *addr1, *addr2;
     MEMORY_BASIC_INFORMATION info;
-    SYSTEM_INFO si;
 
     if (!pNtMapViewOfSection) return;
 
-    GetSystemInfo(&si);
-
     SetLastError(0xdeadbeef);
-    hfile = CreateFile(dll_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+    hfile = CreateFileA(dll_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
     ok(hfile != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError());
 
     SetLastError(0xdeadbeef);
-    hmap = CreateFileMapping(hfile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, 0);
+    hmap = CreateFileMappingW(hfile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, 0);
     ok(hmap != 0, "CreateFileMapping error %d\n", GetLastError());
 
     offset.u.LowPart  = 0;
@@ -640,7 +774,7 @@ static void test_image_mapping(const char *dll_name, DWORD scn_page_access, BOOL
     size = VirtualQuery((char *)addr1 + section.VirtualAddress, &info, sizeof(info));
     ok(size == sizeof(info), "VirtualQuery error %d\n", GetLastError());
     ok(info.BaseAddress == (char *)addr1 + section.VirtualAddress, "got %p != expected %p\n", info.BaseAddress, (char *)addr1 + section.VirtualAddress);
-    ok(info.RegionSize == si.dwPageSize, "got %#lx != expected %#x\n", info.RegionSize, si.dwPageSize);
+    ok(info.RegionSize == page_size, "got %#lx != expected %#x\n", info.RegionSize, page_size);
     ok(info.Protect == scn_page_access, "got %#x != expected %#x\n", info.Protect, scn_page_access);
     ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
     ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%#x != PAGE_EXECUTE_WRITECOPY\n", info.AllocationProtect);
@@ -668,7 +802,7 @@ static void test_image_mapping(const char *dll_name, DWORD scn_page_access, BOOL
     size = VirtualQuery((char *)addr2 + section.VirtualAddress, &info, sizeof(info));
     ok(size == sizeof(info), "VirtualQuery error %d\n", GetLastError());
     ok(info.BaseAddress == (char *)addr2 + section.VirtualAddress, "got %p != expected %p\n", info.BaseAddress, (char *)addr2 + section.VirtualAddress);
-    ok(info.RegionSize == si.dwPageSize, "got %#lx != expected %#x\n", info.RegionSize, si.dwPageSize);
+    ok(info.RegionSize == page_size, "got %#lx != expected %#x\n", info.RegionSize, page_size);
     ok(info.Protect == scn_page_access, "got %#x != expected %#x\n", info.Protect, scn_page_access);
     ok(info.AllocationBase == addr2, "%p != %p\n", info.AllocationBase, addr2);
     ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%#x != PAGE_EXECUTE_WRITECOPY\n", info.AllocationProtect);
@@ -686,7 +820,7 @@ static void test_image_mapping(const char *dll_name, DWORD scn_page_access, BOOL
     size = VirtualQuery((char *)addr2 + section.VirtualAddress, &info, sizeof(info));
     ok(size == sizeof(info), "VirtualQuery error %d\n", GetLastError());
     ok(info.BaseAddress == (char *)addr2 + section.VirtualAddress, "got %p != expected %p\n", info.BaseAddress, (char *)addr2 + section.VirtualAddress);
-    ok(info.RegionSize == si.dwPageSize, "got %#lx != expected %#x\n", info.RegionSize, si.dwPageSize);
+    ok(info.RegionSize == page_size, "got %#lx != expected %#x\n", info.RegionSize, page_size);
     ok(info.Protect == scn_page_access, "got %#x != expected %#x\n", info.Protect, scn_page_access);
     ok(info.AllocationBase == addr2, "%p != %p\n", info.AllocationBase, addr2);
     ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%#x != PAGE_EXECUTE_WRITECOPY\n", info.AllocationProtect);
@@ -696,7 +830,7 @@ static void test_image_mapping(const char *dll_name, DWORD scn_page_access, BOOL
     UnmapViewOfFile(addr2);
 
     SetLastError(0xdeadbeef);
-    addr2 = LoadLibrary(dll_name);
+    addr2 = LoadLibraryA(dll_name);
     if (is_dll)
     {
         ok(!addr2, "LoadLibrary should fail, is_dll %d\n", is_dll);
@@ -778,12 +912,9 @@ static void test_VirtualProtect(void *base, void *section)
     };
     DWORD ret, orig_prot, old_prot, rw_prot, exec_prot, i, j;
     MEMORY_BASIC_INFORMATION info;
-    SYSTEM_INFO si;
-
-    GetSystemInfo(&si);
 
     SetLastError(0xdeadbeef);
-    ret = VirtualProtect(section, si.dwPageSize, PAGE_NOACCESS, &old_prot);
+    ret = VirtualProtect(section, page_size, PAGE_NOACCESS, &old_prot);
     ok(ret, "VirtualProtect error %d\n", GetLastError());
 
     orig_prot = old_prot;
@@ -794,7 +925,7 @@ static void test_VirtualProtect(void *base, void *section)
         ret = VirtualQuery(section, &info, sizeof(info));
         ok(ret, "VirtualQuery failed %d\n", GetLastError());
         ok(info.BaseAddress == section, "%d: got %p != expected %p\n", i, info.BaseAddress, section);
-        ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
+        ok(info.RegionSize == page_size, "%d: got %#lx != expected %#x\n", i, info.RegionSize, page_size);
         ok(info.Protect == PAGE_NOACCESS, "%d: got %#x != expected PAGE_NOACCESS\n", i, info.Protect);
         ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
         ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
@@ -803,7 +934,7 @@ static void test_VirtualProtect(void *base, void *section)
 
         old_prot = 0xdeadbeef;
         SetLastError(0xdeadbeef);
-        ret = VirtualProtect(section, si.dwPageSize, td[i].prot_set, &old_prot);
+        ret = VirtualProtect(section, page_size, td[i].prot_set, &old_prot);
         if (td[i].prot_get)
         {
             ok(ret, "%d: VirtualProtect error %d, requested prot %#x\n", i, GetLastError(), td[i].prot_set);
@@ -813,7 +944,7 @@ static void test_VirtualProtect(void *base, void *section)
             ret = VirtualQuery(section, &info, sizeof(info));
             ok(ret, "VirtualQuery failed %d\n", GetLastError());
             ok(info.BaseAddress == section, "%d: got %p != expected %p\n", i, info.BaseAddress, section);
-            ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
+            ok(info.RegionSize == page_size, "%d: got %#lx != expected %#x\n", i, info.RegionSize, page_size);
             ok(info.Protect == td[i].prot_get, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].prot_get);
             ok(info.AllocationBase == base, "%d: %p != %p\n", i, info.AllocationBase, base);
             ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
@@ -828,7 +959,7 @@ static void test_VirtualProtect(void *base, void *section)
 
         old_prot = 0xdeadbeef;
         SetLastError(0xdeadbeef);
-        ret = VirtualProtect(section, si.dwPageSize, PAGE_NOACCESS, &old_prot);
+        ret = VirtualProtect(section, page_size, PAGE_NOACCESS, &old_prot);
         ok(ret, "%d: VirtualProtect error %d\n", i, GetLastError());
         if (td[i].prot_get)
             ok(old_prot == td[i].prot_get, "%d: got %#x != expected %#x\n", i, old_prot, td[i].prot_get);
@@ -847,7 +978,7 @@ static void test_VirtualProtect(void *base, void *section)
             DWORD prot = exec_prot | rw_prot;
 
             SetLastError(0xdeadbeef);
-            ret = VirtualProtect(section, si.dwPageSize, prot, &old_prot);
+            ret = VirtualProtect(section, page_size, prot, &old_prot);
             if ((rw_prot && exec_prot) || (!rw_prot && !exec_prot))
             {
                 ok(!ret, "VirtualProtect(%02x) should fail\n", prot);
@@ -863,7 +994,7 @@ static void test_VirtualProtect(void *base, void *section)
     }
 
     SetLastError(0xdeadbeef);
-    ret = VirtualProtect(section, si.dwPageSize, orig_prot, &old_prot);
+    ret = VirtualProtect(section, page_size, orig_prot, &old_prot);
     ok(ret, "VirtualProtect error %d\n", GetLastError());
 }
 
@@ -908,25 +1039,22 @@ static void test_section_access(void)
     DWORD dummy, file_align;
     HANDLE hfile;
     HMODULE hlib;
-    SYSTEM_INFO si;
     char temp_path[MAX_PATH];
     char dll_name[MAX_PATH];
     SIZE_T size;
     MEMORY_BASIC_INFORMATION info;
-    STARTUPINFO sti;
+    STARTUPINFOA sti;
     PROCESS_INFORMATION pi;
     DWORD ret;
 
-    GetSystemInfo(&si);
-
     /* prevent displaying of the "Unable to load this DLL" message box */
     SetErrorMode(SEM_FAILCRITICALERRORS);
 
-    GetTempPath(MAX_PATH, temp_path);
+    GetTempPathA(MAX_PATH, temp_path);
 
     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
     {
-        GetTempFileName(temp_path, "ldr", 0, dll_name);
+        GetTempFileNameA(temp_path, "ldr", 0, dll_name);
 
         /*trace("creating %s\n", dll_name);*/
         hfile = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
@@ -944,9 +1072,9 @@ static void test_section_access(void)
         nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
         nt_header.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL | IMAGE_FILE_RELOCS_STRIPPED;
 
-        nt_header.OptionalHeader.SectionAlignment = si.dwPageSize;
+        nt_header.OptionalHeader.SectionAlignment = page_size;
         nt_header.OptionalHeader.FileAlignment = 0x200;
-        nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + si.dwPageSize;
+        nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + page_size;
         nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER);
         SetLastError(0xdeadbeef);
         ret = WriteFile(hfile, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL);
@@ -978,7 +1106,7 @@ static void test_section_access(void)
         CloseHandle(hfile);
 
         SetLastError(0xdeadbeef);
-        hlib = LoadLibrary(dll_name);
+        hlib = LoadLibraryA(dll_name);
         ok(hlib != 0, "LoadLibrary error %d\n", GetLastError());
 
         SetLastError(0xdeadbeef);
@@ -986,7 +1114,7 @@ static void test_section_access(void)
         ok(size == sizeof(info),
             "%d: VirtualQuery error %d\n", i, GetLastError());
         ok(info.BaseAddress == (char *)hlib + section.VirtualAddress, "%d: got %p != expected %p\n", i, info.BaseAddress, (char *)hlib + section.VirtualAddress);
-        ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
+        ok(info.RegionSize == page_size, "%d: got %#lx != expected %#x\n", i, info.RegionSize, page_size);
         ok(info.Protect == td[i].scn_page_access, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].scn_page_access);
         ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib);
         ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
@@ -1021,7 +1149,7 @@ static void test_section_access(void)
         /* reset IMAGE_FILE_DLL otherwise CreateProcess fails */
         nt_header.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_RELOCS_STRIPPED;
         SetLastError(0xdeadbeef);
-        hfile = CreateFile(dll_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
+        hfile = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
         /* LoadLibrary called on an already memory-mapped file in
          * test_image_mapping() above leads to a file handle leak
          * under nt4, and inability to overwrite and delete the file
@@ -1040,7 +1168,7 @@ static void test_section_access(void)
         memset(&sti, 0, sizeof(sti));
         sti.cb = sizeof(sti);
         SetLastError(0xdeadbeef);
-        ret = CreateProcess(dll_name, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &sti, &pi);
+        ret = CreateProcessA(dll_name, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &sti, &pi);
         ok(ret, "CreateProcess() error %d\n", GetLastError());
 
         SetLastError(0xdeadbeef);
@@ -1048,7 +1176,7 @@ static void test_section_access(void)
         ok(size == sizeof(info),
             "%d: VirtualQuery error %d\n", i, GetLastError());
         ok(info.BaseAddress == (char *)hlib + section.VirtualAddress, "%d: got %p != expected %p\n", i, info.BaseAddress, (char *)hlib + section.VirtualAddress);
-        ok(info.RegionSize == si.dwPageSize, "%d: got %#lx != expected %#x\n", i, info.RegionSize, si.dwPageSize);
+        ok(info.RegionSize == page_size, "%d: got %#lx != expected %#x\n", i, info.RegionSize, page_size);
         ok(info.Protect == td[i].scn_page_access, "%d: got %#x != expected %#x\n", i, info.Protect, td[i].scn_page_access);
         ok(info.AllocationBase == hlib, "%d: %p != %p\n", i, info.AllocationBase, hlib);
         ok(info.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "%d: %#x != PAGE_EXECUTE_WRITECOPY\n", i, info.AllocationProtect);
@@ -1075,11 +1203,142 @@ static void test_section_access(void)
 
 nt4_is_broken:
         SetLastError(0xdeadbeef);
-        ret = DeleteFile(dll_name);
+        ret = DeleteFileA(dll_name);
         ok(ret || broken(!ret) /* nt4 */, "DeleteFile error %d\n", GetLastError());
     }
 }
 
+static void test_import_resolution(void)
+{
+    char temp_path[MAX_PATH];
+    char dll_name[MAX_PATH];
+    DWORD dummy;
+    void *expect;
+    char *str;
+    HANDLE hfile;
+    HMODULE mod, mod2;
+    struct imports
+    {
+        IMAGE_IMPORT_DESCRIPTOR descr[2];
+        IMAGE_THUNK_DATA original_thunks[2];
+        IMAGE_THUNK_DATA thunks[2];
+        char module[16];
+        struct { WORD hint; char name[32]; } function;
+        IMAGE_TLS_DIRECTORY tls;
+        char tls_data[16];
+        SHORT tls_index;
+    } data, *ptr;
+    IMAGE_NT_HEADERS nt;
+    IMAGE_SECTION_HEADER section;
+    int test;
+
+    for (test = 0; test < 3; test++)
+    {
+#define DATA_RVA(ptr) (page_size + ((char *)(ptr) - (char *)&data))
+        nt = nt_header;
+        nt.FileHeader.NumberOfSections = 1;
+        nt.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
+        nt.FileHeader.Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_RELOCS_STRIPPED;
+        if (test != 2) nt.FileHeader.Characteristics |= IMAGE_FILE_DLL;
+        nt.OptionalHeader.ImageBase = 0x12340000;
+        nt.OptionalHeader.SizeOfImage = 2 * page_size;
+        nt.OptionalHeader.SizeOfHeaders = nt.OptionalHeader.FileAlignment;
+        nt.OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
+        memset( nt.OptionalHeader.DataDirectory, 0, sizeof(nt.OptionalHeader.DataDirectory) );
+        nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = sizeof(data.descr);
+        nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = DATA_RVA(data.descr);
+        nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size = sizeof(data.tls);
+        nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress = DATA_RVA(&data.tls);
+
+        memset( &data, 0, sizeof(data) );
+        data.descr[0].u.OriginalFirstThunk = DATA_RVA( data.original_thunks );
+        data.descr[0].FirstThunk = DATA_RVA( data.thunks );
+        data.descr[0].Name = DATA_RVA( data.module );
+        strcpy( data.module, "kernel32.dll" );
+        strcpy( data.function.name, "CreateEventA" );
+        data.original_thunks[0].u1.AddressOfData = DATA_RVA( &data.function );
+        data.thunks[0].u1.AddressOfData = 0xdeadbeef;
+
+        data.tls.StartAddressOfRawData = nt.OptionalHeader.ImageBase + DATA_RVA( data.tls_data );
+        data.tls.EndAddressOfRawData = data.tls.StartAddressOfRawData + sizeof(data.tls_data);
+        data.tls.AddressOfIndex = nt.OptionalHeader.ImageBase + DATA_RVA( &data.tls_index );
+        strcpy( data.tls_data, "hello world" );
+        data.tls_index = 9999;
+
+        GetTempPathA(MAX_PATH, temp_path);
+        GetTempFileNameA(temp_path, "ldr", 0, dll_name);
+
+        hfile = CreateFileA(dll_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, 0);
+        ok( hfile != INVALID_HANDLE_VALUE, "creation failed\n" );
+
+        memset( &section, 0, sizeof(section) );
+        memcpy( section.Name, ".text", sizeof(".text") );
+        section.PointerToRawData = nt.OptionalHeader.FileAlignment;
+        section.VirtualAddress = nt.OptionalHeader.SectionAlignment;
+        section.Misc.VirtualSize = sizeof(data);
+        section.SizeOfRawData = sizeof(data);
+        section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
+
+        WriteFile(hfile, &dos_header, sizeof(dos_header), &dummy, NULL);
+        WriteFile(hfile, &nt, sizeof(nt), &dummy, NULL);
+        WriteFile(hfile, &section, sizeof(section), &dummy, NULL);
+
+        SetFilePointer( hfile, section.PointerToRawData, NULL, SEEK_SET );
+        WriteFile(hfile, &data, sizeof(data), &dummy, NULL);
+
+        CloseHandle( hfile );
+
+        switch (test)
+        {
+        case 0:  /* normal load */
+            mod = LoadLibraryA( dll_name );
+            ok( mod != NULL, "failed to load err %u\n", GetLastError() );
+            if (!mod) break;
+            ptr = (struct imports *)((char *)mod + page_size);
+            expect = GetProcAddress( GetModuleHandleA( data.module ), data.function.name );
+            ok( (void *)ptr->thunks[0].u1.Function == expect, "thunk %p instead of %p for %s.%s\n",
+                (void *)ptr->thunks[0].u1.Function, expect, data.module, data.function.name );
+            ok( ptr->tls_index < 32 || broken(ptr->tls_index == 9999), /* before vista */
+                "wrong tls index %d\n", ptr->tls_index );
+            if (ptr->tls_index != 9999)
+            {
+                str = ((char **)NtCurrentTeb()->ThreadLocalStoragePointer)[ptr->tls_index];
+                ok( !strcmp( str, "hello world" ), "wrong tls data '%s' at %p\n", str, str );
+            }
+            FreeLibrary( mod );
+            break;
+        case 1:  /* load with DONT_RESOLVE_DLL_REFERENCES doesn't resolve imports */
+            mod = LoadLibraryExA( dll_name, 0, DONT_RESOLVE_DLL_REFERENCES );
+            ok( mod != NULL, "failed to load err %u\n", GetLastError() );
+            if (!mod) break;
+            ptr = (struct imports *)((char *)mod + page_size);
+            ok( ptr->thunks[0].u1.Function == 0xdeadbeef, "thunk resolved to %p for %s.%s\n",
+                (void *)ptr->thunks[0].u1.Function, data.module, data.function.name );
+            ok( ptr->tls_index == 9999, "wrong tls index %d\n", ptr->tls_index );
+
+            mod2 = LoadLibraryA( dll_name );
+            ok( mod2 == mod, "loaded twice %p / %p\n", mod, mod2 );
+            ok( ptr->thunks[0].u1.Function == 0xdeadbeef, "thunk resolved to %p for %s.%s\n",
+                (void *)ptr->thunks[0].u1.Function, data.module, data.function.name );
+            ok( ptr->tls_index == 9999, "wrong tls index %d\n", ptr->tls_index );
+            FreeLibrary( mod );
+            break;
+        case 2:  /* load without IMAGE_FILE_DLL doesn't resolve imports */
+            mod = LoadLibraryA( dll_name );
+            ok( mod != NULL, "failed to load err %u\n", GetLastError() );
+            if (!mod) break;
+            ptr = (struct imports *)((char *)mod + page_size);
+            ok( ptr->thunks[0].u1.Function == 0xdeadbeef, "thunk resolved to %p for %s.%s\n",
+                (void *)ptr->thunks[0].u1.Function, data.module, data.function.name );
+            ok( ptr->tls_index == 9999, "wrong tls index %d\n", ptr->tls_index );
+            FreeLibrary( mod );
+            break;
+        }
+        DeleteFileA( dll_name );
+#undef DATA_RVA
+    }
+}
+
 #define MAX_COUNT 10
 static HANDLE attached_thread[MAX_COUNT];
 static DWORD attached_thread_count;
@@ -1312,7 +1571,7 @@ static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param)
         }
 
         SetLastError(0xdeadbeef);
-        process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
+        process = OpenProcess(PROCESS_ALL_ACCESS_NT4, FALSE, GetCurrentProcessId());
         ok(process != NULL, "OpenProcess error %d\n", GetLastError());
 
         noop_thread_started = 0;
@@ -1340,7 +1599,7 @@ static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param)
         }
 
         SetLastError(0xdeadbeef);
-        handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, NULL);
+        handle = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, NULL);
         ok(handle != 0, "CreateFileMapping error %d\n", GetLastError());
 
         offset.u.LowPart = 0;
@@ -1356,15 +1615,15 @@ static BOOL WINAPI dll_entry_point(HINSTANCE hinst, DWORD reason, LPVOID param)
         CloseHandle(handle);
         CloseHandle(process);
 
-        handle = GetModuleHandle("winver.exe");
+        handle = GetModuleHandleA("winver.exe");
         ok(!handle, "winver.exe shouldn't be loaded yet\n");
         SetLastError(0xdeadbeef);
-        handle = LoadLibrary("winver.exe");
+        handle = LoadLibraryA("winver.exe");
         ok(handle != 0, "LoadLibrary error %d\n", GetLastError());
         SetLastError(0xdeadbeef);
         ret = FreeLibrary(handle);
         ok(ret, "FreeLibrary error %d\n", GetLastError());
-        handle = GetModuleHandle("winver.exe");
+        handle = GetModuleHandleA("winver.exe");
         if (param)
             ok(handle != 0, "winver.exe should not be unloaded\n");
         else
@@ -1445,34 +1704,34 @@ static void child_process(const char *dll_name, DWORD target_offset)
     trace("phase %d: writing %p at %#x\n", test_dll_phase, dll_entry_point, target_offset);
 
     SetLastError(0xdeadbeef);
-    mutex = CreateMutex(NULL, FALSE, NULL);
+    mutex = CreateMutexW(NULL, FALSE, NULL);
     ok(mutex != 0, "CreateMutex error %d\n", GetLastError());
 
     SetLastError(0xdeadbeef);
-    semaphore = CreateSemaphore(NULL, 1, 1, NULL);
+    semaphore = CreateSemaphoreW(NULL, 1, 1, NULL);
     ok(semaphore != 0, "CreateSemaphore error %d\n", GetLastError());
 
     SetLastError(0xdeadbeef);
-    event = CreateEvent(NULL, TRUE, FALSE, NULL);
+    event = CreateEventW(NULL, TRUE, FALSE, NULL);
     ok(event != 0, "CreateEvent error %d\n", GetLastError());
 
     SetLastError(0xdeadbeef);
-    loader_lock_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+    loader_lock_event = CreateEventW(NULL, FALSE, FALSE, NULL);
     ok(loader_lock_event != 0, "CreateEvent error %d\n", GetLastError());
 
     SetLastError(0xdeadbeef);
-    peb_lock_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+    peb_lock_event = CreateEventW(NULL, FALSE, FALSE, NULL);
     ok(peb_lock_event != 0, "CreateEvent error %d\n", GetLastError());
 
     SetLastError(0xdeadbeef);
-    heap_lock_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+    heap_lock_event = CreateEventW(NULL, FALSE, FALSE, NULL);
     ok(heap_lock_event != 0, "CreateEvent error %d\n", GetLastError());
 
     SetLastError(0xdeadbeef);
-    ack_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+    ack_event = CreateEventW(NULL, FALSE, FALSE, NULL);
     ok(ack_event != 0, "CreateEvent error %d\n", GetLastError());
 
-    file = CreateFile(dll_name, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
+    file = CreateFileA(dll_name, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
     if (file == INVALID_HANDLE_VALUE)
     {
         ok(0, "could not open %s\n", dll_name);
@@ -1486,11 +1745,11 @@ static void child_process(const char *dll_name, DWORD target_offset)
     CloseHandle(file);
 
     SetLastError(0xdeadbeef);
-    hmod = LoadLibrary(dll_name);
+    hmod = LoadLibraryA(dll_name);
     ok(hmod != 0, "LoadLibrary error %d\n", GetLastError());
 
     SetLastError(0xdeadbeef);
-    stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);
+    stop_event = CreateEventW(NULL, TRUE, FALSE, NULL);
     ok(stop_event != 0, "CreateEvent error %d\n", GetLastError());
 
     SetLastError(0xdeadbeef);
@@ -1535,7 +1794,7 @@ static void child_process(const char *dll_name, DWORD target_offset)
     ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret);
 
     SetLastError(0xdeadbeef);
-    process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
+    process = OpenProcess(PROCESS_ALL_ACCESS_NT4, FALSE, GetCurrentProcessId());
     ok(process != NULL, "OpenProcess error %d\n", GetLastError());
 
     SetLastError(0xdeadbeef);
@@ -1570,7 +1829,7 @@ static void child_process(const char *dll_name, DWORD target_offset)
         ret = pRtlDllShutdownInProgress();
         ok(!ret, "RtlDllShutdownInProgress returned %d\n", ret);
 
-        hmod = GetModuleHandle(dll_name);
+        hmod = GetModuleHandleA(dll_name);
         ok(hmod != 0, "DLL should not be unloaded\n");
 
         SetLastError(0xdeadbeef);
@@ -1591,7 +1850,7 @@ static void child_process(const char *dll_name, DWORD target_offset)
         ret = pRtlDllShutdownInProgress();
         ok(ret, "RtlDllShutdownInProgress returned %d\n", ret);
 
-        hmod = GetModuleHandle(dll_name);
+        hmod = GetModuleHandleA(dll_name);
         ok(hmod != 0, "DLL should not be unloaded\n");
 
         memset(&pbi, 0, sizeof(pbi));
@@ -1616,7 +1875,7 @@ static void child_process(const char *dll_name, DWORD target_offset)
         SetLastError(0xdeadbeef);
         ret = FreeLibrary(hmod);
         ok(ret, "FreeLibrary error %d\n", GetLastError());
-        hmod = GetModuleHandle(dll_name);
+        hmod = GetModuleHandleA(dll_name);
         ok(!hmod, "DLL should be unloaded\n");
 
         if (test_dll_phase == 2)
@@ -1748,7 +2007,7 @@ static void test_ExitProcess(void)
     DWORD ret, target_offset, old_prot;
     char **argv, buf[256];
     PROCESS_INFORMATION pi;
-    STARTUPINFO si = { sizeof(si) };
+    STARTUPINFOA si = { sizeof(si) };
     CONTEXT ctx;
     struct PROCESS_BASIC_INFORMATION_PRIVATE pbi;
     MEMORY_BASIC_INFORMATION mbi;
@@ -1781,11 +2040,11 @@ static void test_ExitProcess(void)
     /* prevent displaying of the "Unable to load this DLL" message box */
     SetErrorMode(SEM_FAILCRITICALERRORS);
 
-    GetTempPath(MAX_PATH, temp_path);
-    GetTempFileName(temp_path, "ldr", 0, dll_name);
+    GetTempPathA(MAX_PATH, temp_path);
+    GetTempFileNameA(temp_path, "ldr", 0, dll_name);
 
     /*trace("creating %s\n", dll_name);*/
-    file = CreateFile(dll_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
+    file = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
     if (file == INVALID_HANDLE_VALUE)
     {
         ok(0, "could not create %s\n", dll_name);
@@ -1841,7 +2100,7 @@ static void test_ExitProcess(void)
     /* phase 0 */
     *child_failures = -1;
     sprintf(cmdline, "\"%s\" loader %s %u 0", argv[0], dll_name, target_offset);
-    ret = CreateProcess(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+    ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
     ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError());
     ret = WaitForSingleObject(pi.hProcess, 10000);
     ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n");
@@ -1859,7 +2118,7 @@ static void test_ExitProcess(void)
     /* phase 1 */
     *child_failures = -1;
     sprintf(cmdline, "\"%s\" loader %s %u 1", argv[0], dll_name, target_offset);
-    ret = CreateProcess(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+    ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
     ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError());
     ret = WaitForSingleObject(pi.hProcess, 10000);
     ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n");
@@ -1877,7 +2136,7 @@ static void test_ExitProcess(void)
     /* phase 2 */
     *child_failures = -1;
     sprintf(cmdline, "\"%s\" loader %s %u 2", argv[0], dll_name, target_offset);
-    ret = CreateProcess(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+    ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
     ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError());
     ret = WaitForSingleObject(pi.hProcess, 10000);
     ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n");
@@ -1895,7 +2154,7 @@ static void test_ExitProcess(void)
     /* phase 3 */
     *child_failures = -1;
     sprintf(cmdline, "\"%s\" loader %s %u 3", argv[0], dll_name, target_offset);
-    ret = CreateProcess(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+    ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
     ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError());
     ret = WaitForSingleObject(pi.hProcess, 10000);
     ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n");
@@ -1915,7 +2174,7 @@ static void test_ExitProcess(void)
     {
         *child_failures = -1;
         sprintf(cmdline, "\"%s\" loader %s %u 4", argv[0], dll_name, target_offset);
-        ret = CreateProcess(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+        ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
         ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError());
         ret = WaitForSingleObject(pi.hProcess, 10000);
         ok(ret == WAIT_OBJECT_0, "child process failed to terminate\n");
@@ -1938,7 +2197,7 @@ static void test_ExitProcess(void)
     {
         *child_failures = -1;
         sprintf(cmdline, "\"%s\" loader %s %u 5", argv[0], dll_name, target_offset);
-        ret = CreateProcess(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+        ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
         ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError());
         ret = WaitForSingleObject(pi.hProcess, 5000);
         ok(ret == WAIT_TIMEOUT, "child process should fail to terminate\n");
@@ -1965,7 +2224,7 @@ static void test_ExitProcess(void)
     /* phase 6 */
     *child_failures = -1;
     sprintf(cmdline, "\"%s\" loader %s %u 6", argv[0], dll_name, target_offset);
-    ret = CreateProcess(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+    ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
     ok(ret, "CreateProcess(%s) error %d\n", cmdline, GetLastError());
     ret = WaitForSingleObject(pi.hProcess, 5000);
     ok(ret == WAIT_TIMEOUT || broken(ret == WAIT_OBJECT_0) /* XP */, "child process should fail to terminate\n");
@@ -1988,7 +2247,7 @@ static void test_ExitProcess(void)
 
     /* test remote process termination */
     SetLastError(0xdeadbeef);
-    ret = CreateProcess(argv[0], NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
+    ret = CreateProcessA(argv[0], NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
     ok(ret, "CreateProcess(%s) error %d\n", argv[0], GetLastError());
 
     SetLastError(0xdeadbeef);
@@ -1999,7 +2258,6 @@ static void test_ExitProcess(void)
     ok(ret, "VirtualProtectEx error %d\n", GetLastError());
     ok(old_prot == PAGE_READWRITE, "expected PAGE_READWRITE, got %#x\n", old_prot);
     SetLastError(0xdeadbeef);
-    ok(0, "I do *not* love goats!\n");
     size = VirtualQueryEx(pi.hProcess, NULL, &mbi, sizeof(mbi));
     ok(size == sizeof(mbi), "VirtualQueryEx error %d\n", GetLastError());
 
@@ -2009,7 +2267,7 @@ static void test_ExitProcess(void)
     ok(size == 4, "expected 4, got %lu\n", size);
 
     SetLastError(0xdeadbeef);
-    hmap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, NULL);
+    hmap = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, NULL);
     ok(hmap != 0, "CreateFileMapping error %d\n", GetLastError());
 
     SetLastError(0xdeadbeef);
@@ -2063,7 +2321,7 @@ static void test_ExitProcess(void)
     ok(ret == WAIT_OBJECT_0, "WaitForSingleObject failed: %x\n", ret);
 
     SetLastError(0xdeadbeef);
-    process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pi.dwProcessId);
+    process = OpenProcess(PROCESS_ALL_ACCESS_NT4, FALSE, pi.dwProcessId);
     ok(process != NULL, "OpenProcess error %d\n", GetLastError());
     CloseHandle(process);
 
@@ -2136,7 +2394,6 @@ static void test_ExitProcess(void)
     ok(!addr, "VirtualAllocEx should fail\n");
     ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
     SetLastError(0xdeadbeef);
-    ok(0, "I do *not* love goats!\n");
     size = VirtualQueryEx(pi.hProcess, NULL, &mbi, sizeof(mbi));
     ok(!size, "VirtualQueryEx should fail\n");
     ok(GetLastError() == ERROR_ACCESS_DENIED, "expected ERROR_ACCESS_DENIED, got %d\n", GetLastError());
@@ -2182,36 +2439,350 @@ if (0)
     CloseHandle(pi.hThread);
     CloseHandle(pi.hProcess);
 
-    ret = DeleteFile(dll_name);
+    ret = DeleteFileA(dll_name);
     ok(ret, "DeleteFile error %d\n", GetLastError());
 }
 
+static PVOID WINAPI failuredllhook(ULONG ul, DELAYLOAD_INFO* pd)
+{
+    ok(ul == 4, "expected 4, got %u\n", ul);
+    ok(!!pd, "no delayload info supplied\n");
+    if (pd)
+    {
+        ok(pd->Size == sizeof(*pd), "got %u\n", pd->Size);
+        ok(!!pd->DelayloadDescriptor, "no DelayloadDescriptor supplied\n");
+        if (pd->DelayloadDescriptor)
+        {
+            ok(pd->DelayloadDescriptor->Attributes.AllAttributes == 1,
+               "expected 1, got %u\n", pd->DelayloadDescriptor->Attributes.AllAttributes);
+            ok(pd->DelayloadDescriptor->DllNameRVA == 0x2000,
+               "expected 0x2000, got %x\n", pd->DelayloadDescriptor->DllNameRVA);
+            ok(pd->DelayloadDescriptor->ModuleHandleRVA == 0x201a,
+               "expected 0x201a, got %x\n", pd->DelayloadDescriptor->ModuleHandleRVA);
+            ok(pd->DelayloadDescriptor->ImportAddressTableRVA > pd->DelayloadDescriptor->ModuleHandleRVA,
+               "expected %x > %x\n", pd->DelayloadDescriptor->ImportAddressTableRVA,
+               pd->DelayloadDescriptor->ModuleHandleRVA);
+            ok(pd->DelayloadDescriptor->ImportNameTableRVA > pd->DelayloadDescriptor->ImportAddressTableRVA,
+               "expected %x > %x\n", pd->DelayloadDescriptor->ImportNameTableRVA,
+               pd->DelayloadDescriptor->ImportAddressTableRVA);
+            ok(pd->DelayloadDescriptor->BoundImportAddressTableRVA == 0,
+               "expected 0, got %x\n", pd->DelayloadDescriptor->BoundImportAddressTableRVA);
+            ok(pd->DelayloadDescriptor->UnloadInformationTableRVA == 0,
+               "expected 0, got %x\n", pd->DelayloadDescriptor->UnloadInformationTableRVA);
+            ok(pd->DelayloadDescriptor->TimeDateStamp == 0,
+               "expected 0, got %x\n", pd->DelayloadDescriptor->TimeDateStamp);
+        }
+
+        ok(!!pd->ThunkAddress, "no ThunkAddress supplied\n");
+        if (pd->ThunkAddress)
+            ok(pd->ThunkAddress->u1.Ordinal == 0, "expected 0, got %x\n", (UINT)pd->ThunkAddress->u1.Ordinal);
+
+        ok(!!pd->TargetDllName, "no TargetDllName supplied\n");
+        if (pd->TargetDllName)
+            ok(!strcmp(pd->TargetDllName, "secur32.dll"),
+               "expected \"secur32.dll\", got \"%s\"\n", pd->TargetDllName);
+
+        ok(pd->TargetApiDescriptor.ImportDescribedByName == 0,
+           "expected 0, got %x\n", pd->TargetApiDescriptor.ImportDescribedByName);
+        ok(pd->TargetApiDescriptor.Description.Ordinal == 0 ||
+           pd->TargetApiDescriptor.Description.Ordinal == 999,
+           "expected 0, got %x\n", pd->TargetApiDescriptor.Description.Ordinal);
+
+        ok(!!pd->TargetModuleBase, "no TargetModuleBase supplied\n");
+        ok(pd->Unused == NULL, "expected NULL, got %p\n", pd->Unused);
+        ok(pd->LastError, "no LastError supplied\n");
+    }
+    cb_count++;
+    return (void*)0xdeadbeef;
+}
+
+static void test_ResolveDelayLoadedAPI(void)
+{
+    static const char test_dll[] = "secur32.dll";
+    static const char test_func[] = "SealMessage";
+    static const char filler[0x1000];
+    char temp_path[MAX_PATH];
+    char dll_name[MAX_PATH];
+    IMAGE_DELAYLOAD_DESCRIPTOR idd, *delaydir;
+    IMAGE_THUNK_DATA itd32;
+    HANDLE hfile;
+    HMODULE hlib;
+    DWORD dummy, file_size, i;
+    WORD hint = 0;
+    BOOL ret;
+    static const struct test_data
+    {
+        BOOL func;
+        UINT_PTR ordinal;
+        BOOL succeeds;
+    } td[] =
+    {
+        {
+            TRUE, 0, TRUE
+        },
+        {
+            FALSE, IMAGE_ORDINAL_FLAG | 2, TRUE
+        },
+        {
+            FALSE, IMAGE_ORDINAL_FLAG | 5, TRUE
+        },
+        {
+            FALSE, IMAGE_ORDINAL_FLAG | 0, FALSE
+        },
+        {
+            FALSE, IMAGE_ORDINAL_FLAG | 999, FALSE
+        },
+    };
+
+    if (!pResolveDelayLoadedAPI)
+    {
+        todo_wine win_skip("ResolveDelayLoadedAPI is not available\n");
+        return;
+    }
+
+    if (0) /* crashes on native */
+    {
+        SetLastError(0xdeadbeef);
+        ok(!pResolveDelayLoadedAPI(NULL, NULL, NULL, NULL, NULL, 0),
+           "ResolveDelayLoadedAPI succeeded\n");
+        ok(GetLastError() == 0xdeadbeef, "GetLastError changed to %x\n", GetLastError());
+
+        cb_count = 0;
+        SetLastError(0xdeadbeef);
+        ok(!pResolveDelayLoadedAPI(NULL, NULL, failuredllhook, NULL, NULL, 0),
+           "ResolveDelayLoadedAPI succeeded\n");
+        ok(GetLastError() == 0xdeadbeef, "GetLastError changed to %x\n", GetLastError());
+        ok(cb_count == 1, "Wrong callback count: %d\n", cb_count);
+    }
+
+    GetTempPathA(MAX_PATH, temp_path);
+    GetTempFileNameA(temp_path, "ldr", 0, dll_name);
+    trace("creating %s\n", dll_name);
+    hfile = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
+    if (hfile == INVALID_HANDLE_VALUE)
+    {
+        ok(0, "could not create %s\n", dll_name);
+        return;
+    }
+
+    SetLastError(0xdeadbeef);
+    ret = WriteFile(hfile, &dos_header, sizeof(dos_header), &dummy, NULL);
+    ok(ret, "WriteFile error %d\n", GetLastError());
+
+    nt_header.FileHeader.NumberOfSections = 2;
+    nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
+
+    nt_header.OptionalHeader.SectionAlignment = 0x1000;
+    nt_header.OptionalHeader.FileAlignment = 0x1000;
+    nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x2200;
+    nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + 2 * sizeof(IMAGE_SECTION_HEADER);
+    nt_header.OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
+    nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress = 0x1000;
+    nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size = 0x100;
+
+    SetLastError(0xdeadbeef);
+    ret = WriteFile(hfile, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL);
+    ok(ret, "WriteFile error %d\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    ret = WriteFile(hfile, &nt_header.OptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER), &dummy, NULL);
+    ok(ret, "WriteFile error %d\n", GetLastError());
+
+    /* sections */
+    section.PointerToRawData = nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress;
+    section.VirtualAddress = nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress;
+    section.Misc.VirtualSize = nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size;
+    section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
+    SetLastError(0xdeadbeef);
+    ret = WriteFile(hfile, &section, sizeof(section), &dummy, NULL);
+    ok(ret, "WriteFile error %d\n", GetLastError());
+
+    section.PointerToRawData = 0x2000;
+    section.VirtualAddress = 0x2000;
+    i = sizeof(td)/sizeof(td[0]);
+    section.Misc.VirtualSize = sizeof(test_dll) + sizeof(hint) + sizeof(test_func) + sizeof(HMODULE) +
+                               2 * (i + 1) * sizeof(IMAGE_THUNK_DATA);
+    ok(section.Misc.VirtualSize <= 0x1000, "Too much tests, add a new section!\n");
+    section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
+    SetLastError(0xdeadbeef);
+    ret = WriteFile(hfile, &section, sizeof(section), &dummy, NULL);
+    ok(ret, "WriteFile error %d\n", GetLastError());
+
+    /* fill up to delay data */
+    file_size = GetFileSize(hfile, NULL);
+    SetLastError(0xdeadbeef);
+    ret = WriteFile(hfile, filler,
+                    nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress - file_size,
+                    &dummy, NULL);
+    ok(ret, "WriteFile error %d\n", GetLastError());
+
+    /* delay data */
+    idd.Attributes.AllAttributes = 1;
+    idd.DllNameRVA = 0x2000;
+    idd.ModuleHandleRVA = idd.DllNameRVA + sizeof(test_dll) + sizeof(hint) + sizeof(test_func);
+    idd.ImportAddressTableRVA = idd.ModuleHandleRVA + sizeof(HMODULE);
+    idd.ImportNameTableRVA = idd.ImportAddressTableRVA + (i + 1) * sizeof(IMAGE_THUNK_DATA);
+    idd.BoundImportAddressTableRVA = 0;
+    idd.UnloadInformationTableRVA = 0;
+    idd.TimeDateStamp = 0;
+
+    SetLastError(0xdeadbeef);
+    ret = WriteFile(hfile, &idd, sizeof(idd), &dummy, NULL);
+    ok(ret, "WriteFile error %d\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    ret = WriteFile(hfile, filler, sizeof(idd), &dummy, NULL);
+    ok(ret, "WriteFile error %d\n", GetLastError());
+
+    /* fill up to extended delay data */
+    file_size = GetFileSize(hfile, NULL);
+    SetLastError(0xdeadbeef);
+    ret = WriteFile(hfile, filler, idd.DllNameRVA - file_size, &dummy, NULL);
+    ok(ret, "WriteFile error %d\n", GetLastError());
+
+    /* extended delay data */
+    SetLastError(0xdeadbeef);
+    ret = WriteFile(hfile, test_dll, sizeof(test_dll), &dummy, NULL);
+    ok(ret, "WriteFile error %d\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    ret = WriteFile(hfile, &hint, sizeof(hint), &dummy, NULL);
+    ok(ret, "WriteFile error %d\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    ret = WriteFile(hfile, test_func, sizeof(test_func), &dummy, NULL);
+    ok(ret, "WriteFile error %d\n", GetLastError());
+
+    file_size = GetFileSize(hfile, NULL);
+    SetLastError(0xdeadbeef);
+    ret = WriteFile(hfile, filler, idd.ImportNameTableRVA - file_size, &dummy, NULL);
+    ok(ret, "WriteFile error %d\n", GetLastError());
+
+    for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+    {
+        if (td[i].func)
+            itd32.u1.AddressOfData = idd.DllNameRVA + sizeof(test_dll);
+        else
+            itd32.u1.Ordinal = td[i].ordinal;
+        SetLastError(0xdeadbeef);
+        ret = WriteFile(hfile, &itd32, sizeof(itd32), &dummy, NULL);
+        ok(ret, "WriteFile error %d\n", GetLastError());
+    }
+
+    itd32.u1.Ordinal = 0;
+    SetLastError(0xdeadbeef);
+    ret = WriteFile(hfile, &itd32, sizeof(itd32), &dummy, NULL);
+    ok(ret, "WriteFile error %d\n", GetLastError());
+
+    /* fill up to eof */
+    file_size = GetFileSize(hfile, NULL);
+    SetLastError(0xdeadbeef);
+    ret = WriteFile(hfile, filler, section.VirtualAddress + section.Misc.VirtualSize - file_size, &dummy, NULL);
+    ok(ret, "WriteFile error %d\n", GetLastError());
+    CloseHandle(hfile);
+
+    SetLastError(0xdeadbeef);
+    hlib = LoadLibraryA(dll_name);
+    ok(hlib != NULL, "LoadLibrary error %u\n", GetLastError());
+    if (!hlib)
+    {
+        skip("couldn't load %s.\n", dll_name);
+        DeleteFileA(dll_name);
+        return;
+    }
+
+    delaydir = RtlImageDirectoryEntryToData(hlib, TRUE, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT, &file_size);
+    if (!delaydir)
+    {
+        skip("haven't found section for delay import directory.\n");
+        FreeLibrary(hlib);
+        DeleteFileA(dll_name);
+        return;
+    }
+
+    for (;;)
+    {
+        IMAGE_THUNK_DATA *itdn, *itda;
+        HMODULE htarget;
+
+        if (!delaydir->DllNameRVA ||
+            !delaydir->ImportAddressTableRVA ||
+            !delaydir->ImportNameTableRVA) break;
+
+        itdn = RVAToAddr(delaydir->ImportNameTableRVA, hlib);
+        itda = RVAToAddr(delaydir->ImportAddressTableRVA, hlib);
+        htarget = LoadLibraryA(RVAToAddr(delaydir->DllNameRVA, hlib));
+
+        for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+        {
+            void *ret, *load;
+
+            if (IMAGE_SNAP_BY_ORDINAL(itdn[i].u1.Ordinal))
+                load = (void *)GetProcAddress(htarget, (LPSTR)IMAGE_ORDINAL(itdn[i].u1.Ordinal));
+            else
+            {
+                const IMAGE_IMPORT_BY_NAME* iibn = RVAToAddr(itdn[i].u1.AddressOfData, hlib);
+                load = (void *)GetProcAddress(htarget, (char*)iibn->Name);
+            }
+
+            cb_count = 0;
+            ret = pResolveDelayLoadedAPI(hlib, delaydir, failuredllhook, NULL, &itda[i], 0);
+            if (td[i].succeeds)
+            {
+                ok(ret != NULL, "Test %u: ResolveDelayLoadedAPI failed\n", i);
+                ok(ret == load, "Test %u: expected %p, got %p\n", i, load, ret);
+                ok(ret == (void*)itda[i].u1.AddressOfData, "Test %u: expected %p, got %p\n",
+                   i, ret, (void*)itda[i].u1.AddressOfData);
+                ok(!cb_count, "Test %u: Wrong callback count: %d\n", i, cb_count);
+            }
+            else
+            {
+                ok(ret == (void*)0xdeadbeef, "Test %u: ResolveDelayLoadedAPI succeeded with %p\n", i, ret);
+                ok(cb_count, "Test %u: Wrong callback count: %d\n", i, cb_count);
+            }
+        }
+        delaydir++;
+    }
+
+    FreeLibrary(hlib);
+    trace("deleting %s\n", dll_name);
+    DeleteFileA(dll_name);
+}
+
 START_TEST(loader)
 {
     int argc;
     char **argv;
-    HANDLE mapping;
-
-    pNtMapViewOfSection = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtMapViewOfSection");
-    pNtUnmapViewOfSection = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtUnmapViewOfSection");
-    pNtTerminateProcess = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtTerminateProcess");
-    pNtQueryInformationProcess = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQueryInformationProcess");
-    pNtSetInformationProcess = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtSetInformationProcess");
-    pLdrShutdownProcess = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "LdrShutdownProcess");
-    pRtlDllShutdownInProgress = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlDllShutdownInProgress");
-    pNtAllocateVirtualMemory = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtAllocateVirtualMemory");
-    pNtFreeVirtualMemory = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtFreeVirtualMemory");
-    pLdrLockLoaderLock = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "LdrLockLoaderLock");
-    pLdrUnlockLoaderLock = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "LdrUnlockLoaderLock");
-    pRtlAcquirePebLock = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlAcquirePebLock");
-    pRtlReleasePebLock = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlReleasePebLock");
-
-    mapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, "winetest_loader");
+    HANDLE ntdll, mapping;
+    SYSTEM_INFO si;
+
+    ntdll = GetModuleHandleA("ntdll.dll");
+    pNtCreateSection = (void *)GetProcAddress(ntdll, "NtCreateSection");
+    pNtMapViewOfSection = (void *)GetProcAddress(ntdll, "NtMapViewOfSection");
+    pNtUnmapViewOfSection = (void *)GetProcAddress(ntdll, "NtUnmapViewOfSection");
+    pNtTerminateProcess = (void *)GetProcAddress(ntdll, "NtTerminateProcess");
+    pNtQueryInformationProcess = (void *)GetProcAddress(ntdll, "NtQueryInformationProcess");
+    pNtSetInformationProcess = (void *)GetProcAddress(ntdll, "NtSetInformationProcess");
+    pLdrShutdownProcess = (void *)GetProcAddress(ntdll, "LdrShutdownProcess");
+    pRtlDllShutdownInProgress = (void *)GetProcAddress(ntdll, "RtlDllShutdownInProgress");
+    pNtAllocateVirtualMemory = (void *)GetProcAddress(ntdll, "NtAllocateVirtualMemory");
+    pNtFreeVirtualMemory = (void *)GetProcAddress(ntdll, "NtFreeVirtualMemory");
+    pLdrLockLoaderLock = (void *)GetProcAddress(ntdll, "LdrLockLoaderLock");
+    pLdrUnlockLoaderLock = (void *)GetProcAddress(ntdll, "LdrUnlockLoaderLock");
+    pRtlAcquirePebLock = (void *)GetProcAddress(ntdll, "RtlAcquirePebLock");
+    pRtlReleasePebLock = (void *)GetProcAddress(ntdll, "RtlReleasePebLock");
+    pResolveDelayLoadedAPI = (void *)GetProcAddress(GetModuleHandleA("kernel32.dll"), "ResolveDelayLoadedAPI");
+
+    GetSystemInfo( &si );
+    page_size = si.dwPageSize;
+    dos_header.e_magic = IMAGE_DOS_SIGNATURE;
+    dos_header.e_lfanew = sizeof(dos_header);
+
+    mapping = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, "winetest_loader");
     ok(mapping != 0, "CreateFileMapping failed\n");
     child_failures = MapViewOfFile(mapping, FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, 4096);
     if (*child_failures == -1)
     {
-        is_child = 1;
         *child_failures = 0;
     }
     else
@@ -2226,7 +2797,9 @@ START_TEST(loader)
     }
 
     test_Loader();
+    test_ResolveDelayLoadedAPI();
     test_ImportDescriptors();
     test_section_access();
+    test_import_resolution();
     test_ExitProcess();
 }
index 96013df..4d4f9c2 100755 (executable)
@@ -64,7 +64,7 @@ static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch )
     return NULL;
 }
 
-static inline int isdigitW( WCHAR wc )
+static inline BOOL isdigitW( WCHAR wc )
 {
     WORD type;
     GetStringTypeW( CT_CTYPE1, &wc, 1, &type );
@@ -75,9 +75,9 @@ static inline int isdigitW( WCHAR wc )
 static HMODULE hKernel32;
 static WORD enumCount;
 
-static BOOL (WINAPI *pEnumSystemLanguageGroupsA)(LANGUAGEGROUP_ENUMPROC, DWORD, LONG_PTR);
-static BOOL (WINAPI *pEnumLanguageGroupLocalesA)(LANGGROUPLOCALE_ENUMPROC, LGRPID, DWORD, LONG_PTR);
-static BOOL (WINAPI *pEnumUILanguagesA)(UILANGUAGE_ENUMPROC, DWORD, LONG_PTR);
+static BOOL (WINAPI *pEnumSystemLanguageGroupsA)(LANGUAGEGROUP_ENUMPROCA, DWORD, LONG_PTR);
+static BOOL (WINAPI *pEnumLanguageGroupLocalesA)(LANGGROUPLOCALE_ENUMPROCA, LGRPID, DWORD, LONG_PTR);
+static BOOL (WINAPI *pEnumUILanguagesA)(UILANGUAGE_ENUMPROCA, DWORD, LONG_PTR);
 static BOOL (WINAPI *pEnumSystemLocalesEx)(LOCALE_ENUMPROCEX, DWORD, LPARAM, LPVOID);
 static INT (WINAPI *pLCMapStringEx)(LPCWSTR, DWORD, LPCWSTR, INT, LPWSTR, INT, LPNLSVERSIONINFO, LPVOID, LPARAM);
 static LCID (WINAPI *pLocaleNameToLCID)(LPCWSTR, DWORD);
@@ -91,6 +91,8 @@ static INT (WINAPI *pIdnToUnicode)(DWORD, LPCWSTR, INT, LPWSTR, INT);
 static INT (WINAPI *pGetLocaleInfoEx)(LPCWSTR, LCTYPE, LPWSTR, INT);
 static BOOL (WINAPI *pIsValidLocaleName)(LPCWSTR);
 static INT (WINAPI *pCompareStringOrdinal)(const WCHAR *, INT, const WCHAR *, INT, BOOL);
+static INT (WINAPI *pCompareStringEx)(LPCWSTR, DWORD, LPCWSTR, INT, LPCWSTR, INT,
+                                      LPNLSVERSIONINFO, LPVOID, LPARAM);
 
 static void InitFunctionPointers(void)
 {
@@ -111,6 +113,7 @@ static void InitFunctionPointers(void)
   pGetLocaleInfoEx = (void*)GetProcAddress(hKernel32, "GetLocaleInfoEx");
   pIsValidLocaleName = (void*)GetProcAddress(hKernel32, "IsValidLocaleName");
   pCompareStringOrdinal = (void*)GetProcAddress(hKernel32, "CompareStringOrdinal");
+  pCompareStringEx = (void*)GetProcAddress(hKernel32, "CompareStringEx");
 }
 
 #define eq(received, expected, label, type) \
@@ -121,7 +124,7 @@ static void InitFunctionPointers(void)
 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
 
 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0xdeadbeef); buffer[0] = '\0'
-#define EXPECT_LENA ok(ret == lstrlen(Expected)+1, "Expected Len %d, got %d\n", lstrlen(Expected)+1, ret)
+#define EXPECT_LENA ok(ret == lstrlenA(Expected)+1, "Expected len %d, got %d\n", lstrlenA(Expected)+1, ret)
 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
   "Expected '%s', got '%s'\n", Expected, buffer)
 
@@ -660,21 +663,23 @@ static void test_GetDateFormatA(void)
       "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
 
   STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
-  ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
+  ret = GetDateFormatA(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
   if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
          ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
 
-  STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
-  ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
+  SetLastError(0xdeadbeef); buffer[0] = '\0'; /* DATE_LONGDATE */
+  ret = GetDateFormatA(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
-  EXPECT_LENA; EXPECT_EQA;
+  ok(strcmp(buffer, "Saturday, May 04, 2002") == 0 ||
+     strcmp(buffer, "Saturday, May 4, 2002") == 0 /* Win 8 */,
+     "got an unexpected date string '%s'\n", buffer);
 
   /* test for expected DATE_YEARMONTH behavior with null format */
   /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
   STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
   SetLastError(0xdeadbeef);
-  ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
+  ret = GetDateFormatA(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
   ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
   EXPECT_EQA;
@@ -683,12 +688,12 @@ static void test_GetDateFormatA(void)
   /* and return values */
   STRINGSA("m/d/y", ""); /* Invalid flags */
   SetLastError(0xdeadbeef);
-  ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
+  ret = GetDateFormatA(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
                       &curtime, input, buffer, COUNTOF(buffer));
   ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
      "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
 
-  ret = GetDateFormat(lcid_ru, 0, &curtime, "ddMMMM", buffer, COUNTOF(buffer));
+  ret = GetDateFormatA(lcid_ru, 0, &curtime, "ddMMMM", buffer, COUNTOF(buffer));
   if (!ret)
   {
     win_skip("LANG_RUSSIAN locale data unavailable\n");
@@ -697,37 +702,37 @@ static void test_GetDateFormatA(void)
 
   /* month part should be in genitive form */
   strcpy(genitive_month, buffer + 2);
-  ret = GetDateFormat(lcid_ru, 0, &curtime, "MMMM", buffer, COUNTOF(buffer));
+  ret = GetDateFormatA(lcid_ru, 0, &curtime, "MMMM", buffer, COUNTOF(buffer));
   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
   strcpy(month, buffer);
   ok(strcmp(genitive_month, month) != 0, "Expected different month forms\n");
 
-  ret = GetDateFormat(lcid_ru, 0, &curtime, "ddd", buffer, COUNTOF(buffer));
+  ret = GetDateFormatA(lcid_ru, 0, &curtime, "ddd", buffer, COUNTOF(buffer));
   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
   strcpy(short_day, buffer);
 
   STRINGSA("dd MMMMddd dd", "");
   sprintf(Expected, "04 %s%s 04", genitive_month, short_day);
-  ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+  ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
   EXPECT_EQA;
 
   STRINGSA("MMMMddd dd", "");
   sprintf(Expected, "%s%s 04", month, short_day);
-  ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+  ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
   EXPECT_EQA;
 
   STRINGSA("MMMMddd", "");
   sprintf(Expected, "%s%s", month, short_day);
-  ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+  ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
   EXPECT_EQA;
 
   STRINGSA("MMMMdd", "");
   sprintf(Expected, "%s04", genitive_month);
   sprintf(Broken, "%s04", month);
-  ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+  ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
   ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
      broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
@@ -736,7 +741,7 @@ static void test_GetDateFormatA(void)
   STRINGSA("MMMMdd ddd", "");
   sprintf(Expected, "%s04 %s", genitive_month, short_day);
   sprintf(Broken, "%s04 %s", month, short_day);
-  ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+  ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
   ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
      broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
@@ -744,14 +749,14 @@ static void test_GetDateFormatA(void)
 
   STRINGSA("dd dddMMMM", "");
   sprintf(Expected, "04 %s%s", short_day, month);
-  ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+  ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
   EXPECT_EQA;
 
   STRINGSA("dd dddMMMM ddd MMMMdd", "");
   sprintf(Expected, "04 %s%s %s %s04", short_day, month, short_day, genitive_month);
   sprintf(Broken, "04 %s%s %s %s04", short_day, month, short_day, month);
-  ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+  ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
   ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
      broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
@@ -761,7 +766,7 @@ static void test_GetDateFormatA(void)
   STRINGSA("ddd',' MMMM dd", "");
   sprintf(Expected, "%s, %s 04", short_day, genitive_month);
   sprintf(Broken, "%s, %s 04", short_day, month);
-  ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+  ret = GetDateFormatA(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
   ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
   ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
      broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
@@ -1455,7 +1460,7 @@ static void test_CompareStringA(void)
     ret = CompareStringA(lcid, NORM_IGNORECASE, "_", -1, ".", -1);
     todo_wine ok(ret == CSTR_GREATER_THAN, "\"_\" vs \".\" expected CSTR_GREATER_THAN, got %d\n", ret);
 
-    ret = lstrcmpi("#", ".");
+    ret = lstrcmpiA("#", ".");
     todo_wine ok(ret == -1, "\"#\" vs \".\" expected -1, got %d\n", ret);
 
     lcid = MAKELCID(MAKELANGID(LANG_POLISH, SUBLANG_DEFAULT), SORT_DEFAULT);
@@ -1473,6 +1478,202 @@ static void test_CompareStringA(void)
         "ret %d, error %d, expected value %d\n", ret, GetLastError(), CSTR_EQUAL);
 }
 
+struct comparestringex_test {
+    const char *locale;
+    DWORD flags;
+    const WCHAR first[2];
+    const WCHAR second[2];
+    INT ret;
+    INT broken;
+    BOOL todo;
+};
+
+static const struct comparestringex_test comparestringex_tests[] = {
+    /* default behavior */
+    { /* 0 */
+      "tr-TR", 0,
+      {'i',0},   {'I',0},   CSTR_LESS_THAN,    -1,                FALSE
+    },
+    { /* 1 */
+      "tr-TR", 0,
+      {'i',0},   {0x130,0}, CSTR_LESS_THAN,    -1,                FALSE
+    },
+    { /* 2 */
+      "tr-TR", 0,
+      {'i',0},   {0x131,0}, CSTR_LESS_THAN,    -1,                FALSE
+    },
+    { /* 3 */
+      "tr-TR", 0,
+      {'I',0},   {0x130,0}, CSTR_LESS_THAN,    -1,                TRUE
+    },
+    { /* 4 */
+      "tr-TR", 0,
+      {'I',0},   {0x131,0}, CSTR_LESS_THAN,    -1,                FALSE
+    },
+    { /* 5 */
+      "tr-TR", 0,
+      {0x130,0}, {0x131,0}, CSTR_GREATER_THAN, -1,                TRUE
+    },
+    /* with NORM_IGNORECASE */
+    { /* 6 */
+      "tr-TR", NORM_IGNORECASE,
+      {'i',0},   {'I',0},   CSTR_EQUAL,        -1,                FALSE
+    },
+    { /* 7 */
+      "tr-TR", NORM_IGNORECASE,
+      {'i',0},   {0x130,0}, CSTR_LESS_THAN,    -1,                TRUE
+    },
+    { /* 8 */
+      "tr-TR", NORM_IGNORECASE,
+      {'i',0},   {0x131,0}, CSTR_LESS_THAN,    -1,                FALSE
+    },
+    { /* 9 */
+      "tr-TR", NORM_IGNORECASE,
+      {'I',0},   {0x130,0}, CSTR_LESS_THAN,    -1,                TRUE
+    },
+    { /* 10 */
+      "tr-TR", NORM_IGNORECASE,
+      {'I',0},   {0x131,0}, CSTR_LESS_THAN,    -1,                FALSE
+    },
+    { /* 11 */
+      "tr-TR", NORM_IGNORECASE,
+      {0x130,0}, {0x131,0}, CSTR_GREATER_THAN, -1,                TRUE
+    },
+    /* with NORM_LINGUISTIC_CASING */
+    { /* 12 */
+      "tr-TR", NORM_LINGUISTIC_CASING,
+      {'i',0},   {'I',0},   CSTR_GREATER_THAN, CSTR_LESS_THAN,    TRUE
+    },
+    { /* 13 */
+      "tr-TR", NORM_LINGUISTIC_CASING,
+      {'i',0},   {0x130,0}, CSTR_LESS_THAN,    -1,                FALSE
+    },
+    { /* 14 */
+      "tr-TR", NORM_LINGUISTIC_CASING,
+      {'i',0},   {0x131,0}, CSTR_GREATER_THAN, CSTR_LESS_THAN,    TRUE
+    },
+    { /* 15 */
+      "tr-TR", NORM_LINGUISTIC_CASING,
+      {'I',0},   {0x130,0}, CSTR_LESS_THAN,    -1,                TRUE
+    },
+    { /* 16 */
+      "tr-TR", NORM_LINGUISTIC_CASING,
+      {'I',0},   {0x131,0}, CSTR_GREATER_THAN, CSTR_LESS_THAN,    TRUE
+    },
+    { /* 17 */
+      "tr-TR", NORM_LINGUISTIC_CASING,
+      {0x130,0}, {0x131,0}, CSTR_GREATER_THAN, -1,                TRUE
+    },
+    /* with LINGUISTIC_IGNORECASE */
+    { /* 18 */
+      "tr-TR", LINGUISTIC_IGNORECASE,
+      {'i',0},   {'I',0},   CSTR_EQUAL,        -1,                TRUE
+    },
+    { /* 19 */
+      "tr-TR", LINGUISTIC_IGNORECASE,
+      {'i',0},   {0x130,0}, CSTR_LESS_THAN,    -1,                FALSE
+    },
+    { /* 20 */
+      "tr-TR", LINGUISTIC_IGNORECASE,
+      {'i',0},   {0x131,0}, CSTR_LESS_THAN,    -1,                FALSE
+    },
+    { /* 21 */
+      "tr-TR", LINGUISTIC_IGNORECASE,
+      {'I',0},   {0x130,0}, CSTR_LESS_THAN,    -1,                TRUE
+    },
+    { /* 22 */
+      "tr-TR", LINGUISTIC_IGNORECASE,
+      {'I',0},   {0x131,0}, CSTR_LESS_THAN,    -1,                FALSE
+    },
+    { /* 23 */
+      "tr-TR", LINGUISTIC_IGNORECASE,
+      {0x130,0}, {0x131,0}, CSTR_GREATER_THAN, -1,                TRUE
+    },
+    /* with NORM_LINGUISTIC_CASING | NORM_IGNORECASE */
+    { /* 24 */
+      "tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
+      {'i',0},   {'I',0},   CSTR_GREATER_THAN, CSTR_EQUAL,        TRUE
+    },
+    { /* 25 */
+      "tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
+      {'i',0},   {0x130,0}, CSTR_EQUAL,        CSTR_LESS_THAN,    FALSE
+    },
+    { /* 26 */
+      "tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
+      {'i',0},   {0x131,0}, CSTR_GREATER_THAN, CSTR_LESS_THAN,    TRUE
+    },
+    { /* 27 */
+      "tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
+      {'I',0},   {0x130,0}, CSTR_LESS_THAN,    -1,                TRUE
+     },
+    { /* 28 */
+      "tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
+      {'I',0},   {0x131,0}, CSTR_EQUAL,        CSTR_LESS_THAN,    TRUE
+    },
+    { /* 29 */
+      "tr-TR", NORM_LINGUISTIC_CASING | NORM_IGNORECASE,
+      {0x130,0}, {0x131,0}, CSTR_GREATER_THAN, -1,                TRUE
+    },
+    /* with NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE */
+    { /* 30 */
+      "tr-TR", NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE,
+      {'i',0},   {'I',0},   CSTR_GREATER_THAN, CSTR_EQUAL,        TRUE
+    },
+    { /* 31 */
+      "tr-TR", NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE,
+      {'i',0},   {0x130,0}, CSTR_EQUAL,        CSTR_LESS_THAN,    TRUE
+    },
+    { /* 32 */
+      "tr-TR", NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE,
+      {'i',0},   {0x131,0}, CSTR_GREATER_THAN, CSTR_LESS_THAN,    TRUE
+    },
+    { /* 33 */
+      "tr-TR", NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE,
+      {'I',0},   {0x130,0}, CSTR_LESS_THAN,    -1,                TRUE
+    },
+    { /* 34 */
+      "tr-TR", NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE,
+      {'I',0},   {0x131,0}, CSTR_EQUAL,        CSTR_LESS_THAN,    TRUE
+    },
+    { /* 35 */
+      "tr-TR", NORM_LINGUISTIC_CASING | LINGUISTIC_IGNORECASE,
+      {0x130,0}, {0x131,0}, CSTR_GREATER_THAN, CSTR_LESS_THAN,    TRUE
+    }
+};
+
+static void test_CompareStringEx(void)
+{
+    const char *op[] = {"ERROR", "CSTR_LESS_THAN", "CSTR_EQUAL", "CSTR_GREATER_THAN"};
+    WCHAR locale[6];
+    INT ret, i;
+
+    /* CompareStringEx is only available on Vista+ */
+    if (!pCompareStringEx)
+    {
+        win_skip("CompareStringEx not supported\n");
+        return;
+    }
+
+    for (i = 0; i < sizeof(comparestringex_tests)/sizeof(comparestringex_tests[0]); i++)
+    {
+        const struct comparestringex_test *e = &comparestringex_tests[i];
+
+        MultiByteToWideChar(CP_ACP, 0, e->locale, -1, locale, sizeof(locale)/sizeof(WCHAR));
+        ret = pCompareStringEx(locale, e->flags, e->first, -1, e->second, -1, NULL, NULL, 0);
+        if (e->todo)
+        {
+            todo_wine ok(ret == e->ret || broken(ret == e->broken),
+                         "%d: got %s, expected %s\n", i, op[ret], op[e->ret]);
+        }
+        else
+        {
+            ok(ret == e->ret || broken(ret == e->broken),
+               "%d: got %s, expected %s\n", i, op[ret], op[e->ret]);
+        }
+    }
+
+}
+
 static void test_LCMapStringA(void)
 {
     int ret, ret2;
@@ -2321,6 +2522,7 @@ static void test_FoldStringW(void)
     0x0030, /* '0'-'9' */
     0x0660, /* Eastern Arabic */
     0x06F0, /* Arabic - Hindu */
+    0x07C0, /* Nko */
     0x0966, /* Devengari */
     0x09E6, /* Bengalii */
     0x0A66, /* Gurmukhi */
@@ -2332,16 +2534,37 @@ static void test_FoldStringW(void)
     0x0D66, /* Maylayalam */
     0x0E50, /* Thai */
     0x0ED0, /* Laos */
-    0x0F29, /* Tibet - 0 is out of sequence */
+    0x0F20, /* Tibet */
+    0x0F29, /* Tibet half - 0 is out of sequence */
+    0x1040, /* Myanmar */
+    0x1090, /* Myanmar Shan */
+    0x1368, /* Ethiopic - no 0 */
+    0x17E0, /* Khmer */
+    0x1810, /* Mongolian */
+    0x1946, /* Limbu */
+    0x19D0, /* New Tai Lue */
+    0x1A80, /* Tai Tham Hora */
+    0x1A90, /* Tai Tham Tham */
+    0x1B50, /* Balinese */
+    0x1BB0, /* Sundanese */
+    0x1C40, /* Lepcha */
+    0x1C50, /* Ol Chiki */
     0x2070, /* Superscript - 1, 2, 3 are out of sequence */
     0x2080, /* Subscript */
     0x245F, /* Circled - 0 is out of sequence */
     0x2473, /* Bracketed */
     0x2487, /* Full stop */
+    0x24F4, /* Double Circled */
     0x2775, /* Inverted circled - No 0 */
     0x277F, /* Patterned circled - No 0 */
     0x2789, /* Inverted Patterned circled - No 0 */
     0x3020, /* Hangzhou */
+    0xA620, /* Vai */
+    0xA8D0, /* Saurashtra */
+    0xA900, /* Kayah Li */
+    0xA9D0, /* Javanese */
+    0xAA50, /* Cham */
+    0xABF0, /* Meetei Mayek */
     0xff10, /* Pliene chasse (?) */
     0xffff  /* Terminator */
   };
@@ -2351,8 +2574,17 @@ static void test_FoldStringW(void)
       0xB9,   /* Superscript 1 */
       0xB2,   /* Superscript 2 */
       0xB3,   /* Superscript 3 */
+      0x0C78, /* Telugu Fraction 0 */
+      0x0C79, /* Telugu Fraction 1 */
+      0x0C7A, /* Telugu Fraction 2 */
+      0x0C7B, /* Telugu Fraction 3 */
+      0x0C7C, /* Telugu Fraction 1 */
+      0x0C7D, /* Telugu Fraction 2 */
+      0x0C7E, /* Telugu Fraction 3 */
       0x0F33, /* Tibetan half zero */
+      0x19DA, /* New Tai Lue Tham 1 */
       0x24EA, /* Circled 0 */
+      0x24FF, /* Negative Circled 0 */
       0x3007, /* Ideographic number zero */
       '\0'    /* Terminator */
   };
@@ -2361,8 +2593,10 @@ static void test_FoldStringW(void)
   {
       0x0BE6, /* No Tamil 0 */
       0x0F29, /* No Tibetan half zero (out of sequence) */
+      0x1368, /* No Ethiopic 0 */
       0x2473, /* No Bracketed 0 */
       0x2487, /* No 0 Full stop */
+      0x24F4, /* No double circled 0 */
       0x2775, /* No inverted circled 0 */
       0x277F, /* No patterned circled */
       0x2789, /* No inverted Patterned circled */
@@ -2490,10 +2724,11 @@ static void test_FoldStringW(void)
       ok(ret == 2, "Expected ret == 2, got %d, error %d\n", ret, GetLastError());
 
       ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
-         /* Wine (correctly) maps all Unicode 4.0+ digits */
-         isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF || ch == 0x19da ||
-         (ch >= 0x1369 && ch <= 0x1371),
-         "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
+         (ch >= 0xa8e0 && ch <= 0xa8e9),  /* combining Devanagari on Win8 */
+         "MAP_FOLDDIGITS: ch 0x%04x Expected unchanged got %04x\n", ch, dst[0]);
+      ok(!isdigitW(ch) || strchrW(outOfSequenceDigits, ch) ||
+         broken( ch >= 0xbf0 && ch <= 0xbf2 ), /* win2k */
+         "char %04x should not be a digit\n", ch );
     }
 
     if (digitRanges[j] == 0xffff)
@@ -2520,7 +2755,7 @@ static void test_FoldStringW(void)
          (digitRanges[j] == 0x3020 && dst[0] == ch) || /* Hangzhou not present in all Windows versions */
          (digitRanges[j] == 0x0F29 && dst[0] == ch) || /* Tibetan not present in all Windows versions */
          strchrW(noDigitAvailable, c),
-         "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
+         "MAP_FOLDDIGITS: ch %04x Expected %04x got %04x\n",
          ch, '0' + digitRanges[j] - ch, dst[0]);
     }
     prev_ch = ch;
@@ -3108,6 +3343,7 @@ static void test_IdnToNameprepUnicode(void)
         DWORD in_len;
         const WCHAR in[64];
         DWORD ret;
+        DWORD broken_ret;
         const WCHAR out[64];
         DWORD flags;
         DWORD err;
@@ -3115,77 +3351,77 @@ static void test_IdnToNameprepUnicode(void)
     } test_data[] = {
         {
             5, {'t','e','s','t',0},
-            5, {'t','e','s','t',0},
+            5, 5, {'t','e','s','t',0},
             0, 0xdeadbeef
         },
         {
             3, {'a',0xe111,'b'},
-            0, {0},
+            0, 0, {0},
             0, ERROR_INVALID_NAME
         },
         {
             4, {'t',0,'e',0},
-            0, {0},
+            0, 0, {0},
             0, ERROR_INVALID_NAME
         },
         {
             1, {'T',0},
-            1, {'T',0},
+            1, 1, {'T',0},
             0, 0xdeadbeef
         },
         {
             1, {0},
-            0, {0},
+            0, 0, {0},
             0, ERROR_INVALID_NAME
         },
         {
             6, {' ','-','/','[',']',0},
-            6, {' ','-','/','[',']',0},
+            6, 6, {' ','-','/','[',']',0},
             0, 0xdeadbeef
         },
         {
             3, {'a','-','a'},
-            3, {'a','-','a'},
+            3, 3, {'a','-','a'},
             IDN_USE_STD3_ASCII_RULES, 0xdeadbeef
         },
         {
             3, {'a','a','-'},
-            0, {0},
+            0, 0, {0},
             IDN_USE_STD3_ASCII_RULES, ERROR_INVALID_NAME
         },
         { /* FoldString is not working as expected when MAP_FOLDCZONE is specified (composition+compatibility) */
             10, {'T',0xdf,0x130,0x143,0x37a,0x6a,0x30c,' ',0xaa,0},
-            12, {'t','s','s','i',0x307,0x144,' ',0x3b9,0x1f0,' ','a',0},
+            12, 12, {'t','s','s','i',0x307,0x144,' ',0x3b9,0x1f0,' ','a',0},
             0, 0xdeadbeef, TRUE
         },
         {
             11, {'t',0xad,0x34f,0x1806,0x180b,0x180c,0x180d,0x200b,0x200c,0x200d,0},
-            2, {'t',0},
+            2, 0, {'t',0},
             0, 0xdeadbeef
         },
         { /* Another example of incorrectly working FoldString (composition) */
             2, {0x3b0, 0},
-            2, {0x3b0, 0},
+            2, 2, {0x3b0, 0},
             0, 0xdeadbeef, TRUE
         },
         {
             2, {0x221, 0},
-            0, {0},
+            0, 2, {0},
             0, ERROR_NO_UNICODE_TRANSLATION
         },
         {
             2, {0x221, 0},
-            2, {0x221, 0},
+            2, 2, {0x221, 0},
             IDN_ALLOW_UNASSIGNED, 0xdeadbeef
         },
         {
             5, {'a','.','.','a',0},
-            0, {0},
+            0, 0, {0},
             0, ERROR_INVALID_NAME
         },
         {
             3, {'a','.',0},
-            3, {'a','.',0},
+            3, 3, {'a','.',0},
             0, 0xdeadbeef
         },
     };
@@ -3245,7 +3481,8 @@ static void test_IdnToNameprepUnicode(void)
     ret = pIdnToNameprepUnicode(4, NULL, 0, NULL, 0);
     err = GetLastError();
     ok(ret == 0, "ret = %d\n", ret);
-    ok(err == ERROR_INVALID_FLAGS, "err = %d\n", err);
+    ok(err == ERROR_INVALID_FLAGS || err == ERROR_INVALID_PARAMETER /* Win8 */,
+       "err = %d\n", err);
 
     for (i=0; i<sizeof(test_data)/sizeof(*test_data); i++)
     {
@@ -3253,15 +3490,23 @@ static void test_IdnToNameprepUnicode(void)
         ret = pIdnToNameprepUnicode(test_data[i].flags, test_data[i].in,
                 test_data[i].in_len, buf, sizeof(buf)/sizeof(WCHAR));
         err = GetLastError();
-        if(!test_data[i].todo) {
-            ok(ret == test_data[i].ret, "%d) ret = %d\n", i, ret);
-            ok(err == test_data[i].err, "%d) err = %d\n", i, err);
-            ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
-                    "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
-        }else {
-            todo_wine ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
-                    "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
+
+        if (!test_data[i].todo)
+        {
+            ok(ret == test_data[i].ret ||
+                    broken(ret == test_data[i].broken_ret), "%d) ret = %d\n", i, ret);
         }
+        else
+        {
+            todo_wine ok(ret == test_data[i].ret ||
+                    broken(ret == test_data[i].broken_ret), "%d) ret = %d\n", i, ret);
+        }
+        if(ret != test_data[i].ret)
+            continue;
+
+        ok(err == test_data[i].err, "%d) err = %d\n", i, err);
+        ok(!memcmp(test_data[i].out, buf, ret*sizeof(WCHAR)),
+                "%d) buf = %s\n", i, wine_dbgstr_wn(buf, ret));
     }
 }
 
@@ -3599,6 +3844,7 @@ START_TEST(locale)
   test_GetCurrencyFormatA(); /* Also tests the W version */
   test_GetNumberFormatA();   /* Also tests the W version */
   test_CompareStringA();
+  test_CompareStringEx();
   test_LCMapStringA();
   test_LCMapStringW();
   test_LCMapStringEx();
index fb3ec34..da595e9 100755 (executable)
@@ -42,24 +42,24 @@ static int mailslot_test(void)
             &dwMsgCount, &dwTimeout ), "getmailslotinfo succeeded\n");
 
     /* open a mailslot that doesn't exist */
-    hWriter = CreateFile(szmspath, GENERIC_READ|GENERIC_WRITE,
+    hWriter = CreateFileA(szmspath, GENERIC_READ|GENERIC_WRITE,
                              FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
     ok( hWriter == INVALID_HANDLE_VALUE, "nonexistent mailslot\n");
 
     /* open a mailslot without the right name */
-    hSlot = CreateMailslot( "blah", 0, 0, NULL );
+    hSlot = CreateMailslotA( "blah", 0, 0, NULL );
     ok( hSlot == INVALID_HANDLE_VALUE,
             "Created mailslot with invalid name\n");
     ok( GetLastError() == ERROR_INVALID_NAME,
             "error should be ERROR_INVALID_NAME\n");
 
     /* open a mailslot with a null name */
-    hSlot = CreateMailslot( NULL, 0, 0, NULL );
+    hSlot = CreateMailslotA( NULL, 0, 0, NULL );
     ok( hSlot == INVALID_HANDLE_VALUE, "Created mailslot with invalid name\n");
     ok( GetLastError() == ERROR_PATH_NOT_FOUND, "error should be ERROR_PATH_NOT_FOUND\n");
 
     /* valid open, but with wacky parameters ... then check them */
-    hSlot = CreateMailslot( szmspath, -1, -1, NULL );
+    hSlot = CreateMailslotA( szmspath, -1, -1, NULL );
     ok( hSlot != INVALID_HANDLE_VALUE , "mailslot with valid name failed\n");
     dwMax = dwNext = dwMsgCount = dwTimeout = 0;
     ok( GetMailslotInfo( hSlot, &dwMax, &dwNext, &dwMsgCount, &dwTimeout ),
@@ -73,10 +73,25 @@ static int mailslot_test(void)
     ok( CloseHandle(hSlot), "failed to close mailslot\n");
 
     /* now open it for real */
-    hSlot = CreateMailslot( szmspath, 0, 0, NULL );
+    hSlot = CreateMailslotA( szmspath, 0, 0, NULL );
     ok( hSlot != INVALID_HANDLE_VALUE , "valid mailslot failed\n");
 
     /* try and read/write to it */
+    count = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = ReadFile(INVALID_HANDLE_VALUE, buffer, 0, &count, NULL);
+    ok(!ret, "ReadFile should fail\n");
+    ok(GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError());
+    ok(count == 0, "expected 0, got %u\n", count);
+
+    count = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = ReadFile(hSlot, buffer, 0, &count, NULL);
+    ok(!ret, "ReadFile should fail\n");
+todo_wine
+    ok(GetLastError() == ERROR_SEM_TIMEOUT, "wrong error %u\n", GetLastError());
+    ok(count == 0, "expected 0, got %u\n", count);
+
     count = 0;
     memset(buffer, 0, sizeof buffer);
     ret = ReadFile( hSlot, buffer, sizeof buffer, &count, NULL);
@@ -88,14 +103,14 @@ static int mailslot_test(void)
     ok( GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError() );
 
     /* now try and open the client, but with the wrong sharing mode */
-    hWriter = CreateFile(szmspath, GENERIC_WRITE,
+    hWriter = CreateFileA(szmspath, GENERIC_WRITE,
                              0, NULL, OPEN_EXISTING, 0, NULL);
     ok( hWriter != INVALID_HANDLE_VALUE /* vista */ || GetLastError() == ERROR_SHARING_VIOLATION,
         "error should be ERROR_SHARING_VIOLATION got %p / %u\n", hWriter, GetLastError());
     if (hWriter != INVALID_HANDLE_VALUE) CloseHandle( hWriter );
 
     /* now open the client with the correct sharing mode */
-    hWriter = CreateFile(szmspath, GENERIC_READ|GENERIC_WRITE,
+    hWriter = CreateFileA(szmspath, GENERIC_READ|GENERIC_WRITE,
                              FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
     ok( hWriter != INVALID_HANDLE_VALUE, "existing mailslot err %u\n", GetLastError());
 
@@ -141,25 +156,25 @@ static int mailslot_test(void)
     else ok( count == 0, "wrong count %u\n", count );
 
     /* now try open another writer... should fail */
-    hWriter2 = CreateFile(szmspath, GENERIC_READ|GENERIC_WRITE,
+    hWriter2 = CreateFileA(szmspath, GENERIC_READ|GENERIC_WRITE,
                      FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
     /* succeeds on vista, don't test */
     if (hWriter2 != INVALID_HANDLE_VALUE) CloseHandle( hWriter2 );
 
     /* now try open another as a reader ... also fails */
-    hWriter2 = CreateFile(szmspath, GENERIC_READ,
+    hWriter2 = CreateFileA(szmspath, GENERIC_READ,
                      FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
     /* succeeds on vista, don't test */
     if (hWriter2 != INVALID_HANDLE_VALUE) CloseHandle( hWriter2 );
 
     /* now try open another as a writer ... still fails */
-    hWriter2 = CreateFile(szmspath, GENERIC_WRITE,
+    hWriter2 = CreateFileA(szmspath, GENERIC_WRITE,
                      FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
     /* succeeds on vista, don't test */
     if (hWriter2 != INVALID_HANDLE_VALUE) CloseHandle( hWriter2 );
 
     /* now open another one */
-    hSlot2 = CreateMailslot( szmspath, 0, 0, NULL );
+    hSlot2 = CreateMailslotA( szmspath, 0, 0, NULL );
     ok( hSlot2 == INVALID_HANDLE_VALUE , "opened two mailslots\n");
 
     /* close the client again */
@@ -169,7 +184,7 @@ static int mailslot_test(void)
      * now try reopen it with slightly different permissions ...
      * shared writing
      */
-    hWriter = CreateFile(szmspath, GENERIC_WRITE,
+    hWriter = CreateFileA(szmspath, GENERIC_WRITE,
               FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
     ok( hWriter != INVALID_HANDLE_VALUE, "sharing writer\n");
 
@@ -177,13 +192,13 @@ static int mailslot_test(void)
      * now try open another as a writer ...
      * but don't share with the first ... fail
      */
-    hWriter2 = CreateFile(szmspath, GENERIC_WRITE,
+    hWriter2 = CreateFileA(szmspath, GENERIC_WRITE,
                      FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
     /* succeeds on vista, don't test */
     if (hWriter2 != INVALID_HANDLE_VALUE) CloseHandle( hWriter2 );
 
     /* now try open another as a writer ... and share with the first */
-    hWriter2 = CreateFile(szmspath, GENERIC_WRITE,
+    hWriter2 = CreateFileA(szmspath, GENERIC_WRITE,
               FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
     ok( hWriter2 != INVALID_HANDLE_VALUE, "2nd sharing writer\n");
 
@@ -301,7 +316,7 @@ static int mailslot_test(void)
     ok( CloseHandle( hSlot ), "closing the mailslot\n");
 
     /* test timeouts */
-    hSlot = CreateMailslot( szmspath, 0, 1000, NULL );
+    hSlot = CreateMailslotA( szmspath, 0, 1000, NULL );
     ok( hSlot != INVALID_HANDLE_VALUE , "valid mailslot failed\n");
     count = 0;
     memset(buffer, 0, sizeof buffer);
index e8d51e1..0d140a4 100755 (executable)
@@ -46,7 +46,7 @@ static void testGetModuleFileName(const char* name)
     WCHAR       bufW[MAX_PATH];
     DWORD       len1A, len1W = 0, len2A, len2W = 0;
 
-    hMod = (name) ? GetModuleHandle(name) : NULL;
+    hMod = (name) ? GetModuleHandleA(name) : NULL;
 
     /* first test, with enough space in buffer */
     memset(bufA, '-', sizeof(bufA));
@@ -157,7 +157,7 @@ static void testNestedLoadLibraryA(void)
      * - it must not already be loaded
      * - it must not have a 16-bit counterpart
      */
-    GetWindowsDirectory(path1, sizeof(path1));
+    GetWindowsDirectoryA(path1, sizeof(path1));
     strcat(path1, "\\system\\");
     strcat(path1, dllname);
     hModule1 = LoadLibraryA(path1);
@@ -167,7 +167,7 @@ static void testNestedLoadLibraryA(void)
         return;
     }
 
-    GetWindowsDirectory(path2, sizeof(path2));
+    GetWindowsDirectoryA(path2, sizeof(path2));
     strcat(path2, "\\system32\\");
     strcat(path2, dllname);
     hModule2 = LoadLibraryA(path2);
@@ -189,7 +189,7 @@ static void testNestedLoadLibraryA(void)
     ok(FreeLibrary(hModule3), "FreeLibrary() failed\n");
     ok(FreeLibrary(hModule2), "FreeLibrary() failed\n");
     ok(FreeLibrary(hModule1), "FreeLibrary() failed\n");
-    ok(GetModuleHandle(dllname) == NULL, "%s was not fully unloaded\n", dllname);
+    ok(GetModuleHandleA(dllname) == NULL, "%s was not fully unloaded\n", dllname);
 
     /* Try to load the dll again, if refcounting is ok, this should work */
     hModule1 = LoadLibraryA(path1);
@@ -261,7 +261,8 @@ static void testLoadLibraryEx(void)
     hmodule = LoadLibraryExA("", NULL, 0);
     ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
     ok(GetLastError() == ERROR_MOD_NOT_FOUND ||
-       GetLastError() == ERROR_DLL_NOT_FOUND, /* win9x */
+       GetLastError() == ERROR_DLL_NOT_FOUND /* win9x */ ||
+       GetLastError() == ERROR_INVALID_PARAMETER /* win8 */,
        "Expected ERROR_MOD_NOT_FOUND or ERROR_DLL_NOT_FOUND, got %d\n",
        GetLastError());
 
@@ -347,7 +348,7 @@ static void testLoadLibraryEx(void)
     if (!hmodule)  /* succeeds on xp and older */
         ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
 
-    CloseHandle(hmodule);
+    FreeLibrary(hmodule);
 
     /* load kernel32.dll with no path */
     SetLastError(0xdeadbeef);
@@ -357,7 +358,7 @@ static void testLoadLibraryEx(void)
        GetLastError() == ERROR_SUCCESS, /* win9x */
        "Expected 0xdeadbeef or ERROR_SUCCESS, got %d\n", GetLastError());
 
-    CloseHandle(hmodule);
+    FreeLibrary(hmodule);
 
     GetCurrentDirectoryA(MAX_PATH, path);
     if (path[lstrlenA(path) - 1] != '\\')
@@ -375,7 +376,7 @@ static void testLoadLibraryEx(void)
        broken(GetLastError() == ERROR_INVALID_HANDLE),  /* nt4 */
        "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
 
-    /* Free the loaded dll when its the first time this dll is loaded
+    /* Free the loaded dll when it's the first time this dll is loaded
        in process - First time should pass, second fail */
     SetLastError(0xdeadbeef);
     hmodule = LoadLibraryExA("comctl32.dll", NULL, LOAD_LIBRARY_AS_DATAFILE);
@@ -388,8 +389,19 @@ static void testLoadLibraryEx(void)
     ret = FreeLibrary(hmodule);
     ok(!ret, "Unexpected ability to free the module, failed with %d\n", GetLastError());
 
-    CloseHandle(hmodule);
-
+    /* load with full path, name without extension */
+    GetSystemDirectoryA(path, MAX_PATH);
+    if (path[lstrlenA(path) - 1] != '\\')
+        lstrcatA(path, "\\");
+    lstrcatA(path, "kernel32");
+    hmodule = LoadLibraryExA(path, NULL, 0);
+    ok(hmodule != NULL, "got %p\n", hmodule);
+    FreeLibrary(hmodule);
+
+    /* same with alterate search path */
+    hmodule = LoadLibraryExA(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+    ok(hmodule != NULL, "got %p\n", hmodule);
+    FreeLibrary(hmodule);
 }
 
 static void testGetDllDirectory(void)
@@ -438,7 +450,8 @@ static void testGetDllDirectory(void)
         bufferA[length] = 'A';
         bufferA[length + 1] = 'A';
         ret = pGetDllDirectoryA(length + 1, bufferA);
-        ok(ret == length, "i=%d, Expected %u, got %u\n", i, length, ret);
+        ok(ret == length || broken(ret + 1 == length) /* win8 */,
+           "i=%d, Expected %u(+1), got %u\n", i, length, ret);
         ok(bufferA[length + 1] == 'A', "i=%d, Buffer overflow\n", i);
         ok(strcmp(bufferA, dll_directories[i]) == 0, "i=%d, Wrong path returned: '%s'\n", i, bufferA);
 
@@ -450,13 +463,11 @@ static void testGetDllDirectory(void)
         ok(cmpStrAW(dll_directories[i], bufferW, length, length),
            "i=%d, Wrong path returned: %s\n", i, wine_dbgstr_w(bufferW));
 
-        /* zero size buffer
-         * the A version always null-terminates the buffer,
-         * the W version doesn't do it on some platforms */
+        /* Zero size buffer. The buffer may or may not be terminated depending
+         * on the Windows version and whether the A or W API is called. */
         bufferA[0] = 'A';
         ret = pGetDllDirectoryA(0, bufferA);
         ok(ret == length + 1, "i=%d, Expected %u, got %u\n", i, length + 1, ret);
-        ok(bufferA[0] == 0, "i=%d, Buffer not null terminated\n", i);
 
         bufferW[0] = 'A';
         ret = pGetDllDirectoryW(0, bufferW);
@@ -468,7 +479,8 @@ static void testGetDllDirectory(void)
         bufferA[0] = 'A';
         ret = pGetDllDirectoryA(length, bufferA);
         ok(ret == length + 1, "i=%d, Expected %u, got %u\n", i, length + 1, ret);
-        ok(bufferA[0] == 0, "i=%d, Buffer not null terminated\n", i);
+        if (length != 0)
+            ok(bufferA[0] == 0, "i=%d, Buffer not null terminated\n", i);
 
         bufferW[0] = 'A';
         ret = pGetDllDirectoryW(length, bufferW);
index c49a76f..0f07ea6 100755 (executable)
 
 #define NOT_A_VALID_DRIVE '@'
 
+#ifdef __i386__
+#define ARCH "x86"
+#elif defined __x86_64__
+#define ARCH "amd64"
+#else
+#define ARCH "none"
+#endif
+
 /* the following characters don't work well with GetFullPathNameA
    in Win98.  I don't know if this is a FAT thing, or if it is an OS thing
    but I don't test these characters now.
@@ -61,6 +69,12 @@ static BOOL  (WINAPI *pNeedCurrentDirectoryForExePathW)(LPCWSTR);
 static DWORD (WINAPI *pSearchPathA)(LPCSTR,LPCSTR,LPCSTR,DWORD,LPSTR,LPSTR*);
 static DWORD (WINAPI *pSearchPathW)(LPCWSTR,LPCWSTR,LPCWSTR,DWORD,LPWSTR,LPWSTR*);
 
+static BOOL   (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
+static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
+static BOOL   (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
+static BOOL   (WINAPI *pGetCurrentActCtx)(HANDLE *);
+static void   (WINAPI *pReleaseActCtx)(HANDLE);
+
 /* a structure to deal with wine todos somewhat cleanly */
 typedef struct {
   DWORD shortlen;
@@ -184,21 +198,22 @@ static void test_ValidPathA(const CHAR *curdir, const CHAR *subdir, const CHAR *
 
 /* split path into leading directory, and 8.3 filename */
 static void test_SplitShortPathA(CHAR *path,CHAR *dir,CHAR *eight,CHAR *three) {
-  int done,error;
+  BOOL done = FALSE, error = FALSE;
   int ext,fil;
   int len,i;
   len=lstrlenA(path);
-  ext=len; fil=len; done=0; error=0;
+  ext=len;
+  fil=len;
 /* walk backwards over path looking for '.' or '\\' separators */
   for(i=len-1;(i>=0) && (!done);i--) {
     if(path[i]=='.')
-      if(ext!=len) error=1; else ext=i;
+      if(ext!=len) error=TRUE; else ext=i;
     else if(path[i]=='\\') {
       if(i==len-1) {
-        error=1;
+        error=TRUE;
       } else {
         fil=i;
-        done=1;
+        done=TRUE;
       }
     }
   }
@@ -293,7 +308,7 @@ static void test_setdir(CHAR *olddir,CHAR *newdir,
        "%s: SetCurrentDirectory did not change the directory, though it passed\n",
        errstr);
     ok(SetCurrentDirectoryA(olddir),
-       "%s: Couldn't set directory to it's original value\n",errstr);
+       "%s: Couldn't set directory to its original value\n",errstr);
   } else {
 /* else thest that it fails correctly */
     chklen=lstrlenA(olddir);
@@ -1058,7 +1073,7 @@ static void test_GetLongPathNameA(void)
     memset(temppath, 0, MAX_PATH);
     length = pGetLongPathNameA(tempfile, temppath, 4);
     /* We have a failure so length should be the minimum plus the terminating '0'  */
-    ok(length >= lstrlen(tempfile) + 1, "Wrong length\n");
+    ok(length >= strlen(tempfile) + 1, "Wrong length\n");
     ok(temppath[0] == 0, "Buffer should not have been touched\n");
 
     /* Some UNC syntax tests */
@@ -1089,7 +1104,7 @@ static void test_GetLongPathNameA(void)
     /* Now an UNC path with the computername */
     lstrcpyA(unc_prefix, "\\\\");
     hostsize = sizeof(unc_prefix) - 2;
-    GetComputerName(unc_prefix + 2, &hostsize);
+    GetComputerNameA(unc_prefix + 2, &hostsize);
     lstrcatA(unc_prefix, "\\");
 
     /* Create a short syntax for the whole unc path */
@@ -1302,7 +1317,7 @@ static void test_GetSystemDirectory(void)
     DWORD   total;
 
     SetLastError(0xdeadbeef);
-    res = GetSystemDirectory(NULL, 0);
+    res = GetSystemDirectoryA(NULL, 0);
     /* res includes the terminating Zero */
     ok(res > 0, "returned %d with %d (expected '>0')\n", res, GetLastError());
 
@@ -1310,10 +1325,10 @@ static void test_GetSystemDirectory(void)
 
     /* this crashes on XP */
     if (0)
-        GetSystemDirectory(NULL, total);
+        GetSystemDirectoryA(NULL, total);
 
     SetLastError(0xdeadbeef);
-    res = GetSystemDirectory(NULL, total-1);
+    res = GetSystemDirectoryA(NULL, total-1);
     /* 95+NT: total (includes the terminating Zero)
        98+ME: 0 with ERROR_INVALID_PARAMETER */
     ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
@@ -1324,7 +1339,7 @@ static void test_GetSystemDirectory(void)
 
     buffer[0] = '\0';
     SetLastError(0xdeadbeef);
-    res = GetSystemDirectory(buffer, total);
+    res = GetSystemDirectoryA(buffer, total);
     /* res does not include the terminating Zero */
     ok( (res == (total-1)) && (buffer[0]),
         "returned %d with %d and '%s' (expected '%d' and a string)\n",
@@ -1332,7 +1347,7 @@ static void test_GetSystemDirectory(void)
 
     buffer[0] = '\0';
     SetLastError(0xdeadbeef);
-    res = GetSystemDirectory(buffer, total + 1);
+    res = GetSystemDirectoryA(buffer, total + 1);
     /* res does not include the terminating Zero */
     ok( (res == (total-1)) && (buffer[0]),
         "returned %d with %d and '%s' (expected '%d' and a string)\n",
@@ -1341,7 +1356,7 @@ static void test_GetSystemDirectory(void)
     memset(buffer, '#', total + 1);
     buffer[total + 2] = '\0';
     SetLastError(0xdeadbeef);
-    res = GetSystemDirectory(buffer, total-1);
+    res = GetSystemDirectoryA(buffer, total-1);
     /* res includes the terminating Zero) */
     ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
         res, GetLastError(), buffer, total);
@@ -1349,7 +1364,7 @@ static void test_GetSystemDirectory(void)
     memset(buffer, '#', total + 1);
     buffer[total + 2] = '\0';
     SetLastError(0xdeadbeef);
-    res = GetSystemDirectory(buffer, total-2);
+    res = GetSystemDirectoryA(buffer, total-2);
     /* res includes the terminating Zero) */
     ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
         res, GetLastError(), buffer, total);
@@ -1362,17 +1377,17 @@ static void test_GetWindowsDirectory(void)
     DWORD   total;
 
     SetLastError(0xdeadbeef);
-    res = GetWindowsDirectory(NULL, 0);
+    res = GetWindowsDirectoryA(NULL, 0);
     /* res includes the terminating Zero */
     ok(res > 0, "returned %d with %d (expected '>0')\n", res, GetLastError());
 
     total = res;
     /* this crashes on XP */
     if (0)
-        GetWindowsDirectory(NULL, total);
+        GetWindowsDirectoryA(NULL, total);
 
     SetLastError(0xdeadbeef);
-    res = GetWindowsDirectory(NULL, total-1);
+    res = GetWindowsDirectoryA(NULL, total-1);
     /* 95+NT: total (includes the terminating Zero)
        98+ME: 0 with ERROR_INVALID_PARAMETER */
     ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
@@ -1383,7 +1398,7 @@ static void test_GetWindowsDirectory(void)
 
     buffer[0] = '\0';
     SetLastError(0xdeadbeef);
-    res = GetWindowsDirectory(buffer, total);
+    res = GetWindowsDirectoryA(buffer, total);
     /* res does not include the terminating Zero */
     ok( (res == (total-1)) && (buffer[0]),
         "returned %d with %d and '%s' (expected '%d' and a string)\n",
@@ -1391,7 +1406,7 @@ static void test_GetWindowsDirectory(void)
 
     buffer[0] = '\0';
     SetLastError(0xdeadbeef);
-    res = GetWindowsDirectory(buffer, total + 1);
+    res = GetWindowsDirectoryA(buffer, total + 1);
     /* res does not include the terminating Zero */
     ok( (res == (total-1)) && (buffer[0]),
         "returned %d with %d and '%s' (expected '%d' and a string)\n",
@@ -1400,7 +1415,7 @@ static void test_GetWindowsDirectory(void)
     memset(buffer, '#', total + 1);
     buffer[total + 2] = '\0';
     SetLastError(0xdeadbeef);
-    res = GetWindowsDirectory(buffer, total-1);
+    res = GetWindowsDirectoryA(buffer, total-1);
     /* res includes the terminating Zero) */
     ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
         res, GetLastError(), buffer, total);
@@ -1408,7 +1423,7 @@ static void test_GetWindowsDirectory(void)
     memset(buffer, '#', total + 1);
     buffer[total + 2] = '\0';
     SetLastError(0xdeadbeef);
-    res = GetWindowsDirectory(buffer, total-2);
+    res = GetWindowsDirectoryA(buffer, total-2);
     /* res includes the terminating Zero) */
     ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
         res, GetLastError(), buffer, total);
@@ -1477,7 +1492,7 @@ static void test_drive_letter_case(void)
 
     memset(buf, 0, sizeof(buf));
     SetLastError(0xdeadbeef);
-    ret = GetWindowsDirectory(buf, sizeof(buf));
+    ret = GetWindowsDirectoryA(buf, sizeof(buf));
     ok(ret, "GetWindowsDirectory error %u\n", GetLastError());
     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
@@ -1486,7 +1501,7 @@ static void test_drive_letter_case(void)
     /* re-use the buffer returned by GetFullPathName */
     buf[2] = '/';
     SetLastError(0xdeadbeef);
-    ret = GetFullPathName(buf + 2, sizeof(buf), buf, NULL);
+    ret = GetFullPathNameA(buf + 2, sizeof(buf), buf, NULL);
     ok(ret, "GetFullPathName error %u\n", GetLastError());
     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
@@ -1494,7 +1509,7 @@ static void test_drive_letter_case(void)
 
     memset(buf, 0, sizeof(buf));
     SetLastError(0xdeadbeef);
-    ret = GetSystemDirectory(buf, sizeof(buf));
+    ret = GetSystemDirectoryA(buf, sizeof(buf));
     ok(ret, "GetSystemDirectory error %u\n", GetLastError());
     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
@@ -1502,7 +1517,7 @@ static void test_drive_letter_case(void)
 
     memset(buf, 0, sizeof(buf));
     SetLastError(0xdeadbeef);
-    ret = GetCurrentDirectory(sizeof(buf), buf);
+    ret = GetCurrentDirectoryA(sizeof(buf), buf);
     ok(ret, "GetCurrentDirectory error %u\n", GetLastError());
     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
@@ -1511,7 +1526,7 @@ static void test_drive_letter_case(void)
     /* TEMP is an environment variable, so it can't be tested for case-sensitivity */
     memset(buf, 0, sizeof(buf));
     SetLastError(0xdeadbeef);
-    ret = GetTempPath(sizeof(buf), buf);
+    ret = GetTempPathA(sizeof(buf), buf);
     ok(ret, "GetTempPath error %u\n", GetLastError());
     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
     if (buf[0])
@@ -1522,7 +1537,7 @@ static void test_drive_letter_case(void)
 
     memset(buf, 0, sizeof(buf));
     SetLastError(0xdeadbeef);
-    ret = GetFullPathName(".", sizeof(buf), buf, NULL);
+    ret = GetFullPathNameA(".", sizeof(buf), buf, NULL);
     ok(ret, "GetFullPathName error %u\n", GetLastError());
     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
@@ -1530,7 +1545,7 @@ static void test_drive_letter_case(void)
 
     /* re-use the buffer returned by GetFullPathName */
     SetLastError(0xdeadbeef);
-    ret = GetShortPathName(buf, buf, sizeof(buf));
+    ret = GetShortPathNameA(buf, buf, sizeof(buf));
     ok(ret, "GetShortPathName error %u\n", GetLastError());
     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
@@ -1549,10 +1564,90 @@ static void test_drive_letter_case(void)
 #undef is_upper_case_letter
 }
 
+static const char manifest_dep[] =
+"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
+"<assemblyIdentity version=\"1.2.3.4\"  name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>"
+"    <file name=\"testdep.dll\" />"
+"    <file name=\"ole32\" />"
+"    <file name=\"kernel32.dll\" />"
+"</assembly>";
+
+static const char manifest_main[] =
+"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
+"<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
+"<dependency>"
+" <dependentAssembly>"
+"  <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH "\" />"
+" </dependentAssembly>"
+"</dependency>"
+"</assembly>";
+
+static void create_manifest_file(const char *filename, const char *manifest)
+{
+    WCHAR path[MAX_PATH], manifest_path[MAX_PATH];
+    HANDLE file;
+    DWORD size;
+
+    MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH );
+
+    GetTempPathW(sizeof(manifest_path)/sizeof(WCHAR), manifest_path);
+    lstrcatW(manifest_path, path);
+