Index: rostests/apitests/kernel32/CMakeLists.txt =================================================================== --- rostests/apitests/kernel32/CMakeLists.txt (revision 75222) +++ rostests/apitests/kernel32/CMakeLists.txt (working copy) @@ -7,6 +7,7 @@ DefaultActCtx.c DeviceIoControl.c dosdev.c + FileAttributes.c FindActCtxSectionStringW.c FindFiles.c GetComputerNameEx.c Index: rostests/apitests/kernel32/FileAttributes.c =================================================================== --- rostests/apitests/kernel32/FileAttributes.c (nonexistent) +++ rostests/apitests/kernel32/FileAttributes.c (working copy) @@ -0,0 +1,228 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Test for SetFileAttributes + * PROGRAMMERS: Katayama Hirofumi MZ + */ + +#include + +#define WIN32_NO_STATUS +#define _INC_WINDOWS +#define COM_NO_WINDOWS_H +#include +#include + +#define IGNORE_ATTRS \ + (FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_ENCRYPTED | \ + FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_TEMPORARY) + +typedef enum ENTRY_TYPE +{ + ET_MAKE, + ET_DELETE, + ET_DELETE_FORCE, + ET_CHECK, + ET_COPY, + ET_MOVE, + ET_SET +} ENTRY_TYPE; + +typedef struct ENTRY +{ + INT EntryNumber; /* # */ + ENTRY_TYPE EntryType; + BOOL Ret; + DWORD Param1; + DWORD Param2; +} ENTRY; + +typedef struct NODE +{ + const char *Path; + BOOL IsDir; +} NODE; + +static const NODE s_nodes[] = +{ + { "file1.txt", FALSE }, /* 0 */ + { "dir1", TRUE }, /* 1 */ + { "dir1\\file2.txt", FALSE }, /* 2 */ + { "dir1\\dir2", TRUE }, /* 3 */ +}; + +static const ENTRY s_entries[] = +{ + { 0, ET_MAKE, TRUE, 0 }, + { 1, ET_MAKE, TRUE, 1 }, + { 2, ET_MAKE, TRUE, 2 }, + { 3, ET_MAKE, TRUE, 3 }, + + { 4, ET_CHECK, TRUE, 0, 0 }, + { 5, ET_CHECK, TRUE, 1, FILE_ATTRIBUTE_DIRECTORY }, + { 6, ET_CHECK, TRUE, 2, 0 }, + { 7, ET_CHECK, TRUE, 3, FILE_ATTRIBUTE_DIRECTORY }, + + { 8, ET_DELETE, TRUE, 3 }, + { 9, ET_DELETE, TRUE, 2 }, + { 10, ET_DELETE, TRUE, 1 }, + { 11, ET_DELETE, TRUE, 0 }, + + { 12, ET_MAKE, TRUE, 0, FILE_ATTRIBUTE_READONLY }, + { 13, ET_DELETE, FALSE, 0 }, + { 14, ET_DELETE_FORCE, TRUE, 0 }, + + { 15, ET_MAKE, TRUE, 0, FILE_ATTRIBUTE_READONLY }, + { 16, ET_CHECK, TRUE, 0, FILE_ATTRIBUTE_READONLY }, + { 17, ET_SET, TRUE, 0, 0 }, + { 18, ET_CHECK, TRUE, 0, FILE_ATTRIBUTE_NORMAL }, + { 19, ET_DELETE, TRUE, 0 }, + + { 20, ET_MAKE, TRUE, 0, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN }, + { 21, ET_CHECK, TRUE, 0, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN }, + { 22, ET_DELETE, FALSE, 0 }, + { 23, ET_DELETE_FORCE, TRUE, 0 }, + + { 24, ET_MAKE, TRUE, 0, FILE_ATTRIBUTE_SYSTEM }, + { 25, ET_CHECK, TRUE, 0, FILE_ATTRIBUTE_SYSTEM }, + { 26, ET_DELETE, TRUE, 0 }, + + { 27, ET_MAKE, TRUE, 0 }, + { 28, ET_CHECK, TRUE, 0, 0 }, + { 29, ET_DELETE, TRUE, 0 }, + + { 30, ET_MAKE, TRUE, 1 }, + { 31, ET_MAKE, TRUE, 2 }, + + { 32, ET_SET, TRUE, 2, FILE_ATTRIBUTE_READONLY }, + { 33, ET_CHECK, TRUE, 2, FILE_ATTRIBUTE_READONLY }, + + { 34, ET_SET, TRUE, 2, FILE_ATTRIBUTE_DIRECTORY }, + { 35, ET_CHECK, TRUE, 2, FILE_ATTRIBUTE_NORMAL }, + + { 36, ET_SET, TRUE, 2, FILE_ATTRIBUTE_NORMAL }, + { 37, ET_CHECK, TRUE, 2, FILE_ATTRIBUTE_NORMAL }, + + { 38, ET_SET, TRUE, 2, FILE_ATTRIBUTE_SYSTEM }, + { 39, ET_CHECK, TRUE, 2, FILE_ATTRIBUTE_SYSTEM }, + + { 40, ET_SET, TRUE, 2, 0 }, + { 41, ET_CHECK, TRUE, 2, FILE_ATTRIBUTE_NORMAL }, + + { 42, ET_SET, TRUE, 1, FILE_ATTRIBUTE_HIDDEN }, + { 43, ET_CHECK, TRUE, 1, FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN }, + { 44, ET_CHECK, TRUE, 2, FILE_ATTRIBUTE_NORMAL }, + + { 45, ET_SET, TRUE, 1, 0 }, + { 46, ET_SET, FALSE, 0, 0 }, + { 47, ET_SET, FALSE, 3, 0 }, + + { 48, ET_DELETE, FALSE, 3 }, + { 49, ET_DELETE, TRUE, 2 }, + { 50, ET_DELETE, TRUE, 1 }, + { 51, ET_DELETE, FALSE, 0 }, +}; + +BOOL MakeFileA(const char *path, DWORD attr) +{ + HANDLE hFile; + hFile = CreateFileA(path, GENERIC_WRITE, FILE_SHARE_READ, NULL, + CREATE_ALWAYS, attr, NULL); + CloseHandle(hFile); + return hFile != INVALID_HANDLE_VALUE; +} + +void DoEntry(INT EntryNumber, const ENTRY *pEntry) +{ + const NODE *pNode1, *pNode2; + BOOL Ret; + DWORD attrs; + switch (pEntry->EntryType) + { + case ET_MAKE: + pNode1 = &s_nodes[pEntry->Param1]; + attrs = GetFileAttributes(pNode1->Path); + attrs &= ~FILE_ATTRIBUTE_READONLY; + SetFileAttributesA(pNode1->Path, attrs); + if (pNode1->IsDir) + { + RemoveDirectoryA(pNode1->Path); + Ret = CreateDirectoryA(pNode1->Path, NULL); + } + else + { + DeleteFileA(pNode1->Path); + Ret = MakeFileA(pNode1->Path, pEntry->Param2); + } + break; + case ET_DELETE: + pNode1 = &s_nodes[pEntry->Param1]; + if (pNode1->IsDir) + { + Ret = RemoveDirectoryA(pNode1->Path); + } + else + { + Ret = DeleteFileA(pNode1->Path); + } + break; + case ET_DELETE_FORCE: + pNode1 = &s_nodes[pEntry->Param1]; + attrs = GetFileAttributes(pNode1->Path); + attrs &= ~FILE_ATTRIBUTE_READONLY; + SetFileAttributesA(pNode1->Path, attrs); + if (pNode1->IsDir) + { + Ret = RemoveDirectoryA(pNode1->Path); + } + else + { + Ret = DeleteFileA(pNode1->Path); + } + break; + case ET_CHECK: + pNode1 = &s_nodes[pEntry->Param1]; + attrs = GetFileAttributes(pNode1->Path); + if (attrs != INVALID_FILE_ATTRIBUTES) + { + Ret = ((attrs & ~IGNORE_ATTRS) == (pEntry->Param2 & ~IGNORE_ATTRS)); + } + else + { + Ret = FALSE; + } + break; + case ET_COPY: + pNode1 = &s_nodes[pEntry->Param1]; + pNode2 = &s_nodes[pEntry->Param2]; + Ret = CopyFileA(pNode1->Path, pNode2->Path, FALSE); + break; + case ET_MOVE: + pNode1 = &s_nodes[pEntry->Param1]; + pNode2 = &s_nodes[pEntry->Param2]; + Ret = MoveFileA(pNode1->Path, pNode2->Path); + break; + case ET_SET: + pNode1 = &s_nodes[pEntry->Param1]; + Ret = SetFileAttributesA(pNode1->Path, pEntry->Param2); + break; + } + + ok(pEntry->Ret == Ret, "Entry #%d: Ret expected %d, was %d\n", + EntryNumber, pEntry->Ret, Ret); + if (!Ret && pEntry->EntryType == ET_CHECK) + { + trace("Entry #%d: attrs was 0x%08lX, expected 0x%08lX\n", + EntryNumber, attrs, pEntry->Param2); + } +} + +START_TEST(FileAttributes) +{ + UINT i, Count = _countof(s_entries); + + for (i = 0; i < Count; ++i) + { + DoEntry(s_entries[i].EntryNumber, &s_entries[i]); + } +} Index: rostests/apitests/kernel32/testlist.c =================================================================== --- rostests/apitests/kernel32/testlist.c (revision 75222) +++ rostests/apitests/kernel32/testlist.c (working copy) @@ -8,6 +8,7 @@ extern void func_DefaultActCtx(void); extern void func_DeviceIoControl(void); extern void func_dosdev(void); +extern void func_FileAttributes(void); extern void func_FindActCtxSectionStringW(void); extern void func_FindFiles(void); extern void func_GetComputerNameEx(void); @@ -36,6 +37,7 @@ { "DefaultActCtx", func_DefaultActCtx }, { "DeviceIoControl", func_DeviceIoControl }, { "dosdev", func_dosdev }, + { "FileAttributes", func_FileAttributes }, { "FindActCtxSectionStringW", func_FindActCtxSectionStringW }, { "FindFiles", func_FindFiles }, { "GetComputerNameEx", func_GetComputerNameEx },