473 lines
11 KiB
C
473 lines
11 KiB
C
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
tree.c
|
|
|
|
Abstract:
|
|
|
|
Implements routines that do operations on entire trees
|
|
|
|
Author:
|
|
|
|
Jim Schmidt (jimschm) 08-Mar-2000
|
|
|
|
Revision History:
|
|
|
|
<alias> <date> <comments>
|
|
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
|
|
//
|
|
// Includes
|
|
//
|
|
|
|
// None
|
|
|
|
#define DBG_TREE "Tree"
|
|
|
|
//
|
|
// Strings
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Constants
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Macros
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Types
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Macro expansion list
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Private function prototypes
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Macro expansion definition
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Code
|
|
//
|
|
|
|
BOOL
|
|
FiRemoveAllFilesInDirA (
|
|
IN PCSTR Dir
|
|
)
|
|
{
|
|
FILETREE_ENUMA e;
|
|
PCSTR pattern;
|
|
BOOL result = TRUE;
|
|
|
|
pattern = ObsBuildEncodedObjectStringExA (Dir, "*", FALSE);
|
|
|
|
if (EnumFirstFileInTreeExA (&e, pattern, 0, FALSE, FALSE, TRUE, TRUE, 1, FALSE, NULL)) {
|
|
do {
|
|
SetFileAttributesA (e.NativeFullName, FILE_ATTRIBUTE_NORMAL);
|
|
|
|
if (!DeleteFileA (e.NativeFullName)) {
|
|
AbortEnumFileInTreeA (&e);
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
|
|
} while (EnumNextFileInTreeA (&e));
|
|
}
|
|
|
|
ObsFreeA (pattern);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
BOOL
|
|
FiRemoveAllFilesInDirW (
|
|
IN PCWSTR Dir
|
|
)
|
|
{
|
|
FILETREE_ENUMW e;
|
|
PCWSTR pattern;
|
|
BOOL result = TRUE;
|
|
|
|
pattern = ObsBuildEncodedObjectStringExW (Dir, L"*", FALSE);
|
|
|
|
if (EnumFirstFileInTreeExW (&e, pattern, 0, FALSE, FALSE, TRUE, TRUE, 1, FALSE, NULL)) {
|
|
do {
|
|
SetFileAttributesW (e.NativeFullName, FILE_ATTRIBUTE_NORMAL);
|
|
|
|
if (!DeleteFileW (e.NativeFullName)) {
|
|
AbortEnumFileInTreeW (&e);
|
|
result = FALSE;
|
|
break;
|
|
}
|
|
|
|
} while (EnumNextFileInTreeW (&e));
|
|
}
|
|
|
|
ObsFreeW (pattern);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
BOOL
|
|
FiRemoveAllFilesInTreeExA (
|
|
IN PCSTR Dir,
|
|
IN BOOL RemoveRoot
|
|
)
|
|
{
|
|
FILETREE_ENUMA e;
|
|
PCSTR pattern;
|
|
BOOL result = TRUE;
|
|
PSTR encodedStr;
|
|
PCSTR dirPattern;
|
|
|
|
encodedStr = DuplicatePathStringA (Dir, TcharCountA (Dir));
|
|
ObsEncodeStringExA (encodedStr, Dir, "^");
|
|
dirPattern = JoinPathsA (encodedStr, "*");
|
|
FreePathStringA (encodedStr);
|
|
pattern = ObsBuildEncodedObjectStringExA (dirPattern, "*", FALSE);
|
|
|
|
if (EnumFirstFileInTreeExA (&e, pattern, 0, TRUE, FALSE, FALSE, TRUE, FILEENUM_ALL_SUBLEVELS, FALSE, NULL)) {
|
|
do {
|
|
if (e.Attributes & FILE_ATTRIBUTE_DIRECTORY) {
|
|
result = RemoveDirectoryA (e.NativeFullName);
|
|
} else {
|
|
SetFileAttributesA (e.NativeFullName, FILE_ATTRIBUTE_NORMAL);
|
|
result = DeleteFileA (e.NativeFullName);
|
|
}
|
|
if (!result) {
|
|
AbortEnumFileInTreeA (&e);
|
|
break;
|
|
}
|
|
} while (EnumNextFileInTreeA (&e));
|
|
}
|
|
|
|
if (result) {
|
|
if (RemoveRoot) {
|
|
result = RemoveDirectoryA (Dir);
|
|
}
|
|
}
|
|
|
|
ObsFreeA (pattern);
|
|
FreePathStringA (dirPattern);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
BOOL
|
|
FiRemoveAllFilesInTreeExW (
|
|
IN PCWSTR Dir,
|
|
IN BOOL RemoveRoot
|
|
)
|
|
{
|
|
FILETREE_ENUMW e;
|
|
PCWSTR pattern;
|
|
BOOL result = TRUE;
|
|
PWSTR encodedStr;
|
|
PCWSTR dirPattern;
|
|
|
|
encodedStr = DuplicatePathStringW (Dir, TcharCountW (Dir));
|
|
ObsEncodeStringExW (encodedStr, Dir, L"^");
|
|
dirPattern = JoinPathsW (encodedStr, L"*");
|
|
FreePathStringW (encodedStr);
|
|
pattern = ObsBuildEncodedObjectStringExW (dirPattern, L"*", FALSE);
|
|
|
|
if (EnumFirstFileInTreeExW (&e, pattern, 0, TRUE, FALSE, FALSE, TRUE, FILEENUM_ALL_SUBLEVELS, FALSE, NULL)) {
|
|
do {
|
|
if (e.Attributes & FILE_ATTRIBUTE_DIRECTORY) {
|
|
result = RemoveDirectoryW (e.NativeFullName);
|
|
} else {
|
|
SetFileAttributesW (e.NativeFullName, FILE_ATTRIBUTE_NORMAL);
|
|
result = DeleteFileW (e.NativeFullName);
|
|
}
|
|
if (!result) {
|
|
AbortEnumFileInTreeW (&e);
|
|
break;
|
|
}
|
|
} while (EnumNextFileInTreeW (&e));
|
|
}
|
|
|
|
if (result) {
|
|
if (RemoveRoot) {
|
|
result = RemoveDirectoryW (Dir);
|
|
}
|
|
}
|
|
|
|
ObsFreeW (pattern);
|
|
FreePathStringW (dirPattern);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
BOOL
|
|
FiCopyAllFilesInDirExA (
|
|
IN PCSTR Source,
|
|
IN PCSTR Dest,
|
|
IN BOOL SkipExisting
|
|
)
|
|
{
|
|
FILETREE_ENUMA e;
|
|
PCSTR pattern;
|
|
BOOL result = TRUE;
|
|
PCSTR subPath;
|
|
PCSTR destPath;
|
|
BOOL fileResult;
|
|
|
|
pattern = ObsBuildEncodedObjectStringExA (Source, "*", FALSE);
|
|
|
|
if (EnumFirstFileInTreeExA (&e, pattern, 0, FALSE, FALSE, TRUE, TRUE, 1, FALSE, NULL)) {
|
|
do {
|
|
subPath = e.NativeFullName;
|
|
subPath = (PCSTR) ((PBYTE) subPath + e.FileEnumInfo.PathPattern->ExactRootBytes);
|
|
|
|
destPath = JoinPathsA (Dest, subPath);
|
|
|
|
SetFileAttributesA (destPath, FILE_ATTRIBUTE_NORMAL);
|
|
fileResult = CopyFileA (e.NativeFullName, destPath, SkipExisting);
|
|
if (fileResult) {
|
|
fileResult = SetFileAttributesA (destPath, e.Attributes);
|
|
}
|
|
|
|
FreePathStringA (destPath);
|
|
|
|
if (!fileResult) {
|
|
if ((!SkipExisting) ||
|
|
(GetLastError() != ERROR_FILE_EXISTS)) {
|
|
result = FALSE;
|
|
DEBUGMSGA ((DBG_WARNING, "Unable to copy %s", e.NativeFullName));
|
|
}
|
|
}
|
|
|
|
} while (EnumNextFileInTreeA (&e));
|
|
}
|
|
|
|
ObsFreeA (pattern);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
BOOL
|
|
FiCopyAllFilesInDirExW (
|
|
IN PCWSTR Source,
|
|
IN PCWSTR Dest,
|
|
IN BOOL SkipExisting
|
|
)
|
|
{
|
|
FILETREE_ENUMW e;
|
|
PCWSTR pattern;
|
|
BOOL result = TRUE;
|
|
PCWSTR subPath;
|
|
PCWSTR destPath;
|
|
BOOL fileResult;
|
|
|
|
pattern = ObsBuildEncodedObjectStringExW (Source, L"*", FALSE);
|
|
|
|
if (EnumFirstFileInTreeExW (&e, pattern, 0, FALSE, FALSE, TRUE, TRUE, 1, FALSE, NULL)) {
|
|
do {
|
|
subPath = e.NativeFullName;
|
|
subPath = (PCWSTR) ((PBYTE) subPath + e.FileEnumInfo.PathPattern->ExactRootBytes);
|
|
|
|
destPath = JoinPathsW (Dest, subPath);
|
|
|
|
SetFileAttributesW (destPath, FILE_ATTRIBUTE_NORMAL);
|
|
fileResult = CopyFileW (e.NativeFullName, destPath, SkipExisting);
|
|
if (fileResult) {
|
|
fileResult = SetFileAttributesW (destPath, e.Attributes);
|
|
}
|
|
|
|
FreePathStringW (destPath);
|
|
|
|
if (!fileResult) {
|
|
if ((!SkipExisting) ||
|
|
(GetLastError() != ERROR_FILE_EXISTS)) {
|
|
result = FALSE;
|
|
DEBUGMSGW ((DBG_WARNING, "Unable to copy %s", e.NativeFullName));
|
|
}
|
|
}
|
|
|
|
} while (EnumNextFileInTreeW (&e));
|
|
}
|
|
|
|
ObsFreeW (pattern);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
BOOL
|
|
FiCopyAllFilesInTreeExA (
|
|
IN PCSTR Source,
|
|
IN PCSTR Dest,
|
|
IN BOOL SkipExisting
|
|
)
|
|
{
|
|
FILETREE_ENUMA e;
|
|
PCSTR pattern;
|
|
BOOL result = TRUE;
|
|
PCSTR dirPattern;
|
|
PCSTR subPath;
|
|
PCSTR destPath;
|
|
BOOL fileResult;
|
|
|
|
dirPattern = JoinPathsA (Source, "*");
|
|
pattern = ObsBuildEncodedObjectStringExA (dirPattern, "*", FALSE);
|
|
|
|
if (EnumFirstFileInTreeExA (
|
|
&e,
|
|
pattern,
|
|
0, // drive enum types
|
|
TRUE, // enum containers
|
|
TRUE, // containers first
|
|
FALSE, // files first
|
|
FALSE, // depth first
|
|
FILEENUM_ALL_SUBLEVELS, // max sublevel
|
|
FALSE, // use exclusions
|
|
NULL // callback on error
|
|
)) {
|
|
|
|
do {
|
|
|
|
subPath = e.NativeFullName;
|
|
subPath = (PCSTR) ((PBYTE) subPath + e.FileEnumInfo.PathPattern->ExactRootBytes);
|
|
|
|
destPath = JoinPathsA (Dest, subPath);
|
|
|
|
if (e.Attributes & FILE_ATTRIBUTE_DIRECTORY) {
|
|
fileResult = BfCreateDirectoryA (destPath);
|
|
if (fileResult) {
|
|
fileResult = SetFileAttributesA (destPath, e.Attributes);
|
|
}
|
|
} else {
|
|
SetFileAttributesA (destPath, FILE_ATTRIBUTE_NORMAL);
|
|
fileResult = CopyFileA (e.NativeFullName, destPath, SkipExisting);
|
|
if (fileResult) {
|
|
fileResult = SetFileAttributesA (destPath, e.Attributes);
|
|
}
|
|
}
|
|
|
|
FreePathStringA (destPath);
|
|
|
|
if (!fileResult) {
|
|
if ((!SkipExisting) ||
|
|
(GetLastError() != ERROR_FILE_EXISTS)) {
|
|
result = FALSE;
|
|
DEBUGMSGA ((DBG_WARNING, "Unable to copy %s", e.NativeFullName));
|
|
}
|
|
}
|
|
|
|
} while (EnumNextFileInTreeA (&e));
|
|
}
|
|
|
|
ObsFreeA (pattern);
|
|
FreePathStringA (dirPattern);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
BOOL
|
|
FiCopyAllFilesInTreeExW (
|
|
IN PCWSTR Source,
|
|
IN PCWSTR Dest,
|
|
IN BOOL SkipExisting
|
|
)
|
|
{
|
|
FILETREE_ENUMW e;
|
|
PCWSTR pattern;
|
|
BOOL result = TRUE;
|
|
PCWSTR dirPattern;
|
|
PCWSTR subPath;
|
|
PCWSTR destPath;
|
|
BOOL fileResult;
|
|
|
|
dirPattern = JoinPathsW (Source, L"*");
|
|
pattern = ObsBuildEncodedObjectStringExW (dirPattern, L"*", FALSE);
|
|
|
|
if (EnumFirstFileInTreeExW (
|
|
&e,
|
|
pattern,
|
|
0, // drive enum types
|
|
TRUE, // enum containers
|
|
TRUE, // containers first
|
|
FALSE, // files first
|
|
FALSE, // depth first
|
|
FILEENUM_ALL_SUBLEVELS, // max sublevel
|
|
FALSE, // use exclusions
|
|
NULL // callback on error
|
|
)) {
|
|
|
|
do {
|
|
|
|
subPath = e.NativeFullName;
|
|
subPath = (PCWSTR) ((PBYTE) subPath + e.FileEnumInfo.PathPattern->ExactRootBytes);
|
|
|
|
destPath = JoinPathsW (Dest, subPath);
|
|
|
|
if (e.Attributes & FILE_ATTRIBUTE_DIRECTORY) {
|
|
fileResult = BfCreateDirectoryW (destPath);
|
|
if (fileResult) {
|
|
fileResult = SetFileAttributesW (destPath, e.Attributes);
|
|
}
|
|
} else {
|
|
SetFileAttributesW (destPath, FILE_ATTRIBUTE_NORMAL);
|
|
fileResult = CopyFileW (e.NativeFullName, destPath, SkipExisting);
|
|
if (fileResult) {
|
|
fileResult = SetFileAttributesW (destPath, e.Attributes);
|
|
}
|
|
}
|
|
|
|
FreePathStringW (destPath);
|
|
|
|
if (!fileResult) {
|
|
if ((!SkipExisting) ||
|
|
(GetLastError() != ERROR_FILE_EXISTS)) {
|
|
result = FALSE;
|
|
DEBUGMSGW ((DBG_WARNING, "Unable to copy %s", e.NativeFullName));
|
|
}
|
|
}
|
|
|
|
} while (EnumNextFileInTreeW (&e));
|
|
}
|
|
|
|
ObsFreeW (pattern);
|
|
FreePathStringW (dirPattern);
|
|
|
|
return result;
|
|
}
|