Index: reactos/dll/win32/advpack/files.c =================================================================== --- reactos/dll/win32/advpack/files.c (revision 74543) +++ reactos/dll/win32/advpack/files.c (working copy) @@ -2,6 +2,7 @@ * Advpack file functions * * Copyright 2006 James Hawkins + * Copyright 2017 Katayama Hirofumi MZ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -314,67 +315,146 @@ return HRESULT_FROM_WIN32(dwLastError); } -static HRESULT DELNODE_recurse_dirtree(LPWSTR fname, DWORD flags) +static HRESULT DELNODE_delete_file(LPWSTR fname) { - DWORD fattrs = GetFileAttributesW(fname); - HRESULT ret = E_FAIL; + if (GetFileAttributesW(fname) != INVALID_FILE_ATTRIBUTES) + { + SetFileAttributesW(fname, FILE_ATTRIBUTE_NORMAL); + if (DeleteFileW(fname)) + { + return S_OK; + } + } + return E_FAIL; +} - static const WCHAR asterisk[] = {'*',0}; - static const WCHAR dot[] = {'.',0}; - static const WCHAR dotdot[] = {'.','.',0}; +static HRESULT DELNODE_remove_dir(LPWSTR fname, DWORD flags) +{ + if (GetFileAttributesW(fname) != INVALID_FILE_ATTRIBUTES) + { + if (!(flags & ADN_DEL_IF_EMPTY)) + { + if (flags & ADN_DONT_DEL_DIR) + { + return S_OK; + } + } - if (fattrs & FILE_ATTRIBUTE_DIRECTORY) + SetFileAttributesW(fname, FILE_ATTRIBUTE_NORMAL); + if (RemoveDirectoryW(fname) || (flags & ADN_DONT_DEL_SUBDIRS)) + { + return S_OK; + } + } + return E_FAIL; +} + +static inline BOOL is_dots(LPCWSTR name) +{ + static const WCHAR dot[] = {'.', 0}; + static const WCHAR dotdot[] = {'.', '.', 0}; + return (lstrcmpW(dot, name) == 0 || lstrcmpW(dotdot, name) == 0); +} + +static HRESULT DELNODE_delete_tree(LPWSTR fname, DWORD flags) +{ + static const WCHAR asterisk[] = {'*', 0}; + HANDLE hFind; + WIN32_FIND_DATAW FoundData; + int fname_len; + + /* generate a path with wildcard suitable for iterating */ + fname_len = lstrlenW(fname); + if (fname_len && fname[fname_len - 1] != L'\\') { - HANDLE hFindFile; - WIN32_FIND_DATAW w32fd; - BOOL done = TRUE; - int fname_len = lstrlenW(fname); + fname[fname_len++] = L'\\'; + } + lstrcpyW(fname + fname_len, asterisk); - /* Generate a path with wildcard suitable for iterating */ - if (fname_len && fname[fname_len-1] != '\\') fname[fname_len++] = '\\'; - lstrcpyW(fname + fname_len, asterisk); + /* is it empty? */ + if (flags & ADN_DEL_IF_EMPTY) + { + hFind = FindFirstFileW(fname, &FoundData); + if (hFind != INVALID_HANDLE_VALUE) + { + do + { + if (!is_dots(FoundData.cFileName)) + { + FindClose(hFind); + return E_FAIL; /* not empty */ + } + } while (FindNextFileW(hFind, &FoundData)); - if ((hFindFile = FindFirstFileW(fname, &w32fd)) != INVALID_HANDLE_VALUE) + FindClose(hFind); + } + } + + /* iterate the directory */ + hFind = FindFirstFileW(fname, &FoundData); + if (hFind != INVALID_HANDLE_VALUE) + { + do { - /* Iterate through the files in the directory */ - for (done = FALSE; !done; done = !FindNextFileW(hFindFile, &w32fd)) + if (!is_dots(FoundData.cFileName)) { - TRACE("%s\n", debugstr_w(w32fd.cFileName)); - if (lstrcmpW(dot, w32fd.cFileName) != 0 && - lstrcmpW(dotdot, w32fd.cFileName) != 0) + /* make a path */ + lstrcpyW(fname + fname_len, FoundData.cFileName); + + if (FoundData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - lstrcpyW(fname + fname_len, w32fd.cFileName); - if (DELNODE_recurse_dirtree(fname, flags) != S_OK) + /* it's a directory */ + if (!(flags & ADN_DONT_DEL_SUBDIRS)) { - break; /* Failure */ + /* recurse */ + DWORD new_flags = (flags & ~ADN_DONT_DEL_DIR); + if (S_OK != DELNODE_delete_tree(fname, new_flags)) + { + FindClose(hFind); + return E_FAIL; + } } } + else + { + /* not a directory */ + if (S_OK != DELNODE_delete_file(fname)) + { + FindClose(hFind); + return E_FAIL; + } + } } - FindClose(hFindFile); - } + } while (FindNextFileW(hFind, &FoundData)); - /* We're done with this directory, so restore the old path without wildcard */ - *(fname + fname_len) = '\0'; + FindClose(hFind); + } - if (done) - { - TRACE("%s: directory\n", debugstr_w(fname)); - if (SetFileAttributesW(fname, FILE_ATTRIBUTE_NORMAL) && RemoveDirectoryW(fname)) - { - ret = S_OK; - } - } + /* restore the old path without wildcard */ + *(fname + fname_len) = L'\0'; + + return DELNODE_remove_dir(fname, flags); +} + +static HRESULT DELNODE_delete(LPWSTR fname, DWORD flags) +{ + DWORD fattrs = GetFileAttributesW(fname); + + if (fattrs == INVALID_FILE_ATTRIBUTES) + { + TRACE("%s: doesn't exist\n", debugstr_w(fname)); + return E_FAIL; } + else if (fattrs & FILE_ATTRIBUTE_DIRECTORY) + { + TRACE("%s: directory\n", debugstr_w(fname)); + return DELNODE_delete_tree(fname, flags); + } else { TRACE("%s: file\n", debugstr_w(fname)); - if (SetFileAttributesW(fname, FILE_ATTRIBUTE_NORMAL) && DeleteFileW(fname)) - { - ret = S_OK; - } + return DELNODE_delete_file(fname); } - - return ret; } /*********************************************************************** @@ -432,7 +512,7 @@ /* TODO: Should check for system directory deletion etc. here */ - ret = DELNODE_recurse_dirtree(fname, dwFlags); + ret = DELNODE_delete(fname, dwFlags); } return ret;