windows-nt/Source/XPSP1/NT/ds/security/cryptoapi/common/pkiutil/dir.cpp
2020-09-26 16:20:57 +08:00

427 lines
11 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1995 - 1999
//
// File: dir.cpp
//
// Contents: Directory functions
//
// Functions: I_RecursiveCreateDirectory
//
// History: 06-Aug-99 reidk created
//--------------------------------------------------------------------------
#include "global.hxx"
#include "crypthlp.h"
#include "unicode.h"
#include <dbgdef.h>
BOOL I_RecursiveCreateDirectory(
IN LPCWSTR pwszDir,
IN LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
{
BOOL fResult;
DWORD dwAttr;
DWORD dwErr;
LPCWSTR pwsz;
DWORD cch;
WCHAR wch;
LPWSTR pwszParent = NULL;
dwAttr = GetFileAttributesU(pwszDir);
if (0xFFFFFFFF != dwAttr) {
if (FILE_ATTRIBUTE_DIRECTORY & dwAttr)
return TRUE;
goto InvalidDirectoryAttr;
}
dwErr = GetLastError();
if (!(ERROR_PATH_NOT_FOUND == dwErr || ERROR_FILE_NOT_FOUND == dwErr))
goto GetFileAttrError;
if (CreateDirectoryU(
pwszDir,
lpSecurityAttributes
)) {
SetFileAttributesU(pwszDir, FILE_ATTRIBUTE_SYSTEM);
return TRUE;
}
dwErr = GetLastError();
if (!(ERROR_PATH_NOT_FOUND == dwErr || ERROR_FILE_NOT_FOUND == dwErr))
goto CreateDirectoryError;
// Peal off the last path name component
cch = wcslen(pwszDir);
pwsz = pwszDir + cch;
while (L'\\' != *pwsz) {
if (pwsz == pwszDir)
// Path didn't have a \.
goto BadDirectoryPath;
pwsz--;
}
cch = (DWORD)(pwsz - pwszDir);
if (0 == cch)
// Detected leading \Path
goto BadDirectoryPath;
// Check for leading \\ or x:\.
wch = *(pwsz - 1);
if ((1 == cch && L'\\' == wch) || (2 == cch && L':' == wch))
goto BadDirectoryPath;
if (NULL == (pwszParent = (LPWSTR) PkiNonzeroAlloc((cch + 1) *
sizeof(WCHAR))))
goto OutOfMemory;
memcpy(pwszParent, pwszDir, cch * sizeof(WCHAR));
pwszParent[cch] = L'\0';
if (!I_RecursiveCreateDirectory(pwszParent, lpSecurityAttributes))
goto ErrorReturn;
if (!CreateDirectoryU(
pwszDir,
lpSecurityAttributes
)) {
dwErr = GetLastError();
goto CreateDirectory2Error;
}
SetFileAttributesU(pwszDir, FILE_ATTRIBUTE_SYSTEM);
fResult = TRUE;
CommonReturn:
PkiFree(pwszParent);
return fResult;
ErrorReturn:
fResult = FALSE;
goto CommonReturn;
SET_ERROR(InvalidDirectoryAttr, ERROR_FILE_INVALID)
SET_ERROR_VAR(GetFileAttrError, dwErr)
SET_ERROR_VAR(CreateDirectoryError, dwErr)
SET_ERROR(BadDirectoryPath, ERROR_BAD_PATHNAME)
TRACE_ERROR(OutOfMemory)
SET_ERROR_VAR(CreateDirectory2Error, dwErr)
}
BOOL
I_RecursiveDeleteDirectory(
IN LPCWSTR pwszDelete
)
{
BOOL fResult = TRUE;
HANDLE hFindHandle = INVALID_HANDLE_VALUE;
LPWSTR pwszSearch = NULL;
WIN32_FIND_DATAW FindData;
LPWSTR pwszDirOrFileDelete = NULL;
DWORD dwErr = 0;
//
// Create search string
//
pwszSearch = (LPWSTR) malloc((wcslen(pwszDelete) + 3) * sizeof(WCHAR));// length + '\' + '*' + '/0'
if (pwszSearch == NULL)
{
goto ErrorMemory;
}
wcscpy(pwszSearch, pwszDelete);
if ((pwszSearch[wcslen(pwszSearch) - 1] != L'\\'))
{
wcscat(pwszSearch, L"\\");
}
wcscat(pwszSearch, L"*");
//
// Loop for each item (file or dir) in pwszDelete, and delete/remove it
//
hFindHandle = FindFirstFileU(pwszSearch, &FindData);
if (hFindHandle == INVALID_HANDLE_VALUE)
{
// nothing found, get out
if (GetLastError() == ERROR_NO_MORE_FILES)
{
SetFileAttributesU(pwszDelete, FILE_ATTRIBUTE_NORMAL);
RemoveDirectoryW(pwszDelete);
goto CommonReturn;
}
else
{
goto ErrorFindFirstFile;
}
}
while (1)
{
if ((wcscmp(FindData.cFileName, L".") != 0) &&
(wcscmp(FindData.cFileName, L"..") != 0))
{
//
// name of dir or file to delete
//
pwszDirOrFileDelete = (LPWSTR) malloc((wcslen(pwszDelete) +
wcslen(FindData.cFileName) +
2) * sizeof(WCHAR));
if (pwszDirOrFileDelete == NULL)
{
goto ErrorMemory;
}
wcscpy(pwszDirOrFileDelete, pwszDelete);
if ((pwszDirOrFileDelete[wcslen(pwszDirOrFileDelete) - 1] != L'\\'))
{
wcscat(pwszDirOrFileDelete, L"\\");
}
wcscat(pwszDirOrFileDelete, FindData.cFileName);
//
// check to see if this is a dir or a file
//
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
//
// Recursive delete
//
if (!I_RecursiveDeleteDirectory(pwszDirOrFileDelete))
{
goto ErrorReturn;
}
}
else
{
SetFileAttributesU(pwszDirOrFileDelete, FILE_ATTRIBUTE_NORMAL);
if (!DeleteFileU(pwszDirOrFileDelete))
{
//goto ErrorReturn;
}
}
free(pwszDirOrFileDelete);
pwszDirOrFileDelete = NULL;
}
if (!FindNextFileU(hFindHandle, &FindData))
{
if (GetLastError() == ERROR_NO_MORE_FILES)
{
break;
}
else
{
goto ErrorFindNextFile;
}
}
}
SetFileAttributesU(pwszDelete, FILE_ATTRIBUTE_NORMAL);
RemoveDirectoryW(pwszDelete);
CommonReturn:
dwErr = GetLastError();
if (pwszSearch != NULL)
{
free(pwszSearch);
}
if (pwszDirOrFileDelete != NULL)
{
free(pwszDirOrFileDelete);
}
if (hFindHandle != INVALID_HANDLE_VALUE)
{
FindClose(hFindHandle);
}
SetLastError(dwErr);
return (fResult);
ErrorReturn:
fResult = FALSE;
goto CommonReturn;
SET_ERROR_EX(DBG_SS_TRUST, ErrorMemory, ERROR_NOT_ENOUGH_MEMORY)
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorFindFirstFile)
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorFindNextFile)
}
BOOL
I_RecursiveCopyDirectory(
IN LPCWSTR pwszDirFrom,
IN LPCWSTR pwszDirTo
)
{
BOOL fResult = TRUE;
HANDLE hFindHandle = INVALID_HANDLE_VALUE;
LPWSTR pwszSearch = NULL;
WIN32_FIND_DATAW FindData;
LPWSTR pwszDirOrFileFrom = NULL;
LPWSTR pwszDirOrFileTo = NULL;
DWORD dwErr = 0;
//
// Create search string
//
pwszSearch = (LPWSTR) malloc((wcslen(pwszDirFrom) + 3) * sizeof(WCHAR)); // length + '\' + '*' + '/0'
if (pwszSearch == NULL)
{
goto ErrorMemory;
}
wcscpy(pwszSearch, pwszDirFrom);
if ((pwszSearch[wcslen(pwszSearch) - 1] != L'\\'))
{
wcscat(pwszSearch, L"\\");
}
wcscat(pwszSearch, L"*");
//
// Loop for each item (file or dir) in pwszDirFrom, and
// copy it to pwszDirTo
//
hFindHandle = FindFirstFileU(pwszSearch, &FindData);
if (hFindHandle == INVALID_HANDLE_VALUE)
{
// nothing found, get out
if (GetLastError() == ERROR_NO_MORE_FILES)
{
goto CommonReturn;
}
else
{
goto ErrorFindFirstFile;
}
}
while (1)
{
if ((wcscmp(FindData.cFileName, L".") != 0) &&
(wcscmp(FindData.cFileName, L"..") != 0))
{
//
// name of dir or file to copy from
//
pwszDirOrFileFrom = (LPWSTR) malloc((wcslen(pwszDirFrom) + wcslen(FindData.cFileName) + 2) * sizeof(WCHAR));
if (pwszDirOrFileFrom == NULL)
{
goto ErrorMemory;
}
wcscpy(pwszDirOrFileFrom, pwszDirFrom);
if ((pwszDirOrFileFrom[wcslen(pwszDirOrFileFrom) - 1] != L'\\'))
{
wcscat(pwszDirOrFileFrom, L"\\");
}
wcscat(pwszDirOrFileFrom, FindData.cFileName);
//
// name of dir or file to copy to
//
pwszDirOrFileTo = (LPWSTR) malloc((wcslen(pwszDirTo) + wcslen(FindData.cFileName) + 2) * sizeof(WCHAR));
if (pwszDirOrFileTo == NULL)
{
goto ErrorMemory;
}
wcscpy(pwszDirOrFileTo, pwszDirTo);
if ((pwszDirOrFileTo[wcslen(pwszDirOrFileTo) - 1] != L'\\'))
{
wcscat(pwszDirOrFileTo, L"\\");
}
wcscat(pwszDirOrFileTo, FindData.cFileName);
//
// check to see if this is a dir or a file
//
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
//
// Create new dir then recursive copy
//
if (!I_RecursiveCreateDirectory(pwszDirOrFileTo, NULL))
{
goto ErrorReturn;
}
if (!I_RecursiveCopyDirectory(pwszDirOrFileFrom, pwszDirOrFileTo))
{
goto ErrorReturn;
}
}
else
{
if (!CopyFileU(pwszDirOrFileFrom, pwszDirOrFileTo, TRUE))
{
goto ErrorCopyFile;
}
}
free(pwszDirOrFileFrom);
pwszDirOrFileFrom = NULL;
free(pwszDirOrFileTo);
pwszDirOrFileTo = NULL;
}
if (!FindNextFileU(hFindHandle, &FindData))
{
if (GetLastError() == ERROR_NO_MORE_FILES)
{
goto CommonReturn;
}
else
{
goto ErrorFindNextFile;
}
}
}
CommonReturn:
dwErr = GetLastError();
if (pwszSearch != NULL)
{
free(pwszSearch);
}
if (pwszDirOrFileFrom != NULL)
{
free(pwszDirOrFileFrom);
}
if (pwszDirOrFileTo != NULL)
{
free(pwszDirOrFileTo);
}
if (hFindHandle != INVALID_HANDLE_VALUE)
{
FindClose(hFindHandle);
}
SetLastError(dwErr);
return (fResult);
ErrorReturn:
fResult = FALSE;
goto CommonReturn;
SET_ERROR(ErrorMemory, ERROR_NOT_ENOUGH_MEMORY)
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorFindFirstFile)
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorCopyFile)
TRACE_ERROR_EX(DBG_SS_TRUST, ErrorFindNextFile)
}