Index: rostests/apitests/advpack/CMakeLists.txt =================================================================== --- rostests/apitests/advpack/CMakeLists.txt (nonexistent) +++ rostests/apitests/advpack/CMakeLists.txt (working copy) @@ -0,0 +1,10 @@ + +list(APPEND SOURCE + DelNode.c + testlist.c) + +add_executable(advpack_apitest ${SOURCE}) +target_link_libraries(advpack_apitest wine ${PSEH_LIB}) +set_module_type(advpack_apitest win32cui) +add_importlibs(advpack_apitest advpack msvcrt kernel32 ntdll) +add_rostests_file(TARGET advpack_apitest) Index: rostests/apitests/advpack/DelNode.c =================================================================== --- rostests/apitests/advpack/DelNode.c (nonexistent) +++ rostests/apitests/advpack/DelNode.c (working copy) @@ -0,0 +1,518 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Test for advpack.dll DelNode function + * PROGRAMMERS: Katayama Hirofumi MZ + */ +#include + +#include +#define WIN32_NO_STATUS +#include +#include + +/* Flags for DelNode */ +#define ADN_DEL_IF_EMPTY 0x00000001 +#define ADN_DONT_DEL_SUBDIRS 0x00000002 +#define ADN_DONT_DEL_DIR 0x00000004 +#define ADN_DEL_UNC_PATHS 0x00000008 + +/* DelNodeA and DelNodeW in advpack.dll */ +typedef HRESULT (WINAPI *DELNODEA)(LPCSTR, DWORD); +typedef HRESULT (WINAPI *DELNODEW)(LPCWSTR, DWORD); + +static HINSTANCE s_hAdvPack = NULL; +static DELNODEA s_pDelNodeA = NULL; +static DELNODEW s_pDelNodeW = NULL; + +typedef struct { + const char *item; + BOOL is_dir; +} NODEA; + +static const NODEA s_nodesA[] = +{ + { "dir1", TRUE }, /* 0 */ + { "dir1\\dir2", TRUE }, /* 1 */ + { "dir1\\dir2\\file1", FALSE }, /* 2 */ +}; + +typedef struct { + const WCHAR *item; + BOOL is_dir; +} NODEW; + +static const NODEW s_nodesW[] = +{ + { L"dir1", TRUE }, /* 0 */ + { L"dir1\\dir2", TRUE }, /* 1 */ + { L"dir1\\dir2\\file1", FALSE }, /* 2 */ +}; + +typedef enum +{ + EAT_CREATE, + EAT_DELETE, + EAT_CHECK_EXIST, + EAT_CHECK_NON_EXIST, + EAT_CALL +} ENTRY_ACTION_TYPE; + +typedef struct { + int node; + ENTRY_ACTION_TYPE action_type; + DWORD flags; + HRESULT ret; +} ENTRY; + +/* TODO: ADN_DEL_UNC_PATHS */ +#define FLAGS0 0 +#define FLAGS1 ADN_DEL_IF_EMPTY +#define FLAGS2 ADN_DONT_DEL_DIR +#define FLAGS3 ADN_DONT_DEL_SUBDIRS +#define FLAGS4 (ADN_DONT_DEL_DIR | ADN_DONT_DEL_SUBDIRS) +#define FLAGS5 (ADN_DEL_IF_EMPTY | ADN_DONT_DEL_DIR) +#define FLAGS6 (ADN_DEL_IF_EMPTY | ADN_DONT_DEL_SUBDIRS) +#define FLAGS7 (ADN_DEL_IF_EMPTY | ADN_DONT_DEL_DIR | ADN_DONT_DEL_SUBDIRS) +#define FLAGS8 0xFFFFFFFF + +static const ENTRY s_entries[] = +{ + /* #0 */ { 0, EAT_CREATE }, + /* #1 */ { 1, EAT_CREATE }, + /* #2 */ { 1, EAT_DELETE }, + /* #3 */ { 0, EAT_DELETE }, + + /* ------------------------------- */ + + /* #4 */ { 0, EAT_CREATE }, + /* #5 */ { 1, EAT_CREATE }, + /* #6 */ { 0, EAT_CALL, FLAGS0, S_OK }, + /* #7 */ { 0, EAT_CHECK_NON_EXIST }, + + /* #8 */ { 0, EAT_CREATE }, + /* #9 */ { 1, EAT_CREATE }, + /* #10 */ { 0, EAT_CALL, FLAGS1, E_FAIL }, + /* #11 */ { 0, EAT_CHECK_EXIST }, + + /* #12 */ { 0, EAT_CREATE }, + /* #13 */ { 1, EAT_CREATE }, + /* #14 */ { 0, EAT_CALL, FLAGS2, S_OK }, + /* #15 */ { 0, EAT_CHECK_EXIST }, + + /* #16 */ { 0, EAT_CREATE }, + /* #17 */ { 1, EAT_CREATE }, + /* #18 */ { 0, EAT_CALL, FLAGS3, S_OK }, + /* #19 */ { 0, EAT_CHECK_EXIST }, + + /* #20 */ { 0, EAT_CREATE }, + /* #21 */ { 1, EAT_CREATE }, + /* #22 */ { 0, EAT_CALL, FLAGS4, S_OK }, + /* #23 */ { 0, EAT_CHECK_EXIST }, + + /* #24 */ { 0, EAT_CREATE }, + /* #25 */ { 1, EAT_CREATE }, + /* #26 */ { 0, EAT_CALL, FLAGS5, E_FAIL }, + /* #27 */ { 0, EAT_CHECK_EXIST }, + + /* #28 */ { 0, EAT_CREATE }, + /* #29 */ { 1, EAT_CREATE }, + /* #30 */ { 0, EAT_CALL, FLAGS6, E_FAIL }, + /* #31 */ { 0, EAT_CHECK_EXIST }, + + /* #32 */ { 0, EAT_CREATE }, + /* #33 */ { 1, EAT_CREATE }, + /* #34 */ { 0, EAT_CALL, FLAGS7, E_FAIL }, + /* #35 */ { 0, EAT_CHECK_EXIST }, + + /* #36 */ { 0, EAT_CREATE }, + /* #37 */ { 1, EAT_CREATE }, + /* #38 */ { 0, EAT_CALL, FLAGS8, E_FAIL }, + /* #39 */ { 0, EAT_CHECK_EXIST }, + + /* ------------------------------- */ + + /* #40 */ { 0, EAT_CREATE }, + /* #41 */ { 1, EAT_CREATE }, + /* #42 */ { 2, EAT_CREATE }, + /* #43 */ { 0, EAT_CALL, FLAGS0, S_OK }, + /* #44 */ { 0, EAT_CHECK_NON_EXIST }, + + /* #45 */ { 0, EAT_CREATE }, + /* #46 */ { 1, EAT_CREATE }, + /* #47 */ { 2, EAT_CREATE }, + /* #48 */ { 0, EAT_CALL, FLAGS1, E_FAIL }, + /* #49 */ { 0, EAT_CHECK_EXIST }, + + /* #50 */ { 0, EAT_CREATE }, + /* #51 */ { 1, EAT_CREATE }, + /* #52 */ { 2, EAT_CREATE }, + /* #53 */ { 0, EAT_CALL, FLAGS2, S_OK }, + /* #54 */ { 0, EAT_CHECK_EXIST }, + + /* #55 */ { 0, EAT_CREATE }, + /* #56 */ { 1, EAT_CREATE }, + /* #57 */ { 2, EAT_CREATE }, + /* #58 */ { 0, EAT_CALL, FLAGS3, S_OK }, + /* #59 */ { 0, EAT_CHECK_EXIST }, + + /* #60 */ { 0, EAT_CREATE }, + /* #61 */ { 1, EAT_CREATE }, + /* #62 */ { 2, EAT_CREATE }, + /* #63 */ { 0, EAT_CALL, FLAGS4, S_OK }, + /* #64 */ { 0, EAT_CHECK_EXIST }, + + /* #65 */ { 0, EAT_CREATE }, + /* #66 */ { 1, EAT_CREATE }, + /* #67 */ { 2, EAT_CREATE }, + /* #68 */ { 0, EAT_CALL, FLAGS5, E_FAIL }, + /* #69 */ { 0, EAT_CHECK_EXIST }, + + /* #70 */ { 0, EAT_CREATE }, + /* #71 */ { 1, EAT_CREATE }, + /* #72 */ { 2, EAT_CREATE }, + /* #73 */ { 0, EAT_CALL, FLAGS6, E_FAIL }, + /* #74 */ { 0, EAT_CHECK_EXIST }, + + /* #75 */ { 0, EAT_CREATE }, + /* #76 */ { 1, EAT_CREATE }, + /* #77 */ { 2, EAT_CREATE }, + /* #78 */ { 0, EAT_CALL, FLAGS7, E_FAIL }, + /* #79 */ { 0, EAT_CHECK_EXIST }, + + /* #80 */ { 0, EAT_CREATE }, + /* #81 */ { 1, EAT_CREATE }, + /* #82 */ { 2, EAT_CREATE }, + /* #83 */ { 0, EAT_CALL, FLAGS8, E_FAIL }, + /* #84 */ { 0, EAT_CHECK_EXIST }, + + /* ------------------------------- */ + + /* #85 */ { 1, EAT_CREATE }, + /* #86 */ { 2, EAT_CREATE }, + /* #87 */ { 1, EAT_CALL, FLAGS0, S_OK }, + /* #88 */ { 1, EAT_CHECK_NON_EXIST }, + + /* #89 */ { 1, EAT_CREATE }, + /* #90 */ { 2, EAT_CREATE }, + /* #91 */ { 1, EAT_CALL, FLAGS1, E_FAIL }, + /* #92 */ { 1, EAT_CHECK_EXIST }, + /* #93 */ { 2, EAT_CHECK_EXIST }, + + /* #94 */ { 1, EAT_CREATE }, + /* #95 */ { 2, EAT_CREATE }, + /* #96 */ { 1, EAT_CALL, FLAGS2, S_OK }, + /* #97 */ { 1, EAT_CHECK_EXIST }, + /* #98 */ { 2, EAT_CHECK_NON_EXIST }, + + /* #99 */ { 1, EAT_CREATE }, + /* #100 */ { 2, EAT_CREATE }, + /* #101 */ { 1, EAT_CALL, FLAGS3, S_OK }, + /* #102 */ { 1, EAT_CHECK_NON_EXIST }, + + /* #103 */ { 1, EAT_CREATE }, + /* #104 */ { 2, EAT_CREATE }, + /* #105 */ { 1, EAT_CALL, FLAGS4, S_OK }, + /* #106 */ { 1, EAT_CHECK_EXIST }, + /* #107 */ { 2, EAT_CHECK_NON_EXIST }, + + /* #108 */ { 1, EAT_CREATE }, + /* #109 */ { 2, EAT_CREATE }, + /* #110 */ { 1, EAT_CALL, FLAGS5, E_FAIL }, + /* #111 */ { 1, EAT_CHECK_EXIST }, + /* #112 */ { 2, EAT_CHECK_EXIST }, + + /* #113 */ { 1, EAT_CREATE }, + /* #114 */ { 2, EAT_CREATE }, + /* #115 */ { 1, EAT_CALL, FLAGS6, E_FAIL }, + /* #116 */ { 1, EAT_CHECK_EXIST }, + /* #117 */ { 2, EAT_CHECK_EXIST }, + + /* #118 */ { 1, EAT_CREATE }, + /* #119 */ { 2, EAT_CREATE }, + /* #120 */ { 1, EAT_CALL, FLAGS7, E_FAIL }, + /* #121 */ { 1, EAT_CHECK_EXIST }, + /* #122 */ { 2, EAT_CHECK_EXIST }, + + /* #123 */ { 1, EAT_CREATE }, + /* #124 */ { 2, EAT_CREATE }, + /* #125 */ { 1, EAT_CALL, FLAGS8, E_FAIL }, + /* #126 */ { 1, EAT_CHECK_EXIST }, + /* #127 */ { 2, EAT_CHECK_EXIST }, + + /* ------------------------------- */ + + /* #128 */ { 1, EAT_CREATE }, + + /* #129 */ { 2, EAT_CREATE }, + /* #130 */ { 2, EAT_CALL, FLAGS0, S_OK }, + /* #131 */ { 2, EAT_CHECK_NON_EXIST }, + + /* #132 */ { 2, EAT_CREATE }, + /* #133 */ { 2, EAT_CALL, FLAGS1, S_OK }, + /* #134 */ { 2, EAT_CHECK_NON_EXIST }, + + /* #135 */ { 2, EAT_CREATE }, + /* #136 */ { 2, EAT_CALL, FLAGS2, S_OK }, + /* #137 */ { 2, EAT_CHECK_NON_EXIST }, + + /* #138 */ { 2, EAT_CREATE }, + /* #139 */ { 2, EAT_CALL, FLAGS3, S_OK }, + /* #140 */ { 2, EAT_CHECK_NON_EXIST }, + + /* #141 */ { 2, EAT_CREATE }, + /* #142 */ { 2, EAT_CALL, FLAGS4, S_OK }, + /* #143 */ { 2, EAT_CHECK_NON_EXIST }, + + /* #144 */ { 2, EAT_CREATE }, + /* #145 */ { 2, EAT_CALL, FLAGS5, S_OK }, + /* #146 */ { 2, EAT_CHECK_NON_EXIST }, + + /* #147 */ { 2, EAT_CREATE }, + /* #148 */ { 2, EAT_CALL, FLAGS6, S_OK }, + /* #149 */ { 2, EAT_CHECK_NON_EXIST }, + + /* #150 */ { 2, EAT_CREATE }, + /* #151 */ { 2, EAT_CALL, FLAGS7, S_OK }, + /* #152 */ { 2, EAT_CHECK_NON_EXIST }, + + /* #153 */ { 2, EAT_CREATE }, + /* #154 */ { 2, EAT_CALL, FLAGS8, S_OK }, + /* #155 */ { 2, EAT_CHECK_NON_EXIST }, + + /* ------------------------------- */ + + /* #156 */ { 2, EAT_DELETE }, + /* #157 */ { 1, EAT_DELETE }, + /* #158 */ { 0, EAT_DELETE }, +}; + +char s_cur_dir_A[MAX_PATH] = ""; +WCHAR s_cur_dir_W[MAX_PATH] = L""; + +static char *GetPathA(const char *item) +{ + static char s_path[MAX_PATH]; + lstrcpyA(s_path, s_cur_dir_A); + lstrcatA(s_path, "\\"); + lstrcatA(s_path, item); + return s_path; +} + +static WCHAR *GetPathW(const WCHAR *item) +{ + static WCHAR s_path[MAX_PATH]; + lstrcpyW(s_path, s_cur_dir_W); + lstrcatW(s_path, L"\\"); + lstrcatW(s_path, item); + return s_path; +} + +static void cleanupA(void) +{ + size_t i, k; + for (k = 0; k < 4; ++k) + { + for (i = 0; i < _countof(s_nodesA); ++i) + { + const NODEA *node = &s_nodesA[i]; + char *path = GetPathA(node->item); + + DeleteFileA(path); + RemoveDirectoryA(path); + } + } +} + +static void Test_DelNodeA(void) +{ + DWORD attr; + size_t i; + + if (!GetCurrentDirectoryA(_countof(s_cur_dir_A), s_cur_dir_A)) + { + skip("GetCurrentDirectoryA failed\n"); + return; + } + + cleanupA(); + + for (i = 0; i < _countof(s_entries); ++i) + { + const ENTRY *entry = &s_entries[i]; + const NODEA *node = &s_nodesA[entry->node]; + char *path = GetPathA(node->item); + int ret; + + switch (entry->action_type) + { + case EAT_CREATE: + if (node->is_dir) + { + CreateDirectoryA(path, NULL); + + attr = GetFileAttributesA(path); + ok(attr != INVALID_FILE_ATTRIBUTES, "Entry #%d: path:%s, attr:0x%08lX\n", i, path, attr); + ok((attr & FILE_ATTRIBUTE_DIRECTORY), "Entry #%d: path:%s, attr:0x%08lX\n", i, path, attr); + } + else + { + fclose(fopen(path, "w")); + + attr = GetFileAttributesA(path); + ok(attr != INVALID_FILE_ATTRIBUTES, "Entry #%d: attr was 0x%08lX\n", i, attr); + ok(!(attr & FILE_ATTRIBUTE_DIRECTORY), "Entry #%d: attr was 0x%08lX\n", i, attr); + } + break; + case EAT_DELETE: + if (node->is_dir) + { + RemoveDirectoryA(path); + } + else + { + DeleteFileA(path); + } + attr = GetFileAttributesA(path); + ok(attr == INVALID_FILE_ATTRIBUTES, "Entry #%d: cannot delete\n", i); + break; + case EAT_CHECK_EXIST: + attr = GetFileAttributesA(path); + ok(attr != INVALID_FILE_ATTRIBUTES, "Entry #%d: attr was 0x%08lX\n", i, attr); + break; + case EAT_CHECK_NON_EXIST: + attr = GetFileAttributesA(path); + ok(attr == INVALID_FILE_ATTRIBUTES, "Entry #%d: attr was 0x%08lX\n", i, attr); + break; + case EAT_CALL: + ret = (*s_pDelNodeA)(path, entry->flags); + ok(ret == entry->ret, "Entry #%d: ret:%d, path:%s, flags:0x%08lX\n", + i, ret, path, entry->flags); + break; + } + } + + cleanupA(); +} + +static void cleanupW(void) +{ + size_t i, k; + for (k = 0; k < 4; ++k) + { + for (i = 0; i < _countof(s_nodesW); ++i) + { + const NODEW *node = &s_nodesW[i]; + WCHAR *path = GetPathW(node->item); + + DeleteFileW(path); + RemoveDirectoryW(path); + } + } +} + +static void Test_DelNodeW(void) +{ + DWORD attr; + size_t i; + + if (!GetCurrentDirectoryW(_countof(s_cur_dir_W), s_cur_dir_W)) + { + skip("GetCurrentDirectoryA failed\n"); + return; + } + + cleanupW(); + + for (i = 0; i < _countof(s_entries); ++i) + { + const ENTRY *entry = &s_entries[i]; + const NODEW *node = &s_nodesW[entry->node]; + WCHAR *path = GetPathW(node->item); + int ret; + + switch (entry->action_type) + { + case EAT_CREATE: + if (node->is_dir) + { + CreateDirectoryW(path, NULL); + + attr = GetFileAttributesW(path); + ok(attr != INVALID_FILE_ATTRIBUTES, "Entry #%d: path:%S, attr:0x%08lX\n", i, path, attr); + ok((attr & FILE_ATTRIBUTE_DIRECTORY), "Entry #%d: path:%S, attr:0x%08lX\n", i, path, attr); + } + else + { + fclose(_wfopen(path, L"w")); + + attr = GetFileAttributesW(path); + ok(attr != INVALID_FILE_ATTRIBUTES, "Entry #%d: attr was 0x%08lX\n", i, attr); + ok(!(attr & FILE_ATTRIBUTE_DIRECTORY), "Entry #%d: attr was 0x%08lX\n", i, attr); + } + break; + case EAT_DELETE: + if (node->is_dir) + { + RemoveDirectoryW(path); + } + else + { + DeleteFileW(path); + } + attr = GetFileAttributesW(path); + ok(attr == INVALID_FILE_ATTRIBUTES, "Entry #%d: cannot delete\n", i); + break; + case EAT_CHECK_EXIST: + attr = GetFileAttributesW(path); + ok(attr != INVALID_FILE_ATTRIBUTES, "Entry #%d: attr was 0x%08lX\n", i, attr); + break; + case EAT_CHECK_NON_EXIST: + attr = GetFileAttributesW(path); + ok(attr == INVALID_FILE_ATTRIBUTES, "Entry #%d: attr was 0x%08lX\n", i, attr); + break; + case EAT_CALL: + ret = (*s_pDelNodeW)(path, entry->flags); + ok(ret == entry->ret, "Entry #%d: ret:%d, path:%S, flags:0x%08lX\n", + i, ret, path, entry->flags); + break; + } + } + + cleanupW(); +} + +START_TEST(DelNode) +{ + s_hAdvPack = LoadLibraryA("advpack.dll"); + if (s_hAdvPack == NULL) + { + skip("unable to load advpack.dll\n"); + return; + } + + /* DelNodeA */ + s_pDelNodeA = (DELNODEA)GetProcAddress(s_hAdvPack, "DelNodeA"); + if (s_pDelNodeA) + { + Test_DelNodeA(); + } + else + { + skip("DelNodeA not found in advpack.dll\n"); + } + + /* DelNodeW */ + s_pDelNodeW = (DELNODEW)GetProcAddress(s_hAdvPack, "DelNodeW"); + if (s_pDelNodeW) + { + Test_DelNodeW(); + } + else + { + skip("DelNodeW not found in advpack.dll\n"); + } + + FreeLibrary(s_hAdvPack); + s_hAdvPack = NULL; +} Index: rostests/apitests/advpack/testlist.c =================================================================== --- rostests/apitests/advpack/testlist.c (nonexistent) +++ rostests/apitests/advpack/testlist.c (working copy) @@ -0,0 +1,13 @@ +#define __ROS_LONG64__ + +#define STANDALONE +#include + +extern void func_DelNode(void); + +const struct test winetest_testlist[] = +{ + { "DelNode", func_DelNode }, + { 0, 0 } +}; + Index: rostests/apitests/CMakeLists.txt =================================================================== --- rostests/apitests/CMakeLists.txt (revision 74543) +++ rostests/apitests/CMakeLists.txt (working copy) @@ -1,6 +1,7 @@ include_directories(include) add_subdirectory(advapi32) +add_subdirectory(advpack) add_subdirectory(apphelp) add_subdirectory(appshim) add_subdirectory(atl)